Lombok 안전 사용 규칙(@Builder/@Value/@With)
Lombok은 보일러플레이트를 크게 줄여줍니다.
하지만 무심코 @Data를 붙이거나 @Builder 디폴트값/불변성 규칙을 놓치면
생산성보다 버그가 앞서옵니다. 아래 규칙은 “팀에서 Lombok을 안전하게 쓰기 위한 최소 합의”입니다.
1) @Data 남용 금지
@Data는 모든 필드를 대상으로 equals/hashCode/toString을 생성합니다. 엔티티/DTO에 무분별하게 쓰면 성능/보안(PII 노출) 문제가 생깁니다. 대신 @Getter + 필요한 것만 @EqualsAndHashCode(of="id") 같이 선별하세요.
2) @Builder 기본값 규칙
@Builder
public class User {
private final String id;
@Builder.Default private final Role role = Role.USER; // ✅ 디폴트 보존
}
@Builder.Default 없이 디폴트를 설정하면 빌더가 null로 덮어쓰는 문제가 생깁니다. 또한 불변 필드에 null이 들어가지 않도록 @NonNull을 병행합니다.
3) @Value(불변)와 컬렉션
@Value
public class Profile {
String name;
List<String> tags; // ⚠️ 리스트 자체는 가변
public Profile(String name, List<String> tags) {
this.name = name;
this.tags = List.copyOf(tags); // 방어적 복사로 불변 보장
}
}
@Value는 필드를 final로 만들지만, 컬렉션 내용까지 불변으로 바꾸진 않습니다. 방어적 복사/불변 래핑으로 외부 변경을 차단하세요.
4) @With로 부분 변경 모델링
@Value @With
public class Money {
long amount; String currency;
}
// 사용: money.withAmount(2000)
@With는 불변 객체의 “값 한두 개만 바뀐 복사”를 우아하게 만듭니다.
5) Jackson/JPA와의 궁합
- Jackson: DTO에
@NoArgsConstructor가 필요할 수 있습니다(필요 시만). record를 쓰면 NoArgs 없이도 잘 동작합니다. - JPA: 엔티티에는 Lombok의
@Builder보다 명시적 생성자를 권장.@EqualsAndHashCode는 식별자만 기준으로.
6) Delombok/구성 파일
# lombok.config (루트)
lombok.addLombokGeneratedAnnotation = true
lombok.equalsAndHashCode.callSuper = skip
lombok.anyConstructor.suppressConstructorProperties = true
CI에서 delombok을 돌려 생성 결과를 확인하면 문제를 조기 발견할 수 있습니다.
7) @Builder와 검증 조합
@Getter @Builder
public class SignUp {
@NonNull String email;
@NonNull String password;
public SignUp(String email, String password) {
if (!email.contains("@")) throw new IllegalArgumentException("email");
if (password.length() < 8) throw new IllegalArgumentException("pwd");
this.email = email; this.password = password;
}
}
빌더가 생성자를 우회하지 않도록 “필수 검증은 생성자에서” 수행하세요.
요약 체크리스트
@Data금지, 필요한 애노테이션만 선택@Builder.Default로 디폴트 보존- 불변 + 컬렉션은 방어적 복사
@With로 부분 변경- Jackson/JPA 요구사항 분리, 테스트로 확인
👉 1편: Maven→Gradle 마이그레이션 함정 7가지
👉 2편: JUnit5 + Mockito: Given-When-Then 패턴
'Java & Spring' 카테고리의 다른 글
| 메서드명 쿼리 vs @Query vs QueryDSL 비교 (0) | 2025.10.02 |
|---|---|
| 연관관계 주인/지연로딩 N+1 체크리스트 (0) | 2025.10.02 |
| JUnit5 + Mockito: Given-When-Then 패턴 (0) | 2025.10.01 |
| Maven→Gradle 마이그레이션 함정 7가지 (0) | 2025.10.01 |
| Pageable 응답 DTO 규격(정렬·페이지 표준화) (0) | 2025.09.30 |