Lombok 활용 가이드 - 보일러플레이트 제거



Lombok은 Java의 반복적인 코드(getter, setter, 생성자 등)를 어노테이션으로 자동 생성해주는 라이브러리입니다.



언제 사용하나요?



  • DTO, Entity 클래스의 getter/setter 자동 생성

  • 생성자, Builder 패턴 자동 구현

  • 로깅 코드 간소화

  • equals, hashCode, toString 자동 생성



의존성 추가


<!-- Maven -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
<scope>provided</scope>
</dependency>

// Gradle
compileOnly \047org.projectlombok:lombok:1.18.30\047
annotationProcessor \047org.projectlombok:lombok:1.18.30\047


IDE 설정


# IntelliJ: File → Settings → Plugins → Lombok 설치
# Enable annotation processing 체크

# Eclipse: lombok.jar 다운로드 후 실행
java -jar lombok.jar


@Getter / @Setter


// Before
public class User {
private String name;
private int age;

public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
}

// After - Lombok
@Getter @Setter
public class User {
private String name;
private int age;
}

// 필드 레벨 적용
public class User {
@Getter @Setter
private String name;

@Getter // setter 없이 getter만
private int age;
}


@NoArgsConstructor / @AllArgsConstructor / @RequiredArgsConstructor


@NoArgsConstructor   // 기본 생성자
@AllArgsConstructor // 모든 필드 생성자
public class User {
private String name;
private int age;
}
// → User(), User(String name, int age) 생성

@RequiredArgsConstructor // final/NonNull 필드만
public class UserService {
private final UserRepository userRepository; // 생성자 주입됨
private final EmailService emailService;
}
// → UserService(UserRepository, EmailService) 생성


@Data - 올인원


@Data  // @Getter + @Setter + @ToString + @EqualsAndHashCode + @RequiredArgsConstructor
public class User {
private String name;
private int age;
}

// 주의: Entity에는 @Data 대신 개별 어노테이션 사용 권장
// (equals/hashCode의 순환참조 문제)


@Builder - 빌더 패턴


@Builder
public class User {
private String name;
private int age;
private String email;
}

// 사용
User user = User.builder()
.name("홍길동")
.age(30)
.email("hong@test.com")
.build();

// 기본값 설정
@Builder
public class Order {
@Builder.Default
private String status = "PENDING";

@Builder.Default
private List<Item> items = new ArrayList<>();
}


@Slf4j - 로깅


@Slf4j
@Service
public class UserService {

public void createUser(User user) {
log.info("Creating user: {}", user.getName());
log.debug("User details: {}", user);
log.error("Error occurred", exception);
}
}

// log 변수가 자동 생성됨
// private static final Logger log = LoggerFactory.getLogger(UserService.class);


@ToString


@ToString
public class User {
private String name;
private int age;

@ToString.Exclude // 출력에서 제외
private String password;
}

// 결과: User(name=홍길동, age=30)

@ToString(callSuper = true) // 부모 클래스 포함
@ToString(onlyExplicitlyIncluded = true) // 명시적 포함만
public class User {
@ToString.Include
private String name;
}


@EqualsAndHashCode


@EqualsAndHashCode
public class User {
private Long id;
private String name;
}

// 특정 필드만 비교
@EqualsAndHashCode(of = {"id"})
public class User {
private Long id;
private String name; // equals 비교에서 제외
}

// Entity에서는 보통 ID만 비교
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
public class User {
@EqualsAndHashCode.Include
private Long id;
}


@Value - 불변 객체


@Value  // 모든 필드 final + private, getter만, 생성자
public class Money {
int amount;
String currency;
}

// @Value = @Getter + @AllArgsConstructor + @ToString
// + @EqualsAndHashCode + 필드 private final


@With - 불변 객체 복사


@Value
@With
public class User {
String name;
int age;
}

User user1 = new User("홍길동", 30);
User user2 = user1.withAge(31); // name은 유지, age만 변경된 새 객체


실전 조합 예시


// Entity
@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
@Builder
public class User {
@Id @GeneratedValue
private Long id;
private String name;
}

// DTO
@Getter
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class UserDto {
private String name;
private int age;
}

// Service
@Slf4j
@Service
@RequiredArgsConstructor
public class UserService {
private final UserRepository userRepository;
}