프로그래밍

DTO, 테스트 코드 관련 궁금증

개인 플젝 하던중 궁금증이 생겨서 질문 드립니다! 자바 스프링 환경이라 예시나 내용이 자바 스프링 스러울?수 있습니다.

 

  1. 엔티티와 DTO간의 전환은 어디쪽에서 해주는게 좋은지?
    1. 예를 들어 Entity.of(DTO) 이런식으로 엔티티 객체에서 DTO -> Entity로 변경을 하는게 좋은지 아니면 DTO.toEntity() 이런식으로 DTO에서 자신이 만들어지게 된 목적을 갖는 엔티티로 변환을 해주는게 좋은지 애매합니다.
    2. 사실 정답이 있을까? 싶긴한데 관례상이나 많이들 따르는 방식이 있는지 궁금합니다.
  2. DTO 자체에서 validation이 들어가야하는경우 DTO자체에 validation 메서드를 작성하는게 좋을지? 아니면 외부에 validation 역할과 책임을 위임하는게 좋은지?
    1. 예를 들어서 비밀번호 변경에 관한 DTO가 있다고 가정하고, 이 DTO에는 비밀번호 값과 비밀번호 확인값을 필드로 갖고있을때 DTO.validtaion() 이런 메서드를 작성하고 DTO 내부적으로 this.password == this.passwordCheck 이런 동작을 하는게 맞는지?
    2. 그리고 만약 DTO내부적으로 validation 메서드를 작성한다고하면 private로 두고 DTO.toEntity() 같은 엔티티 전환 메서드 호출할때 내부적으로 호출하는게 좋을지? 아니면 public으로 공개하고 service 같은 곳에서 Entity.of(DTO)를 하기전에 DTO.valid()를 호출하는게 좋을지?
    3. 아니면 Validator 라는 다른 객체에게 해당 역할과 책임을 위임하고 Validation.valid(DTO) 이런 식으로 빼는게 맞을지?
    4. 아니면 이것도 그냥 상황따라 편한대로 작성하면 될까요?
  3. service 레이어에서 비슷한 동작이지만 도메인상 중요한 내용이나 민감한 정보에 관한 것은 따로 빼는게 좋은지?
    1. 예를 들어 유저정보를 수정하는 edit을 서비스레이어에 작성할때 비밀번호변경 같은 민감한 정보를 수정하는 로직은 editPassword() 이런식으로 별도의 메서드로 빼고, 별도의 DTO를 따로 빼는지?
  4. service 레이어 테스트에서 그전 단계인 controller 레이어나 혹은 스프링 시큐리티 같은 곳에서 걸러지는 내용까지도 테스트 해야하는지?
    1. 예를 들어 글 수정 기능에 대한 테스트 코드를 작성한다고 했을때, service 레이어에서는 글쓴이의 존재, 해당 글의 존재 확인 로직만 있을때 글쓴이가 해당 글의 권한이 있는지 등을 실패 케이스 까지 고려해서 작성하는지?
    2. 보통 권한이나 역할 관련 체크 로직은 스프링 시큐리티를 사용할때 서비스레이어에서 빠지는것 같은데, 서비스 레이어 테스트 코드에도 역활과 권한 관련 실패 케이스 테스트를 다 작성하는지 궁금합니다. 보통 컨트롤러 테스트에서 목킹해서 하는거 같던데

 

현 회사가 스프링관련 환경도 아니고 사수도 없어서 혼자 개인플젝 하다가 생긴 궁금증에 대해 조언을 구합니다.

16개의 댓글

2023.12.05

일단 궁금해서 ChatGPT한테 물어봤는데 대충 대답이 아래와 같네요

 

1. 이건 정답이 없고 각자 장단이 있다. 트레이드 오프 고려해서 정해라

2. 외부에 validator로 분리하는게 SRP를 만족해서 좋긴한데 절대적인건 아니다 이것도 알아서 해라

3. 가능하면 민감한 정보를 수정하거나 하는것은 별도의 로직(메서드)와 별도의 DTO로 분리하는게 좋다.

4. service레이어에서는 메인 로직만 (유저 유무, 수정이 올바르게 되었는지?)만 테스트 코드로 확인하고 권한과 역할 관련 검증은 컨트롤러 테스트 에서 해라

 

라고 하는데 어느정도 맞는거 같나요...?

0
2023.12.05

DTO는 서비스 차이와 노하우 영역이라서 저는 지나갈게용~

0
2023.12.05
@베트남외노자

ㅜㅜ그래도 의견정도는 낼수 있잖아요!

0
2023.12.05

