Chapter 6: 응용 서비스와 표현 영역
💡 책에서 기억하고 싶은 내용
응용 서비스의 역할
응용 서비스는 사용자(client)가 요청한 기능을 실행한다
사용자의 요청을 처리하기 위해 리포지터리에서
도메인 객체
를 가져와 사용한다
응용 서비스의 주요 역할은
도메인 객체
를 사용해서 사용자이 요청을 처리하는 것이므로표현(사용자) 영역
입장에서 보았을 때 응용 서비스는 도메인 영역 ↔ 표현 영역을 연결해 주는 창구 역할을 한다응용 서비스는 주로
도메인 객체 간 흐름을 제어
하기 때문에 아래와 같이 단순한 형태를 갖는다리포지터리에서 애그리거트를 구한다
애그리거트의 도메인 기능을 실행한다
결과를 리턴한다
새로운 애그리거트를 생성하는 응용 서비스 역시 간단하다
데이터 중복 등 데이터가 유효한지 검사한다
애그리거트를 생성한다
리포지터리에 애그리거트를 저장한다
결과를 리턴한다
응용 서비스는
트랜잭션 처리
도 담당한다응용 서비스는 도메인의 상태 변경을 트랜잭션으로 처리해야 한다
도메인 로직 넣지 않기
도메인 로직은 도메인 영역에 위치하고, 응용 서비스는 도메인 로직을 구현하지 않는다
ex) 암호 변경 기능
암호 변경 기능을 위한 응용 서비스는 Member 애그리거트와 관련 리포지터리를 이용해서 도메인 객체 간의
실행 흐름을 제어
한다
도메인 로직을 도메인 영역과 응용 서비스에 분산해서 구현하면
코드 품질
에 문제가 발생한다코드의
응집성
이 떨어진다도메인 데이터와 그 데이터를 조작하는 도메인 로직이 한 영역에 위치하지 않고,
서로 다른 영역에 위치
한다는 것은 도메인 로직을 파악하기 위해여러 영역을 분석
해야 한다는 것을 의미한다
여러 응용 서비스에서 동일한 도메인 로직을 구현할 가능성이 높아진다
일부 도메인 로직이 응용 서비스에 출현하면서 발생하는 위의 두 가지 문제는 결과적으로 코드 변경을 어렵게 만든다
그러므로, 도메인 로직을 도메인 영역에 모아서
코드 중복
을 줄이고응집도
를 높여야 한다
응용 서비스의 크기
한 응용 서비스 클래스에 해당 도메인의 모든 기능 구현하기
장점
각 기능에서 동일한 로직을 위한 코드 중복을 제거하기 쉬움
단점
한 서비스 클래스의 크기 (LoC)가 커짐
코드 크기가 커지면 연관성이 적은 코드가 한 클래스에 함께 위치할 가능성이 높아짐
결국 관련 없는 코드가 뒤섞여 코드를 이해하는 데 방해가 됨
구분되는 기능별로 응용 서비스 클래스를 따로 구현하기
장점
코드 품질을 일정 수준으로 유지하는 데 도움이 됨
각 클래스별로 필요한 의존 객체만 포함하므로, 다른 기능을 구현한 코드에 영향을 받지 않음
단점
클래스의 개수가 많아짐
각 기능마다 동일한 로직을 구현할 경우, 여러 클래스에서 중복해서 동일한 로직을 구현할 가능성이 있다
하지만 이 경우
별도 클래스에 로직을 구현
해서 코드가중복
되는 것을방지
할 수 있다!
응용 서비스의 인터페이스와 클래스
응용 서비스를 구현할 때 논쟁이 될 만한 것이
인터페이스
가 필요한 지이다인터페이스
가 필요한 상황: 구현 클래스가 여러 개인 경우but, 인터페이스와 클래스를 따로 구현하면
소스 파일만 많아지고,
구현 클래스에 대한 간접 참조가 증가해서 전체 구조가 복잡해진다
따라서 인터페이스가 명확하게 필요하기 전까지는 응용 서비스에 대한 인터페이스를 작성하는 것이 좋은 선택이라고 볼 수는 없다
메서드 파라미터와 값 리턴
응용 서비스가 제공하는 메서드는 도메인을 이용해서 사용자가
요구한 기능을 실행
하는 데 필요한 값을파라미터
로 전달받아야 한다스프링 MVC와 같은 웹 프레임워크는 웹 요청 파라미터를
자바 객체
로변환
하는 기능을 제공 하므로, 응용 서비스에 데이터로 전달할요청 파라미터
가두 개 이상 존재
하면 데이터 전달을 위한별도 클래스
를 사용하는 것이 편리하다응용 서비스의 결과를 표현 영역에서 사용해야 하면, 응용 서비스 메서드의 결과로 필요한 데이터를 리턴한다
대표적으로
식별자
가 있다
응용 서비스에서 애그리거트 자체를 리턴하면, 코딩은 편할 수 있지만 도메인의 로직 실행을 응용 서비스와 표현 영역 두 곳에서 할 수 있게 된다
이것은 기능 실행 로직을 응용 서비스와 표현 영역에
분산
시켜 코드의응집도
를 낮추는 원인이 된다
응용 서비스는 표현 영역에서 필요한 데이터만 리턴하는 것이 기능 실행 로직의 응집도를 높이는 확실한 방법이다
표현 영역에 의존하지 않기
응용 서비스의 파라미터 타입을 결정할 때 주의할 점은
표현 영역과 관련된 타입
을 사용하면 안 된다는 점이다ex) 표현 영역에 해당하는
HttpServletRequest
나HttpSession
을 응용 서비스에 파라미터로 전달하면 안 된다
응용 서비스에서 표현 영역에 대한 의존이 발생하면,
응용 서비스만 단독으로 테스트 하기가 어려워진다
게다가 표현 영역의
구현이 변경
되면, 응용 서비스의 구현도 함께 변경해야 하는 문제도 발생한다가장 심각한 것은 응용 서비스가
표현 영역의 역할까지 대신하는 상황
이 벌어질 수도 있다는 것이다
위와 같은 문제가 발생하지 않도록 철저하게 응용 서비스가 표현 영역의 기술을 사용하지 않도록 해야한다
이를 위한 방법으로 서비스 메서드의 파라미터와 리턴 타입으로
표현 영역의 구현 기술
을 사용하지 않는 방법이 있다
표현 영역
표현 영역의 책임
은 크게 다음과 같다사용자가 시스템을 사용할 수 있는
흐름(화면)
을 제공하고, 제어한다사용자의
요청
을 알맞은 응용 서비스에 전달하고,결과
를 사용자에게 제공한다사용자의 요청 데이터를 응용 서비스가 요구하는 형식으로 변환하고,
응용 서비스의 결과를 사용자에게 응답할 수 있는 형식으로 변환한다
사용자의
세션
을 관리한다
값 검증
값 검증은 표현 영역과 응용 서비스 두 곳 모두 수행할 수 있다
원칙적으로 모든 값에 대한 검증은 응용 서비스에서 처리한다
표현 영역에서 필수 값과 값의 형식을 검사하면, 실질적으로 응용 서비스는 ID 중복 여부와 같은
논리적 오류
만 검사하면 된다즉, 표현 영영과 응용 서비스가 값 검사를 나눠서 수행하는 것이다
응용 서비스를 사용하는 표현 영역의 코드가 한 곳이면 구현의 편리함을 위해 아래와 같이 역할을 나누어 검증을 수행할 수도 있다
표현 영역
: 필수 값, 값의 형식, 범위 등을 검증응용 서비스 영역
: 데이터의 존재 유무와 같은 논리적 오류를 검증
권한 검사
아래의 세 곳에서 권한 검사를 수행할 수 있다
표현 영역
인증된 사용자인지 아닌지 검사
ex)
회원 정보 변경 기능
인증된 사용자만 접근 가능하도록
URL 접근 제어
인증된 사용자가 아닐 경우 로그인 화면으로 redirect
서블릿 필터 (Servlet Filter)
에서 접근제어 하기 좋다스프링 시큐리티도
필터
를 이용해서 인증 정보를 생성하고, 웹 접근을 제어한다
응용 서비스
URL 만으로 접근 제어를 할 수 없는 경우 응용 서비스의
메서드 단위
로 권한 검사 수행꼭 응용 서비스에서 직접 권한 검사 해야하는 것은 아님
ex)
스프링 시큐리티
- AOP 를 활용해서 annotation으로서비스 메서드
에 대한 권한 검사 수행
도메인
개별 도메인 객체 단위로 권한 검사를 해야 하는 경우, 직접 권한 검사 로직 구현
스프링 시큐리티
와 같은 보안 프레임워크를 확장해서 개별 도메인 객체 수준의 권한 검사 기능을 프레임워크에 통합할 수도 있음but, 높은 이해가 필요
이해도가 높지 않아 프레임워크 확장을 원하는 수준으로 할 수 없다면, 해당 도메인에 맞는 권한 검사 기능을 직접 구현하는 것이 유지 보수에 유리함
조회 전용 기능과 응용 서비스
서비스에서 추가적으로 수행하는 로직이 없고 단일 쿼리만 실행하는 조회 전용 기능이면, 서비스를 만들 필요 없이
표현 영역
에서 바로 조회 전용 기능을 사용해도 문제 없다
Last updated