Fluent API를 사용한 Builder 패턴
점층적 생성자를 피하도록 fluent 빌더로 복잡한 객체를 단계별로 구성합니다.
Fluent API를 사용한 Builder 패턴은(는) CoddyKit의 무료 Java Academy 강의입니다. 이것은 4개 중 4번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Java Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Java Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
점층적 생성자 문제
클래스에 선택적 매개변수가 많으면 2개 매개변수용, 3개 매개변수용, 4개 매개변수용 생성자처럼 생성자가 계속 늘어납니다. Builder 패턴은 유창한 단계별 구성 API로 이 문제를 해결합니다.
// Without builder — hard to read:
Pizza p = new Pizza("large", "thin", true, false, true, false, "mozzarella");기본 Builder 구조
정적 중첩 Builder 클래스를 생성합니다. 외부 클래스에는 Builder를 매개변수로 받는 private 생성자를 둡니다. Builder의 각 설정 메서드는 유창한 연결을 위해 this를 반환합니다.
public final class Pizza {
private final String size, crustType, cheese;
private final boolean extraSauce, pepperoni;
private Pizza(Builder b) {
this.size = b.size; this.crustType = b.crustType;
this.cheese = b.cheese; this.extraSauce = b.extraSauce;
this.pepperoni = b.pepperoni;
}
public static class Builder {
private final String size;
private String crustType = "regular", cheese = "mozzarella";
private boolean extraSauce, pepperoni;
public Builder(String size) { this.size = size; }
public Builder crustType(String c) { this.crustType = c; return this; }
public Builder cheese(String c) { this.cheese = c; return this; }
public Builder extraSauce() { this.extraSauce = true; return this; }
public Builder pepperoni() { this.pepperoni = true; return this; }
public Pizza build() { return new Pizza(this); }
}
}유창한 API 사용
Builder의 코드는 문장처럼 읽힙니다. 필수 매개변수는 생성자에 넣고, 선택적 매개변수는 메서드 호출로 지정합니다. 마지막 build() 호출이 불변 객체를 생성합니다.
Pizza p = new Pizza.Builder("large")
.crustType("thin")
.extraSauce()
.pepperoni()
.build();
System.out.println(p);build()에서 유효성 검사하기
객체를 생성하기 전에 build() 내부에 유효성 검사 로직을 추가합니다. 유효하지 않은 조합에는 IllegalStateException 또는 IllegalArgumentException을 발생시킵니다.
public Pizza build() {
if (size == null || size.isBlank())
throw new IllegalArgumentException("Size required");
if (extraSauce && crustType.equals("stuffed"))
throw new IllegalStateException("No extra sauce on stuffed crust");
return new Pizza(this);
}불변 객체를 위한 Builder
외부 클래스는 Builder에서 한 번에 생성되므로 모든 필드를 final로 지정할 수 있습니다. 그 결과 객체 전체가 불변이고 스레드 안전해집니다.
public final class Address {
private final String street, city, country;
private final String postalCode;
private Address(Builder b) { ... } // all finals
// no setters — immutable!
}Self 타입을 사용하는 제네릭 Builder
상속 계층에서는 재귀적 제네릭 형식 매개변수(SELF extends Builder<SELF>)를 사용합니다. 그러면 하위 클래스의 Builder가 연결된 메서드에서 하위 클래스 유형을 반환할 수 있습니다.
public abstract static class Builder<SELF extends Builder<SELF>> {
String name;
@SuppressWarnings("unchecked")
public SELF name(String n) { this.name = n; return (SELF) this; }
public abstract Vehicle build();
}Lombok @Builder
Lombok의 @Builder는 컴파일 시점에 Builder에 필요한 전체 기반 코드를 생성합니다. 기본 필드 값에는 @Builder.Default를 사용하고, 컬렉션에는 @Singular를 사용합니다.
@Builder
public class Report {
private final String title;
@Builder.Default private final int pageCount = 1;
@Singular private final List<String> authors;
}
// Usage:
Report r = Report.builder().title("Q4").author("Alice").author("Bob").build();JDK의 Builder
많은 JDK 클래스가 Builder 스타일 API를 사용합니다. 예를 들어 StringBuilder, HttpRequest.newBuilder(), ProcessBuilder, Stream.Builder가 있습니다. 이 패턴을 알아보시기 바랍니다.
HttpRequest req = HttpRequest.newBuilder()
.uri(URI.create("https://api.example.com/users"))
.header("Accept", "application/json")
.GET()
.build();Builder와 팩토리
객체에 많은 매개변수가 필요하고 단계별 구성이 필요할 때는 Builder를 사용합니다. 모든 변형이 단순하고 한 번의 호출로 생성할 수 있을 때는 팩토리를 사용합니다.
테스트 데이터를 위한 Builder
Builder는 테스트에서 특히 유용합니다. 도우미에 기본 Builder를 만든 다음 각 테스트 사례와 관련된 필드만 재정의하면 테스트를 DRY하게 유지하면서 읽기 쉽게 작성할 수 있습니다.
User defaultUser() { return new User.Builder("test@example.com").name("Test User").build(); }
User adminUser() { return new User.Builder("admin@example.com").name("Admin").role(ADMIN).build(); }스레드 안전성
Builder 자체는 스레드 안전하지 않으므로 여러 스레드에서 하나의 Builder를 공유하지 마십시오. 모든 필드가 final이고 변경 가능한 객체를 공유하지 않는다면, Builder로 생성한 제품은 불변이며 스레드 안전할 수 있습니다.
빠른 확인
Builder 메서드를 "유창하다"고 말할 수 있는 조건은 무엇입니까?
정리
Builder는 점층적 생성자 문제를 해결합니다. 정적 중첩 Builder 클래스를 사용하고, 각 설정 메서드에서 this를 반환하며, build()에서 유효성 검사를 수행하고, 불변 객체를 생성합니다. Lombok의 @Builder는 반복적인 기반 코드를 자동화합니다.
자주 묻는 질문
“Fluent API를 사용한 Builder 패턴” 강의는 무료인가요?
네 — “Fluent API를 사용한 Builder 패턴” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Java Academy 강의 전체를 잠금 해제할 수 있습니다. Java Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
“Fluent API를 사용한 Builder 패턴”에서 뭘 배우나요?
점층적 생성자를 피하도록 fluent 빌더로 복잡한 객체를 단계별로 구성합니다. 브라우저에서 직접 실행하는 실습 코드로 Java Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
Java Academy을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 Java Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 4번째 강의입니다.
“Fluent API를 사용한 Builder 패턴” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 Java Academy 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 Java Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- Singleton: 스레드 안전한 구현
- 팩터리 메서드 패턴
- 제품군을 위한 Abstract Factory
- Fluent API를 사용한 Builder 패턴