Spring Boot Lombok 실무 사용법: 설치부터 Annotation 적용과 오류 해결까지

Spring Boot에서 Lombok을 사용하는 이유부터 설치와 설정, 주요 annotation의 실무 사용법, IntelliJ와 Gradle 환경에서 Lombok 실행 안됨 문제를 해결하는 방법까지 실제 프로젝트 기준으로 정리합니다.

 

Spring Boot에서 Lombok을 사용하는 이유

Spring Boot 프로젝트를 개발하다 보면 DTO, Entity, Request, Response 같은 Java 클래스를 계속 만들게 됩니다. 이때 필드마다 getter와 setter를 작성하고 생성자, toString(), equals(), hashCode()까지 직접 구현하면 코드가 빠르게 길어집니다.

Spring Boot Lombok은 반복적으로 작성하는 Java 코드를 컴파일 과정에서 자동 생성해 주는 라이브러리입니다.

예를 들어 다음과 같은 클래스가 있다고 가정해 보겠습니다.

public class UserResponse {

    private Long id;
    private String name;
    private String email;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }
}

필드가 3개뿐인데도 클래스가 상당히 길어집니다. Lombok을 적용하면 같은 목적의 코드를 훨씬 간결하게 작성할 수 있습니다.

@Getter
@Setter
public class UserResponse {

    private Long id;
    private String name;
    private String email;
}

개발자가 직접 getter와 setter를 작성하지 않았지만 컴파일 과정에서 필요한 메서드가 생성됩니다.

Lombok을 사용하는 핵심 이유는 단순히 코드 줄 수를 줄이는 데 있지 않습니다. 반복 코드 제거, 클래스의 핵심 구조 파악, 유지보수성 향상이 더 중요한 목적입니다.

다만 Lombok annotation을 무조건 많이 붙인다고 좋은 코드는 아닙니다. DTO, Entity, Service 등 클래스의 역할에 맞게 필요한 annotation만 선택하는 것이 실무에서 가장 중요합니다.

Spring Boot Lombok 설치 및 설정 방법

Gradle 프로젝트에 Lombok 적용하기

Spring Boot Gradle 프로젝트에서는 일반적으로 build.gradle의 dependencies 영역에 다음 설정을 추가합니다.

dependencies {
    compileOnly 'org.projectlombok:lombok'
    annotationProcessor 'org.projectlombok:lombok'

    testCompileOnly 'org.projectlombok:lombok'
    testAnnotationProcessor 'org.projectlombok:lombok'
}

여기서 중요한 설정은 다음 두 가지입니다.

설정역할

compileOnly 컴파일할 때 Lombok을 사용할 수 있도록 설정
annotationProcessor Lombok annotation을 분석해 코드를 생성
testCompileOnly 테스트 코드에서 Lombok 사용
testAnnotationProcessor 테스트 코드의 annotation 처리

Spring Boot Lombok 설정에서 자주 발생하는 실수는 compileOnly만 추가하고 annotationProcessor를 누락하는 것입니다.

의존성이 추가된 것처럼 보여도 annotation 처리 과정이 정상적으로 실행되지 않으면 getter, 생성자, builder 등이 생성되지 않을 수 있습니다.

프로젝트에 Spring Boot Dependency Management가 적용되어 있다면 Lombok 버전을 별도로 작성하지 않는 구성이 흔합니다. 다만 사용하는 Spring Boot와 Gradle 구성에 따라 의존성 관리 방식이 다를 수 있으므로 프로젝트 설정을 함께 확인해야 합니다.

Maven 프로젝트에 Lombok 설치하기

Maven을 사용하는 경우 pom.xml에 Lombok 의존성을 추가합니다.

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>

Maven 프로젝트에서도 annotation processor 설정이 빌드 환경에 따라 영향을 줄 수 있습니다. IDE에서는 정상인데 실제 빌드 서버에서 실패한다면 Maven 컴파일러 설정과 Lombok annotation 처리 여부를 확인하는 것이 좋습니다.

IntelliJ에서 Lombok 설정 확인하기

Spring Boot Lombok 설치를 완료했는데 코드에 빨간 줄이 표시되거나 getter를 찾지 못한다면 IDE 설정을 확인해야 합니다.

IntelliJ에서는 다음 항목을 확인합니다.

Settings → Build, Execution, Deployment → Compiler → Annotation Processors

여기서 Enable annotation processing이 활성화되어 있는지 확인합니다.

