본문 바로가기

spring

DTO 는 어떻게 써야하나

Dto 를 서비스단까지 가져간 후, Entity 객체로 바꿈.

이 떄, 바꾸는 로직은 Entity 객체의 생성자에 작성.

 

 

Controller 와 Service 로직 사이의 DTO 와 Entity 변환은 다음과 같은 경우의 수가 있을 수 있다.

결정하는 기준은 한가지다.

DTO 와 Entity 간의 변환은 어디에서 이루어질 것인가 ?

 

요청 : Controller -> Service

  • Controller에서 DTO를 Entity로 변환시켜 Entity 를 Service에게 파라미터로 넘김.
  • Controller에서 DTO 를 Service에 파라미터로 바로 넘기고, Service가 Entity 로 바꿈.

응답 : Service -> Controller

  • Service가 Controller로 응답을 보낼 때, Entity를 리턴하고 Controller가 이를 DTO로 변환하여 사용자에게 응답.
  • Service가 Controller로 응답을 보낼 때, Entity를 DTO로 변환시켜 리턴.

나는 보통 Domain 모델이 Service 안에서만 사용되게 함으로서 Domain 모델을 보호하는 관점으로 사용하고 있다.

또한, 아래에 기술할 JPA 와의 문제 때문에 반환 타입은 Entity 로 하지 않는 것이 좋아 보인다.

하지만, Entity 를 바로 반환하지 않고 DTO 로 바꾸는 로직이 추가되기에 코드의 복잡성이 증가할 수 있지만, 충분히 감안 가능할 부분으로 생각된다.

 

 

  • DTO의 Repo단 진입은 다들 공통적으로 지양.
  • 서비스 반환 타입 : DTO vs Model
    • 위 아래에 언급하는 상황들로, Model 을 바로 반환하기보단 DTO 로 반환하는 것이 나아 보인다.
  • DTO 변환 위치
    • Presentation(ex. Controller) vs Service
    • DTO 와 Entity 두개를 모두 쓰기로 결정했다면, Controller 에서 변환할 이유는 없는것 같다.
    • Service 단에서 변환하면 도메인 모델을 presentation 까지 끌고나가지 않아 보호를 할 수 있다.

 

 

 

컨트롤러에서 받은 값을 DTO 로 서비스로 넘겨줌.

서비스에서는 DTO 에서 값을 꺼내어 Entity 생성 or 다른 도메인의 서비스 호출 or dao 작업.

서비스단에는 비지니스 로직이 있어서는 안됨. 비지니스 로직은 각 도메인 모델에 있고, 서비스단에서 도메인 모델의 비지니스 로직 메서드에 메세지를 보내서 처리.

이후 서비스에서 responseDTO 에 데이터를 넣어서 컨트롤러로 반환.

즉, 서비스에서 들어오는 것도 DTO, 나가는 것도 DTO.

 

 

 

결합도(coupling)과 응집도(cohesiveness)는 구분해서 생각해볼 수 있습니다. 예로드신 유효값 검증에 대한 비즈니스 로직이 UI적 특성 - 예컨대 주민번호를 두 개의 입력으로 나누어 받는다던지 - 하는 내용에 의존한다면 말씀대로 이를 엔티티에 구현하는 것은 계층간의 불필요한 결합도를 증가시킬 것입니다.

하지만 유효값 검증이 사용자라는 엔티티라는 개념 자체에 강하게 종속된 개념 - 예들들어 사용자의 아이디에 대한 규칙 - 이라면 그런 개념을 엔티티에서 분리하는 것이 오히려 응집성을 해치는 결과를 가져올 수 있습니다.

응집도가 떨어진다는 것은, 예컨대 연관된 코드를 한 곳에서 파악하기 어렵고 UI 구현을 바꾸었는데 핵심 비즈니스 코드까지 재구현을 해야한다던지 하는 식의 문제를 야기할 수 있습니다.

- Okky 에서의 한 댓글 - 

 

JPA 관점

JPA 에서는 양방향 관계 맵핑에서 Entity 를 toString() 이나 롬복을 쓰면 무한루프에 빠질 위험이 있다.

마찬가지로, 만약 Entity 를 컨트롤러단에서 Rest API 로 바로 JSON 형태로 바꿔서 응답을 보낸다 하면, 같은 위험에 빠질 수 있다.

또한, Entity 를 바로 반환하게 되면 이후 Entity 의 변경은 API 스펙의 변경으로 이어질 수 밖에 없다.

따라서 Entity 를 컨트롤러에서 반환하지 말고, DTO 로 변환하여 반환하여야 한다.