본문 바로가기

[기획 & PM & BE] BE:OUR 프로젝트

[BE:OUR] Entity 클래스 어노테이션 @Builder, @AllArgsConstructor, @NoArgsConstructor

 

 일반적으로 Entity 클래스에 @Builder, @AllArgsConstructor, @NoArgsConstructor 어노테이션을 한 번에 붙여 코드를 작성하곤 한다. 나도 그래왔는데, 이번에 코드 리뷰를 하며 이를 엄격하게 관리하는 방법에 대해 공부하고, PR을 작성해보았다.

 

 

(수정 전 코드)

package com.beour.token.entity;

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Builder
@Getter
@Entity
@NoArgsConstructor
@AllArgsConstructor
public class RefreshToken {

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

    private String loginId;
    private String refresh;
    private String expiration;

}

 

(수정 후 코드)

package com.beour.token.entity;

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import lombok.*;

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

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

    private String loginId;
    private String refresh;
    private String expiration;

    @Builder
    public RefreshToken(String loginId, String refresh, String expiration) {
        this.loginId = loginId;
        this.refresh = refresh;
        this.expiration = expiration;
    }
}

 

수정한 코드는 불필요한 어노테이션을 제거하고,
객체 생성 방식(Builder + 생성자 접근 제어)을 명확하게 다듬은 구조입니다.

아래에 두 버전의 차이점, 그리고 장단점을 상세히 비교해드릴게요.

 

✅ 변경 요약

항목 수정 전 수정 후

@AllArgsConstructor O ❌ 제거
@Builder 클래스에 붙음 생성자에 붙음
@NoArgsConstructor 기본 (public) access = PROTECTED
생성자 정의 없음 (롬복에 의존) 명시적으로 정의
접근 제어 모두 public 생성자 protected 생성자 (JPA 용), 나머지는 빌더만 허용

 

✅ 장점

1. 불변 객체에 더 가까워짐

  • 생성자와 필드에 Setter가 없고,
  • 생성은 오직 @Builder로만 가능 → 불변 객체처럼 동작합니다.

2. 명확한 생성자 구조

  • @Builder를 생성자에 붙이면,
    어떤 필드들이 객체 생성에 사용되는지 명확하게 드러납니다.
  • 실수로 id 같은 DB 자동 생성 필드를 포함하는 것을 방지할 수 있어요.

3. JPA에서만 허용되는 생성자 제한

  • @NoArgsConstructor(access = PROTECTED)로 설정하면,
    외부에서 실수로 new RefreshToken()을 호출하지 못하게 제한됩니다.
  • 하지만 JPA 내부에서는 기본 생성자가 필요하므로 문제 없이 작동합니다.

4. 불필요한 어노테이션 제거

  • @AllArgsConstructor는 Builder와 겹치는 경우가 많기 때문에 제거한 것이 바람직합니다.

 

❗ 단점 또는 고려할 점

1. 생성자 직접 작성 필요

  • 이전에는 롬복이 모든 생성자를 자동으로 만들어줬지만,
    지금은 명시적으로 생성자를 작성해야 하므로 코드가 약간 늘어납니다.

2. 전체 필드 생성자가 필요하다면 직접 추가해야 함

  • 예: 테스트 코드 등에서 모든 필드를 한 번에 세팅하고 싶은 경우
  • 하지만 id가 자동 생성 필드라면 보통 생성자에서 포함하지 않는 게 맞습니다.

 

🧾 정리 – 장단점 표

구분 설명

✅ 장점 - 불변 객체처럼 설계됨- 생성자 + 빌더 구조가 명확- JPA 기본 생성자만 허용- 불필요한 어노테이션 제거
⚠️ 단점 - 생성자 수동 작성 필요- 필요 시 모든 필드를 세팅하는 생성자를 추가해야 함 (테스트 등)

 

✨ 결론

수정하신 방식이 더 깔끔하고 안전한 방식입니다.
특히 JPA + DDD 스타일, 혹은 실무에서 유지보수가 쉬운 코드를 위해
이러한 구조가 널리 권장되고 있어요.

 

 

 


[참고 자료]

@Builder, @All/NoArgsConstructor 제대로 알고 사용하자!

https://velog.io/@maketheworldwise/Builder-AllNoArgsConstructor-%EC%A0%9C%EB%8C%80%EB%A1%9C-%EC%95%8C%EA%B3%A0-%EC%82%AC%EC%9A%A9%ED%95%98%EC%9E%90