Java Lombok으로 보일러플레이트 코드 줄이기

Java Lombok의 어노테이션 기반 코드 생성 방식과 주요 기능, JPA·DTO 적용 사례 및 운영 시 주의사항을 정리한다.

2026-08-14 · 최초 발행 2025-06-28

반복 메서드가 클래스의 의도를 가릴 때

Java 클래스는 캡슐화를 위해 필드 접근 메서드, 생성자, 동등성 비교, 문자열 표현을 자주 직접 작성한다. 엔티티 하나에도 getter와 setter가 수십 줄 들어갈 수 있고, 필드가 바뀌면 관련 메서드도 함께 손봐야 한다.

Lombok은 이런 반복 코드를 어노테이션으로 선언하고 컴파일 시점에 필요한 코드를 생성하는 라이브러리다. getter, setter, constructor, equals, hashCode, toString 같은 일반적인 메서드를 자동으로 만들며, 2009년에 처음 출시됐다. 소스 파일에서는 클래스의 핵심 필드와 의도를 더 직접적으로 읽을 수 있게 된다.

자주 쓰는 어노테이션의 역할

@Getter@Setter는 필드의 접근자와 설정자를 만든다. 클래스 전체나 개별 필드에 적용할 수 있다.

@Getter @Setter
public class User {
    private String name;
    private String email;

    // 위 어노테이션으로 아래 메서드들이 자동 생성됨
    // public String getName() { return this.name; }
    // public void setName(String name) { this.name = name; }
    // public String getEmail() { return this.email; }
    // public void setEmail(String email) { this.email = email; }
}

@ToString은 객체의 문자열 표현을 생성한다. 로그나 디버깅에서 노출하면 안 되는 필드는 exclude로 제외할 수 있다.

@ToString(exclude = "password")
public class User {
    private String username;
    private String password; // toString() 결과에서 제외됨
    private String email;
}

@EqualsAndHashCode는 객체 비교와 해시 기반 컬렉션 사용에 필요한 equals()hashCode()를 만든다.

@EqualsAndHashCode(callSuper = false)
public class Employee {
    private Long id;
    private String name;
    // id와 name 기반으로 equals, hashCode 메서드 생성
}

생성자에는 목적에 맞춰 @NoArgsConstructor, @AllArgsConstructor, @RequiredArgsConstructor를 선택할 수 있다. 마지막 어노테이션은 final 또는 @NonNull 필드만 인자로 받는다.

@RequiredArgsConstructor
@AllArgsConstructor
public class Product {
    private final Long id;     // RequiredArgsConstructor에 포함
    private final String code; // RequiredArgsConstructor에 포함
    private String name;       // AllArgsConstructor에만 포함
    private double price;      // AllArgsConstructor에만 포함
}

@Data@Getter, @Setter, @ToString, @EqualsAndHashCode, @RequiredArgsConstructor를 묶은 복합 어노테이션이다.

@Data
public class Customer {
    private Long id;
    private String name;
    private String address;
    // 위 어노테이션 하나로 모든 기본 메서드 자동 생성
}

객체 생성 코드에는 @Builder를 붙여 빌더 패턴 구현을 생성할 수 있다.

@Builder
public class Order {
    private Long id;
    private String customerName;
    private LocalDate orderDate;
    private List<OrderItem> items;

    // 사용 예:
    // Order order = Order.builder()
    //     .id(1L)
    //     .customerName("홍길동")
    //     .orderDate(LocalDate.now())
    //     .items(items)
    //     .build();
}

@Slf4j는 SLF4J 로거 객체를 선언한다.

@Slf4j
public class LogExample {
    public void doSomething() {
        log.info("Something is happening");
        // private static final Logger log = LoggerFactory.getLogger(LogExample.class);
        // 위 코드가 자동 생성됨
    }
}

컴파일 과정에서 만들어지는 코드

Lombok은 어노테이션 프로세서를 이용해 컴파일 단계의 Abstract Syntax Tree(AST)를 조작한다. 생성된 메서드는 실제 .class 파일에 포함되므로, 런타임에 별도 코드 생성 비용이 발생하지 않는다.

Java 소스코드 + Lombok어노테이션Lombok 애노테이션 프로세서AST 조작메서드 자동 생성컴파일된 클래스 파일

프로젝트에 추가하는 방법

Maven에서는 의존성을 다음과 같이 선언한다.

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.26</version>
    <scope>provided</scope>
</dependency>

Gradle 설정은 다음과 같다.

compileOnly 'org.projectlombok:lombok:1.18.26'
annotationProcessor 'org.projectlombok:lombok:1.18.26'

