개발(0)/JPA
💡 자주 쓰는 롬복(Lombok) 어노테이션과 패턴
까만밀가루
2025. 6. 12. 14:28
개인 프로젝트에 롬복을 쓰는데 습관처럼 쓰는데, 회사 직원이 물어보면서 다시 공부하게 된 롬복
여기서 다시 정리해봅니다
📋 Lombok 어노테이션 종류/역할
어노테이션 | 역할/설명 | 실무 사용 예 |
@Getter | 모든 필드의 getter 자동 생성 | 거의 필수. DTO, Entity 모두에서 널리 사용 |
@Setter | 모든 필드의 setter 자동 생성 | Entity, DTO에서 불변성 지키고 싶으면 지양 |
@NoArgsConstructor | 파라미터 없는 기본 생성자 자동 생성 | JPA Entity 필수 (보통 access=PROTECTED) |
@AllArgsConstructor | 모든 필드를 파라미터로 받는 생성자 자동 생성 | 빌더와 같이 쓰기 필수! (access=PRIVATE 추천) |
@RequiredArgsConstructor | final/@NonNull 필드만 받는 생성자 자동 생성 | 서비스/컨트롤러 등 의존성 주입(DI)에서 가끔 사용 |
@Builder | 빌더 패턴 자동 생성 (가장 많이 씀) | 대부분 클래스 단위로 선언 |
@EqualsAndHashCode | equals, hashCode 메서드 자동 생성 | 엔티티 PK, VO에서 가끔 사용 |
@ToString | toString 메서드 자동 생성 | 로그/디버깅용, but 엔티티 연관관계 필드 주의! |
@Data | Getter/Setter, toString, equals, hashCode, RequiredArgsConstructor 자동 생성 | 편하긴 하지만, 실무에서는 거의 |
💡 @Data를 요즘 안 쓰는 이유?
1. 의도치 않은 setter/equals/hashCode 생성
- @Data는 모든 필드에 Setter, equals, hashCode, toString까지 다 만들어줌
- Entity/DTO에서 불변성을 깨뜨리거나, 연관관계 필드의 순환 참조(toString, equals 등)로 버그 발생 위험
2. 과도한 메서드 생성, 관리 어려움
- 내가 원치 않는 메서드까지 자동 생성 → 디버깅, 유지보수 때 혼란
3. 실무 표준은 "명확하게 필요한 것만!"
- @Getter, @NoArgsConstructor, @AllArgsConstructor, @Builder
→ 각 목적에 맞게 명확하게 조합해서 쓰는 게 실무 표준 - Entity에는 Setter를 아예 안 쓰거나, 필요한 필드에만 개별로 붙임
🚩 내가 사용한 조합
@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED) // JPA Entity 필수
@AllArgsConstructor(access = AccessLevel.PRIVATE) // 빌더 생성자
@Builder // 객체 생성 편의성
@Table(name = "survey")
public class Survey { ... }
- 기본적으로 생성하는 파라미터 없는 생성자 생성한 뒤 AllArgsConstructor과 Builder를 쓴다.
처음 Builder만 써야한다고 생각했는데 에러가 나서 AllArgsConstructor과 Builder에 대해 더 공부했다.
🔍 Q. @AllArgsConstructor, @Builder의 차이는?
A. 전체 파라미터 생성자 vs. 빌더 패턴
- @AllArgsConstructor
→ 모든 필드를 파라미터로 받는 생성자를 만들어줌
→ 직접 new로 객체 생성
→ 필드가 많으면 가독성 떨어지고, 순서 잘못 넣으면 에러
Survey s = new Survey(1L, "설문제목", ...);
- @Builder
→ 빌더 패턴을 자동 생성
→ 필요한 필드만 선택적으로 할당, 순서 상관 없이 명확하게 객체 생성
→ 내부적으로 “모든 필드 생성자”를 써서 객체를 만든다
Survey s = Survey.builder()
.id(1L)
.name("설문제목")
.build();
B. 빌더는 '모든 필드 생성자'가 필수!
- 빌더 패턴이 정상적으로 동작하려면
모든 필드를 받는 생성자가 필요함 - @NoArgsConstructor만 있으면, 이 생성자가 없어 에러 발생
- 특정 생성자에만 붙이기도 가능:
일부 파라미터만 빌더로 만들고 싶으면, 생성자에 직접 붙일 수도 있지만
→ 잘 안 씀 (유지보수 불리, 코드 일관성 떨어짐) - 해결:
@AllArgsConstructor도 같이 선언하면 해결
(실무에서는 @NoArgsConstructor + @AllArgsConstructor + @Builder 조합이 표준)
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor(access = AccessLevel.PRIVATE) // 실수로 new 못하게!
@Builder
public class Survey { ... }
C. 두 어노테이션의 “핵심 차이점
@AllArgsConstructor | @Builder | |
생성 방법 | new Survey(1L, "이름") | Survey.builder().id(1L).name("이름").build() |
파라미터 순서 | 반드시 지켜야 함 | 순서 상관 없음, 일부 필드만 선택 가능 |
가독성 | 낮음 (필드 많으면 헷갈림) | 높음, 명확하게 필드별로 할당 |
유지보수 | 힘듦 (필드 추가/삭제 시 생성자 수정 필요) | 쉬움 (필드 추가/삭제에도 코드 영향 적음) |
필드 생략 | 불가 (모든 필드 값 필수) | 가능 (필요한 것만 채워서 build 가능) |
아직 실무에서 써본적은 없지만 앞으로를 위해 제대로 알아두면 좋을 거 같아 정리한 롬복
어노테이션이나 의존성을 필요할까봐 막 넣었다면 요즘은 최대한 사용하는 것 위주로 넣으려고 한다.(그래도 어려움)