일반적으로 계층형 구조에 맞춰서 패키지를 구성하는데 이는 Persistence - Service - Presentation 으로 구성되는 경우가 일반적이다. 웹 체스 미션을 할 때는 DTO를 Service에서 반환을 했는데 이는 Service가 Controller에 종속적이라는 의미일 수도 있다는 피드백을 받고 이번에는 DTO로 변환해주는 과정을 Presentation 층에서 할 수 있도록 설계를 해봤다.
public class Line {
private Long id;
private String name;
private String color;
private List<Station> stations;
}
public class LineResponse {
private Long id;
private String name;
private String color;
private List<StationResponse> stations;
}
얼핏보면 Line
과 LineResponse
는 동일한 객체처럼 보일 수 있다. 코드를 자세하게 작성하지는 않았지만 2가지 큰 차이점이 존재한다.
스프링의 경우 객체의 기본 생성자가 있으면 반환할 때 Json 형식으로 변경을 해준다. 따라서 LineResponse
에는 기본 생성자가 존재한다. 만약 Line
에 기본생성자를 써서 반환타입으로 이용한다면 다음 차이점에서 문제가 될 수 있다.
Line
은 엔티티다. 따라서 내부에 비지니스 로직이 들어있다. 현재는 이름이 같은 값인지 확인하는 로직만 있는데 나중에 요구사항이 늘어난다면 로직이 늘어날 수 있다. LineResponse
는 DTO이기 때문에 말 그대로 데이터 전송 용도로만 사용하기 위해서 비지니스 로직을 갖고있지 않는다.
이 두가지 차이점으로 엔티티와 DTO를 구분하고 Service에서는 도메인 혹은 엔티티를 통해 내부 비지니스 로직을 만들고 Controller에서 적절한 DTO를 반환하여 원하는 view에 필요한 값을 전달할 수 있도록 설계를 했다.
계층화의 핵심은 각 계층은 응집도가 높으면서, 다른 계층과는 낮은 결합도를 가지는데 있다.
이를 위해서는 기본적으로 상위 계층은 하위 계층을 사용할 수 있지만, 하위 계층은 본인의 상위 계층으로 누가 있는지 인식 못하도록 해야한다.
그렇다면 당연히 view에 의존하고 있는 LineResponse
를 Service 계층에서 반환하는 것은 바람직하지 않다.