IntelliJ 버전과 프로젝트 설정에 따라 Lombok 지원 방식이 달라질 수 있으므로 다음 항목도 함께 점검하는 것이 좋습니다.

  • Gradle 의존성이 정상적으로 내려받아졌는지 확인
  • Annotation Processing 활성화 여부 확인
  • Gradle 프로젝트 새로고침
  • IDE 캐시 문제 확인
  • 실제 Gradle 빌드 성공 여부 확인

중요한 점은 IDE의 빨간 줄과 실제 컴파일 오류를 구분하는 것입니다.

IDE에서는 오류처럼 표시되지만 ./gradlew build는 성공하는 경우가 있습니다. 반대로 IDE에서는 정상처럼 보여도 CI/CD 서버에서 빌드가 실패할 수 있습니다.

Spring Boot Lombok Annotation 실무 사용법

@Getter: 가장 부담 없이 사용할 수 있는 Annotation

@Getter는 필드의 getter 메서드를 자동 생성합니다.

@Getter
public class UserResponse {

    private Long id;
    private String name;
}

실무에서는 DTO, Response 객체, 설정 객체 등 값을 읽는 클래스에 자주 사용합니다.

클래스 전체가 아니라 특정 필드에만 적용할 수도 있습니다.

public class User {

    @Getter
    private Long id;

    private String password;
}

외부에서 읽을 필요가 없는 필드에는 getter를 만들지 않는 방식으로 접근 범위를 줄일 수 있습니다.

모든 필드에 무조건 getter를 만드는 것보다 객체의 역할을 먼저 생각하는 편이 좋습니다.

@Setter: 편리하지만 사용 범위를 제한해야 한다

@Setter는 setter 메서드를 자동으로 생성합니다.

@Getter
@Setter
public class UserRequest {

    private String name;
    private String email;
}

Request DTO처럼 데이터 바인딩이 필요한 객체에서는 편리합니다. 그러나 도메인 객체나 JPA Entity에 클래스 단위로 무조건 @Setter를 적용하면 객체의 상태가 어디에서든 변경될 수 있습니다.

예를 들어 다음 코드는 간단하지만 상태 변경 의도를 파악하기 어렵습니다.

user.setStatus("ACTIVE");

업무 의미가 중요한 경우에는 다음처럼 명확한 메서드를 만드는 편이 낫습니다.

public void activate() {
    this.status = "ACTIVE";
}

실무에서 @Setter는 필요한 범위에만 제한적으로 적용하는 것이 안전합니다.

@NoArgsConstructor: 기본 생성자 자동 생성

@NoArgsConstructor는 파라미터가 없는 기본 생성자를 만듭니다.

@NoArgsConstructor
public class UserRequest {

    private String name;
    private String email;
}

JSON 역직렬화, 프레임워크 객체 생성, JPA Entity 등에서 기본 생성자가 필요한 경우 사용합니다.

JPA Entity에서는 생성자의 접근 범위를 제한하는 방식도 많이 사용합니다.

@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Entity
public class User {

    @Id
    private Long id;
}

이렇게 하면 프레임워크에서 필요한 기본 생성자는 유지하면서 애플리케이션 코드에서 의미 없이 객체를 생성하는 것을 줄일 수 있습니다.

@AllArgsConstructor: 모든 필드를 받는 생성자 생성

@AllArgsConstructor는 선언된 모든 필드를 파라미터로 받는 생성자를 생성합니다.

@AllArgsConstructor
public class UserResponse {

    private Long id;
    private String name;
    private String email;
}

간단한 DTO에서는 편리하지만 필드가 많아지면 생성자 호출 코드를 읽기 어려워집니다.

new UserResponse(1L, "홍길동", "user@example.com");

필드가 많거나 같은 타입의 값이 반복된다면 순서를 잘못 넣을 가능성도 있습니다. 이런 경우에는 Builder 패턴을 검토할 수 있습니다.

@RequiredArgsConstructor: Spring Boot에서 가장 자주 사용하는 Annotation 중 하나

@RequiredArgsConstructor는 final 필드와 @NonNull이 붙은 필드를 대상으로 생성자를 자동 생성합니다.

Spring Boot Service에서 생성자 주입을 사용할 때 특히 유용합니다.

@Service
@RequiredArgsConstructor
public class UserService {

    private final UserRepository userRepository;
    private final EmailService emailService;
}

Lombok을 사용하지 않으면 다음 생성자를 직접 작성해야 합니다.

public UserService(
        UserRepository userRepository,
        EmailService emailService
) {
    this.userRepository = userRepository;
    this.emailService = emailService;
}

의존성이 늘어날수록 생성자 코드도 길어집니다. @RequiredArgsConstructor를 사용하면 final 필드를 유지하면서 생성자 주입 코드를 간결하게 작성할 수 있습니다.

