////
Search

6장 - 응용 서비스와 표현영역

Created
2023/01/16 01:24
Tags

6.1 표현 영역과 응용 영역

도메인 영역을 잘 구현하지 않으면 사용자의 요구를 충족하는 제대로 된 소프트웨어를 만들지 못한다.
하지만 도메인 영역만 잘 만든다고 끝나는 것은 아니다.
도메인이 제 기능을 하기 위해선 사용자와 도메인을 잘 연결해 주는 매개체가 필요하다.
표현 영역은 사용자의 요청을 해석
URL, 요청 파라미터, 쿠키, 헤더 등을 이용해 사용자가 실행하고 싶은 기능을 판별하고 그 기능을 제공하는 응용 서비스를 실행
실제 사용자가 원하는 기능을 제공하는 것은 응용 영역에 위치한 서비스
사용자가 회원 가입을 요청했다면 실제 그 요청을 위한 기능을 제공해주는 주체는 응용 서비스에 위치함
표현 영역은 응용 서비스가 요구하는 형식으로 사용자 요청을 변환
응용 서비스의 메서드가 요구하는 파라미터와 표현 영역이 사용자로부터 전달받은 데이터는 형식이 일치하지 않기 때문
사용자와 상호작용은 표현 영역이 처리
응용 서비스는 표현 영역에 의존하지 않음

6.2 응용 서비스의 역할

응용 서비스는 사용자가 요청한 기능을 실행한다.
응용 서비스는 사용자의 요청을 처리하기 위해 리포지터리에서 도메인 객체를 가져와 사용
응용 서비스의 주요 역할은 도메인 객체를 사용해 사용자의 요청을 처리하는 것
표현 영역입장에서 보았을 때 응용 서비스는 도메인 영역과 표현 영역을 연결해 주는 창구
응용 서비스는 주로 도메인 객체 간의 흐름을 제어하기 때문에 단순한 형태를 가짐
서비스가 복잡하다면 서비스에서 도메인 로직의 일부를 구현하고 있을 가능성이 높다.
서비스가 도메인 로직을 일부 구현하면 코드 중복, 로직 분산 등 코드 품질에 안좋은 영향을 줄 수 있다.
서비스는 트랜잭션 처리도 담당
도메인의 상태 변경을 트랜잭션으로 처리해야 함

6.2.1 도메인 로직 넣지 않기

도메인 로직은 도메인 영역에 위치하고 응용 서비스는 도메인 로직을 구현하지 않는다.
도메인 로직을 도메인 영역과 응용 서비스에 분산해서 구현하면 코드 품질에 문제가 발생
1.
코드의 응집성이 떨어짐
2.
여러 응용 서비스에서 서로 다른 영역에 위치한다는 것은 도메인 로직을 파악하기 위해 여러 영역을 분석해야 한다는 것을 의미
코드 중복을 막기 위해 서브스 영역에 별도의 보조 클래스를 만들 수 있지만, 애초에 도메인 영역에 기능을 구현했으면 응용 서비스는 그 기능을 사용하기만 하면 됨
일부 도메인 로직이 응용 서비스에 출현하면서 발생하는 두 가지 문제(응집도 떨어짐, 코드 중복)는 결과적으로 코드 변경을 어렵게 만든다.

6.3 응용 서비스의 구현

응용 서비스는 표현 영역과 도메인 영역을 연결하는 매개체 역할을 한다.
이는 디자인 패턴에서 파사드와 같은 역할을 한다.
응용 서비스 자체는 복잡한 로직을 수행하지 않기 때문에 응용 서비스의 구현은 어렵지 않다.

6.3.1 응용 서비스의 크기

