본문 바로가기

Java, JavaScript/Spring Boot

[Spring Boot] dto의 toEntity를 어떻게 사용해야할까?

728x90

POST, PUT과 같이 서버의 리소스를 생성, 수정할 경우에 dto의 toEntity 함수를 어떻게 작성하면 좋을지에 관한 고민입니다. 게시글 작성 예시를 중심으로 살펴보겠습니다. 게시글을 작성할 때에는 제목, 설명 그리고 작성자가 필요합니다. 게시글을 작성 과정은 다음과 같습니다.

 

  1. 회원은 로그인을 진행한다.
  2. 로그인에 성공하면 JWT 토큰을 발급받는다.
  3. 게시글 작성 폼에 들어와서 제목과 설명글을 작성한다.
  4. 게시글 작성하기 버튼을 클릭하여 게시글 정보를 서버에 저장한다.

위의 과정을 토대로 dto를 설계할 때에 제목과 설명은 다른 entity와 관계가 없기 때문에 문제가 되지 않습니다. 문제가 되는 부분은 회원과 관계를 가지는 작성자 부분입니다. 작성자를 고려한 dto 설계는 크게 2가지가 있습니다.

 

  1. dto에 따로 field를 만들어서 member를 입력받는다. (contorller에서 처리)
  2. toEntity 함수를 호출할 때 member를 인자로 받아서 처리한다. (service에서 처리)

다음은 1번을 토대로 작성한 코드입니다.

 

@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public static class PostCreateRequestDto {
    private String title;
    private String description;     
    private Member member;

    public PostCreateRequestDto(String title, String description) {
        this.title = title;
        this.description = description;
    }
    
    public Post toEntity() {
        return Post.builder()
                .member(member)
                .title(title)
                .description(description).build();
    }
        
    public void setMember(Member member) {
        this.member = member;
    }
}

 

 

위와 같이 코드를 작성하면 다음과 같은 단점을 얻게 됩니다.

 

  • 클라이언트가 요청을 보낼 때에는 member field를 사용하지 않아 리소스를 낭비한다.
  • dto에 추가적인 setter 함수를 작성해야한다.
  • contorller에서 setter 함수를 호출하여 dto의 값을 한번 더 설정해야 한다.

하지만 contorller에서 member를 설정해주고, service로 넘겨주기 때문에 service에서는 toEntity 함수를 호출하여 저장하는 과정만 필요하기 때문에 service의 코드 양을 줄일 수 있다는 장점도 있었습니다.

 

다음은 2번을 토대로 작성한 코드입니다.

 

@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public static class PostCreateRequestDto {
    private String title;
    private String description;

    public PostCreateRequestDto(String title, String description) {
        this.title = title;
        this.description = description;
    }

    public Post toEntity(Member member) {
        return Post.builder()
                .member(member)
                .title(title)
                .description(description).build();
    }
}

 

위와 같이 코드를 작성하면 다음과 같은 단점을 얻게 됩니다.

 

  • service에서 member를 찾는 코드를 추가해야 한다.
  • 연관관계에 따라 toEntity 함수의 모양이 일정하지 않게 된다.

결과적으로 controller에서 dto의 모든 값을 설정하고, service에 값을 넘겨야 한다면 1번의 방법을 선택하고, dto는 최소한의 필요한 값만을 가지고 service에 넘어가야 한다면 2번의 방법을 선택하여 사용하면 될 것 같습니다. 그리고 연관관계가 많지 않은 경우에도 2번의 방법을 선택하면 조금 더 깔끔하게 코드를 작성할 수 있을 것 같습니다.

728x90