실무에서 Spring Boot Lombok을 사용하는 가장 대표적인 패턴 중 하나입니다.

@Builder: 객체 생성 코드를 읽기 쉽게 만든다

필드가 많은 DTO를 생성할 때 Builder 패턴을 사용하면 어떤 값이 어디에 들어가는지 명확하게 확인할 수 있습니다.

@Getter
@Builder
public class UserResponse {

    private Long id;
    private String name;
    private String email;
}

객체 생성은 다음과 같이 작성합니다.

UserResponse response = UserResponse.builder()
        .id(1L)
        .name("홍길동")
        .email("user@example.com")
        .build();

생성자 방식보다 필드의 의미를 파악하기 쉽습니다.

다만 @Builder도 모든 클래스에 붙이는 것은 권장하기 어렵습니다. 필수값이 반드시 존재해야 하는 객체라면 Builder를 통해 누락된 상태의 객체가 만들어질 가능성을 함께 검토해야 합니다.

Builder는 편리한 생성 방식이지 객체의 유효성을 자동으로 보장하는 기능은 아닙니다.

@Data: 편하지만 가장 신중하게 사용해야 한다

@Data는 여러 기능을 한 번에 제공합니다.

  • @Getter
  • @Setter
  • @RequiredArgsConstructor
  • @ToString
  • @EqualsAndHashCode

간단한 데이터 클래스에서는 매우 편리합니다.

@Data
public class UserRequest {

    private String name;
    private String email;
}

하지만 실무에서는 @Data를 습관적으로 사용하는 것을 주의해야 합니다.

특히 JPA Entity에 적용하면 모든 필드의 setter가 생성되고, toString(), equals(), hashCode()의 동작이 객체 관계와 맞물려 예상하지 못한 문제를 만들 가능성이 있습니다.

JPA Entity에는 @Data 하나를 붙이기보다 필요한 Lombok annotation을 개별적으로 선택하는 방식이 더 명확합니다.

실무에서는 어떤 Lombok Annotation을 사용해야 할까?

클래스 역할에 따라 다음처럼 구분하면 관리하기 쉽습니다.

클래스 종류주로 검토할 Annotation주의사항

Request DTO @Getter, @Setter, @NoArgsConstructor 데이터 바인딩 방식 확인
Response DTO @Getter, @Builder 불필요한 Setter 최소화
Service @RequiredArgsConstructor final 의존성과 생성자 주입
JPA Entity @Getter, @NoArgsConstructor @Data, 무분별한 @Setter 주의
단순 내부 DTO @Getter, @Builder 객체 생성 방식에 따라 선택
설정 클래스 @Getter, @Setter 바인딩 구조 확인

가장 중요한 기준은 Lombok annotation의 개수를 줄이는 것이 아니라 클래스의 의도를 명확하게 유지하는 것입니다.

Spring Boot Lombok 실무 적용 예제

Service에서 생성자 주입하기

Spring Boot Service에서는 다음 패턴을 자주 사용할 수 있습니다.

@Service
@RequiredArgsConstructor
public class OrderService {

    private final OrderRepository orderRepository;
    private final PaymentService paymentService;

    public void createOrder() {
        // 주문 처리
    }
}

@Autowired를 필드에 직접 붙이지 않고 final 필드와 생성자 주입을 사용합니다.

이 방식은 다음과 같은 장점이 있습니다.

  • 의존 관계를 쉽게 확인할 수 있음
  • 필드를 final로 유지할 수 있음
  • 테스트에서 필요한 의존성을 명시적으로 전달하기 쉬움
  • 반복적인 생성자 코드 감소

Response DTO에 Builder 적용하기

Controller에서 반환할 응답 객체는 다음과 같이 구성할 수 있습니다.

@Getter
@Builder
public class ProductResponse {

    private Long id;
    private String name;
    private int price;
}

Service에서는 다음과 같이 생성합니다.

return ProductResponse.builder()
        .id(product.getId())
        .name(product.getName())
        .price(product.getPrice())
        .build();

필드 순서에 의존하지 않기 때문에 생성자 호출보다 코드를 읽기 쉽습니다.

JPA Entity에는 필요한 기능만 적용하기

Entity는 다음처럼 최소한의 Lombok annotation만 사용하는 방법을 검토할 수 있습니다.

@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Product {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    private int price;

    public void changePrice(int price) {
        this.price = price;
    }
}

가격을 변경하기 위해 클래스 전체에 @Setter를 붙이는 대신 changePrice()라는 명확한 메서드를 제공합니다.

