코드 리뷰 중 @Data 쓰지 말라는 피드백이 보여서, 생각난 김에 정리한다.
@Data가 하는 일
@Data
public class User {
private Long id;
private String name;
}
이 한 줄이 @Getter, @Setter, @ToString, @EqualsAndHashCode, @RequiredArgsConstructor를 전부 생성한다.
문제는 너무 많은 걸 자동으로 한다는 거다.
실제로 겪은 문제
1. 불변 객체를 못 만듦
@Data
public class User {
private Long id;
private String email;
}
// setter가 자동 생성되어서 아래처럼 변경 가능
user.setId(999L); // 엔티티 ID 변경
해결
@Getter
@Builder
public class User {
private final Long id;
private final String email;
}
2. 민감 정보 로그 노출
@Data
public class Member {
private String username;
private String password;
}
// 로그 찍으면...
System.out.println(member);
// Member(username=kim, password=1234) <- 비밀번호 노출
해결
@Getter
@ToString(exclude = "password")
public class Member {
private String username;
private String password;
}
3. JPA 양방향 연관관계에서 무한루프
@Entity
@Data
public class Order {
@OneToMany(mappedBy = "order")
private List<OrderItem> items;
}
@Entity
@Data
public class OrderItem {
@ManyToOne
private Order order;
}
// StackOverflowError 발생
System.out.println(order);
toString()이 서로를 계속 호출함.
해결
@Entity
@Getter
@ToString(exclude = "items")
@EqualsAndHashCode(of = "id")
public class Order {
@Id
private Long id;
@OneToMany(mappedBy = "order")
private List<OrderItem> items;
}
4. 비즈니스 로직을 우회하여 직접 데이터 세팅 가능
@Data
public class BankAccount {
private BigDecimal balance;
}
// setter로 검증 없이 변경 가능
account.setBalance(new BigDecimal("-1000")); // 음수 잔액?
해결
@Getter
@Builder
public class BankAccount {
private BigDecimal balance;
public void deposit(BigDecimal amount) {
if (amount.compareTo(BigDecimal.ZERO) <= 0) {
throw new IllegalArgumentException("양수만 가능");
}
this.balance = this.balance.add(amount);
}
}
대신 이렇게 쓰자(예시)
DTO/VO
@Getter
@Builder
@AllArgsConstructor
public class UserDto {
private final Long id;
private final String name;
}
JPA Entity
@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@ToString(exclude = "연관관계필드")
@EqualsAndHashCode(of = "id")
public class Member {
@Id
private Long id;
private String name;
}
간단한 불변 객체
@Value // final + getter만 생성
public class Point {
int x;
int y;
}
정리
- @Data는 너무 많은 걸 자동으로 함
- 특히 JPA 엔티티에선 위험함
- 필요한 것만 명시적으로 선택하자
- Setter는 정말 필요할 때만
'개발 고민' 카테고리의 다른 글
| [개발 고민] webSocket, SSE(Server Sent Event) 중 뭐가 좋을까? (0) | 2026.01.18 |
|---|---|
| [개발 고민]MySQL 조인 순서 최적화로 쿼리 속도 개선하기 (0) | 2026.01.16 |
| [개발일지_safeHome] 12. 등기부등본 분석 작업 관련 DB 설계 및 서비스 개발(임시) (0) | 2026.01.08 |
| 멀티테넌시 아키텍처 (0) | 2025.04.02 |
| SaaS와 멀티테넌시 (0) | 2025.04.02 |