Spring DTO의 사용이유

justindevcode·2022년 9월 29일
1

Spring DTO의 사용이유

DTO는 Data Transfer Object의 약자로 DTO는 말 그대로 데이터를 Transfer(이동)하기 위한 객체이다. 각 클레스를이동할때마다 DTO라는 이동수단으로 데이터를 옴기는것같다.

DTO를 처음 본건 Controller에서 Client에게 데이터를 넘겨줄때이다. 쉽게는 BD에서 끄집어낸 객체 그모두를 전송할수는없다. 유저의 객체를 꺼냈다면 아이디 비밀번호 등 개인정보가 모두 들어있을건데 그것을 필요한것만 담아서 보내야한다는것이다.

단순하게 유저객체를 꺼내서 그중 필요한 것만 변수에 담아서 보내는 것이라 단순하게 생각할수있다.

나는 이전에 Controller,Service,Repository의 이동을 엔티티 = Domain의 틀로 이동한다했는데 DB에 전송되는 가장 중요한틀에 Controller,Service,Repository이동하다보면 다른 로직이 첨가될수가 있다는것이다. 자세히 알아보자.


DTO를 사용하는 이유

데이터를 움직일때 왜 Entity 객체를 그대로 사용하지 않고 굳이 DTO를 사용하는 것일까?
그 이유는 다음과 같다.

  1. View Layer와 DB Layer의 역할을 분리하기 위해서
    -> 객체를 표현하기 위한 계층과 저장하는 계층의 역할을 분리하기 위해서 DTO를 사용한다.

  2. Entity 객체의 변경을 피하기 위하여
    -> Entity 객체를 그대로 사용하면 프로그래머의 의도와 다르게 데이터가 변질될 수 있다. 

  3. View와 통신하는 DTO 클래스는 자주 변경된다
    -> View(클라이언트)와 통신하는 DTO 클래스, 예를 들어 ResponseDTO, RequestDTO는 요구사항에 따라 자주 변경된다. 어떤 요청에서는 특정 값이 추가될 수도 있고, 특정값이 없을 수도 있다.  따라서 Entity 클래스와 분리하여 관리해야 한다. 

  4. 도메인 모델링을 지키기 위하여
    도메인 설계를 잘하였다고 하더라도 원하는 데이터를 표시하기가 쉽지 않을 수 있다. 예를 들어 Entity 클래스의 특정 컬럼들을 조합하여 특정 포맷을 출력하고 싶다고 하자. Entity 클래스에 표현을 위한 필드나 로직이 추가되면 객체 설계를 망가뜨릴 수 있다. 따라서 DTO에 표현을 위한 로직을 추가해서 사용하는 것이 Entity의 도메인 모델링을 지킬 수 있다.


예시

엔티티

public class User {

    public Long id;
    public String name;
    public String email;
    public String password; //외부에 노출되서는 안 될 정보
    public DetailInformation detailInformation; //외부에 노출되서는 안 될 정보

    //비즈니스 로직, getter, setter 등 생략
}

Controller

@GetMapping
public ResponseEntity<User> showArticle(@PathVariable long id) {
   User user = userService.findById(id);
   return ResponseEntity.ok().body(user);
}

이상황에서 return ResponseEntity.ok().body(user);을 넘겨준다면 password까지 다 넘어가게된다.


DTO

public class UserDto {

    public final long id;
    public final String name;
    public final String email;

    //생성자 생략

    public static UserDto from(User user) {
        return new UserDto(user.getId(), user.getName(), user.getEmail());
    }
}

Controller

@GetMapping
public ResponseEntity<UserDto> showArticle(@PathVariable long id) {
    User user = userService.findById(id);
    return ResponseEntity.ok().body(UserDto.from(user));
}

필요한것만 담아서 보내는 DTO를 만들어 사용하면 필요한것만 보낼수있다. return ResponseEntity.ok().body(UserDto.from(user));


공부하면 공부할수록 정말 객체지향의 끝을 느끼고있는 기분이다. Django도 그냥 냅다 있는 view에다가 비즈니스로직 다만들고 위의 예시같은 상황 생기면 그냥 A = user.id, B =user.email 이런 식으로 A,B리턴하고 말아버릴거도같다.
다른 블로그글보니 node.js쪽도 비슷한느낌인거같다.

이런 캡슐화 객체지향 전부 대규모서비스로 갈수록 더 필요해질거같은데
Django도 node.js도 이런 설계가 가능하긴하지만 Spring은 좀더 강제? 다들그렇게쓰니까? 아무튼 눈에보이는 구현에만 급급한 초보개발자에게도 갭슐화와 객체지향을 강제로 경험할수있으니 좋은거같다.


참고 블로그
https://tecoble.techcourse.co.kr/post/2021-04-25-dto-layer-scope/
https://velog.io/@aidenshin/DTO%EC%97%90-%EA%B4%80%ED%95%9C-%EA%B3%A0%EC%B0%B0

profile
("Hello World!");

0개의 댓글