Lombok 사용시 주의 사항

전하윤·2025년 7월 15일
0

Spring

목록 보기
1/1
post-thumbnail

이 글에서는 Lombok의 단순한 사용법이 아닌,
개발을 하면서 직접 느낀 주의해야 할 점을 중심으로 다룹니다.

1. Lombok이란?

Lombok은 Java에서 반복되는 코드(예: getter, setter, toString, 생성자 등)를
어노테이션 한 줄로 자동 생성해주는 라이브러리다.
코드가 심플해지고, 생산성이 대폭 올라간다.


2. Lombok 기본 어노테이션 요약

어노테이션설명
@Getter/@Settergetter/setter 자동생성 (클래스/필드별 지정)
@NoArgsConstructor기본 생성자 생성
@AllArgsConstructor모든 필드 생성자 생성
@RequiredArgsConstructorfinal/@NonNull 필드 생성자 생성
@Builder빌더패턴 생성자
@EqualsAndHashCodeequals/hashCode 자동 생성
@ToStringtoString 자동 생성
@Data위의 대부분 기능 포함, 실무에선 비추천
@Slf4j/@Log4j2로그 객체 자동 주입

3. Lombok 사용시 주의 할 점

Setter 남발 금지 (특히 Entity)

  • 모든 필드에 @Setter를 남발하면, 불변성이나 캡슐화가 깨진다.
  • 엔티티의 필드값이 아무곳에서나 수정되면 디버깅/유지보수에 악몽을 경험 할지도
  • 되도록 생성자/빌더 패턴으로 생성하고, 꼭 필요한 필드에만 Setter을 사용하자
@Getter
@NoArgsConstructor
public class User {
    private String name; // setter X
    private String email; // setter X
    private int age;

	@Setter
    private String nickname;
    
    }
}

예를 들어 소셜로그인으로 로그인 하는 회원에 관해 nickname 외에는 수정할 수 없게 제약을 걸어놓는 상황.


4. Entity 생성은 Builder/생성자로, 수정은 setter/별도 메서드

  • Entity 생성(등록):
    → 빌더 패턴(@Builder), 생성자(@AllArgsConstructor)로 필수값을 한번에 확정

  • Entity 값 수정(업데이트):
    → 비즈니스 로직에서만 setter or 별도의 변경 메서드로 값 변경
    (예: changeEmail(String email) 등)


@Getter
@NoArgsConstructor
public class User {
    private String name;
    private String email;
    private int age;

    @Setter
    private String nickname;

    // 빌더 패턴 사용: 모든 필드 초기화
    @Builder
    public User(String name, String email, int age, String nickname) {
        this.name = name;
        this.email = email;
        this.age = age;
        this.nickname = nickname;
    }
}

// 사용 예시

        User user = User.builder()
                .name("홍길동")
                .email("gildong@kakao.com")
                .age(25)
                .nickname("길동이")
                .build();

        // 2. 생성 후 닉네임만 setter로 변경 가능
        user.setNickname("길동쓰");

        // 3. 아래 코드는 컴파일 에러!
        // user.setName("해커");
        // user.setEmail("hacker@evil.com");
        // user.setAge(100);

5. @Data 사용 지양

  • @Data는 선언시 getter/setter, equals/hashCode, toString, RequiredArgsConstructor 전부 생성이 된다.
  • 겉보기에는 편해보이지만, 필요하지 않는 기능까지 사용이 되면서, 객체의 불변성이나 캡슐화 이 깨지거나, 불필요한 메서드 생성이 되는 단점이 있다.
  • @Getter @Setter @Builder 등등 필요한 것만 명시적으로 사용하는게 이롭다.

6. JPA에서 올바른 조합

  • JPA는 DB에서 데이터를 조회할 때 프록시/리플렉션을 활용하여 기본 생성자(No-Args Constructor)로 객체를 생성함.

  • 즉, 기본 생성자가 반드시 필요
    (없으면 런타임 에러 발생: “No default constructor for entity” 등)

import lombok.*;

@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED) // JPA를 위한 기본 생성자(필수)
public class User {

    @Id @GeneratedValue
    private Long id;

    private String name;

    private String email;

    @Builder // 빌더 패턴을 위한 생성자(직접 작성)
    public User(String name, String email) {
        this.name = name;
        this.email = email;
    }
}
  • @NoArgsConstructor(access = PROTECTED) : JPA 프레임워크 전용 기본 생성자 제공(외부에서 직접 사용 불가)
  • @Builder 생성자: 개발자가 사용할 생성자 제공

7. @RequiredArgsConstructor 사용

  • @RequiredArgsConstructor는 클래스 내에서 final 혹은 @NonNull이 붙은 필드의 생성자 파라미터를 자동으로 생성해준다

  • 꼭 생성 시에만 값이 할당되어야 하거나, 의존성 주입(DI)이 필요한 클래스(예: 서비스, 엔티티, DTO, 도메인 객체 등)에 사용하면 유용하다.

import lombok.Getter;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;

@Getter
@RequiredArgsConstructor
public class Book {

    @NonNull
    private String title;           // 생성자 파라미터 (필수)
    private final String author;    // 생성자 파라미터 (필수)
    private int pageCount;          // 생성자에 포함X (선택값)
    private String publisher;       // 생성자에 포함X (선택값)
}

Lombok 실전 사용 버전

import lombok.*;
import javax.persistence.*;

@Entity
@Table(name = "bookstore")
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@ToString(exclude = "contactNumber")
@EqualsAndHashCode(of = {"name", "address"}, callSuper = false)
public class Bookstore extends BaseTimeEntity {

    private String name;                // 서점명
    private String address;             // 도로명 주소
    private String businessType;        // 업종(서점/중고서점 등)
    private String owner;               // 대표자명
    private String contactNumber;       // 연락처 (toString에서 제외)
    private boolean openOnWeekend;      // 주말 영업 여부
    private String postalCode;          // 우편번호
    private double longitude;           // 경도
    private double latitude;            // 위도

    @Builder
    public Bookstore(String name, String address, String businessType, String owner,
                     String contactNumber, boolean openOnWeekend, String postalCode,
                     double longitude, double latitude) {
        this.name = name;
        this.address = address;
        this.businessType = businessType;
        this.owner = owner;
        this.contactNumber = contactNumber;
        this.openOnWeekend = openOnWeekend;
        this.postalCode = postalCode;
        this.longitude = longitude;
        this.latitude = latitude;
    }
}

위의 예시를 통해 전달하고자 하는 내용은 아래와 같다.

동일한 서점 정보 중복 방지

  • @EqualsAndHashCode(of = {"name", "address"})
  • 서점명(name)과 주소(address)가 동일하다면 같은 객체로 판단

민감 정보 출력 방지

  • @ToString(exclude = "contactNumber")
  • 연락처(contactNumber)는 toString에서 제외해, 로그 등에서 불필요하게 노출되는 것을 막음

생성은 빌더로

  • @Builder로 여러 데이터가 섞여 들어오는 상황에서도 안전하게 객체 생성 가능

JPA 기본 생성자 제공

  • @NoArgsConstructor(access = PROTECTED)
  • JPA 프레임워크만 사용할 수 있도록 보호
profile
개발에 대한 고민과 성장의 기록을 일기장처럼 성찰하며 남기는 공간

0개의 댓글