@Builder Annotation에 대해서 왜 궁금했을까❓
- SSAFY 1학기 프로젝트 Validation, Swagger 등을 추가하며 리팩토링 하는 과정에서 대부분의 사람들이 @Builder를 이용하여 코드를 짜는 것을 보았다.
- 많이 사용한다는 것은 이점이 있을 것이라 생각이 되었고 이번 기회에 학습하고 좋다면 리팩토링 과정에 추가해보려 한다.
@Builder
우선 @Builder 패턴으로 객체를 생성하면 좋은 점 4가지를 뽑을 수 있는데 살펴보도록 하자
1. 필요한 데이터만 설정할 수 있다.
// 1. Dummy Data Insert
User user = new User("cks._.hong", 0, 176)
// 2. 생성자, 정적 팩토리 메소드를 추가하는 방법
@NoArgsConstructor
@AllArgsConstructor
public class User {
private String name;
private int age;
private int height;
public User (String name, int height) {
this.name = name;
this.height = height;
}
public static User of(String name, int height) {
return new User(name, 0, 176);
}
}
- 만약 User를 생성할 때, age가 필요없다면 dummy data를 넣어주거나 age가 없는 생성자를 새로 만들어줘야 한다.
- 약간의 변화에도 여러 부분에 영향을 끼치게 되어 위와 같은 과정을 반복해야 될 것이고 시간 낭비로 이어질 것이다.
User user = User.builder()
.name("cks._.hong")
.height(176).build();
- 이렇게 Builder 패턴을 적용하게 되면 필요한 데이터만 설정할 수 있게 된다.
2. 유연성을 확보할 수 있다.
public void builderTest() {
// 기존 코드
User user = new User("cks._.hong", 27, 176);
// 변경 코드
User user = new User("cks._.hong", 27, 176, 75);
...
}
- 기존의 코드에 weight 변수가 추가가 된다면 작성되어 있는 모든 코드를 수정해야만 하거나 새로운 생성자를 추가해줘야만 한다.
- 하지만, Builder 패턴을 사용한다면 새로운 변수가 추가되어도 영향을 주지 않아 유연하게 객체의 값을 설정할 수 있을 것이다.
3. 가독성을 높일 수 있다.
public void builderTest() {
// Constructor
User user = new User("cks._.hong", 27, 176);
// Builder
User user = User.builder()
.name("cks._.hong")
.age(27)
.height(176).build();
...
}
- 생성자를 이용할 경우 각 파라미터의 역할이 무엇인지 한 눈에 알아보기 쉽지 않다.
- 하지만, Builder 패턴을 적용하면 직관적으로 어떤 값에 설정이 되는 지 알 수 있다.
4. 변경 가능성을 최소화할 수 있다.
- 나도 마찬가지고 SSAFY 교육생들 대부분은 Spring boot를 접한지 얼마 되지 않았고 교육 받은 내용이 수정자 패턴(Setter)이어서 대부분 Setter를 이용하여 객체를 설정한다.
- 이러한 방법은 불필요한 변경 가능성을 열어두는 것이며 유지보수 시에 값이 할당된 지점을 찾기 힘들게 만들 것이다.
- Builder 패턴을 객체 생성에만 사용한다면 잘못된 값이 들어왔을 때 어느 부분이 잘못되었는지 찾기 쉬워져서 유지 보수에 이점이 있을 것이다.
- 변경 가능성을 최소화하는 방법은 변수에 final을 선언하여 불변성을 확보하는 것이다.
@Builder
@RequiredArgsConstructor
public class User {
private final String name;
private final int age;
private final int height;
}
- 위의 User 클래스를 다음과 같이 수정할 수 있지만 경우에 따라서 final을 붙일 수 없는 경우가 존재할 것이다.
- 이러한 경우에 Setter를 구현하지 않았다면 final이 없어도 값을 변경시키지 못해 불변성을 확보할 것이다.