| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | |
| 7 | 8 | 9 | 10 | 11 | 12 | 13 |
| 14 | 15 | 16 | 17 | 18 | 19 | 20 |
| 21 | 22 | 23 | 24 | 25 | 26 | 27 |
| 28 | 29 | 30 |
- securitycontextholderfilter
- AWS
- docker compose
- 서블릿 컨테이너
- @Transactional
- @ComponentScan
- Spring Data JPA
- 쿠버네티스
- MSA
- 스프링 부트
- mybatis
- DLQ
- kafka
- CORS
- 페이징
- 컨테이너
- 지연 로딩
- Spring
- Routing Key
- DI
- Spring Container
- Web
- docker
- dockerhub
- Dead Letter Queue
- redis
- JPA
- JdbcTemplate
- JWT
- JPQL
- Today
- Total
look-forest
웹 API 어댑터 개발 (작성중) 본문
Entity vs DTO
provided port에서 dto가 아닌 도메인을 반환하는 이유?
/**
* 회원의 등록과 관련된 기능을 제공한다.
*/
public interface MemberRegister {
Member register(@Valid MemberRegisterRequest registerRequest);
Member activate(Long memberId);
Member deactivate(Long memberId);
Member updateInfo(Long memberId, @Valid MemberInfoUpdateRequest memberInfoUpdateRequest);
}
도메인 로직을 적용하고 엔티티의 정보를 돌려줄 때 어떤 타입을 사용하는가?
- 엔티티(애그리거트 루트)
- dto
애플리케이션(서비스) 계층의 리턴 타입은 DTO여야 한다?
계층형 아키텍처에서 각 계층은 자기 바로 다음 하위 계층에만 의존해야 한다는 제약이 있다.
엔티티가 프레젠테이션 로직을 가진 어댑터(컨트롤러)로 유출되면, 도메인 로직을 담은 메소드를 실행할 수 있는 문제가 있다.
OSIV와 결합하면 컨트롤러에서 DB 변경이 일어날 수 있다.
애플리케이션(서비스) 계층의 리턴 타입은 가능하다면 엔티티로 한다.
1. 계층형 아키텍처에서 각 계층은 자기 바로 다음 하위 계층에만 의존해야 한다는 제약이 있다.
-> 현대 엔터프라이즈 애플리케이션은 이 제약을 완화시킨 완화된(relaxed) 계층형 아키텍처를 주로 사용한다.
의존의 방향은 맞아야하지만, 중간에 건너뛰는 것도 가능하다.
계층형 아키텍처의 목적은 시스템의 관심사를 분리하는 것이다. 이를 통해 전체적인 결합도를 낮추고 인지 과부하를 방지.
2. 엔티티가 프레젠테이션 로직을 가진 어댑터(컨트롤러)로 유출되면, 도메인 로직을 담은 메소드를 실행할 수 있는 문제가 있다.
-> 단순 조회가 아닌 변경이 일어날 수 있는 도메인 로직을 쓰면 안되는 것은 맞다. 엔티티를 넘기는 것 자체가 문제인 것은 아니다.
어차피 세컨더리 어댑터(리포지토리 구현 어댑터 등)에서도 엔티티가 전달되거나 생성될 수 밖에 없다.
3. OSIV와 결합하면 컨트롤러에서 DB 변경이 일어날 수 있다.
-> OSVI가 적용됐다고 하더라도 애플리케이션에서 리턴할 때 트랜잭션이 종료되고, 거기서 커밋/롤백되고 끝난다.
따라서 이후의 엔티티의 변경사항은 DB에 커밋되지 않는다.
다만 세션(영속성 컨텍스트)는 열어뒀기에 조회는 가능하다. 이건 문제가 되진 않는다.
+개발 가이드와 코드 리뷰를 통해서 내부의 로직이 외부에 새어나가는 코드 작성하지 않게 한다. 정적 분석 도구나 아키텍처 테스트의 도움을 받아서 엔티티의 조회 메소드 외의 메소드가 사용되는 것을 체크할 수 있다.
DTO를 리턴하는 방식은 프레젠테이션 로직이 애플리케이션 레이어로 침투하는 것이다.
view 로직에 따라 DTO의 구성이 달라진다. DTO를 생성하고 매핑하는 코드가 애플리케이션 계층에 있으면, DTO가 변경할 때마다 애플리케이션 로직이 변경된다. 하위(내부) 계층이 상위(외부) 계층의 로직을 의존하는 것은 계층형과 헥사고날 아키텍처 모두의 근간을 깨는 행위이다. DTO가 변경되면 컨트롤러만 고치자.
애플리케이션은 엔티티(애그리거트 루트)를 돌려주고, 어떤 정보를 사용자에게 전달할 지 선택하는 뷰 로직은 프레젠테이션 관심사를 가진 웹 API 어댑터가 담당한다.
다만, 엔티티 단위가 아닌 복잡한 리포트성 조회 결과는 DTO를 리턴한다. 이 자체가 도메인 로직이라고 본다.
테스트
통합 테스트는 실제 db에 변경을 가하는 것까지. DB까지 검증. mock 셋팅을 하냐 안하냐의 차이이다.
api 테스트는 통합 테스트가 기본이다.
단위 테스트는 선택. 실제와 다를 수도 있고, mocking하는게 귀찮다. api 로직이 복잡하거나 api 개발을 먼저할 경우에 만듬.
기존 MockMvc보다 MockMvcTester가 더 편리하다.
통합테스트에서는 MockMvcTester를 기본적으로 만들어주지 않기 때문에 @AutoConfigureMockMvc를 붙인다.
@MockMvcTest는 @DataJpaTest 처럼 필요한 빈만 등록해준다.
ArchUnit은 코드의 정적 분석을 통해 패키지, 클래스, 계층 간의 의존성 등 미리 정의된 아키텍처 규칙이 잘 지켜지고 있는지 자동으로 검증하는 데 사용
참고 자료 & 이미지 출처
토비의 클린 스프링 - 도메인 모델 패턴과 헥사고날 아키텍처
'Architecture > 도메인 모델과 헥사고날 아키텍처(Clean Spring)' 카테고리의 다른 글
| 애그리거트를 이용한 일관성 있는 도메인 모델 설계(작성중) (0) | 2025.09.06 |
|---|---|
| JPA와 도메인 모델 패턴 (작성 중) (0) | 2025.09.04 |
| 헥사고날 아키텍처 (0) | 2025.09.02 |
| 도메인 모델 (0) | 2025.09.02 |