응용 서비스 자체의 구현은 어렵지 않지만 몇 가지 생각할 거리가 있다. 그중 하나가 응용 서비스의 크기다.
회원 도메인을 예시로 생각해보면 회원가입/탈퇴/암호 변경/비밀번호 초기화 등의 기능을 구현하기 위해 도메인 모델을 사용하게 됨
방법 1 - 한 응용 서비스 클래스에 회원 도메인의 모든 기능 구현하기
각 기능에서 동일한 로직을 위한 코드 중복을 제거하기 쉬운 장점
한 서비스 클래스의 크기가 커진다는 것이 단점
코드 크기가 커지면 연관성이 적은 코드가 한 클래스에 함게 위치할 가능성이 높아지고 결과적으로 관련없는 코드가 뒤섞여 코드를 이해하는데 방해가 됨
한 클래스에 코드가 모이기 시작하면 엄연히 분리하는 것이 좋은 상황임에도 습관적으로 기존에 존재하는 클래스에 억지로 끼워넣게 됨
결과적으로 점점 코드 품질을 낮추는 결과를 초래
방법 2 - 구분되는 기능별로 응용 서비스 클래스를 따로 구현
이 방식을 사용하면 클래스 개수는 많아지지만 한 클래스에 관련 기능을 모두 구현하는 것과 비교해 코드 품질을 일정 수준으로 유지하는 데 도움이 됨
각 기능마다 동일한 로직을 구현할 경우 여러 클래스에 중복해서 동일한 코드를 구현할 가능성이 있다.
별도 클래스에 로직을 구현해 코드 중복을 방지할 수 있음

6.3.2 응용 서비스의 인터페이스와 클래스

응용 서비스 구현시 논쟁이 될 만한 것은 인터페이스가 필요한 지이다.
인터페이스가 필요한 몇 가지 상황이 있는데 그중 하나는 구현 클래스가 여러 개인 경우
응용 서비스는 런타임에 교체하는 경우가 거의 없고 한 응용 서비스의 구현 클래스가 두 개인 경우도 드물다.
때문에 인터페이스와 클래스를 따로 구현하면 소스 파일만 많아지고 구현 클래스에 대한 간점 참조가 증가해 저체 구조가 복잡해진다.
따라서 인터페이스가 명확하게 필요하기 전까지 응용 서비스에 대한 인터페이스를 작성하는 것이 좋은 선택이라 볼 수 없음
TDD를 즐겨하고 표현 영역부터 개발을 시작한다면, 미리 응용 서비스를 구현할 수 없으므로 응용 서비스의 인터페이스부터 작성하게 될 것
이때 응용 서비스의 인터페이스를 이용해 컨트롤러 구현을 완성해 나갈 수 있음
표현 영역이 아닌 도메인 영역이나 응용 영역의 개발을 먼저 시작하면 응용 클래스가 먼저 만들어짐
Mock 테스트 등의 도구를 이용해 테스트용 대역 객체를 만들 수 있기 때문에 인터페이스가 없어도 표현 영역을 테스트할 수 있음
결과적으로 응용 서비스에 대한 인터페이스 필요성을 약화시킴

6.3.3 메서트 파라미터와 값 리턴

응용 서비스가 제공하는 메서드는 도메인을 이용해 사용자가 요구한 기능을 실행하는데 필요한 값을 파라미터로 전달받아야 함
응용 서비스는 파라미터로 전달받은 데이터를 사용해서 필요한 기능을 구현하면 된다.
스프링 MVC와 같은 프레임워크는 웹 요청 파라미터를 자바 객채로 변환하는 기능을 제공하므로 응용 서비스에 데이터로 전달할 요청 파라미터가 두 개 이상 존재하면 데이터 전달을위한 별도 클래스를 사용하는것이 편리함
응용 서비스의 결과를 표현 영역에서 사용해야 하면 응용 서비스 메서드의 결과로 필요한 데이터를 리턴한다.
응용 서비스에서 애그리거트 자체를 리턴하면 코딩은 편할 수 있지만 도메인의 로직 실행을 응용 서비스와 표현 영역 두 곳에서 할 수 있게된다.
이것은 코드를 분산시켜 응집도를 낮추게 하는 원인이 된다.
응용 서비스는 표현 영역에서 필요한 데이터만 리턴하는 것이 기능 실행 로직의 응집도를 높이는 확실한 방법이다.

6.3.4 표현 영역에 의존하지 않기

응용 서비스의 파라미터 타입을 결정할 때 주의할 점은 표현 영역과 관련된 타입을 사용하면 안된다는 점이다.
HttpSevelteRequest나 HttpSession을 응용 서비스의 파라미터로 전달하면 안된다.
HttpSession이나 쿠키는 표현 영역의 상태에 해당하는데 이 상태를 응용 서비스에서 변경해 버리면 표현 영역의 코드만으로 표현 영역의 상태가 어떻게 변경되는지 추적이 어렵다.
즉 표현 영역의 응집도가 깨지는 것
결과적으로 코드의 유지 보수 비용을 증가시키는 원인

