[DDD] 도메인 주도 개발 시작하기 - 6장

Y_Sevin·2023년 8월 13일
0

6.1 표현 영역과 응용 영역

도메인이 제 기능을 하기 위해선 사용자와 도메인을 연결해 주는 매개체가 필요함 (응용 영역, 표현 영역)

표현 영역

  • 사용자의 요청을 해석 (HTTP요청)
  • 응용 서비스의 실행 결과를 형식에 맞게 응답 (HTML, JSON)
    응용 영역
  • 실제 사용자가 원하는 기능 제공

6.2 응용 서비스의 역할

  • 도메인 객체를 사용해 사용자의 요청을 처리
  • 도메인 영역과 표현 영역을 연결
  • 트랜젝션 처리
    • 응용서비스가 복잡하다면 응용 서비스에서 도메인 로직을 구현하고 있을 가능성이 있음
    • 도메인 로직을 도메인 영역과 응용서비스에 분산해서 구현하면 코드 품질에 문제가 발생함
      --> 코드의 응집성이 떻어지고 응용 서비스에서 동일한 도메인 로직을 구현할 가능성이 높아짐

소프트웨어의 가치를 높이려면 도메인 로직을 도메인 영역에 모아서 코드 중복이 발생하지 않도록 하고 응집도를 높여야함

6.3 응용 서비스의 구현

6.3.1 응용 서비스의 크기
응용 서비스를 구현할때 응용서비스의 크기를 생각해야함
응용 서비스 구현 방식
1. 한 응용 서비스 클래스에 회원 도메인의 모든 기능 구현
정점 : 동일 코드에 대한 중복 로직을 private메서드 호출을 통해 제거할 수 있음
단점 : 한 서비스 클래스의 크기가 커짐. 관련 없는 코드가 뒤섞여 코드 이해를 방해함

2. 구분되는 기능별로 응용 서비스 클래스를 따로 구현
장점 : 코드 품질을 일정 수준으로 유지하는 데 도움을 줌
단점 : 클래스 개수가 많아짐, 클래스의 기능이 분산되어 중복 코드를 구현할 가능성이 있음
-> 공통되는 로직을 별도 클래스에 구현하여 코드 중복을 방지할 수 있음

6.3.2 응용 서비스의 인터페이스와 클래스
응용서비스를 구현할때 인터페이스를 구현하곤 한다. 항상 인터페이스를 만들고 이를 상속한 클래스를 만드는 것이 필요할까?

  • 구현 클래스가 여러개인 경우 필요하지만 막상 런타임에 구현객체를 교체하는 경우와 구현 클래스가 2개인 경우는 드뭄
    책에서는 인터페이스를 작성하는건 별로 좋지 않아보인다고 한다. 근데 의존성을 떨어트리라며......

6.3.4 표현 영역에 의존하지 않기
응용 서비스의 파라미터 타입을 결정할 때 표현 영역과 관련된 타입을 사용하면 안 됨

  • HttpServletRequest와 같이 표현 영역에서 사용되는 클래스를 응용 서비스 영역의 파라미터로 전달하면 안됨
  • 응용 서비스에서 표현 영역에 대한 의존이 발생하면 응용 서비스만 단독으로 테스트하기가 어려워짐
  • 표현 영역의 구현이 변경되면 응용 서비스의 구현도 함께 변경되야 하며 응용 서비스가 표현 영역의 역할까지 대신하는 상황 나타날 수도 있음

6.4 표현영역

표현 영역의 책임
1. 사용자가 시스템을 사용할 수 있도록 알맞은 흐름(화면)을 제공하고 제어함

  • 사용자가 요청한 내용을 응답제공 (폼 화면 응답, 결과 응답)
  1. 사용자의 요청을 알맞은 응용 서비스에 전달하고 사용자에게 제공
  • 응용 서비스에 필요한 파라미터 타입으로 변환하고 결과를 사용자에게 응답 할 수 있는 형식으로 변환
  1. 사용자의 세션을 관리
  • 웹은 쿠키나 서버 세션을 이용해서 사용자의 연결 상태를 관리

6.5 값 검증

표현 : 필수 값, 값 형식, 범위 등에 대한 검증은 표현영역에서 진행
응용 : 데이터 존재 유무 등 논리적 오류에 대한 검증 응용영역에서 진행

6.6 권한검사

  • 권한 검사는 보통 표현 응용서비스 도메인 에서 검사를 수행할 수 있음

  • 표현 영역에서의 권한 검사는 인증된 사용자인지 검사 함

  • 스프링 시큐리티의 AOP를 활용해서 응용 서비스에서 권한 검사를 진행 할 수 있음 @PreAuthorize("hasRole('ADMIN')")

  • 개별 도메인 객체단위로 권한 검사를 해야하는 경우 권한검사 로직을 구현 해야함
    Ex) 본인이 작성한 게시글은 본인만 삭제가능

public class DeleteArticleService {
 
    public void delete(String userId, Long articleId) {
        Article article = articleRepository.findById(articleId);
        checkArticleExistence(artice);
        permissionService.checkDeletePermission(userId, article);
        article.markDeleted();
    }
}

6.7 조회전용 기능과 응용 서비스

  • 서비스에서 수행하는 추가 로직이 없고, 단일 쿼리만 실행하는 조회 전용으로 트랜잭션이 필요하지 않은 경우에는 서비스 없이 표현 영역에서 바로 사용해도 문제가 없음..
  • 사용자 요청기능을 실행하는 데 별다른 기여를 하지 못한다면 굳이 서비스를 만들지 않아도 됨
profile
매일은 아니더라도 꾸준히 올리자는 마음으로 시작하는 개발블로그😎

1개의 댓글

comment-user-thumbnail
2023년 8월 13일

글 잘 봤습니다.

답글 달기