DTO

InnomDB·2022년 10월 18일
1

Nest

목록 보기
6/6
post-thumbnail

<주의>

이 글은 경험과 생각을 바탕으로 쓰는 글이기 때문에 틀린 부분이 존재할 수 있습니다.


DTO(Data Transfer Object)의 약자로서, 데이터를 오브젝트로 변환하는 객체입니다.

어떠한 값이 어떤 타입을 가지고 이 값이 필수인지 옵션인지 정의하기 위한 파일이라고 보시면 됩니다.

이러한 DTO를 왜 사용해야 하는걸까요? 그 부분부터 알아보겠습니다.

Web에 다루는 Data는 JSON format의 데이터입니다. 그 말은 즉, 사용자가 서버로 데이터를 전송할 때도 JSON format이라는 뜻입니다. JSON data를 객체로 나타내기 위해 Nest에서는 GlobalInterceptor로 Serializer(직렬화)를 등록해둡니다. 그리고 clinet가 보낸 data가 Controller에서 정의한 Dto class type으로 객체화 시켜주는 것입니다.

자~ 이제 DTO를 조금 더 알기 위해선 계층 구조에 대해서 알아야 합니다.

사진 출처: https://jojoldu.tistory.com/m/603

이해하기 쉽게 설명하자면
Presentation = Controller / Service = Service / Domain = Entity / Data Access = DAO(DTO)

여기서 왜 도메인이 엔티티지? 라고 생각하실 수 있습니다.

도메인이라는 것은 앱의 기능, 요구사항을 개발하는 영역을 말합니다.
사실 이렇게 말하면 잘 모르겠습니다.

그냥 쉽게 예를 들어 설명하면
예를 들어, 내가 Entity에 비즈니스 로직의 주도권을 가지고 개발하면 그것이 도메인 주도 개발입니다.
이렇게 되면 서비스의 많은 로직이 엔티티로 이동하고, 서비스는 엔티티를 호출하는 정도의 얇은 비즈니스 로직을 갖게 됩니다.
반대로 entity는 단순히 데이터만 전달하는 역할을 하고 서비스에 비즈니스 로직을 담아 개발하기도 합니다.

전자는 엔티티를 객체로 사용하는 것이고, 후자는 엔티티를 자료 구조로 사용하는 방식입니다.

우리가 보통 비즈니스 로직에 무엇을 담습니까? 요구사항을 담아요. 아이디는 뭐 30자가 안되게 해라~ 비밀번호는 암호화해라~ 이런것들을 개발하는 영역이 도메인입니다. 근데 막 도메인이 뭐야 하고 글 찾다보면 도메인 객체라는 말도 많이 보입니다. 이게 뭔가 하면 우리는 entity를 class로 정의합니다. 왜냐 class는 흔히 붕어빵 틀 객체는 붕어빵이라고 합니다. 그 말이 뭡니까 class는 요구 사항을 담는 틀!!
그걸 new 생성자를 이용해 생성하면 그게 도메인 객체~

참 쉽쥬~?

사실 쉽지 않습니다.

지금은 그냥 위처럼 이해하고 넘어갑시다. 언젠간 우리 모두 이해하게 되는 날이 올것입니다.!!
사실 이런 거는 따로 블로그 주제로 써야되는데 왜 여기다가 쓰냐하면 모놀리식 블로그기 때문입니다~

그래서 너무 멀리 돌아왔는데 다시 계층 구조로 돌아가면 저는 개발을 할 때 각 계층마다 하위 계층까지만 접근하는 것이 혹시 모를 오류? 버그?에 대비하기 좋다고 생각합니다.

그렇기 떄문에 저는 DTO를 사용하고 이것에 대해 글을 쓰는 것입니다.

예를 들어 Service에서 Entity를 Controller에 반환한다면 Entity에서 숨기고 싶은 정보가 있을 때는 어떻게 해야합니까? 이렇게 된다면 컨트롤러와 서비스 모두 엔티티에 의존하게 됩니다. 엔티티에 대한 의존은 서비스에만 두고 싶기 때문에 저는 Service DTO를 따로 만들어 사용합니다.

또한, 컨트롤러에서 넘긴 DTO를 가지고 Service에서 사용하면 어떻게 됩니까? 서비스는 Controller에 의존하게 됩니다. 게다가 만약 Service의 로직에서 Controller DTO값을 이용해서 도메인까지 간다면?? 끔찍합니다. 높은 응집력!! 느슨한 결합!! 퍼펙트한 코딩의 법칙입니다. 근데 글만 봐도 퍼펙트하긴 글른것 같습니다.... 그렇기 때문에 저는 Controller에서 받은 Dto를 Service에서 Entity로 치환해줍니다.

그럼 여기서 결국 서비스에서는 컨트롤러 DTO를 받으니까 도메인까지는 컨트롤러 DTO가 접근 안하더라고 서비스는 컨트롤러와 엮여 있네라고 생각하실 수 있습니다! 그 대답은 바로 예!! 맞습니다!!

이 부분에 대해서는 많은 고민을 해보았습니다. Controller Dto에 Entity Mapper를 만들어서 Controller에서 넘길 때 Entity로 넘길까?
이렇게 되면 Entity가 수정되면 Controller DTO도 수정되어야 합니다..
또한, Service에서 굳이 Entity를 거치지 않아도 된다면?
뭐 여러 경우의 수를 고민하다보니 결국 DTO안에 mapper를 만들면 뚱뚱한 슈퍼 serivce class가 안생기는 분리적인 관점에선 좋은 방법 같지만 결국 조삼모사 같은 느낌이라 관두고 뚱뚱한 슈퍼 service class로 사용하기로 결정했습니다. 필요하면 그때 나누자!! 라는게 결론이였습니다.

아 마지막으로!!
저는 Entity를 정의하고 TypeOrm에 Data Mapper 패턴을 이용해서 개발합니다.
꼭 DTO들은 Entity와 똑같더라도 만들어줍니다. 왜냐하면 요즘 회사에 MSA를 하는데 각 서비스별로 Admin을 합치다보니까 한 Entity에서 class-transformer로 @Expose() @Exclude()할 수가 없어졌기 때문입니다. Admin과 User에게 요구되는 도메인이 다르기 때문입니다..

도대체 이런걸 DTO 이딴걸 왜 써야되는지 모르시겠다면 한가지만 기억하시면 됩니다. 모든 것은 결국 개발자의 편의를 위해 개발된것들입니다. 지금 당장은 왜 쓰는지 모르겠더라도 언젠가는 '아!~' 하시는 날이 오실겁니다. 물론 저도 마찬가지입니다!

출저:
https://jojoldu.tistory.com/m/603
인프런 1타 강사 - 김영한님 질문과 답변 어딘가..
https://kafcamus.tistory.com/m/12?category=912020
https://techblog.woowahan.com/2711/
https://velog.io/@aidenshin/DTO%EC%97%90-%EA%B4%80%ED%95%9C-%EA%B3%A0%EC%B0%B0
https://jiwondev.tistory.com/m/251

profile
이노오오옴

0개의 댓글