고딩왕 코범석

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

Book Lounge/도메인 주도 개발 시작하기

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

고딩왕 코범석 2022. 7. 16. 21:04
반응형

Index

  1. 표현 영역과 응용 영역
    1. 표현 영역의 역할
  2. 응용 서비스의 역할
    1. 도메인 로직 넣지 않기
  3. 응용 서비스의 구현
    1. 응용 서비스의 크기
    2. 응용 서비스의 인터페이스와 클래스
    3. 메서드 파라미터와 값 리턴
    4. 표현 영역에 의존하지 않기
    5. 트랜잭션 처리
  4. 표현 영역
    1. 표현 영역의 책임
  5. 값 검증
  6. 권한 검사
    1. 권한 검사가 수행되어야 하는 곳?
  7. 조회 전용 기능과 응용 서비스

표현 영역과 응용 영역

표현 영역의 역할

  • URL, 요청 파라미터, 쿠키, 헤더 등을 이용해 사용자가 실행하고 싶은 기능을 판별해 해당 기능을 제공하는 응용 서비스를 실행하는 역할
  • 응용 서비스를 실행하기 위해 응용 서비스가 요구하는 형식으로 사용자 요청을 변경
  • 실행 결과를 사용자에게 알맞은 형식으로 응답
    • HTML, JSON …
  • 응용 영역은 표현 영역에 의존하지 않아야 한다.
    • 즉, 응용 영역은 사용자가 웹 브라우저를 호출하는지, REST API를 호출하는지, TCP 소켓을 사용하는지 알 필요가 없고 기능에 충실해야 한다.

위로

응용 서비스의 역할

  • 응용 서비스는 사용자의 요청을 처리하기 위해 리포지터리에서 도메인 객체를 가져와 사용한다.
    • 즉, 응용 서비스는 표현 영역괃 도메인 영역을 연결해주는 창구 역할을 담당한다.
    • 만약 응용 서비스 로직이 복잡하다면 응용 서비스에서 도메인 로직의 일부를 구현하고 있을 가능성이 높다.
    • 응용 서비스가 도메인 로직을 일부 구현하면 코드 중복, 로직 분산 등 코드 품질에 안좋은 영향을 미칠 수 있다.
  • 트랜잭션 처리도 응용 서비스가 담당한다.
    • 한 도메인의 상태 변경을 트랜잭션으로 처리한다.

도메인 로직 넣지 않기

  • 도메인 로직을 응용 서비스에 위치시키면 다음과 같은 문제들이 발생한다.
    1. 코드의 응집성이 떨어져 도메인 데이터와 데이터를 조작하는 도메인 로직이 한 곳에서 파악하기 힘들다.
      1. 이는 도메인의 로직을 파악하기 위해 여러 영역을 분석해야한다.
    2. 여러 응용 서비스에서 동일한 도메인 로직을 구현할 가능성이 높아진다.
  • 이 두 가지 문제는 코드 변경을 어렵게 만든다.
    • 소프트웨어의 중요한 경쟁력은 변경 용이성인데, 이를 높이려면 도메인 로직을 도메인 영역에 모아 코드 중복을 줄이고 응집도를 높여야한다.

위로

응용 서비스의 구현

  • 응용 서비스는 표현 영역과 도메인 영역을 연결하는 매개체 역할을 담당하는데, 이는 디자인 패턴에서 파사드와 같은 역할을 담당한다.

응용 서비스의 크기

  • 응용 서비스에 대한 크기를 따져보기 전 응용 서비스를 어떻게 만들것인가는 다음과 같은 방법이 있다.
    1. 도메인에 해당하는 서비스를 한 클래스 내에서 구현하기
    2. 기능별 서비스 클래스를 만들기
  • 1번 방법의 경우에 대한 장단점은 다음과 같다.
    • 동일한 코드에 대해 중복을 제거할 수 있다는 장점이 있다.
      • 예를 들어, 여러 메서드에 한 도메인 객체를 찾는 로직이 있다면 이를 private 메서드로 추출하여 중복을 줄일 수 있다.
    • 하지만 클래스의 크기가 커진다는 점이 단점이다.
      • 코드 크기가 커지면 연관 없는 코드들이 한 클래스에 몰릴 가능성이 높다. 이는 코드의 가독성을 저해시킨다.
  • 2번 방법의 경우에 대한 장단점은 다음과 같다.
    • 1번 방법에 비해 코드 품질을 일정 수준으로 유지하는데 도움이 된다. 또한 각 클래스별로 필요한 의존 객체만 포함하므로 다른 기능을 구현한 코드에 대해 영향을 받지 않는다.
    • 클래스의 갯수가 많아진다는 단점이 발생한다.

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

  • 인터페이스는 구현체가 여러 개일 경우와 런타임에 구현 객체를 변경해야할 때 유용하다.
  • 하지만 응용 서비스는 런타임에 교체되는 경우가 거의 없고, 구현 클래스가 여러 개인 경우도 드물다.
  • TDD로 표현 영역부터 개발한다면 인터페이스를 만들고 Mockito를 이용해 인터페이스에 Mock 객체를 주입시킬 수 있어 용이하다. 하지만 Mockito는 클래스에 대한 대역 객체도 생성할 수 있기 때문에 응용 서비스에 대한 인터페이스의 필요성을 약화시킨다.

