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

표현 영역과 응용 영역

  • 표현 영역은 사용자의 요청을 해석한다. 사용자가 웹 브라우저에서 요청을 표현 영역에 전달하고, 요청을 받은 표현 영역은 URL, 요청 파라미터, 쿠키, 헤더 등을 이용해서 사용자가 실행하고 싶은 기능을 판별하고 그 기능을 제공하는 응용 서비스를 실행한다.

  • 실제 사용자가 원하는 기능은 응용 영역에 위치한 서비스가 제공한다. 응용 서비스는 기능을 실행하는 데 필요한 입력 값을 메서드 인자로 받고 실행 결과를 리턴한다.

  • 응용 서비스의 메서드가 요구하는 파라미터와 표현 영역이 사용자로부터 전달받은 데이터는 형식이 일치하지 않기 때문에 표현 영역은 응용 서비스가 요구하는 형식으로 사용자 요청을 변환한다. 응용서비스를 실행 뒤 표현 영역은 실행 결과를 사용자 요청에 맞게 HTML이나 JSON 형식으로 응답한다.

  • 사용자와 상호작용은 표현 영역이 처리하기 때문에, 응용 서비스는 표현 영역에 의존하지 않는다.

응용 서비스의 역할

응용 서비스는 주로 도메인 객체 간의 흐름을 제어하므로 단순한 형태를 갖는다.

응용 서비스는 도메인의 상태 변경을 트랜잭션으로 처리해야 하므로 트랜잭션 처리도 담당한다. 트랜잭션 외에 접근 제어와 이벤트 처리가 있다.

💡 도메인 로직 넣지 않기

응용 서비스가 도메인 로직을 일부 구현하면 코드 중복, 로직 분산 등 코드 품질에 안 좋은 영향을 줄 수 있다.

  • 코드의 응집성이 떨어진다. 도메인 데이터와 그 데이터를 조작하는 도메인 로직이 한 영역에 위치하지 않고 서로 다른 영역에 위치한다는 것은 도메인 로직을 파악하기 위해 여러 영역을 분석해야 한다는 것을 의미한다.

  • 여러 응용 서비스에서 동일한 도메인 로직을 구현할 가능성이 높아진다는 것이다.

응용 서비스의 구현

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

응용서비스의 크기

  • 한 응용 서비스 클래스에 회원 도메인의 모든 기능 구현하기

    • (장) 각 기능에서 동일한 로직을 위한 코드 중복을 제거하기 쉽다.

    • (단) 한 서비스 클래스의 크기가 커진다.

  • ✨ 구분되는 기능별로 응용 서비스 클래스를 따로 구현하기

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

  • 인터페이스가 명확하게 필요하기 전까지는 응용서비스에 대한 인터페이스를 작성하는 것이 좋은 선택이라고 볼 수는 없다.

메서드 파라미터와 값 리턴

  • 응용 서비스는 파라미터로 전달받은 데이터를 사용해서 필요한 기능을 구현하면 된다. 응용 서비스에 데이터로 전달할 요청 파라미터가 두 개 이상 존재하면 데이터 전달을 위한 별도 클래스를 사용하는 것이 편리하다.

  • 응용 서비스는 표현 영역에서 필요한 데이터만 리턴하는 것이 기능 실행 로직의 응집도를 높이는 확실한 방법이다. (ex. 식별자)

표현 영역에 의존하지 않기

  • 응용 서비스의 파라미터 타입을 결정할 때 표현 영역과 관련된 타입을 사용하면 안 된다. 이를 지키기 위한 가장 쉬운 방법이 서비스 메서드의 파라미터와 리턴 타입으로 표현 영역의 구현 기술을 사용하지 않는 것이다 .

트랜잭션 처리

  • 회원 가입에 성공했다고 하면서 실제로 회원 정보를 DB에 삽입하지 않으면 고객은 로그인을 할 수 없다. 배송지 주소를 변경하는 데 실패했다는 안내 화면을 보여줬는데 실제로는 DB에 변경된 배송된 배송지 주소가 반영되어 있다면 고객은 물건을 제대로 받지 못하게 된다.

  • 스프링은 @Transactional이 적용된 메서드가 RuntimeExcpetion을 발생시키면 트랜잭션을 롤백하고 그렇지 않으면 커밋하므로 이 규칙에 따라 코드를 작성하면 트랜잭션 처리 코드를 간결하게 유지할 수 있다.

표현 영역

  • 사용자가 시스템을 사용할 수 있는 흐름을 제공하고 제어한다.

  • 사용자의 요청을 알맞은 응용 서비스에 전달하고 결과를 사용자에게 제공한다.

  • 사용자의 세션을 관리한다.

값 검증

  • 값 검증은 표현 영역과 응용 서비스 두 곳에서 모두 수행할 수 있는데, 원칙적으로 모든 값에 대한 검증은 응용 서비스에서 처리한다.

  • 표현 영역에서 필수 값과 값의 형식을 검사하면 실질적으로 응용 서비스는 ID 중복 여부와 같이 논리적 오류만 검사하면 된다.

    • 표현 영역 - 필수 값, 값의 형식, 범위 등 검증

    • 응용 서비스 - 데이터의 존재 유무와 같은 논리적 오류 검증

ValidationError

권한 검사

보안 프레임워크의 복잡도를 떠나 보통 다음 세 곡에서 권한 검사를 수행할 수 있다.

✔️ 표현 영역 - 인증된 사용자인지 아닌지 검사한다.

  • 서블릿 필터에서 사용자의 인증 정보를 생성하고 인증 여부를 검사한다.

✔️ 응용 서비스 - 메서드 단위로 권한 검사를 수행한다.

  • 스프링 시큐리티는 AOP를 활용해서 애너테이션으로 서비스 메서드에 대한 권한 검사를 할 수 있는 기능을 제공한다.

✔️ 도메인 - 객체 단위로 권한 검사를 해야 하는 경우이다.

  • 게시글 삭제는 본인 또는 관리자 역할을 가진 사용자만 할 수 있다고 할 때, 이 경우 게시글 작성자가 본인인지 확인하려면 게시글 애그리거트를 먼저 로딩해야 한다. 즉 응용 서비스의 메서드 수준에서 권한 검사를 할 수 없기 때문에 직접 권한 검사 로직을 구현해야 한다.

서블릿 필터

스프링 시큐리티

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

  • 서비스에서 조회 전용 기능을 사용하면 서비스 코드가 단순히 조회 전용 기능을 호출하는 형태로 끝날 수 있다.

  • 서비스에서 수행하는 추가적인 로직이 없을 뿐더러 단일 쿼리만 실행하는 조회 전용 기능이어서 트랜잭션이 필요하지도 않다. 굳이 서비스를 만들 필요 없이 표현 영역에서 바로 조회 전용 기능을 사용해도 문제가 없다.

Last updated