엄범

martinfowler.com/bliki/PresentationDomainDataLayering.html  

 

우선, 가장 크고 중요한 개념은 layer다.

일반적으로 많이 사용하는 layer 구분

  • Presentation layer
  • Service layer
  • Business layer
  • Persistence layer

*** 기타 sublayer 들을 포함할 수도 있음.

 

layer를 왜 분리할까? layer를 분리한다는 것에는 어떤 의미가 있는가?

  • layer를 나눈다는 것은, 무언가를 추상화 하는 것이 그 목적이다.
  • 추상화를 잘 했다면, 각기 다른 계층끼리 부품을 갈아끼우듯 변경할 수 있다.
    • 각 layer가 자신의 세부사항을 몰라도 상관 없도록, 잘 추상화해서 제공하고 있었다면 가능하다.
  • 컴포넌트들의 서로의 의존 계층 관계를 깔끔하게 유지할 수 있다.
    • 각 layer를 넘나들면서 스파게티처럼 꼬여 있는 관계가 아니라, 위에서 아래로 떨어지는 간단한 구조 혹은 복잡한 참조는 같은 계층 내에서 끝내는 등 깔끔한 구조로 만들 수 있다.

 

각각의 layer의 역할은 무엇인가? 추상화하고자 하는 것은?

Presentation layer = UI layer

  • = UI layer
  • UI 추상화. Web UI / 앱 / Native GUI 등
  • 즉, UI 변경 되면 같이 변경되는 layer로 본다. (Martin Fowler 의견)
  • vs 자원에 대한 표현 모두를 담당하는 더 큰 범위의 layer로 보는 경우도 있지만, 추상화 책임은 작은 것이 더 낫다.

 

Service layer = Application layer

  • https://martinfowler.com/eaaCatalog/serviceLayer.html  
  • Domain Model을 묶어서 이 소프트웨어에서 사용 가능한 핵심 작업 집합을 설정하는 계층
    • = 이 소프트웨어가 수행해야 하는 작업을 명시
    • = 이 소프트웨어에게 내릴 수 있는 명령을 명시
  • 마틴파울러의 P of EAA에서 Service layer 아래에는 Domain Model이 존재함.
  • 보통 도메인 모델의 비즈니스 로직 하나를 호출하는 것 만으로는 복잡한 작업을 처리할 수 없음.
    • 도메인 모델 여러개를 불러와 요청을 가공하고 비즈니스 로직을 호출하고 응답을 조정해서 또 다른 비즈니스 로직을 호출하고... 이런 작업을 해주는 layer가 있어야 함.
    • 이렇게 여러 비즈니스 로직들을 의미있는 수준으로 묶어 제공하는게 Service layer의 역할
    • 물론 별도의 캡슐화가 필요하지 않은 경우에는 도메인 모델 기능 그대로 서비스로 만들 수도 있음.
  • 게다가 Data Loader, UI, Gateway, 같은 내부 Service 등 다양한 인터페이스로부터 작업 요청을 받는 상황을 가정해 보면.
    • 각 인터페이스의 종류와 목적이 다르지만, 분명 공통적으로 사용하는 작업이 있을 것임.
    • 이 때 공통적으로 사용하는 작업 집합을 각각의 Client에서 직접 정의하도록 하면 중복이 발생함.
    • 중복을 없애기 위해 서버에서 Service layer라는 추상화 계층을 하나 두고, 여기서 묶어서 제공하는게 낫다.
  • 결국 가장 핵심에 가까운 API를 제공하는 계층이 Service layer라고 볼 수 있음.
    • Controller가 그래보이겠지만, 이건 UI layer에 가깝다.
      • 요청이 UI를 통해 들어온거라면 Controller를 거치겠지만, 다른 경로로 들어왔다면? 이 때는 Controller를 거치지 않기 때문에..
  • 단, 핵심 로직은 Business layer에 두고, Service layer는 얇게 유지하는 것이 맞다.

 

Business layer (Domain Model)

  • martinfowler.com/eaaCatalog/domainModel.html
    • An object model of the domain that incorporates both behavior and data.
    • data와 그와 관련된 비즈니스 로직(메서드)을 가지고 있는 객체
  • https://martinfowler.com/bliki/AnemicDomainModel.html  
    • Model 클래스에 field, Getter, Setter만 두고 단순히 DTO 처럼 사용하는 것은 안티패턴이라는 의견.
    • 내가 봐도 그렇다.
    • 이러면 결국 Service Class에 로직이 다 들어가고, Model Class에는 필드밖에 없는데, Class의 "책임"을 생각해 보았을 때나 응집도를 생각해 보았을 때 Model Class에서 로직을 가지고 있는게 더 맞다는 느낌이 강하게 올 때가 많음.

 

Persistence layer

  • Data Source 추상화.

 

Presentation layer와 다음 layer의 구분 기준

