프로젝트를 하기전 스프링의 layer에 대해서 알아보고자 공부함. 영어공부도 할 겸 아래의 블로그 내용을 해석, 정리함.
https://lifelife7777.tistory.com/100
다른 사람의 번역.
<스프링 웹 앱 구조 : 클래식>
많은 개발자들은 아래의 2가지를 이해해야한다.
1. 아키텍쳐 디자인은 필요하다.
2. 화려한 아키텍쳐 다이어그램은 앱의 실제 아키텍쳐를 설명하지 않는다.
실제 아키텍쳐는 개발자들이 쓴 코드에서 찾을 수 있다. 아키텍쳐 디자인을 하지 않고 앱을 만든다면 결국 우리의 앱은 하나 이상의 아키텍쳐를 가진 상태로 만들어 질 것임.(안좋다)
그럼 개발자들이 설계자의 명령을 받아야 하나?
그렇지 않다. 아키텍쳐디자인은 설계자에게 맡겨 두기에는 너무 중요하다. 단순히 type writer 이상의 사람이 되고 싶은 개발자들은 설계를 잘해야 한다.
스프링 앱을 위한 간단하고 더 나은 아키텍쳐를 설계할 때 주의해야할 2개의 규칙을 보고 가자.
<좋은 아키텍쳐를 위한 2개의 규칙>
아키텍쳐디자인은 어렵다고 느낄 수 있다. 이는 많은 개발자들이 아키텍쳐 디자인은 매우 어렵고 똑똑한 사람들만 할 수 있다고 배워왔기 때문임. 이 똑똑한 사람들은 software architects라고 부른다. 그러나 이 일은 그렇게 복잡하지 않다.
소프트웨어 아키텍쳐는 소프트웨어 시스템의 높은 레벨의 구조이며 높은 레벨의 구조를 만드는 분야이고 이 구조의 문서를 작성하는 것이다.
경험이 더 나은 아키텍쳐를 만들 수 있게 도와주는 것은 맞지만, 아키텍쳐의 기본원리는 꽤 간단하다.
1. Seperation of Concerns(SoC) : 관심사의 분리
(concern : 관심사)
SoC는 컴퓨터 프로그램을 여러 개의 섹션으로 나누는 것이다. 분리한 각각의 섹션은 하나의 관심사를 다루도록 한다.
이것을 하기 위해 우리는 "관심사를 정의"해야하고 "각각의 관심사를 어디에서 처리할지" 정해야한다. 즉 이 SoC 규칙은 우리가 몇 개의 layer를 필요로 하는지 그리고 각각의 layer의 역할은 무엇인지 정의하게 해준다.
2. Keep It Simple Stupid(KISS)
대부분의 시스템은 복잡할 때 보다 간단할 때 더 좋다. 복잡성을 없애고 간단함을 추구하는 것이 좋은 아키텍쳐 설계이다. 이 규칙은 굉장히 이성적이다. 레이어를 만드는 데는 비용이 들어간다.(개발 시간, 인력 등) 만약 레이어를 많이 가지고 있는 복잡한 아키텍쳐를 사용한다면 비용이 너무 많이 듦. 다음과 같이 디자인 해서는 안된다.
위의 구조는 SoC는 지켰지만 복잡성이 너무 크다. 간단하게 해야하는 규칙을 적용하지 않았다. 각각의 레이어를 구현하기 위해서는 비용이 많이 든다.
1. 각각의 layer마다 정보를 교환해야하기 때문에 새로운 기능을 만드는 것은 매우 오래걸린다.
2. 아무도 실제로 이 아키텍쳐를 이해하지 못하기 때문에 앱을 유지보수하는 것이 불가능하다.
그렇다면 어떤 아키텍쳐가 좋은가?
3개의 layer는 대부분의 상황에서 충분하다. 웹앱의 역할애 대해 생각해 보면 다음의 관심사가 있다.
- 유저의 요청을 받아 응답을 반환해준다.
- 유저에게 에러메시지를 알려주는 예외처리 메커니즘이 있어야 한다.(
여기서 유저는 개발자인듯.) 브라우저를 사용하는 유저인듯. - It needs a transaction management strategy.
- 인증과 승인을 다뤄야 한다.
- 비즈니스 로직을 구현해야한다.
- 외부 리소스나 데이터 스토리지와 소통해야한다.
우리는 위의 내용을 3개의 레이어를 사용함으로써 달성할 수 있다.
web layer : 웹레이어는 가장 위의 레이어이다. 유저의 입력을 받고 응답을 반환한다. 다른 레이어에서 발생한 예외도 처리해야한다. 웹 레이어가 앱의 시작점이기 때문에 인증과 비인증 유저의 차단의 역할을 한다.
service layer : 트랜잭션의 경계 역할을 하며(?) 앱과 인프라 서비스를 포함한다.(?) 앱서비스는 서비스 레이어의 public API 를 제공. 얘들도 인증의 역할이 있다. 인프라 서비스는 plumbing code를 포함한다. plumbing code는 외부의 파일 시스템, db, 이메일 서비스와 연결된다. 이런 방법은 여러 개의 앱 서비스에서 사용된다.(?)
repository layer : 데이터스토리지와 연결되어 있고 이를 담당하는 레이어임.
특정 레이어에 포함된 컴포넌트는 해당 레이어의 다른 컴포넌트나 아래에 위치한 레이어의 컴포넌트를 사용할 수 있다.(왜 이런 규칙이 있는지는 모르겠다.)
@
layer
- web layer
- service layer
- repository layer
다음으로 우리가 할 일은 각 레이어의 interface를 디자인 하는 것이다. 이 과정에서 우리는 DTO, domain model라는 용어를 만난다.
DTO(data transfer object) : 단순 데이터를 담는 객체임. 레이어와 레이어 사이의 정보교환을 위한 객체임
domain model은 3개의 객체로 이뤄져 있다.
1. domain service : 이는 상태가 없다. 도메인 개념과 연관된 객체들에 대해서 기능을 제공함. 하지만 entity나 value object의 natural part(?)는 아니다.
2. entity is an object that is defined by its identity which stays unchanged through its entire lifecycle.
3. value object describes a property or a thing, and these objects don’t have their own identity or lifecycle. The lifecycle of a value object is bound to the lifecycle of an entity.
이제 각각의 용어를 알았다. 각 레이어의 인터페이스를 디자인해보자.
- web layer는 DTO만 다뤄야 한다.
- 서비스 레이어(이하 서비스)는 메소드 파라미터로 dto와 기본타입들을 받아서 처리한다. 서비스는 도메인 모델 객체를 다룰 수 있다. 하지만 반환하는 것은 항상 web에게 dto만 반환할 수 있다.
- 리포지토리 레이어는 엔티티와 기본타입을 메소드 파라미터로 받고 엔티티를 반환한다.
위와 같은 규칙을 따르면 굳이 DTO가 필요한가라는 의문이 든다. 엔티티와 VO를 웹레이어에 반환하면 안되나?
1. 도메인모델은 앱의 내부 모델을 나타낸다. 이 도메인 모델을 외부로 노출시키면 클라이언트는 이것을 어떻게 사용하는지 알아함. 클라이언트는 자신이 가지고 있지도 않은 도메인 모델에 대해서 신경써야한다. 우리가 DTO를 사용하면 도메인을 숨길 수 있다. 그에 따라 쉽고 깔끔한 API를 제공할 수 있다.
Q: (클라이언트는 프로그래머를 말하는 듯? 만약 브라우저 클라이언트를 말한다면 왜 도메인 모델을 노출시킨다고 해서 클라이언트가 이것을 신경써야하는지 모르겠다.)
2. 도메인에 수정이 필요할 때 문제가 생긴다. DTO와 도메인을 분리하면 DTO만 수정하지 않는다면 도멘은 마음대로 수정할 수 있다.
이 포스트는 클래식 스프링 웹 앱의 아키텍쳐를 서술했다. 하지만 다음과 같은 실제로 궁금해 하는 질문에 답은 못함.
- 왜 layer X가 관심사 Y에 책임을 지는가?
- 우리의 앱이 3개 초과 또는 미만의 레이어를 가지고 있어야 하나?(우리 앱의 적정 레이어 수는 몇 개인가?)
각 레이어의 내부 구조는 어떻게 디자인 하는가? - 정말 레이어가 필요한가?
우리가 달리기 전에 걷기를 배워야 하기 때문에 위의 질문들은 천천히 배우자고함. 다음 포스트는 이런 질문에 대한 튜토리얼이 될 것임.