이게 답이다 라고 하기 전달하기 어려운 영역인거 같은데 딱히 정답은 없을 것으로 보입니다. 다만 혹시 고민하고 있는 1~ 3번 영역은 DDD(도메인 주도 개발)와 헥사고날 아키텍처(클린 아키텍처)에 대한 글과 설계와 코딩 스타일을 본다면 충분한 도움을 얻을 수 있을 것 같습니다.

 

4번의 경우에는 해당 레이어의 책임만 테스트 해도 충분하다고 생각합니다. 다른 레이어에서 적용되는 테스트가 해당 레이어에서 동작하지 않는 것은 불가능한 일이라 생각하기 때문입니다. DDD 관점으로 보면 핵심 도메인에서 대부분의 검증과 로직이 끝나기 때문에 다른 레이어 영역은 단순히 데이터의 전달, 저장, 응답 등으로 특별히 할게 없습니다.

통합테스트 단계에서 알지 못하는 문제가 발생할 경우도 있고, 가능하면 모든 조건과 경계값을 테스트 하는게 이론적으로 좋기는 하나, 어느정도 타협하는게 실제 코드 구현 속도나 현실적인 문제 (시간 이라는 자원이 가장 부족)를 고려 했을 때 핵심 영역을 제외하고는 테스트 코드는 타협하는 걸 추천 드립니다.

1
2023.12.05
@Onyx

ddd관점에서는 사실 엔티티랑 도메인도 분리해야한다고하는데 실제로 지금까지는 jpa엔티티 객체가 사실상 도메인 객체라서 뭔가 와닿지가 않아요 ddd에 대한 공부를 좀더 하면 피부로 느껴 질까요??

 

서비스레이어 테스트에서 해당 고민을 한 이유는 어디까지가 핵심 비즈니스 로직일까? 라는 경계에대한 고민이 있었던거 같습니다

 

단순히 “유저 존재 유무를 체크하고 수정하는것” 까지가 핵심 로직인지 “해당 유저의 권한 체크” 까지도 핵심 로직에 포함되는건지 긴가 민가 했던거 같아여 사실 권한 체크도 기능상 중요한 확인 사항이긴 하니까요

0
2023.12.05
@년째 고민중

결론은 JPA엔티티 = 도메인 객체로 받아드리고 사용하는걸 추천합니다.

사실 DDD 관점에서 JPA를 분리해야 한다는 것은 ORM 기술 구현을 위해 JPA라는 기술 - 현재는 주로 하이버네이트로 구현 되는 이 기술 자체에 의존성이 포함 되어있기 때문에, 만약 나중에 JPA 구현 스펙이 바뀐다면 기존 동작하는 로직이 동일하게 동작하지 않을 수도 있고, 만약 기술의 변경이라도 일어난다면 유지보수가 매우 힘들 것입니다. DDD 에서 추구하는 것은 다른 의존성 없이 순수한 언어 코드로 구현, 동작되며 특정 기술로 부터의 독립을 추구하지만 현실적인 문제로는 어느정도 타협을 해야 합니다.

 

그래서 개인적으로는 JPA엔티티 = Domain객체를 동일하게 취급하는 것은 실무적으로 빠른 개발을 위해서 필요하다고 생각합니다. 도메인을 분리하는 경우 엔티티와 도메인 서로 전환하는 코드가 필요한데 보일러 플레이트 코드라고 생각합니다. 변환 로직 자체를 별도 다른 라이브러리를 사용해도 되는데, 어찌되었던간에 단순히 데이터를 변환하는 일 밖에 안하는 쓸데없는 코드만 생기고, 개발 속도도 느려진다고 생각합니다. 순수한 코드를 추구한다고는 하지만 얻을 수 있는 이점보단 단점이 많다고 생각하므로 결론적으로는 분리하지 않고 사용하는 것을 추천드립니다.

 

혹시 엔티티와 도메인을 분리해야 할 필요가 있다면 (극단적인 예시로)

한 팀 내에서 JPA를 주로 쓰는 팀원과, Mybatis를 주로 쓰는 팀원이 있거나, Mybatis를 통해서만 구현가능한 부분이 있다면, 이 2가지 영역과 시스템 내에서의 문제없는 객체 변환 및 사용을 위해서 순수한 도메인객체를 만들어 볼 수는 있을 것 같습니다...

 