IDE에서도 Lombok 인식 설정이 필요하다. IntelliJ IDEA는 Lombok 플러그인 설치가 필요하며 최신 버전은 기본 지원한다. Eclipse에서는 lombok.jar 실행 후 IDE 경로를 지정하고, VS Code에서는 Lombok Annotations Support 확장 프로그램을 설치한다.

엔티티와 DTO에서의 적용

JPA 엔티티는 필드와 생성자, 반복 메서드가 함께 늘어나기 쉬운 대표적인 대상이다. Lombok을 적용하면 선언부는 간결해지지만, toString과 동등성 비교의 대상 필드는 명시적으로 제어할 수 있다.

// Lombok 사용 전
@Entity
public class User {
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String username;
    private String email;
    private String password;

    public User() {}

    public User(String username, String email, String password) {
        this.username = username;
        this.email = email;
        this.password = password;
    }

    // getter, setter, equals, hashCode, toString 메서드 (약 50줄 이상)
    // ...
}

// Lombok 사용 후
@Entity
@Getter @Setter
@NoArgsConstructor
@AllArgsConstructor
@ToString(exclude = "password")
@EqualsAndHashCode(of = "id")
public class User {
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String username;
    private String email;
    private String password;
}

DTO에는 @Data@Builder를 함께 사용해 데이터 전달과 객체 생성을 단순화할 수 있다.

// Lombok 사용
@Data
@Builder
public class ProductDTO {
    private Long id;
    private String name;
    private BigDecimal price;
    private String category;
    private boolean available;
}

// 실제 사용 예
ProductDTO product = ProductDTO.builder()
    .id(1L)
    .name("스마트폰")
    .price(new BigDecimal("1000000"))
    .category("전자기기")
    .available(true)
    .build();

자동 생성 범위를 설계에 맞추는 법

JPA 양방향 관계에서 @ToString이나 @EqualsAndHashCode를 무심코 사용하면 순환 참조가 생길 수 있다. 관계 필드를 제외 대상으로 지정해야 한다.

@Entity
@ToString(exclude = "department")  // 순환 참조 방지
public class Employee {
    @ManyToOne
    private Department department;
}

@Entity
@ToString(exclude = "employees")  // 순환 참조 방지
public class Department {
    @OneToMany(mappedBy = "department")
    private List<Employee> employees;
}

상속 구조에서는 @EqualsAndHashCodecallSuper 여부도 검토 대상이다. callSuper=true로 설정하면 부모 클래스의 필드까지 equals, hashCode 계산에 포함된다.

@EqualsAndHashCode(callSuper = true)  // 부모 클래스 필드 포함
public class Manager extends Employee {
    private String department;
}

@Data는 모든 필드에 getter와 setter를 생성한다. 불변 객체를 의도한 클래스라면 원치 않는 setter가 생길 수 있으므로, 필요한 어노테이션만 개별적으로 선언하는 편이 안전하다.

@Builder를 사용할 때는 필수 필드가 빠질 가능성도 고려해야 한다. @Builder.Default로 기본값을 지정하고 @NonNull로 null 검사를 강제할 수 있다.

@Builder
public class User {
    private Long id;

    @Builder.Default
    private boolean active = true;  // 기본값 설정

    @NonNull  // null 체크 강제
    private String username;
}

함께 검토할 수 있는 선택지

불변 데이터 클래스에는 Java 14+의 Record 타입을 고려할 수 있다. 객체 간 매핑은 MapStruct, 불변 값 클래스 생성은 Google의 AutoValue 또는 Immutables가 각각 보완 기술이 될 수 있다.

Spring Boot 코드에서의 사용

Spring Boot 프로젝트에서는 Lombok을 Spring Data JPA 엔티티, DTO, 서비스 레이어에 폭넓게 통합할 수 있다. 생성자 주입 패턴과 로거 선언도 어노테이션으로 표현할 수 있다.

@Service
@RequiredArgsConstructor  // 생성자 주입 패턴 구현
@Slf4j
public class UserService {
    private final UserRepository userRepository;

    public User findById(Long id) {
        log.info("Finding user with id: {}", id);
        return userRepository.findById(id)
            .orElseThrow(() -> new UserNotFoundException(id));
    }
}

Lombok은 반복 구현을 줄이고 클래스의 핵심 의도를 드러내는 데 유용하다. 다만 자동 생성되는 메서드가 도메인 모델의 변경 가능성, 연관관계, 상속 구조에 어떤 영향을 주는지는 어노테이션을 붙이는 자리마다 확인해야 한다.

JavaLombokSpring BootJPA코드 생성