Spring과 진짜 초면인 우리


Builder 패턴은 객체 생성과 초기화를 유연하게 처리하기 위한 디자인 패턴입니다.
Builder 패턴을 사용하면 복잡한 객체를 단계별로 구성하고 초기화할 수 있으며, 가독성과 유지보수성을 향상시킬 수 있습니다.
Builder 패턴은 일반적으로 다음과 같은 구조로 구현됩니다:
- 빌더 클래스 (Builder Class): 객체 생성 및 초기화를 담당하는 빌더 클래스입니다. 필요한 속성을 설정하고 객체를 생성하기 위한 메서드들을 제공합니다.
- 제품 클래스 (Product Class): 빌더를 통해 생성되는 최종 객체입니다. 필요한 속성과 메서드를 가지고 있으며, 일반적으로 Getter 메서드를 통해 속성 값을 가져옵니다.
- 빌더 인터페이스 (Builder Interface, 선택적): 빌더 클래스를 구현하기 위한 인터페이스입니다. 복잡한 객체 생성에 대한 일관된 인터페이스를 제공할 수 있습니다.
Builder 패턴은 다음과 같은 장점을 가지고 있습니다:
- 가독성과 유지보수성: 객체 생성과 초기화 과정이 명확하게 분리되어 가독성이 향상되며, 필요한 변경이나 확장에 유연하게 대처할 수 있습니다.
- 선택적인 속성 설정: 빌더 패턴을 사용하면 필요한 속성만 설정할 수 있고, 선택적인 속성은 설정하지 않을 수 있습니다.
- 객체 불변성: 빌더 패턴을 사용하면 최종 객체를 불변으로 만들 수 있어서 스레드 안전성을 보장하거나 객체의 무결성을 유지할 수 있습니다.
Spring 프레임워크에서는 주로 빌더 패턴을 통해 Bean 객체를 생성하고 초기화하는데 활용됩니다.
예를 들어, Lombok의 @Builder 어노테이션을 사용하여 Builder 패턴을 자동으로 생성하거나, 직접 빌더 클래스를 정의하여 객체를 생성할 수 있습니다.
이를 통해 Spring의 의존성 주입(Dependency Injection)과 함께 객체를 생성하고 구성하는 과정을 유연하게 처리할 수 있습니다.
아래는 Java Spring에서 Builder 패턴을 사용하여 객체를 생성하는 간단한 예제입니다:
public class User {
private final String username;
private final String password;
private final String email;
private final int age;
private User(UserBuilder builder) {
this.username = builder.username;
this.password = builder.password;
this.email = builder.email;
this.age = builder.age;
}
public String getUsername() {
return username;
}
public String getPassword() {
return password;
}
public String getEmail() {
return email;
}
public int getAge() {
return age;
}
public static class UserBuilder {
private String username;
private String password;
private String email;
private int age;
public UserBuilder(String username, String password) {
this.username = username;
this.password = password;
}
public UserBuilder email(String email) {
this.email = email;
return this;
}
public UserBuilder age(int age) {
this.age = age;
return this;
}
public User build() {
return new User(this);
}
}
}
// 사용 예시
User user = new User.UserBuilder("eddy", "password1234")
.email("eddy@email.com")
.age(34)
.build();
위의 예제에서 User 클래스는 불변(Immutable) 클래스로서, 생성자를 통해 필수적인 속성을 초기화하고, 빌더 클래스 UserBuilder를 통해 선택적인 속성을 설정합니다.
UserBuilder는 체이닝 메서드를 사용하여 필요한 속성을 설정하고, build() 메서드를 호출하여 최종적으로 User 객체를 생성합니다.
이를 통해 객체 생성과 초기화를 유연하게 처리할 수 있습니다.
++ 롬복의 빌더 어노테이션 사용 예시
lombok.Builder 사용
import lombok.Builder;
@Builder
public class Person {
private String name;
private int age;
private String gender;
private String country;
public static void main(String[] args) {
Person person = Person.builder()
.name("eddy")
.age(34)
.gender("남")
.country("한국")
.build();
}
}
주의🚨🚨
만약 객체 생성 때 필수 값이 있더라도 모든 멤버 변수를 대상으로 하는 빌더에서는 필수값을 넣지 않아도 생성되는 불상사가 발생할 수 있어요!!
아래와 같이 작업에 필요한 매개변수를 설정한 생성자 위에 @Builder 어노테이션을 붙여서 사용하는게 좋아요 🌟🌟
@Builder
public Person(String name, String emailAddress) {
this.name = name;
this.emailAddress = emailAddress;
this.isVerified = false;
this.createdAt = LocalDateTime.now();
this.friendUserIds = new ArrayList<>();
}

생각해 본 빌더의 장점
- 가독성이 좋다. (값 생성에 대한 유연함)
- 필요한 값만 받을 수 있다.(생성자 오버로딩 할 필요 없다..?)
- 객체의 불변성
빌더의 단점
- 어떤 객체를 생성하려면 우선 그것의 빌더를 생성해야 하는 번거로움... (성능이 최우선 고려대상이라면 문제가 있을 것 같음)
- 빌더 패턴은 코드가 길어지므로, 매개변수가 많을 때 사용하는 것이 좋아보임
'Spring과 진짜 초면인 우리들에게' 카테고리의 다른 글
| [Optional 시리즈 1부] Optional 에 값이 있니? or ElseThrow ? (0) | 2023.05.22 |
|---|---|
| 스프링 3계층은...스프링에게 000을 주입해달라고 대신 요청할때는... (0) | 2023.04.19 |
| 00이/가 흘러다닐 길을 만들어 볼까요? REST API URL 규.칙. (2) | 2023.04.14 |
| API가 뷰(view)를 던진다구요...? 데이터만 던진다구요...? (4) | 2023.04.12 |
| @어노테이션@스프링 너무 많아 @ㅅ@ (0) | 2023.04.11 |