무엇이 Presentation layer에 들어가고, 무엇이 Service layer에 들어가는지 결정하는 기준?

  • 현재 UI가 웹이라면, Native GUI / CLI / 앱 도 동시에 제공하게끔 변경했을 때 웹 Presentation 코드와 다른 UI Presentation 코드에 중복이 있는지 생각해본다. 
  • UI에 종속적인 로직인지, 아니면 그 소프트웨어의 핵심 api 로직인지 생각해본다.
    • 예를 들어 계좌 정보와 카드 정보를 동시에 표시하는 web UI를 제공하고 있었는데, 이를 app UI로 변경하는 상황을 생각해보니 바뀐 app UI에서도 여전히 계좌 정보와 카드 정보를 동시에 제공하겠다 싶은 생각이 든다면.
    • 이쯤 되면 계좌 정보와 카드 정보를 service layer에서 묶어서 반환해도 되기는 하지만...
    • 이건 그냥 UI가 바뀌었는데 우연히 필요로 하는 정보가 그대로일 가능성이 큼.
    • 정말로 카드 정보와 계좌 정보를 묶어서 반환하는걸 모든 인터페이스에 핵심 api로 제공해야겠다면 service layer에서, UI specific하다면 Presentation layer에서 묶어서 반환하면 된다.

 

그리고 이러한 layer들을 잘 분리하기 위한 개념으로, MVC 같은 디자인 패턴이 존재한다.

  • MVC, MVVM, MVP 같은 패턴은, Presentation code <> 나머지 code를 어떻게 잘 분리할 것이냐에 대한 패턴이다.
  • 즉, UI를 개발할건데, UI 관련된 코드와 내부의 비즈니스 로직 등을 어떻게 분리할 것인가?에 대해 정리한 패턴

 

그리고 그 layer 안의 컴포넌트로 Controller, View, Model이 존재한다.

MVC 예제

  • MVC가 UI 분리에 관해서 얘기하고 있는, Presentation 패턴이다 보니 Business layer가 어떻게 구성되는지와는 관련이 없다.
  • 즉, Business layer가 Service sublayer를 별도로 두던, 어쩌든, MVC와는 별 상관이 없는 것이다.

 

Controller는 Presentation layer인가? Service layer인가?

Controller의 역할?

  • UI layer 바로 다음에 위치한 non-user interface object로, input system event를 받는 역할
    • UI로부터 사용자 input(요청)을 받아서,
    • 어떤 service layer api를 호출해서 결과를 가져올지 결정하고
    • 어떤 UI(ex, jsp page)에 그 결과를 전달할지 결정한다.
  • 자바로 치면 Servlet(과 관련된 코드들), jsp에 결과를 전달하는 부분 등.

 

Controller는 Presentation layer인가? Service layer인가?

https://en.wikipedia.org/wiki/GRASP_(object-oriented_design)#Controller

요기서는 application/service layer에 속한다고 말하고 있으나... Presentation layer에 속한다고 보는게 맞는 듯.

 

  1. https://martinfowler.com/eaaDev/SupervisingPresenter.html 
    => Presentation은 Controller와 View 두 가지로 분리할 수 있다고 말하고 있음.
  2. 때때로 View에서 수행하지 못하는 Presentation 로직을 처리하기 위해서라도 Controller는 Presentation layer에 있는 것이 맞다고 봄.
  3. 애초에 MVC 자체가 Presentation code와 나머지 code를 어떻게 분리할것이냐에 대한 패턴이기도 함.
  4. UI를 Native GUI로 변경하거나, 앱으로 변경한다고 가정했을 때 Controller가 아예 제거되거나, 변경이 발생해야 함.

그리고 UI가 jsp라고 생각해보면, 어떤 jsp page에 결과를 전달할 것인지 선택하는 역할도 맡고 있음.

 

layer 구분 예제

보통 개발 하다 보면 자주 마주하게 되는 설계 고민이, 다음과 같은 UserResponse를 어느 layer에서 처리해야 하느냐? 에 대한 것이다

```js

Response<T> 타입

{

    "code" : 

    "message" :

    "result" : T

}

```

```js

1 | Model  (Business layer)
2 | -> ModelResponse  (요청에 맞게 필드를 추가/삭제한 타입)
3 | -> Response<ModelResponse>  (code, msg, result로 가공)
4 | -> ResponseEntity<Response<Result>>  (HttpResponse)

```

1~4번 중 어디까지가 Presentation layer이고 어디서부터 Business layer?

 

일단 4번이 Presentation layer, 1번이 Business layer인 것은 확실해보인다.

2번도 Service layer가 확실하고...

 

문제가 되는 건 3번인데..

그래서, 이런 타입의 클래스 명을 Response가 아니라 Result 라던지... 다른 것으로 하고 code & data를 리턴하도록 하면 좋을 것 같네.

 

Spring MVC라면?

```js

1 | Model  (* Business layer)
2 | -> ModelResponse  (@Service)
3 | -> Response<ModelResponse>  (@Service || @Controller)
4 | -> ResponseEntity<Response<Result>>  (@Controller)

```

[코딩 노트] 中 : 클린 코드 : 메서드 레벨에서의 가독성

 

 

참고 문서

https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller

 

https://docs.oracle.com/cd/E19644-01/817-5448/dgdesign.html  

[Spring] MVC

 

martinfowler