1. DTO란?
2. 문제가 발생한 배경
3. 서버와 DTO를 일치시켰는가?
3-1. 서버는 모델을 분리, 클라이언트는 통합하는 경우
3-2. 서버는 모델을 통합, 클라이언트는 분리하는 경우
4. 네이밍이 명확한가?
4-1. 어떤 액션에 필요한 모델인지 명시하자
4-2. 모델 안의 내용은 변경될 수 있음을 염두하자
1. DTO란?
인터넷에 검색하면 나오는 DTO의 정의는
Data Transfer Object. 데이터 전송 객체를 뜻한다.
예를 들어 클라이언트가 API를 호출해서 Response를 받을 때의 객체를 DTO라 부른다.
계층 간의 데이터 교환을 위해 사용하는 객체인 것이다.
위 예시에서는 서버와 클라이언트가 데이터를 주고받을 때 사용하는 객체라고 표현한 것이고..
아무튼 정의는 이런데 내가 오늘 포스팅의 주요 포인트는 정의 따위가 아니다.
DTO를 사용하면서 내가 자주 놓쳤던 부분을 정리해보려고 한다.
2. 문제가 발생한 배경
우리가 커뮤니티를 개발하는 클라이언트 개발자라고 상상해 보자.
그리고 다음과 같은 API가 있다.
- 게시글 삭제 API
- response: 삭제한 게시글의 id
- 게시글 수정 API
- response: 수정한 게시글의 id
// 예시를 간단하게 들기 위해 id만 넣었으나, 실제로는 필드가 조금 더 있었다.
{
post_id: "91rujwc"
}
삭제와 수정 둘 다 위와 같은 response가 내려온다고 했을 때
과연 우리는 respone model을 어떻게 설계해야 할까?
나는 배포 이후에 response가 변경될 확률도 낮을 것 같고
둘의 데이터 형식도 똑같아서 PostIdDto라는 모델을 하나 만들어 사용했다.
그리고 당시에 내가 생각하지 못한 2가지 문제점을 깨달을 수 있었다.
3. 서버와 DTO를 일치시켰는가?
DTO는 서버와의 규약이라고도 볼 수 있다.
"API의 Response는 이런 구조의 모델로 주겠다"는 규약
게시글 삭제와 수정의 데이터 모델이 보기에는 똑같지만
서버에서 이를 각각의 데이터 모델로 분리했다면 클라이언트도 분리하고
하나로 합쳤다면 클라이언트도 합쳐야 한다.
그래야 추후에 문제가 생기지 않는다.
왜? 그 이유를 알아보자.
3-1. 서버는 모델을 분리, 클라이언트는 통합하는 경우
{
post_i: "91rujwc",
modified_at: "2024-05-20T13:21:00+09:00"
}
게시글을 수정했을 때 위와 같이 response에 필드가 하나 추가된다고 해보자.
👦🏻(서버): 게시글 수정 response에 modified_at 추가했어요!
👩(클라이언트): 음 어디 보자.. 게시글 수정 API에서.. response 모델 들어가서.. 여기에 필드 하나 추가 해야겠다!
만약 개발을 한지 오래되었거나, 개발한 본인이 아닌 다른 팀원이 이 작업을 하게 된다면
게시글 삭제 response 또한 같은 모델을 공유한다는 사실을 간과할 수 있다.
단순히 필드 하나 추가 띡 하고 끝내버릴 수 있다는 것이다.
이렇게 되면 게시글 삭제 response에서도 modified_at을 받으려 할 것이고
게시글 삭제할 때는 서버에서 modified_at을 내려주지 않으니 NullPointerException이 발생할 것이다.
3-2. 서버는 모델을 통합, 클라이언트는 분리하는 경우
{
feed_id: "91rujwc"
}
이번엔 post_id의 이름이 feed_id로 바뀌는 상황이라고 해보자
👦🏻(서버): 게시글 수정 response에 id 필드 이름 좀 바꿀게요! (같은 모델 사용하니까 삭제는 굳이 말 안 해줘도 되겠지?)
👩(클라이언트): 네~ (게시글 수정 response만 변경한다)
이런 상황이 충분히 발생할 수 있다.
이름이 다르기 때문에 응답을 못 받아서
이번에도 역시나 예상치 못한 exception이나 버그가 발생할 여지가 있다.
그렇기 때문에 항상 백엔드 개발자에게 확인하여야 한다.
데이터 모델을 통합해서 사용할 건지, 분리해서 사용할 건지 말이다.
4. 네이밍이 명확한가?
4-1. 어떤 액션에 필요한 모델인지 명시하자
아무런 사전 배경 지식 없이 모델명을 보았을 때
이 모델이 무슨 용도로 쓰이는지 직관적으로 알 수 있어야 한다.
- ModifyPostDto
이 모델명을 보면 "아, 게시글을 수정하면 응답받는 데이터 모델이구나"를 추측할 수 있다.
- PostIdDto
반면 이 모델명을 본다면 "게시글 아이디구나, 근데 어떤 경우에 사용하는 거지?"라는 생각이 들것이다.
2개를 놓고 보았을 때 전자가 더 적합하다는 것을 알 수 있다.
4-2. 모델 안의 내용은 변경될 수 있음을 염두하자
- ModifyPostDto
이 모델명은 안에 필드가 추가/삭제 되어도 해석에 문제가 없다.
- PostIdDto
반면 이 모델명은 필드가 추가/삭제 되면 네이밍을 변경해야 할 확률이 높다.
post id 말고 다른 값이 추가되면 어쩔겨...?
이런 측면으로 봤을 때 역시 전자가 더 적합하다는 것을 알 수 있다.
코드를 작성하는 개발자 입장에서는
데이터 모델을 하나만 만들어 여러 API에 사용하는 것이 당장이야 편하겠지.
하지만 액션을 나타내는 네이밍을 제거하고
모델 내용을 나타내는 네이밍을 사용하면 이런 문제점들이 있다는 것이다.
💡 느낀 점
- 우리 회사는 개발 중에도 기획이 자주 바뀌고
배포 이후에도 기능이 추가되고 삭제되는 등 변화가 많은 편이다. (욕하는 거 아님)
그래서 처음에 모델을 설계할 때 이런 부분을 염두에 두지 않으면
결국 미래의 내가 개고생을 하더라. - 어떤 회사는 클라이언트 개발자가 필요한 response를 정리해서 백엔드 개발자한테 준다던데
그런 경우는 Dto가 백엔드랑 맞지 않는 일이 안 생길 것 같기도 하고?
우리 회사에서만 발생하는 문제인지 궁금하긴 하다. - 이건 내가 겪었던 하나의 에피소드일 뿐이다.
그 외에도 DTO 모델을 설계할 때 고민해야 할 부분이 참 많은 것 같다.
📘 참고한 자료
- 우리 팀장님 🥸
'오늘은 뭘 배울까? > Android' 카테고리의 다른 글
Bottom Sheet Dialog 예제 : Modal, Persistent, 모서리 둥글게 등 (5) | 2022.09.14 |
---|---|
안드로이드 다이얼로그 만들기(Custom Dialog까지) (7) | 2022.09.09 |
withContext는 무엇이며 async와 무슨 차이가 있을까? (6) | 2022.09.07 |
Coroutine Dispatcher, 넌 대체 뭐야? (2) | 2022.08.31 |
suspend 함수란 무엇인가요? (0) | 2022.08.29 |
댓글