---
tags: 객체지향, OOP, DDD
---
객체지향에서 서비스 레이어
===
객체지향과 절차지향은 설계가 완전히 다르다.
따라서 레이어가 달라지는데, 기존 절차지향에서 수직적인 3단계 레이어를 가졌다면
- Presentation -> Domain -> Data
객체지향에서는 4개의 레이어로 구분 되게 된다.
- Presentation -> Service -> Domain -> InfraStructure
> 참고로 각 레이어는 아래로 참조할 수는 지만 위로 참조하진 못한다.
> 예를들어 Presentation 에서 바로 Domain 이나 Data 를 사용 해도 되지만 Domain 이나 Data 는 Presentation 을 호출 할 수 없다.
`1. 객체지향과 절차지향 특징 비교` 를 통해 각각 차이와 용어를 정리 하고,
`2. 객체지향에서의 서비스 레이어의 역할` 을 통해 Service 레이어는 대체 역할이 뭔지 정리 해 보자.
## 1. 객체지향과 절차지향 특징 비교
도메인 레이어를 설계하는 방식에는 객체지향과 절차지향 2가지를 비교 하고자 한다.
두 방식에 효율성의 우위가 있는 것은 아니다.
장단점이 존재 하므로 비교를 해보겠다.
#### 절차지향 Transaction Script
- 개발자끼리 협력이 적은 프로젝트 개발시 우위
- 데이터 중심적 이어서 클래스 설계가 필요 없음
- 작업시간, 메모리사용 등 성능을 끌어내기 좋음 (예를들어 알고리즘)
#### 객체지향 Domain Model
- 객체간 역할이 명확하여 읽기 쉽고, 중복이 적어 유지보수도 쉬움
- 객체지향적인 지식이 필요 하며, 개발자 간 협력이 많이 필요함
- 서비스가 자주 변하는 경우 용이함
요약 하자면 절차지향은 빠르게 시작, 빠르게 개발이 가능지만 유지보수가 어렵고, 객체지향은 시작은 더디지만 유지보수가 용이하다.
도메인 레이어 에서 클래스간의 관계도도 조금 다르다.
의사 소통 방향이 절차지향은 수직적이고, 객체지향은 수평적이다.