이렇게 하면 어떤 상태가 어떤 의도로 변경되는지 코드에서 확인하기 쉬워집니다.

Lombok 실행 안됨 문제 해결 방법

Spring Boot Lombok 적용 후 가장 많이 만나는 문제는 annotation을 추가했는데 getter, builder 또는 생성자를 찾지 못하는 상황입니다.

1. Gradle 의존성 확인

먼저 build.gradle을 확인합니다.

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

테스트 코드에서도 Lombok을 사용한다면 테스트 관련 설정도 확인합니다.

testCompileOnly 'org.projectlombok:lombok'
testAnnotationProcessor 'org.projectlombok:lombok'

2. Annotation Processing 확인

IntelliJ 설정에서 Annotation Processing이 활성화되어 있는지 확인합니다.

Settings → Build, Execution, Deployment → Compiler → Annotation Processors

Lombok은 annotation processor를 통해 코드를 생성하므로 이 과정이 정상적으로 동작하는지 확인해야 합니다.

3. Gradle 프로젝트 새로고침

build.gradle을 수정한 뒤 IDE가 변경된 의존성을 아직 반영하지 못한 경우가 있습니다.

Gradle 도구 창에서 프로젝트를 새로고침하거나 터미널에서 다음 명령으로 실제 빌드를 확인합니다.

./gradlew clean build

Windows에서는 프로젝트 환경에 따라 다음 명령을 사용할 수 있습니다.

gradlew.bat clean build

4. IDE 문제인지 실제 빌드 문제인지 구분

다음 상황을 구분해야 합니다.

상황확인할 부분

IDE만 빨간 줄 표시 IntelliJ 인덱스, Lombok 지원, Annotation Processing
Gradle 빌드도 실패 의존성 및 annotationProcessor 설정
로컬 성공, CI 실패 빌드 서버의 JDK·Gradle·프로젝트 설정
테스트만 실패 testCompileOnly, testAnnotationProcessor
Builder만 인식 안 됨 @Builder 위치와 생성 대상 확인

Lombok 실행 안됨 문제를 해결할 때는 IDE 화면만 보지 말고 실제 빌드 명령 결과를 함께 확인해야 합니다.

5. JDK와 Gradle 환경 확인

Spring Boot Lombok 실행 문제가 계속된다면 현재 프로젝트에서 실제로 사용하는 JDK와 Gradle 환경도 확인해야 합니다.

터미널에서 다음 정보를 점검합니다.

java -version

./gradlew --version

IDE가 사용하는 JDK와 터미널의 JDK가 다르면 한쪽에서는 성공하고 다른 환경에서는 실패할 수 있습니다.

특히 CI/CD를 사용하는 프로젝트라면 다음 환경을 비교해야 합니다.

  • 로컬 JDK 버전
  • IDE Project SDK
  • Gradle JVM
  • CI/CD Runner의 JDK
  • Docker 빌드 이미지의 JDK

Lombok 자체 문제처럼 보여도 실제 원인은 빌드 환경 차이인 경우가 있으므로 단계별로 확인하는 것이 좋습니다.

Lombok 사용 시 실무에서 주의할 점

Lombok은 코드가 없는 것이 아니라 생성되는 것이다

소스 코드에 getter가 보이지 않는다고 해서 getter가 존재하지 않는 것은 아닙니다. 컴파일 과정에서 Lombok이 코드를 생성합니다.

따라서 문제를 분석할 때는 다음 구조를 이해해야 합니다.

Java 소스 작성 → Annotation Processing → 코드 생성 → 컴파일

이 흐름을 이해하면 Lombok 실행 안됨 문제를 훨씬 빠르게 추적할 수 있습니다.

@Data를 기본값처럼 사용하지 않는다

처음에는 모든 클래스에 @Data를 붙이는 방식이 편할 수 있습니다. 그러나 프로젝트가 커지면 어떤 기능이 필요한지 구분하기 어려워집니다.

실무에서는 다음처럼 필요한 기능을 명시하는 방식이 더 읽기 좋을 수 있습니다.

@Getter
@Builder
public class UserResponse {
}

이 코드만 봐도 외부에서 값을 읽고 Builder로 생성하는 객체라는 의도를 어느 정도 파악할 수 있습니다.

Entity와 DTO의 Lombok 사용 기준을 구분한다

DTO는 데이터를 전달하는 목적이 강하지만 Entity는 상태와 관계를 관리합니다.

따라서 두 클래스에 동일한 Lombok annotation을 적용할 필요는 없습니다.