메서드 파라미터와 값 리턴

  • 스프링 MVC에서는 웹 요청 파라미터를 자바 객체로 변환하는 기능을 제공하므로 응용 서비스에 데이터로 전달할 요청 파라미터가 두 개 이상 존재하면 데이터 전달을 위한 별도의 클래스를 만드는 것이 좋다.
  • 응용 서비스에서 애그리거트 자체를 리턴하면 편리함이 장점이지만 도메인의 로직 실행을 응용 서비스와 표현 영역 두 곳에서 조작할 수 있게 된다. 이는 응집도를 낮추는 원인이 된다.
  • 응용 서비스에서는 표현 영역에서 필요한 데이터만 리턴하는 것이 기능 실행 로직의 응집도를 확실히 올리는 방법이다.

표현 영역에 의존하지 않기

  • HttpServletRequestHttpSession을 응용 서비스에 파라미터로 전달하면 안 된다. 이유는 다음과 같다.
    • 응용 서비스에서 표현 영역에 대한 의존이 발생하면 응용 서비스만 테스트하기 어려워진다.
    • 표현 영역의 구현이 변경되면 응용 서비스에 대한 변경도 발생한다.
    • HttpSession과 쿠키는 표현 영역의 상태에 해당하는데 이 상태를 응용 서비스에서 변경해버리면 표현 영역의 코드만으로 표현 영역의 상태가 어떻게 변경되는지에 대해 파악이 어려워진다.

트랜잭션 처리

  • 스프링에서 제공하는 @Transactional을 사용하면 간단한 설정만으로 트랜잭션 코드를 수행하고 RuntimeException이 발생하면 Rollback이 발생한다.
  • 코드 또한 간단해지는 이점이 있다.

위로

표현 영역

표현 영역의 책임

  • 사용자가 시스템을 사용할 수 있는 흐름(화면)을 제공하고 제어한다.
  • 사용자의 요청을 알맞은 응용 서비스에 전달하고 결과를 제공한다.
  • 사용자의 세션을 관리한다.
    • 웹은 쿠키나 서버 세션을 이용해 사용자의 연결 상태를 관리한다.

위로

값 검증

  • 값 검증은 표현 영역과 응용 영역에서 모두 수행할 수 있다.
  • 표현 영역에서는 사용자의 입력 값이 잘못입력될 경우 이를 사용자에게 알려줘야하는 책임이 있다.
    • 스프링 MVC에서는 이를 Errors와 BindingResult를 통해 해결한다.
  • 응용 서비스는 정상적인 입력 값을 받고 수행 도중 논리상의 이유로 맞지 않아 예외를 반환해야하는 책임을 가지고 있다.
  • 정리해보자면 표현 영역과 응용 서비스 영역은 다음과 같은 검증 책임을 갖고 있다.
    • 표현 영역
      • 필수 값, 값의 형식, 값의 범위 검증
    • 응용 서비스 영역
      • 데이터의 존재에 대한 유무, 이외의 논리적인 비즈니스 오류
  • 각 영역마다 검증을 하게 되면 예외 상황에 대한 작성 코드량이 늘어나지만 응용 서비스의 완성도가 높아지는 장점이 있다.

위로

권한 검사

권한 검사가 수행되어야 하는 곳?

  • 우선 권한 검사는 다음과 같은 영역에서 이뤄질 수 있다.
    1. 표현 영역
    2. 응용 서비스
    3. 도메인
  • 표현 영역에서의 권한 검사는 인증된 사용자인지 아닌지 검사하는 것이다. 이는 주로 서블릿 필터에서 검증한다.
  • 응용 서비스에서의 권한 검사는 스프링의 AOP를 활용해 어노테이션으로 서비스 메서드에 대한 권한 검사를 수행한다.
  • 개별 도메인에서의 권한 검사가 복잡한데, 응용 서비스 수준에서 검사할 수 없다면 응용 서비스 내 로직에서 애그리거트를 불러와야 개별 도메인에서 권한을 검사할 수 있다. 이 때는 도메인 로직에 권한 체크 로직을 별도로 구현해야한다.

위로

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

  • 조회 기능에서 별도의 트랜잭션이 필요없거나 DAO를 통해 데이터를 조회하는 것 외에 별다른 로직이 없다면 서비스를 만들지 않고 표현 영역에서 바로 조회 전용 기능을 사용해도 문제가 없다.
    • 즉, 응용 서비스가 사용자의 요청 기능을 실행시키는데 별다른 기여를 하지 않는다면 굳이 구현할 이유는 없다.

위로

반응형