# 6. 응용 서비스와 표현 영역
# 6.1 표현 영역과 응용 영역
- 표현 영역 : 사용자의 요청 해석
- 응용 영역 : 실제 사용자가 원하는 기능 제공
# 6.2 응용 서비스의 역할
- 도메인 영역과 표현 영역 연결
- 주로 도메인 객체 간의 흐름 제어
- 보통 단순한 형태를 갖고, 만약 응용 서비스가 복잡하다면 도메인 로직의 일부를 구현하고 있을 가능성이 높음
Q.
public Result doSomeCreation(CreateSomeReq req) { validate(req); // 이런건 어디에 만들어야? SomeAgg newAgg = createSome(req); // SomeAgg 도메인 로직 someAggRepository.save(newAgg); // SomeAgg 응용 계층의 인터페이스에 return createSuccessResult(newAgg); // 애그리거트 응답 생성도 SomeAgg 도메인 로직? }도메인에 정의 or 그냥 함수 분리?
Q. 띱 pr 넣은거에서 레디스에 저장되는 유저 정보는 엔티티로 만들지 않았지만 도메인으로 빼서 정리하는게 좋을까
- 응용 서비스는 트랜잭션 처리도 담당
# 6.2.1 도메인 로직 넣지 않기
- 도메인의 핵심 로직은 꼭 도메인 내에서 실행하도록
도메인 로직을 도메인 영역과 응용 서비스에 분산해서 구현하면
- 코드의 응집성이 떨어짐
- 여러 응용 서비스에서 동일한 도메인 로직을 구현할 가능성이 높아짐
→ 도메인 로직들을 도메인 영역에 잘 모아서 구현하는 것이 중요
# 6.3 응용 서비스의 구현
- 응용 서비스는 디자인 패턴에서 파사드와 같은 역할
# 6.3.1 응용 서비스의 크기
- 한 응용 서비스 클래스에 회원 도메인의 모든 기능 구현
- 각 기능에서 동일 로직에 대한 코드 중복 제거 가능
- 서비스 클래스의 크기가 커지고, 연관성이 적은 코드가 함께 위치하게 됨
- 결과적으로 코드 품질 ↓
- 구분되는 기능별로 응용 서비스 클래스를 따로 구현하기
- 클래스 개수는 많아지지만 코드 품질을 일정 수준으로 유지하는데 도움이 됨
- 코드 중복이 발생할 수 있음 → 별도 클래스에 로직 구현 (e.g., MemberServiceHelper)
# 6.3.2 응용 서비스의 인터페이스와 클래스
응용 서비스의 인터페이스가 필요한 상황 → 구현 클래스가 여러 개인 경우
- 근데 응용 서비스는 런타임에 교체하는 경우가 거의 없음 + 여러 구현 클래스를 가지는 경우도 드뭄
- 결국 소스 파일만 많아지고 구현 클래스에 대한 간접 참조가 증가해서 전체 구조만 복잡해짐
- 정말 필요한 상황 아니면 쓰지말길
# 6.3.3 메서드 파라미터와 값 리턴
- 생략
# 6.3.4 표현 영역에 의존하지 않기
- 표현 영역과 관련된 타입 사용하지 않기 → 응용 서비스만 단독으로 테스트하기 어려워짐 + 표현 영역의 역할을 침범해버릴 수 있음
# 6.3.5 트랜잭션 처리
- 생략
# 6.4 표현 영역
# 표현 영역의 역할
- 사용자가 시스템을 사용할 수 있도록 알맞은 흐름 제공
- 요청을 응답으로 제공
- 사용자의 요청에 맞게 응용 서비스에 기능 실행 요청
- 사용자의 요청을 응용 서비스가 요구하는 형식으로 변환하고 그 결과를 응답 형식으로 변환
- 세션 관리
# 6.5 값 검증
- 값 검증은
표현/응용서비스 두 곳에서 모두 수행 가능 - 원칙적으로 모든 값에 대한 검증은 응용 서비스에서
- 응용에서 에러 코드 모아서 표현에서 하나의 예외로 발생시키기
보통은
- 표현 영역 : 필수 값, 값의 형식, 범위 등을 검증
- 응용 서비스 : 데이터의 존재 유무와 같은 논리적 오류 검증
여기 저자 분은 응용에서 싹다 하신다고 함 → 응용 계층의 완성도 ↑
# 6.6 권한 검사
# 표현 영역
- 인증된 사용자인지 아닌지 검사
- 필터를 사용해서 URL별 권한 검사도 가능
# 응용 영역
- URL 만으로 접근 제어가 불가능한 경우 응용 영역에서 메서드 단위로 권한 검사를 해야 함
- e.g., AOP를 활용해서 애너테이션으로 권한 검사
- 정리하자면 보안 프레임워크에 대한 높은 이해가 있으면 도입 OK, 아니면 직접 권한 검사 기능 구현도 OK
# 6.7 조회 전용 기능과 응용 서비스
- 서비스에서 추가적인 로직을 필요로 하지 않고 단일 쿼리만 실행하는 조회 전용 기능이어서 트랜잭션도 필요 없으면 그냥 표현 영역에서 바로 조회 전용 기능 사용해도 문제 x
- 굳이 다른 영역을 다 사용할 필요 없다는 뜻 같음
- e.g. controller - facade - service에서 굳이 facade를 통할 필요 없음
Q. 근데 Repository 인터페이스가 그럼 Dao로 쓰이는건가