Java에서 객체를 생성할 때 생성자나 정적 팩토리 메서드를 많이 사용한다.
하지만 필드 수가 많고 선택적으로 값을 지정해야 하는 상황에서는 Builder 패턴이 훨씬 더 유연하고 명확한 해법이 된다.
빌더 패턴이란?
- 객체 생성의 복잡성을 줄이고, 가독성과 유지보수성을 높이기 위한 설계 패턴
- 필드가 많은 객체를 가독성 있게 생성할 수 있다.
- 생성자처럼 순서에 의존하지 않으며, 필요한 필드만 선택적으로 설정 가능하다.
기본 문법 (직접 구현)
public class User {
private final String username;
private final String email;
private final int age;
private User(Builder builder) {
this.username = builder.username;
this.email = builder.email;
this.age = builder.age;
}
public static class Builder {
private String username;
private String email;
private int age;
public Builder username(String username) {
this.username = username;
return this;
}
public Builder email(String email) {
this.email = email;
return this;
}
public Builder age(int age) {
this.age = age;
return this;
}
public User build() {
return new User(this);
}
}
}
사용 예시:
User user = new User.Builder()
.username("hong")
.email("hong@example.com")
.age(25)
.build();
Lombok을 이용한 간편 문법
- Lombok의 @Builder 어노테이션을 사용하면 위 구조를 자동으로 만들어준다.
import lombok.Builder;
@Builder
public class User {
private String username;
private String email;
private int age;
}
사용 예시:
User user = User.builder()
.username("hong")
.email("hong@example.com")
.age(25)
.build();
* 팁
- @Builder는 클래스뿐 아니라 생성자, 메서드에도 붙일 수 있다.
- @Builder.Default를 사용하면 빌더에 기본값 지정 가능하다.
@Builder
public class User {
private String name;
@Builder.Default
private int age = 20; // age를 설정하지 않으면 기본값 20
}
특징
항목 | 설명 |
메서드 체이닝 | 각 필드에 대한 메서드 반환 타입이 Builder 자신이다 |
필수 vs 선택 값 | 필수 값은 build() 전에 검증 로직으로 처리 가능 |
순서 상관 없음 | 각 필드를 개별 메서드로 설정 → 파라미터 순서에 의존하지 않음 |
불변성 | final 필드 + private 생성자 활용 시 불변 객체 구현 가능 |
장단점
✅ 장점
장점 | 설명 |
가독성 ↑ | 필드명 명시 → 어떤 값이 어떤 필드에 들어가는지 명확 |
순서 독립 | 파라미터 순서 헷갈릴 일 없음 |
선택적 필드 처리 용이 | 필요 없는 필드는 생략 가능 |
필드 추가에 유연 | 생성자 변경 없이 확장 가능 |
메서드 체이닝 | user.builder().a().b().c() 형태로 깔끔한 작성 가능 |
❌ 단점
단점 | 설명 |
약간의 런타임 오버헤드 | 내부적으로 객체 한 번 더 만들어야 함 |
불변성 강제 어려움 | 빌더는 final 필드와 완전한 불변과는 상충 가능 |
Lombok 없으면 코드 많아짐 | 직접 구현 시 보일러플레이트 코드 증가 |
💡 언제 쓰면 좋을까?
- 필드가 3개 이상이고, 일부 필드만 선택적으로 입력되는 경우
- 테스트 코드에서 다양한 입력 조합을 만들고 싶을 때
- 생성자 파라미터가 순서 헷갈릴 정도로 많을 때
- API 요청/응답 DTO에서 명확하게 값을 넣고 싶을 때
'Java > 문법' 카테고리의 다른 글
생성자 vs 정적 팩토리 메서드 vs 빌더 패턴 (0) | 2025.05.09 |
---|---|
가변 리스트 vs 불변 리스트 (1) | 2025.04.29 |
Map - compute(), computeIfAbsent(), computeIfPresent() (0) | 2025.04.29 |
가변 인자 (...) (0) | 2025.04.29 |
String.split() 문자열 자르기, 나누기 (0) | 2025.04.22 |