6.3.5 트랜잭션 처리

회원 가입에 성공하더라도 DB 에 정보를 삽입하지 않으면 고객은 로그인을 할 수 없다.
이는 트랜잭션과 관련된 문제로 트랜잭션 관리 기능을 이용하면 쉽게 트랜잭션을 처리할 수 있다.
프레임워크에서 제공하는 트랜잭션 기능을 적극 사용하는 것이 좋다.

6.4 표현 영역

표현 영역의 책임은 크게 다음과 같다.
사용자가 시스템을 사용할 수 있는 흐름(화면)을 제공하고 제어한다.
웹 서비스의 표현 영역은 사용자가 요청한 내용을 응답으로 제공한다.
응답에는 다음 화면으로 이동할 수 있는 링크나 데이터를 입력하는 폼 등이 포함된다.
사용자는 표현 영역이 제공한 폼에 알맞은 값을 입력하고 다시 폼을 표현 영역에 전송한다.
사용자의 요청을 알맞은 응용 서비스에 전달하고 결과를 사용자에게 제공한다.
화면을 보여주는데 필요한 데이터를 읽거나 도메인의 상태를 변경해야 할 때 응용 서비스를 사용한다.
이 과정에서 표현 영역은 사용자의 요청 데이터를 응용 서비스가 요구하는 형식으로 변환
응용 서비스의 결과를 사용자에게 응답할 수 있는 형식으로 변환한다.
사용자의 세션을 관리한다.
웹은 쿠키나 서버 세션을 이용해 사용자의 연결 상태를 관리한다.

6.5 값 검증

값 검증은 표현 영역과 응용 서비스 두 곳에서 모두 수행할 수 있다.
원칙적으로 모든 값에 대한 검증은 응용 서비스에서 처리한다.
표현 영역은 잘못된 값이 존재하면 이를 사용자에게 알려주고 값을 다시 입력받아야 한다.
응용 서비스에서 각 값이 유요한지 확인할 목적으로 인셉션을 사용할 때의 문제점은 사용자에게 좋지 않은 경험을 제공한다는 것
매번 폼을 다시 입력하고 보내며 검사해야만 하기 때문
한번에 잘못된 값을 검증받고 싶음
Error 목록을 생성해 값 검증이 끝난 후 하나의 익셉션으로 모아서 발생시켜 해결
표현 영역에서는 필수 값과 값의 형식을 검사하면 실질적으로 응용 서비스는 ID 중복 여부와 같은 논리적 오류만 검사하면 된다.
즉 표현 영영과 응용 서비스가 값 검사를 나눠서 수행하는 것!
표현 영역 : 필수 값, 값의 형식 범위 등을 검증
응용 서비스 : 데이터의 존재 유무와 같은 논리적 오류를 검증

6.6 권한 검사

개발하는 시스템마다 권한의 복잡도가 다르다.
단순한 시스템은 인증 여부만 검사하면 되는데 반해, 어떤 시스템은 관리자인지에 따라 사용 할 수 있는 기능이 달라지기도 한다.
또 실행할 수 있는 기능이 역할마다 달라지는 경우도 있다.
보안 프레임워크의 복잡도를 떠나 보통 세 곳에서 권한 검사를 수행할 수 있다.
표현 영역
서블릿 필터를 이용한 인증URL 에 대한 권한 검사 과정
표현영역에서 할 수 있는 기본적인 검사는 인증된 사용지인이 아닌지 검사하는 것
URL을 처리하는 컨트롤어에 웹 요청을 전달하기 전에 인증 여부를 검사해 인증된 사용자의 웹 요청만 컨트롤러에 전달한다.
응용 서비스
URL 만으로 접근 제어를 할 수 없는 경우 응용 서비스의 메서드 단위로 검사를 수행해야 한다.
이것이 꼭 응용 서비스의 코드에서 직접 권한 검사를 해야 한다는 것을 의미하는 것은 아니다.
AOP를 활용해 서비스 메서드에 대한 권한을 검사할 수 있는 기능을 제공
도메인
개별 도메인 객체 단위로 검사를 해야 하는 경우 구현이 복잡해짐
응용 서비스의 메서드 수준에서 권한 검사를 할 수 없기 때문에 다음과 같이 직접 권한 검사 로직을 구현해야 한다.