Language/Java
[자바/스프링 개발자를 위한 실용주의 프로그래밍][chapter07] : 서비스란 무엇인가?, 애플리케이션/도메인 서비스는 어떻게 다른가?, 서비스의 본질은 ?
j4ko
2024. 9. 19. 01:38
728x90
반응형
목차
개요
- 서비스의 역할은 “도메인 객체나 도메인 서비스라고 불리는 도메인에 일을 위임하는 공간”이어야 한다
- 이는 서비스의 역할을 다음과 같이 크게 3가지 종류의 일을 해야한다는 의미이다.
- 도메인 객체를 불러온다.
- 도메인 객체나 도메인 서비스에 일을 위임한다.
- 도메인 객체의 변경 사항을 저장한다.
- 이는 서비스의 역할을 다음과 같이 크게 3가지 종류의 일을 해야한다는 의미이다.
- 서비스 컴포넌트가 왜 이러한 역할을 해야하는지 알아보자.
- 도메인 서비스란 무엇이며, 스프링에서는 서비스는 왜 서비스라고 부르는지, 서비스 컴포넌트에 추가적으로 기대하는 역할이나 책임은 무엇인지 파헤쳐 보자.
7.1 Manager
: 스프링에서 서비스는 왜 서비스라고 부를까 ?
- 이에 대한 해답은 스프링의 “@Service” 애너테이션이 작성된 실제 코드를 찾아가야한다. 그곳에 해답이 적혀있다.
- “서비스는 도메인 주도 설계”에서 시작된 개념으로 “캡슐화된 상태 없이, 모델과는 독립된 동작을 제공하는 인터페이스”이다.
- “이 애너테이션이 지정된 클래스는 J2EE 패턴 중 하나인 ‘비즈니스 서비스 파사드’나 그와 유사한 것처럼 사용될 수도 있음을 의미한다.
- 이 애너테이션은 매우 일반적인 용어로 각자의 사정에 맞게 의미를 좁혀 사용할 수 있다.
- 이를 요약하면 다음과 같다.
- “@Service”는 에릭 에반스의 DDD에서 영감을 받아 만들어진 애너테이션이다.
- 서비스는 J2EE 패턴 중 하나인 비즈니스 서비스 파사드처럼 사용될 수 있다.
- 정리하자면, 서비스는 도메인 객체가 처리하기 애매한 “연산” 자체를 표현한기 위한 컴포넌트이다.
: 트랜잭션 스크립트와 같이 여러 도메인을 아우르는 액션을 처리하는 클래스는 Manager 클래스가 되기도 한다. (메모)
- 클래스 이름의 접미어에 Manager가 나오면 일반적으로 어떤 모델에 강하게 연관되어있으며, 모델에 관련된 부가적인 논리 로직을 제공하는 공간으로 해석된다.
- 서비스는 곧 매니저 클래스다. 그리고 로직 자체가 “연산”이라서 어떠한 객체도 갖고 있기도 어려운 경우에 만들어지는 클래스가 서비스다.
: 애플리케이션 서비스 와 도메인 서비스
- 애플리케이션 서비스는 애플리케이션을 구축하기 위해 만들어진 서비스임을 뜻한다.
- 도메인 서비스는 도메인을 구축하기 위해 만들어진 서비스임을 뜻한다.
7.2 서비스보다 도메인 모델
: 클래스의 역할은 클래스의 이름을 짓는 순간부터 결정된다.
- Cashier라는 이름은 점원의 역할을 수행하며 능동적, PriceManager라는 이름은 가격과 관련돈 연산 로직만 갖고 있을 것
- PriceManager와 같은 클래스는 유의미한 도메인 객체로서 확장되기 어렵다.
: 도메인과 도메인 서비스는 이름으로 결정되는 것이 아니다.
- 도메인과 도메인 서비스를 구분짓는 것은 행동으로 결정된다.
- 접미어에 Service나 Manager가 없다고해서 이 클래스가 더 이상 서비스가 아니게 되는 것이 아니다.
- 이러한 맥락에서 클래스 이름을 지을 때 서비스를 표현하기 위해 컴포넌트 이름에 접미어로 Service나 Manager를 쓰는 것은 무의미하다.
: 객체지향 관점에서 서비스와 스프링을 바라보기
- 객체지향을 추구하는 스프링 개발자가 서비스를 어떻게 취급해야 하는지 두 가지 조언을 함 (저자)
- 서비스는 가능한 한 적게 만들고, 얇게 유지해야 한다.
- 서비스보다 풍부한 도메인 모델을 만들어야 한다.
- “서비스를 얇게 유지하라”는 조언
- 이는 비즈니스 로직을 도메인 객체로 옮기라는 말과 같다.
- 서비스 코드를 작성할 떄는 현재 작성중인 코드가 “기존 도메인 객체에 들어갈 수는 없는지”와 “새로운 도메인 모델로 만들 수는 없는지”를 고민해 보는 것이 좋다.
- 애플리케이션 서비스보다 도메인 서비스로 만드는 것이 유리하며, 도메인 서비스보다 도메인 모델로 만드는 것이 유리하다.
7.3 작은 기계
: 서비스는 불변하다.
- 서비스는 어떤 가변 상태를 갖는 객체가 아니라 “계산식” 그 자체이다. 그러니 서비스는 불변이어야 한다 서비스 메서드의 실행은 항상 같은 논리를 사용해야한다. 그래서 같은 입력에 항상 같은 응답이 나와야 한다.
- 불변성은 서비스에 기대하는 주요 특징 중 하나이다.
: 서비스 주입
- 스프링을 사용하다보면 “서비스를 필드 주입이나 수정자 주입을 이용해서 초기화하지 말고 생성자 주입을 사용하라” 라는 격언을 접한다.
: 생성자 주입을 사용해야 하는 이유에 대한 보통 근거
- 생성자 주입을 사용하면 명시적으로 의존성을 표현할 수 있다.
- 생성자 주입을 사용하면 테스트하기가 쉬워진다.
- 생성자 주입을 사용하면 순환 의존성을 방지할 수 있다.
: 생성자 주입을 사용해야하는 근본적인 이유
- 앞선 근거들은 부수적인 이점일 뿐이며 이보다 생성자 주입을 사용해야 하는 조금 더 근본적인 이유가 존재한다. 바로 서비스는 원래 불변해야하기 때문이다.
: 항상 똑같이 움직이는 “기계”처럼 동작해야한다.
- 서비스의 상태가 변경된다면 서비스는 영원히 같은 일을 할 수 없다 서비스는 불변성을 유지하고 예측할 수 있는 컴포넌트가 돼야 한다. 같은 입력에는 항상 같은 결과만 나와야한다.
- 서비스는 견고해야한다. 그리고 얇고 작아야한다. 이러한 이유로 서비스는 생성자 주입을 사용해야한다.
: 필드 주입과 수정자 주입을 사용하는 서비스는 클래스를 불변으로 만들지 못한다.
- 서비스를 정의할 떄 이 두 주입 방식을 이용해 클래스를 만들지 않는 것이 올다.
7.4 조언
: 서비스와 관련한 조언
- 서비스의 멤버 변수는 모두 final로 만드세요
- 서비스에 세터가 존재한다면 지우세요
- 서비스는 반드시 생성자 주입으로 바꾸세요
- 서비스의 비즈니스 로직을 도메인에 양보하세요
- 서비스를 얇게 유지하세요
728x90
반응형