본문 바로가기
카테고리 없음

[TIL] DTO 활용하기

by 2nyong 2023. 4. 17.

DTO (Data Transfer Object) 란?

  • 계층 간 데이터 교환을 위해 사용하는 객체
  • 로직을 가지지 않는다.
  • 일반적으로 DTO는 순수한 데이터 객체로, 속성과 그 속성에 접근하기 위한 getter, setter 메소드만 가진 클래스다.

기존 코드

@Entity
public class Board {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @JsonIgnore
    private Long id;

    @Column(nullable = false)
    private String username;

    @Column(nullable = false)
    @JsonIgnore
    private String password;

    @Column(nullable = false)
    private String title;

    @Column(nullable = false)
    private String contents;
}

 

게시판 만들기 프로젝트를 진행하던 중, 게시글 전체 조회시 사용자가 확인할 필요가 없는 게시글의 Id와 사용자가 확인해서는 안되는 게시글의 password를 반환하지 않기 위해 Entity의 각 필드에 @JsonIgnore를 붙여 사용했다.

 

그러다 의문이 들었다. 지금은 Id와 password를 반환할 필요가 없어 @JsonIgnore 어노테이션을 통해 Json에 포함되는 걸 막았다지만, 만약 Id와 password를 반환해야할 경우라면? 

 

이런 상황에 쓸 수 있는 적절한 어노테이션을 찾기 위해 구글링을 시도했지만 찾을 수가 없었다.. 게시글 작성을 위해 이미 아래과 같은 DTO를 사용하고 있었음에도 불구하고, @JsonIgnore라는 어노테이션에 꽃혀버린 나는 이미 작성된 DTO 코드를 응용할 생각은 하지 못한채 새로운 기능만을 찾고 있었다.

 

@Getter
public class BoardRequestDto {
    private String username;
    private String password;
    private String title;
    private String contents;
}

이 DTO는 게시글 작성과 업데이트시에 사용하던 DTO 였다. 조금만 더 생각할걸.. 여기서 password만 제거한 또 다른 DTO코드를 생성했으면 해결할 수 있는 문제였는데!!

 

그러다가 이런 상황을 멘토님에게 여쭤보았고, 문제 해결을 위해 DTO를 활용하기로 하였다.


추가된 코드

@Getter
public class BoardResponseDto {
    private String username;
    private String title;
    private String contents;

    public BoardResponseDto(Board board) {
        this.username = board.getUsername();
        this.title = board.getTitle();
        this.contents = board.getContents();
    }
}

게시글 반환시에 사용할 수 있는 DTO를 새로 만들었고, Entity의 확장으로 인해 추가적으로 반환할게 생길 경우와 코드의 가독성을 위해 생성자에는 Entity인 Board를 받기로 했다. 

 

BoardResponseDto를 활용해 Controller와 Service 코드를 개선했고, 기능은 모두 제대로 작동했다.


응용 버전

Entity가 여러개일 경우에도 위 같은 방법은 역시나 적절한 방법이겠지만, 코드 파일의 개수를 줄이기 위해 아래와 같이 DTO 코드를 작성해볼 수도 있을 것이다.

public class BoardDto {

    @Getter
    static class Response {
        private String username;
        private String title;
        private String contents;

        public Response(Board board) {
            this.username = board.getUsername();
            this.title = board.getTitle();
            this.contents = board.getContents();
        }
    }

    @Getter
    static class Request {
        private String username;
        private String password;
        private String title;
        private String contents;
    }
}

만약 DTO 코드를 위와 같이 작성한다면 코드 파일의 개수를 줄이면서 각 DTO를 사용할 때

BoardDto.Response()
BoardDto.Request()

위와 같이 가독성을 살리는 방향으로 작성할 수도 있을 것 같다.

댓글