그리고 테스트나 설계에 대한 고민이나 기타 전체적인 현재하고 있는 고민은 일단 미루고 코드로 우선 작성하는 것을 추천드립니다. 테스트 코드 작성을 한다는 것 자체가 TDD나 BDD에 대한 방법론을 실천하려고 하는 것 같은데 해당 테스트 코드를 믿고, 작성된 코드를 리팩토링 하다보면 대충 어떤식으로 구조를 바꾸는게 좋겠구나 혹은 이건 이렇게 만들었어야 했네를 조금씩 체득할 수 있습니다. 물론 이미 검증된 설계론이나 코딩 스타일을 배우고 그런식으로 코드를 구성하는 것이 답일 수도 있지만 개인적으로는 전체적인 틀만 생각하고 그냥 우선 코드를 작성하는게 오히려 더 도움이 되었던 것 같습니다. 막상 실무로 나가면 일단 고민하기 보다는 우선 만들고, 나중에 개선하는게 우선 윗 사람들 한테도 보여줄꺼리는 있어서 좋기도 했고, 일단 설계부터 구현 ~ 추가 유지보수 ~ 기능 개선 까지 계속 정답은 없더군요. 그냥 그 시점에서는 최선을 다했고, 다시 보니 좀 이상해서 뜯어 고치다보면 그래도 어제보단 좋은 코드와 설계 구조를 적용 할 수 있을 것으로 생각됩니다.

 

p.s. chatGPT나 phind와 같은 AI를 이용해서 전체적인 설계 구조와 구현코드 및 테스트 코드, 리팩토링 등 거의 모든 부분을 맡길 수 있습니다. 본인 스스로가 1명의 PL이라고 생각하고 코드 짜면 재밌습니다!

3
2023.12.06
@Onyx

양질의 정성스런 댓글 감사합니다 일단 구현완성을 목표로 해보고 하다보면 설계상 문제나 이런게 터져나오겠죠? 그때 수정하면서 공부해야겠네여 감사합니다:)

0
2023.12.05

우리팀은 백오피스 시스템이라서 dto 같은건 구분 안두고 있음

0
2023.12.06

1. 제 3의 converter 에 위임.

- mapper 클래스 별도로 두고 처리하거나, mapstruct 라이브러리 이용.

 

2. validator에 위임

 

3. 케이스가 잘 이해 안감. 별도 함수로 빼면 어떤 장점이 있는지 모르겠음.

 

4. 안함. unit test 는 그 메서드에서 처리 가능한 것만 테스트 하면 됨.

- 너가 말하는 부분은 integration test 에서 확인할 내용임.

 

DTO 는 계층간 데이터 이동하는 외부 의존성 없는 순수한 클래스로 두고, 요 안에서 뭔가 하려는 시도는 지양하는게 좋음.

 

다만, 실무에서는 완벽한 것 보다 완성하는게 훨씬 중요하기 때문에 그때 그때 상황/팀/사람 따라 달라짐.

 

"리팩토링" 이란 말이 굳이 있는 이유임.

 

정도(正道)는 있어도 법은 아님.

 

0
2023.12.06
@예스오얼노

넵 일단 구현먼저 해보고 하다보면 설계상 이상한게 보이겠죠? 감사합니다 :)

0
2023.12.06
@년째 고민중

흔한 예제인 todo 나 게시판 백엔드 만들어보고

베스트 프렉티스나 github 뒤져보셈

"이사람은 이렇게 했네? 내가 한거보다 더 좋은 방법이네?" 를 깨우치는 순간이 있을텐데

이때 사람이 성장하게댐

0
2023.12.06

일단 정해진 것은 없음 하지만 내 사견으론

 

1. Entity 를 생성하는 빌더나 생성자를 통해 생성하는게 좋을 것 같음. Entity 는 모델자체에 신경써야지 DTO에 대핸 종속성을 가질 필요가 있나 싶음.

 

2. DTO 자체는 데이터 덩어리임. 사용하는 측에서 검증을 해야 한다고 생각함. 단 DTO가 재사용되는 경우 모든 곳에서 같은 검증로직을 가진다면 DTO에 구현해도 될듯.

 

3. 난 Service 에서 비밀번호 암호화를 해서 Entity에 변경 함수 호출함. User entity가 비밀번호 암호화 책임까진 없고 해시 체크 책임만 있지 않나 해서.

 

4. Controller 에서 권한 검사하면 Service에서는 이미 권한 검사를 통과했다고 생각하면 될듯? 책임을 설정했으면 그 책임만 지키면 되니까

0
2023.12.06
@우우쓰레기

댓글 감사합니다:)

0
2023.12.06

1.

Entity -> VO

VO -> DTO

 

DTO -> VO

VO -> Entity

 

로 만이 짰었음

난 그냥 양쪽다 구현해서 필요할떄마다 가져다가 썼는데 어느방향으로 하든 솔직히 상관 없다.

 

2.

validator 따로 쓰던지, 서비스로직에서 같이 처리하게 하던지

 

3.

저게 보안문제때문인가? 싶긴 한데 저걸 따로 나눠서 했을때 장점이 뭔지도 모르겠다.

인입 시점에서 이미 그냥 데이터 덩어리로 봐도 되는게 아닌가 싶긴 한데

 

4.

컨트롤러에서 체크가 이미 되었을거고, 서비스는 그냥 기능만 구현하는게 맞지 않을까

 

 

