정적 팩토리 메소드란?

0cean·2024년 1월 31일

프로그래밍

목록 보기
3/5
post-thumbnail

프로젝트를 진행하면서 컨트롤러에서 파라미터로 받는 정보로 dto를 만들어주는데 생각이 많이 들었다. 이미지 리스트와 다른 필드를 한번에 받을 수 없어 RequestParam으로 받는데 이걸 생성자로 생성하자니 생성자가 너무 뚱뚱해지는 동시에 컨트롤러에서 생성자를 만드는것이 컨트롤러의 역할을 침범하는 느낌이 들어 고민이 됬다. 각 계층별로 역할을 침범하고 싶지 않았다.

그럴 때 사용하는게 바로 정적 팩토리 메소드다!

정적 팩토리 메소드란?

생성자 대신 객체를 생성해주는 정적(static) 함수를 뜻한다.

아래 코드는 리뷰작성 요청 dto객체를 만들어주는 of 정적 팩토리 메소드이다.

public static ReviewRequestDto of(List<MultipartFile> reviewImages, int score, String content) {
        return ReviewRequestDto.builder()
                .reviewImages(reviewImages)
                .score(score)
                .content(content)
                .build();
    }

이 of 메소드는 return타입이 ReviewRequestDto이다. 다시 말해, 해당 클래스를 new로 생성자로 만드는 것이 아닌, 정적 메소드를 사용하여 객체를 사용할 수 있다.

정적 팩토리 사용한 부분

public BaseResponse<ReviewResponseDto> createReview(@AuthenticationPrincipal PrincipalDetails principalDetail,
                                                          @RequestParam("reservationId") Long reservationId,
                                                          @RequestParam(value = "reviewImages", required = false) List<MultipartFile> reviewImages,
                                                          @RequestParam(value = "score", required = false, defaultValue = "0") int score,
                                                          @RequestParam(value = "content", required = false) String content) {

    Long userId = principalDetail.getId();

    // ReviewRequestDto 객체를 직접 생성
    ReviewRequestDto requestDto = ReviewRequestDto.builder()
                                                  .reviewImages(reviewImages)
                                                  .score(score)
                                                  .content(content)
                                                  .build();

    ReviewResponseDto createResponseDto = reviewService.save(userId, reservationId, requestDto);
    return new BaseResponse<>(createResponseDto);
}

기존 코드는 이렇게 사용하였다. 이렇게 작성하니 만약 파라미터가 많아지면 그만큼 코드 줄이 늘어나 가독성이 떨어질 것 같았고, 또한 컨트롤러에서 직접 객체를 생성하니 객체 생성책임을 컨트롤러가 가지는 느낌이 들어 어색하게 받아 들여졌다.

public BaseResponse<ReviewResponseDto> createReview(@AuthenticationPrincipal PrincipalDetails principalDetail,
                                                          @RequestParam("reservationId") Long reservationId,
                                                          @RequestParam(value = "reviewImages", required = false) List<MultipartFile> reviewImages,
                                                          @RequestParam(value = "score", required = false, defaultValue = "0") int score,
                                                          @RequestParam(value = "content", required = false) String content) {

        Long userId = principalDetail.getId();
        ReviewRequestDto requestDto = ReviewRequestDto.of(reviewImages, score, content);
        ReviewResponseDto createResponseDto = reviewService.save(userId, reservationId, requestDto);
        return new BaseResponse<>(createResponseDto);
    }

그래서 이렇게 바꾸어 작성하니 가독성도 해결됬고, 객체 생성도 온전히 of 메소드를 통해 Dto측에서 담당하니 고민이 해결되었다. 정적 팩토리 메소드를 사용하니 생성자는 온전히 파라미터 값을 받아 필드를 초기화 해주는 역할만 담당하게 되고, 컨트롤러 또한 온전히 컨트롤러만의 역할에 충실할 수 있게 되었다.

결론

여러 개발자분들의 블로그를 찾아보니 정적팩토리 메소드에도 여러 컨벤션이 있는것 같다.
ex) 파라미터가 1개일 경우엔 from으로 작명한다던지 파라미터가 여러개일 경우엔 of라던지 하지만 결국 컨벤션은 나에게 맞추면 되는 부분이고, 중요한건 정적 팩토리 메소드의 수많은 사용법이라는 것이다.
본인의 생성자가 조금 길어진다면, 혹은 생성자를 private으로 두고싶은데 객체 생성시 어떠한 작업을 하고싶다면 정적 팩토리 메서드를 활용해보자.

profile
주도적인 학습으로 성장하는 개발자가 되겠습니다

0개의 댓글