스프링 웹 계층을 그림으로 나타내면 아래와 같다. 이 포스팅에서는 각 계층에 대한 설명과 계층 간 상호작용이 이루어지는 방식, 개발 시 유의할 점 등에 대해 기술한다.
● 개요: 웹 어플리케이션의 최상위에 존재. 외부 요청과 응답에 대한 전반적인 영역이며 어플리케이션의 진입점이기 때문에 다른 레이어에서 발생한 예외도 처리 함. 인증을 관리하고 권한없는 사용자의 인가를 거부하는 역할도 함.
● 포함: 흔히 사용하는 컨트롤러(@Controller)와 JSP/Freemarker 등의 뷰 템플릿 영역이며, 필터(@Filter), 인터셉터, 컨트롤러 어드바이스(@ControllerAdvice) 등이 모두 Web Layer에 포함됨.
● 데이터 처리: 데이터 전송 객체만 처리해야 함
● 개요: Web Layer 바로 아래 존재하는 객체로, 트랜잭션(Transaction, 데이터베이스의 상태를 변환시키는 하나의 논리적 기능을 수행하기 위한 작업의 단위)에 대한 경계 역할. 어플리케이션과 인프라 서비스를 모두 포함하고 있음.
● 포함: @Service에 사용되는 서비스 영역. 일반적으로 Controller와 Dao 중간 영역에서 사용됨, @Transactional이 사용되어야 하는 영역이기도 함.
● 데이터 처리: 데이터 전송 객체를 메소드의 매개변수로 사용, 도메인 모델 객체를 처리. 그리고 데이터 전송 객체만 웹 레이어로 반환할 수 있음.
+) 작성 시 주의사항: Service는 다른 service를 조합하거나 DAO를 연결하는 역할을 수행, Service는 가볍게, Service에 비즈니스 로직을 구현하면 안됨. (비즈니스 로직은 도메인 모델에서 처리-후술)
● 개요: 가장 낮은 계층으로 사용되는 데이터 스토리지 계층과 통신하는 역할. 데이터베이스와 같이 데이터 저장소(repository)에 접근하는 역할.
● 포함: Database와 같이 데이터 저장소에 접근하는 영역. Dao(Data Access Object)영역과 같은 의미.
● 데이터 처리: 엔티티를 메소드 매개변수로 가져올 수 있고 엔티티를 리턴함.
● 개요: DTO는 단순히 데이터를 저장하는 컨테이너, 즉 Data Transfer Object로, 다른 계층 간 교환을 위한 객체임. DTOs는 이들이 존재하는 영역을 의미.
● 포함: 뷰 템플릿 엔진에서 사용돌 객체, Repository Layer에서 결과로 넘겨 준 객체 등이 DTO에 해당함.
● 개요: Domain 은 Entity이고 전체 라이프 사이클 동안 변경되지 않는 객체이며 Value Object(VO: DTO와 동일 개념이나 readonly속성을 가짐)로, 속성이나 사물을 설명. Domain Model은 Domain을 모든 사람이 동일한 관점에서 이해, 공유할 수 있도록 단순화 시킨 것. VO등도 해당되므로 무조건 데이터베이스의 테이블과 관계가 있어야 하는 것은 아님.
● 예시: 택시 앱을 가정했을 때, 배차, 탑승, 요금 등이 모두 도메인임.
데이터 전송 객체만 웹 레이어로 반환될 수 있는 이유를 생각해보겠다. 엔티티(entity)나 VO를 직접 반환하면 더 간편할 것 같은데 왜 데이터 전송 객체를 사용하는 걸까?
(1) 클라이언트의 데이터를 이용하기 쉽도록 하기 위해
(2) 유지 보수를 유연하게 하기 위해
-> 비즈니스 로직은 Domain Model 계층에만 구현.
이유는 Service Layer는 다양한 Model을 읽어 제공하고, 복잡한 서비스는 더 많은 Model을 읽어 서비스를 제공하기 때믄에 Service의 로직의 복잡도가 매우 높아기지 때문에, 트랜잭션과 도메인 간 순서보장의 기능만 하도록 구성해야 함.
이렇게 복잡도를 낮춤으로써 유지보수와 테스트가 용이한 유연한 소프트웨어가 된다.
https://kyu9341.github.io/java/2020/07/08/java_springBoot_Layer/
이동욱, "스프링 부트와 AWS로 혼자 구현하는 웹 서비스", 프리렉, 2019, p.101~103