Getter 와 Setter는 객체의 필드 값에 접근하는 메서드이다.
return 필요)매개변수 필요)class Person {
private String name;
// Getter: 필드 값 조회
public String getName() {
return name;
}
// Setter: 필드 값 변경
public void setName(String name) {
this.name = name;
}
}
public class Main {
public static void main(String[] args) {
Person p = new Person();
p.setName("hyerin"); // Setter 사용
System.out.println(p.getName()); // Getter 사용 (출력: hyerin)
}
}
1. 정보은닉 & 캡슐화
private 필드를 외부에서 직접 수정하지 못하도록 보호.
외부에서는 Getter/Setter를 통해서만 값을 수정할 수 있다.
2. 데이터 무결성 유지
public void setAge(int age) {
if (age > 0) {
this.age = age;
} else {
System.out.println("나이는 0보다 커야 합니다.");
}
}
3. 유지보수성 향상
🔴 Setter로 값을 변경하는 경우 이유가 명확하지 않다.
// ❌ 잔액이 왜 변경되었는지 알 수 없음
Account myAccount = new Account(500);
myAccount.setBalance(1000);
🟢 해결방법
class Account {
private long balance;
public void deposit(long amount) { // 입금
if (amount > 0) {
balance += amount;
}
}
public void withdraw(long amount) { // 출금
if (amount > balance) {
throw new IllegalArgumentException("잔액 부족");
}
balance -= amount;
}
public long getBalance() {
return balance;
}
}
🔴 Getter로 데이터를 꺼내와서 로직을 처리하면 비즈니스 로직이 분산된다
public void withdraw(long id, long amount) {
Account account = accountRepository.findById(id).orElseThrow();
long newBalance = account.getBalance() - amount;
if (newBalance < 0) {
throw new IllegalArgumentException("잔액 부족");
}
account.setBalance(newBalance);
}
🟢 해결방안
class Account {
private long balance;
public void withdraw(long amount) {
if (amount > balance) {
throw new IllegalArgumentException("잔액 부족");
}
balance -= amount;
}
}
No!
Getter/Setter를 무조건 피하는 게 아니라, "적절하게 사용"하는 것이 중요하다.
1. DTO (Data Transfer Object)
데이터를 전달할 때는 getter/setter가 필요하다.
예를 들어, JSON 응답을 만들 때는 getter가 없으면 데이터 변환이 안 된다.
2. 단순한 객체 조회 (조회만 할 때는 괜찮음)
예를 들어, getName(), getAge() 같은 단순한 정보 조회는 문제 없다.
3. "변경 메서드"가 필요 없을 때
모든 값을 변경할 필요는 없지만, 읽기는 해야 할 경우 getter를 사용할 수 있다.
Getter/Setter를 무조건 사용하지 않는 것이 아니라, 상황에 맞게 적절히 사용해야 함.
Setter 대신 도메인의 의미가 명확한 메서드를 사용하는 것이 유지보수에 유리함.
DTO에서는 Getter/Setter가 필요하지만, 비즈니스 로직이 포함된 객체에서는 최소한으로 사용해야 함.