💡 Builder 패턴이 항상 최선의 선택은 아니다. Builder 패턴이 유용한 경우만 쓰는 것이 좋다. 그렇지 않은 경우에는 오히려 코드르 복잡하게 할 수 있다.
팀 프로젝트 중에 Builder Pattern 관련해서 피드백을 얻었다. 무슨 차이가 있을까? 무슨 장점이 있을까? 어떤 상황에 쓰는 것이 좋을까? 라는 생각이 들었다.
Builder 패턴은 객체 생성 패턴 중 하나로, 복잡한 객체를 단계별로 생성할 수 있도록 도와주는 디자인 패턴이다.
생성자와 Setter 메서드를 직접 사용하는 대신, Builder라는 별도의 클래스를 통해 객체의 각 속성을 설정하고 최종적으로 객체를 생성합니다.
객체를 생성할 때 많은 선택적 매개변수를 설정해야 하는 경우, Builder 패턴은 각 매개변수를 명확하게 지정하고 순서에 상관없이 설정할 수 있게 해준다.
💡 선택적 매개변수란?
함수 또는 메서드 호출 시 필수로 제공하지 않아도 되는 매개변수.
객체 생성 과정이 복잡하고, 조건에 따라 다른 방식으로 객체를 생성해야 하는 경우, Builder 패턴은 객체 생성 로직을 캡슐화하고 유연하게 변경 할 수 있게 해준다.
Builder 패턴은 객체 생성 후에는 상태를 변경할 수 없는 불변 객체를 만드는 데 적합하다.
객체 생성 코드를 더 읽기 쉽고 이해하기 쉽게 만들어준다.
객체 생성에 필요한 매개변수가 적고 필수적인 경우, 간단하게 생성자를 사용하는 것이 더 간결하고 효율적이다.
객체 생성 과정이 간단하고 특별한 로직이 필요하지 않은 경우, Builder 패턴을 사용하는 것은 불필요한 복잡성을 더할 수 있다.
Builder 패턴은 객체 생성 과정에서 추가적인 객체를 생성하고 메서드를 호출하므로, 성능에 민간함 경우에는 생성자를 직접 사용하는 것이 더 효율적일 수 있다.
기존 코드(CommentCreateResponseDto)
//import lombok.Builder; 추가 X
기존 코드 (CommentService - createComment)
@Transactional
public CommentCreateResponseDto createComment(Long userId, Long postId, CommentCreateRequestDto requestDto) {
// 1. 사용자 인증 및 게시글 존재 확인
User user = userRepository.findById(userId)
.orElseThrow(() -> new CustomException(ErrorCode.USER_NOT_FOUND));
Post post = postRepository.findById(postId)
.orElseThrow(() -> new CustomException(ErrorCode.POST_NOT_FOUND));
// 2. 댓글 생성
Comment comment = new Comment(user, post, requestDto.getCommentText());
comment.setCommentLikes(0); // 좋아요 개수 0 초기화
// 3. 댓글 저장
Comment savedComment = commentRepository.save(comment);
// 4. CommentCreateResponseDto 생성 및 반환
return new CommentCreateResponseDto(
savedComment.getId(),
savedComment.getUser().getUserId(),
savedComment.getPost().getId(),
savedComment.getCommentText(),
savedComment.getCommentLikes()
);
}
변경 코드(CommentCreateResponseDto)
import lombok.Builder; 추가 O
private final 타입 변수;
변경 코드 (CommentService - createComment)
@Transactional
public CommentCreateResponseDto createComment(Long userId, Long postId, CommentCreateRequestDto requestDto) {
// 1. 사용자 인증 및 게시글 존재 확인
User user = userRepository.findById(userId)
.orElseThrow(() -> new CustomException(ErrorCode.USER_NOT_FOUND));
Post post = postRepository.findById(postId)
.orElseThrow(() -> new CustomException(ErrorCode.POST_NOT_FOUND));
// 2. 댓글 생성
Comment comment = new Comment(user, post, requestDto.getCommentText());
comment.setCommentLikes(0); // 좋아요 개수 0 초기화
// 3. 댓글 저장
Comment savedComment = commentRepository.save(comment);
// 4. CommentCreateResponseDto 생성 및 반환
return CommentCreateResponseDto.builder()
.commentId(savedComment.getId())
.userId(savedComment.getUser().getUserId())
.postId(savedComment.getPost().getId())
.commentText(savedComment.getCommentText())
.commentLikes(savedComment.getCommentLikes())
.build();
}
CommentCreateResponseDto.builder()...build();:
Builder 패턴을 사용하여 CommentCreateResponseDto 객체를 생성합니다.
각 필드에 해당하는 값을 savedComment 객체에서 가져와 설정합니다.
CommentCreateResponseDto는 Builder 패턴을 사용하여 생성되므로, 가독성이 높고 유지보수가 용이합니다.Comment 엔티티는 new 키워드를 사용하여 직접 생성되므로, 코드가 간결하고 직관적입니다. 엔티티 생성 시 필요한 로직이 복잡하지 않다면, 직접 생성하는 방식이 더 효율적Builder 패턴은 객체 생성 코드를 더 읽기 쉽고 유지보수하기 쉽게 만들어주는 도구이다. 하지만 모든 경우 Builder 패턴을 적용해야하는 것은 아니며, 객체의 복잡성, 매개변수의 개수, 불변셩 여부 등을 고려하여 적절하게 선택하는 것이 좋다.