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() {
// 아무 것도 안 함. 하지만 프록시 만들 땐 꼭 필요!
}
- 이걸 못 만들면 프록시 객체도 못 만들고, 결국 지연 로딩이 작동하지 않음
'프로그래머스 > Spring Boot' 카테고리의 다른 글
| [Spring Boot] Generic (0) | 2025.03.10 |
|---|---|
| [Spring Boot] JpaRepository Optional (1) | 2025.03.02 |
| [Spring Boot] Thymeleaf 템플릿 상속 (Template Inheritance) (0) | 2025.02.06 |
| [Spring Boot] PRG 패턴 (0) | 2024.12.20 |
| [Spring Boot] DTO(Data Transfer Object) (0) | 2024.12.17 |