0
2023.12.06
@교미왕도킹

감사합니당

0
2023.12.06

orm쓰면서 entity랑 dto를 구분하고 매핑하는건 인프라 의존성을 완전히 분리하기 위함이라고 보면 될듯.. 코드 작성방식을 일단 도메인관련 코어로직 작성 및 테스트하고 그 후에 세부사항 레이어들을 붙여나가면서 코드 짤때 이제 매핑계층 붙여서 구현하는 식으로 작성함 이 방식은 순수하게 작성하는 방식이니 dtoToEntity entityToDto mapper계층도 인프라 계층에 작성함

 

validator랑 dto분리하는건 그게 공통로직으로 분리할만하면 하는데 니 언어가 자바라면 유틸클래스 유틸함수에 만들어서 쓰는게 좋을거같음

단순 함수형언어면 필드별로 분리할 때도 있는듯

validator는 db dto는 진짜 dumb하게 붙이고 entity에 붙이는게 좋을거임 굳이 로직분산할 이유는 없으니까 다만 controller에서 들어오는 dto는 또 따로 선언함 입력계층에서도 해당값이 범위내의 유효한값인지 체크하는게 좋으니까

이 부분은 도메인의 복잡도가 거의 없어서 단순 crud수준이면 좀 낭비처럼 느껴질수있음

 

민감하다고 entity에서 로직을 뺀다는걸 말하고 싶은건가? 그 필드를 수정하는 로직은 그 엔티티에 있어야 하는게 맞긴함

그리고 entity로 매핑할때는 일부필드만 조회해서 매핑하지 않도록 해야함 도메인로직이 불안정해질수 있으니까, 최적화관점으로 가면 달라지긴 하지만

dto만 얘기해서 vo를 말하는건가 싶기도한데 money처럼 password라는 vo를 만들어서 구현하는 케이스도 있을수 있음

dto는 vo랑 다름

(수정)

 

인증권한 테스트는 서비스와 분리되어야함

유닛테스트할때 모든 서비스마다 인증권한 테스트를 다 붙일필요는 없으니까

 

0
무분별한 사용은 차단될 수 있습니다.
번호 제목 글쓴이 추천 수 날짜 조회 수
5684 [프로그래밍] 그 혹시 게임쪽 종사자 있음? 17 god79ii 0 3 일 전 544
5683 [프로그래밍] 코린이 ㅅㅂ 뭐가 문젠지 모르겠어요 7 집에가게해줘 0 3 일 전 373
5682 [프로그래밍] Dear Imgui 라고 아시나요? 2 년째모쏠 0 3 일 전 206
5681 [프로그래밍] 현업개발자분들 주말엔 편하게 쉴수있나요? 10 키로 0 4 일 전 758
5680 [프로그래밍] 무엇이든 물어보세요. 28 변현제 0 6 일 전 360
5679 [프로그래밍] 개발자보단 엔지니어가 취업이 잘됨 5 iillillill 2 7 일 전 649
5678 [프로그래밍] 프론트엔드 개발자 연봉 1억 넘는 사람 있어? 13 잠적자 0 7 일 전 574
5677 [프로그래밍] Exiftool 이거 일본어 못 읽는데 13 부터시작하는이세... 0 9 일 전 219
5676 [프로그래밍] 반응형 웹페이지가 내가상상한거랑 좀 다르네 4 평택국 0 10 일 전 413
5675 [프로그래밍] 고졸 FE개발자 연봉, 상황에 조언좀.. 19 쾅꿍꿍 0 10 일 전 556
5674 [프로그래밍] 물경력들 보면 책임을 이해못하는것같음 5 mils 1 11 일 전 380
5673 [프로그래밍] GPT가 코딩 다해주네 3 겜신병자 0 11 일 전 708
5672 [프로그래밍] 크로스플랫폼의 욕심은 끝이없다 4 ye 0 14 일 전 376
5671 [프로그래밍] 월루중에 백준 풀어보고 있는데, 6 오뜨 0 15 일 전 653
5670 [프로그래밍] 같이 일했던 시니어급 개발자 아예 직무 바꿨네.. 15 흐린눈 2 16 일 전 677
5669 [프로그래밍] 안드로이드 스튜디오가 이상해요... 2 집에가게해줘 0 18 일 전 384
5668 [프로그래밍] 양심고백 5 너가전부옳아 0 18 일 전 375
5667 [프로그래밍] 멀티겜만드는거 첨인데 빡시네 4 아님나 0 18 일 전 418
5666 [프로그래밍] vscode에 이런 설정도 있나? 17 너가전부옳아 0 19 일 전 285
5665 [프로그래밍] 네트워크 관련 관련 질문드립니다 6 그러네요 0 21 일 전 210