프로그래머스/Spring Boot

[Lombok] AccessLevel

annovation 2025. 4. 9. 08:51

AccessLevel 

Lombok에서 제공하는 열거형(enum)으로, 어노테이션(@Builder, @NoArgsConstructor, @AllArgsConstructor 등)이 생성하는 메서드나 생성자의 접근 제어자를 지정할 수 있다.


🔑 AccessLevel 종류와 의미

AccessLevel 설명
PUBLIC public 접근자 (어디서나 호출 가능)
PROTECTED protected 접근자 (같은 패키지 또는 자식 클래스에서만 접근 가능)
PACKAGE / MODULE 패키지 전용 접근자 (package-private)
PRIVATE private 접근자 (클래스 내부에서만 사용 가능)
NONE 아예 생성하지 않음 (생성자나 메서드를 생성하지 않도록 설정)

예시

@Builder(access = AccessLevel.PRIVATE)
@AllArgsConstructor(access = AccessLevel.PRIVATE)
@NoArgsConstructor(access = AccessLevel.PROTECTED)

 

✅ @Builder(access = AccessLevel.PRIVATE)

 

  • MyClass.builder() 호출이 클래스 내부에서만 가능
  • 외부에서는 builder()로 객체 만들 수 없음
  • → 보통 static factory method로 래핑할 때 많이 사용
@Builder(access = AccessLevel.PRIVATE) // builder() 외부에서 못 씀
@AllArgsConstructor(access = AccessLevel.PRIVATE) // new MyClass(...)도 못 씀
public class MyClass {
    private String name;
    private int age;

    // ✅ 팩토리 메서드!
    public static MyClass create(String name, int age) {
        return MyClass.builder()
            .name(name)
            .age(age)
            .build();
    }
}

 

  • create()만 공개되니까 → 개발자가 실수로 new로 만들거나 필드 빠뜨리는 일이 없음
  • 모든 생성 로직은 create()에서 통제 가능!

✅ @AllArgsConstructor(access = AccessLevel.PRIVATE)

  • 모든 필드를 받는 생성자가 private
  • 외부에서 new 로 직접 만들 수 없음
  • → 역시 builder 내부나 static method 내부에서만 사용 가능 (객체 생성 방식 통제 가능)
MyClass.builder() // ❌ 컴파일 에러 (private이라 접근 불가)
new MyClass("Alice", 25) // ❌ 이것도 private라 안됨

⬆️ 외부에서는 막혀있음

public static MyClass create(...) {
    return MyClass.builder()...build(); // ✅ 가능
}

⬆️ 내부에서는 가능

 

✅ @NoArgsConstructor(access = AccessLevel.PROTECTED)

  • JPA가 사용할 수 있도록 기본 생성자는 필요하지만, 외부에서는 new MyClass() 못 하게 보호
  • JPA는 DB 레코드를 Java 객체로 변환할 때 내부적으로 리플렉션(= 강제로 생성자 호출) 을 사용해서 객체를 만든다. 즉, new MyEntity() 를 개발자가 직접 호출하지 않아도 JPA가 알아서 만들어야 한다.

🧠 왜 이런 접근제어(AccessLevel)이 필요한가?

1. 객체를 어떻게 생성해야 하는지 ‘제어’할 수 있음

  • 클래스마다 “정상 상태”라는 개념이 존재
  • 모든 필드가 채워지지 않으면 무효한 객체가 될 수 있음
  • 그런데 아무나 new MyClass() 해서 만들 수 있으면? → ❌ 불완전하거나 잘못된 객체가 만들어질 수 있음

👉 그래서 생성 방법을 제한하고, 정해진 방식(Builder, static method 등) 으로만 만들도록 유도

 

2. JPA는 기본 생성자 필요하지만, 외부에서는 막고 싶음

  • JPA는 지연 로딩(lazy loading) 할 때, 진짜 객체 대신에 "가짜 객체(프록시)" 를 먼저 만들어둔다.
User user = order.getUser(); // 이 시점엔 아직 DB에 접근 안 함
  • 그리고 실제로 user 정보가 필요한 순간에 DB에서 값을 불러온다.
  • 이때 JPA는 가짜 객체(UserProxy extends User) 를 만들기 위해 기본 생성자 필요!
protected User() {
    // 아무 것도 안 함. 하지만 프록시 만들 땐 꼭 필요!
}
  • 이걸 못 만들면 프록시 객체도 못 만들고, 결국 지연 로딩이 작동하지 않음