엄범

 

우선, 가장 크고 중요한 개념은 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  
    • 사용 가능한 작업 집합을 설정하고 응답을 조정하는 계층
      • = 이 소프트웨어가 수행해야 하는 작업을 명시
      • = 이 소프트웨어에게 내릴 수 있는 명령을 명시
    • 즉! 비즈니스 로직을 외부에 그대로 공개하는게 아니라,
    • 캡슐화 해서 복잡한 로직들을 트랜잭션 단위로 묶거나, 응답을 만드는 일을 담당
    • 핵심 로직은 Business layer에 두고, Service layer는 얇게 유지하는 것이 맞다.
  • Business layer
    • 비즈니스 로직 처리
    • 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에 들어가고, 무엇이 Business layer에 들어가는지 결정하는데는 완전히 다른 UI를 생각해 보는 것이 도움이 된다.

현재 UI가 웹이라면, Native GUI / CLI / 앱 으로 변경했을 때 웹 Presentation 코드와 다른 UI Presentation 코드에 중복이 있는지 생각해본다. 

중복이 발생한다면 Business layer로 옮겨야 하는 로직일 가능성이 크다.

(즉, 다른 UI로 바꿨을 때 변경되지 않는 부분이라면 Business 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(요청)을 받아서, 어떻게 해야 하는지 알아내는게 핵심 역할임!
  • coordinate or control 하는 책임이므로 적절한 business logic을 호출해서 결과를 가져오고, 응답을 내려주는 일을 한다.
  • 자바로 치면 Servlet(과 관련된 코드들)

 

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가 아예 제거되거나, 변경이 발생해야 함.

 

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번인데..

  • 3번은.. 어쨌든 어떤 문제가 발생했음을 유저한테 전달할 필요가 있다는 거고, 이는 UI와는 별 관련이 없으니까 Service layer에 두는게 맞는 것 같다.
  • Service layer에 안두고 상위 Presentation layer에서 한다고 생각해봐도, 어쨌든 Service layer에서 ErrorCode를 리턴해줘야 하는 것은 똑같으므로 Return Type이 애매해진다.
  • 그리고 사실 오류와 관련된 응답을 모두 GlobalExceptionHandler 쪽으로 빼면 Service에서 Response<>를 굳이 리턴해야 할 필요가 없으니까(항상 성공일 것이므로), 이렇게 되면 굳이 Service layer에 두지 않고 Controller에서 처리하는게 깔끔하긴 하다.

 

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://martinfowler.com/eaaDev/uiArchs.html

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

https://martinfowler.com/eaaDev/SeparatedPresentation.html  

[Spring] MVC