Spring DTO는 어디까지 사용?
DTO의 사용범위는 어디까지? 또, DTO 변환은 어디서?
전에 Controller와 Service 계층 간 데이터 전달을 어떻게 해야 좋을지에 대한 포스팅을 작성했었다. 뭔가 숲보다 나무를 먼저 본? 느낌이긴한데... 하하; 그때 배우던 예제에선 Service가 Entity를 반환했
stella-ul.tistory.com
(위의 글을 읽고 공부해봄)
많은 글을 보면 DTO는 Repository 영역까지 들어오면 안 되고, Service 영역까지만 사용해야 한다고 한다. Repository에 접근하는 건 Entity만 가능하도록 설계하는 게 좋다고..
DTO의 역할은 계층 간 데이터 전달을 위한 객체이며, Repository에서는 도메인(Entity)만 다뤄야 한다는 건 많이 들어서 알고있다.
DTO와 Entity의 역할 및 목적은 명확히 다르다.
Repository에서 DTO를 사용을 지양하는 이유는 다음과 같다.
Repository의 DTO 사용 지양 이유
1. 계층 간 의존성 방향 문제
만약 Repository가 DTO를 쓰게 된다면?
DTO가 아래 계층(Repository)에 침투하게 되어 Controller/Service가 변경된 경우, -> Repository까지 변경해야 할 수 있다.
이로 인해 결합도가 상승하고, 유지보수성이 떨어진
2. DTO는 비즈니스 로직을 표현할 수 없다.
Repository는 보통 쿼리 기준으로 설계되지만, DTO는 UI 맞춤형 구조이기 때문에 도메인 모델과 안 맞을 수 있다.
3. DTO는 계층 간 독립성을 지켜야 한다.
잘못된 예시를 살펴보겠다.
public interface ReservationRepository {
List<ReservationListResponseDTO> findReservationsByClientId(Long clientId);
}
위와 같은 경우, Controller에서 사용하는 응답 구조가 Repository에 노출되기 때문에 심한 결합이 생긴다.
뭔가 이해를 한 건지 만 건지 모르겠다... 알 것 같으면서 설명하라고 하면 못 할 것 같다...
Repository에서 DTO 변환을 하는 경우, 컨트롤러에서 사용하는 응답 구조가 Repository에 노출되는 게 무슨 뜻이지? 이게 심한 결합이라 문제가 된다는 게 무슨 뜻인지 이해가 잘 안 갔다.
다시 한번 제대로 알아봤다.
DTO vs Entity
DTO (Data Transfer Object):
- 클라이언트 요청/응답을 위해 만들어진 프레젠테이션 계층 전용 객체
- 화면(UI)에 필요한 형태로 구조화됨
Entity:
- 도메인 모델. DB 테이블 매핑을 위한 비즈니스 핵심 객체
응답 구조가 Repository에 노출된다?
이는 예시를 통해 보겠다.
프론트에서 예약 목록을 아래와 같이 받고 싶다고 하자.
[
{
"reservationId": 123,
"designerName": "유재석",
"reservationDate": "2025-04-25"
}
]
잘못된 설계: Repository에서 바로 DTO 반환
public interface ReservationRepository {
List<ReservationListResponseDTO> findByClientId(Long clientId);
}
여기서 ReservationListResponseDTO는 프론트에서 요구한 구조.
근데 이게 Repository에 직접 노출된 상태.
왜 문제인가?
1. Presentation 레이어의 변경이 Persistence 레이어로 전파됨
만약 프론트에서 요구가 바뀌어서 reservationId는 빼고, 시간을 보여달라고 한다면?
- ReservationListResponseDTO 수정
- 이걸 사용하는 Repository 코드도 수정해야 함.
→ 위쪽 (Controller/UI)의 요구 변경 → 아래쪽(Repository)까지 영향
→ 이게 강한 결합이다.
2. 관심사 분리가 안 됨
Repository는 DB와의 상호작용만 책임져야 함
DTO는 UI를 위한 데이터 포맷
서로 다른 관심사를 가진 객체가 한 곳에서 뒤섞이면 → 유지보수 어려움
3. Repository를 재사용하기 어려움
나중에 관리자 페이지에서 “예약 목록”을 다르게 보여주려 할 때,
- 기존 Repository가 ReservationListResponseDTO만 반환하니까
- 재사용 못 하고 새로 만들어야 함
→ 재사용성↓, 유연성↓
결론
Repository가 DTO를 반환하면
프론트 요구사항이 Repository까지 영향을 미쳐 하위계층까지 연쇄적으로 수정이 필요.
-> 응답 구조가 노출. 결합이 심함.
따라서 Repository에서는 Entity 사용하기!