[값객체와 @Embdedd 를 이용한 city, street, zipcode 리팩토링
](https://hackmd.io/@bonjugi/SJ68Bw2gr) 을 통해서, 특정 유저의 주소지가 서울 인지 확인하는 로직을 만들었던 적이 있다.
- user.getCity(), user.getZipCode() 로 데이터를 가져와서 비교하는 로직 (절차지향)
- Adrress 객체를 만들어서 inSeoul() 을 이용해 객체에게 물어봤던 방식 (객체지향)
주소가 서울 인지를 확인 하는 것은 Address 가 할 일 이고, 이러한 것들을 도메인 이라고 한다.
## 절차지향 도메인 레이어, 객체지향의 도메인 레이어 비교
DDD 관점 에서, 도메인을 핸들링 하는 영역을 도메인 레이어 라고 한다.
우리가 MyBatis 를 쓰면서 @Service 어노테이션을 붙이고 처리 해 왔던 서비스 로직들은 도메인 로직이라고 부르며, 이 영역을 도메인 레이어 라고 부르는 것이다.
절차지향과 객체지향의 레이어는 다음과 같다.

MyBatis로 전통적인 코딩을 하고 있다면 절차지향에 가깝다.
먼저 Transaction Script (절차지향) 부분 부터 보자.
용어가 달라서 헷갈릴수 있으니 우리 시스템과 대조 해보면 이렇게 이해 하면 된다.
- Presentation = @Controller
- Domain = @Service
- DataSource = xxDAO()
용어가 어느정도 이해 되었다면, 절차지향은 객체지향과 개념적으로 어떻게 다른지 비교 해 보자.
#### Service 가 뚱뚱 하다.
Domain Layer 를 보면, Fat Service 라고 적혀 있다.
도메인 객체 들이 해야 할 일을 미뤘기 때문에, 도메인 레이어가 다 하고 있기 때문에 비대 해진 @Service 가 특징 이다.
> 우리 시스템에서는 Domain Layer 라 부르지 않고 Service Layer 라고 표현 하고 있긴 하다. 하지만 Service Layer 에서 도메인 로직을 처리 하고 있기 때문에 DDD 관점에서는 그냥 Domain Layer 라 부르기도 한다. 그러니 용어에 크게 의미를 두지 말자.
`DDD 를 따르면`, 도메인 로직을 Entity 가 대부분 해결 하기 때문에 Service 는 매우 얇아 지게 된다. (Thin Service)
Service 는 도메인 에게 도메인 로직을 위임 하는 역할과 트랜잭션 관리만 하게 될 것이다.
#### Data Mapper 가 없다.
xxxDAO() 를 진정한 매퍼라고 말 하지 않고, `TableData Gateway` 라고 표현 하고 있다. 단순히 테이블을 열어서 데이터 만을 DTO (Data Transfer Object) 형태로 꺼내 오는게 전부 이기 때문 이다.
`DDD 를 따르면`, 도메인 로직을 확실하게 책임 져 줄 Domain Model 을 가져야 한다. JPA 에서 도메인은 Entity, VO(값 객체) 등이 있다.
#### 모든 레이어에 걸쳐 Anemic Domain Model 이 있다.
컨트롤러를 만들때 부터 이미 쿼리 까지 다 알고 있어야 한다.
예를 들어 user 의 나이와 이름을 변경 하는 페이지를 개발 한다고 가정 하면 쿼리 부터 떠오를 것 이다.
- update user set age=#{age}, name=#{name} where id = #{id}
또 쿼리에 맞는 UserAgeAndNameModel 따위를 만들어서 setAge(), setName() 같은 public 메소드를 만들 것 이다. 이럴거면 모든 필드를 다 public 으로 만든것과 같다.
모든것이 데이터 중심으로 돌아가기 때문에 단지 data 를 set 하는것만이 목적 일 뿐이기 때문 이다.
객체 지향 이라면 객체에게 행위를 시키면 된다. `user.()` 해보면 IDE 가 할수 있는 일들을 어시스트 해 줄 것이다.
- user.changeAge(Integer age);
- user.changeName(String name);
위 changeXX() 메소드는 setXX() 와 기능은 같겠지만 근본은 다르다.
도메인 객체가 도메인 로직을 처리 하기 위해 꼭 필요한 메소드만을 public 으로 제공 한다. 그래서 동사도 명확히 지어 주어야 한다.
### 절차지향 도메인 레이어, 객체지향의 도메인 레이어 비교 정리
절차지향이 무조건 나쁘다는 것은 아니다.
또한 한계가 있지만 MyBatis 를 통해서도 객체지향을 할 수도 있다. (엄청난 비용이 들 뿐..)
어쨋든 편의를 위해 ORM 을 학습하는 이상 객체지향적 설계를 따르는 것이 좋다.
지금까지 한 얘기들은 내 의견이 아니라, 마틴파울러 등 객체지향 대가 들이 제안하는 방식과 용어들을 정리 한 것이다. [빈약한 도메인 모델](https://m.blog.naver.com/muchine98/220304821784) 를 통해 번역 해 준 글도 시간 날 때 보자.
참고로 무조건 받아 들여야 할 스타개발자 이름 3명을 잠시 새기고 지나가자.
- 마틴파울러 (리팩토링, 엔터프라이즈 애플리케이션 아키텍처 패턴)
- 켄트백 (테스트주도개발, 리팩토링, 익스트림프로그래밍)
- 로버트 C. 마틴 (클린코드, 클린아키텍쳐)
## 2. 객체지향에서의 서비스 레이어의 역할
우리가 해왔던 서비스 로직은 도메인 레이어 라고 봐야 한다.
실제로 엔티티와 값객체들이 그 도메인 로직 처리를 충실히 하게 될 것이다.
그렇다면 도메인 로직을 모두 뺐겨버린 서비스 레이어는 대체 무얼 하게 되는가? 아까 Thin Service 라고 표현 했었는데 기억 하는가?
1. Transaction 관리
2. 도메인 객체 일시키기
3. 인프라스트럭쳐 일시키기 (영속화, 메일발송, 문자발송, 로깅 등)
이렇게 세가지를 잘 조율 하는 역할만 하면 된다.
또한 **서비스 레이어가 역할을 수행 함에 있어 도메인 로직을 전혀 몰라도 된다** 는 특징이 있다.