DTO에서는 편의성을 적극 활용하고, Entity에서는 객체의 상태 변경과 연관관계를 고려해 보수적으로 적용하는 방식이 실무에 적합합니다.

팀 전체가 동일한 빌드 환경을 사용해야 한다

한 개발자의 IntelliJ에서만 정상 동작하는 설정은 좋은 프로젝트 설정이 아닙니다.

Lombok은 다음 환경에서 모두 빌드되는지 확인해야 합니다.

  • 개발자 로컬 환경
  • IDE
  • 터미널 Gradle 빌드
  • CI/CD 서버
  • Docker 이미지

프로젝트는 IDE 설정이 아니라 빌드 설정만으로도 정상 컴파일될 수 있어야 합니다.

Spring Boot Lombok 실무 사용 기준 정리

Spring Boot에서 Lombok은 반복 코드를 줄이는 데 매우 유용합니다. 특히 @Getter, @RequiredArgsConstructor, @Builder는 DTO와 Service 코드에서 자주 활용할 수 있습니다.

하지만 모든 클래스에 @Data, @Setter, @Builder를 붙이는 방식은 오히려 클래스의 의도를 흐릴 수 있습니다.

실무에서는 다음 기준으로 접근하는 것이 좋습니다.

  • Service는 final 필드와 @RequiredArgsConstructor를 활용
  • Response DTO는 @Getter와 @Builder를 필요에 따라 적용
  • Request DTO는 데이터 바인딩 방식을 고려해 @Setter 사용 여부 결정
  • JPA Entity는 @Data와 무분별한 @Setter 사용을 주의
  • Lombok 실행 안됨 문제는 annotationProcessor부터 확인
  • IDE 오류와 실제 Gradle 빌드 오류를 구분
  • 로컬과 CI/CD의 JDK 및 빌드 환경을 함께 점검

결국 Spring Boot Lombok 실무 사용법의 핵심은 annotation을 많이 사용하는 것이 아니라 반복 코드는 줄이면서 객체의 역할은 더 명확하게 만드는 것입니다.

FAQ

Spring Boot에서 Lombok을 사용하는 이유는 무엇인가요?

Getter, setter, 생성자, builder처럼 반복적으로 작성하는 코드를 줄이기 위해 사용합니다. 코드가 짧아지는 효과도 있지만 실제로는 클래스의 핵심 필드와 로직에 집중할 수 있다는 점이 더 중요합니다.

Lombok 설치만 하면 바로 실행되나요?

Gradle이나 Maven 의존성 설정 외에도 annotation processing이 정상적으로 동작해야 합니다. Gradle에서는 annotationProcessor 설정을 확인하고 IDE의 Annotation Processing 설정도 함께 점검하는 것이 좋습니다.

Lombok 실행 안됨 오류가 발생하면 무엇부터 확인해야 하나요?

먼저 compileOnly와 annotationProcessor 설정을 확인합니다. 이후 Annotation Processing, Gradle 새로고침, 실제 clean build 결과, JDK와 Gradle 버전을 순서대로 점검하는 것이 효율적입니다.

@Data를 모든 DTO에 사용해도 되나요?

간단한 데이터 클래스에서는 편리하지만 항상 필요한 것은 아닙니다. setter가 필요 없는 Response DTO라면 @Getter만 사용하는 편이 객체의 의도를 더 명확하게 보여줄 수 있습니다.

JPA Entity에 @Data를 사용하면 안 되나요?

무조건 사용할 수 없다는 의미는 아니지만 주의가 필요합니다. @Data는 setter, toString(), equals(), hashCode() 등 여러 기능을 함께 생성합니다. Entity의 상태 변경과 연관관계를 고려하면 필요한 annotation만 개별적으로 적용하는 편이 더 안전한 경우가 많습니다.

@RequiredArgsConstructor와 @AllArgsConstructor의 차이는 무엇인가요?

@RequiredArgsConstructor는 주로 final 필드와 @NonNull 필드를 대상으로 생성자를 만들고, @AllArgsConstructor는 모든 필드를 받는 생성자를 만듭니다. Spring Boot Service의 생성자 주입에는 @RequiredArgsConstructor가 자주 사용됩니다.

Lombok 없이 Spring Boot 개발이 가능한가요?

가능합니다. Lombok은 Spring Boot 필수 라이브러리가 아닙니다. 직접 생성자를 작성하거나 IDE의 코드 생성 기능, Java record 등을 사용할 수도 있습니다. 프로젝트의 Java 버전과 클래스 역할에 따라 적절한 방식을 선택하면 됩니다.