백엔드/웹 개발을 하다보면 controller, service, dao 등을 다루면서 프로젝트의 구조에 대한 고민을 하게 됩니다.
개인 프로젝트를 진행하면서 모듈을 고민하다보니, 기본 개념이 부족한 것 같아 부족했던 지식들을 보충해야겠다는 생각이 들었습니다.
시스템에 대한 이해
서비스는 독립적으로 실행 가능한 어플리케이션을 의미합니다.
시스템은 이 서비스가 1개 이상, 공유 인프라까지 합쳐서 일컫는 단어입니다.
레이어드 아키텍처
일반적인 개발자에게 익숙한 그림으로서, 보통 많은 프로젝트가 이 레이어드 아키텍처에 따라 프로젝트 구조를 구성합니다.
이 개념을 바탕으로 웹 프로젝트를 구성하고자 하면, 다음과 같은 모듈을 구성해볼 수 있습니다.
저의 경우에는 백엔드 프로젝트만 구성하기때문에 User Interface 계층은 다루지 않겠습니다.
Presentation 계층 = API Controller
Pesentation 계층에서는 View Model과 input까지 다루고 있습니다.
이는 Http requset/response와 이것을 처리하는 controller, 즉 API 요청을 처리하는 Controller가 해당된다고 볼 수 있습니다.
프론트와 백엔드는 서로 Http 통신을 통해 데이터를 주고받습니다.
프론트(=클라이언트)에서 백엔드에 정해진 규격(Request DTO)에 따라 데이터를 전송하면,
백엔드는 Api Controller에서 전송받은 데이터를 기반으로 로직을 처리합니다.
이후 프론트에게 데이터를 담아 응답함(Response DTO)으로써 하나의 스레드, 요청이 완료됩니다.
presentation 계층 특징
- 시스템 안에서 의미를 가진다. 시스템에서 사용할 추상화 모듈을 정의한다.
- 외부 통신을 담당한다.
- 애플리케이션/도메인 비즈니스를 모른다.
- 외부에 요청하는 비즈니스 로직만 품고 있다.
- 환경 별 시스템 host, header 관리
- 요청/응답 spec 관리
- 예외 처리 추상화 수준 통일: 예외처리를 한다/안한다 룰을 만들어 모듈을 작성한다.
presentation (api Controller)
- request : application 레이어에서도 request를 사용할 수 있도록 변환할 수 있는 로직을 추가할 수 있습니다.
- response
- controller
Application
어플리케이션의 핵심 플로우, 어플리케이션 비즈니스 로직이 이루어지는 곳입니다.
presentation 계층에서 controller에서 보낸 request 정보를 바탕으로 어떤 로직을 수행할 것인지 작성합니다.
이 때, 어플리케이션 비즈니스 로직은 도메인의 비즈니스 로직과 책임과 역할을 분리하기 위해 최대한 다루지 않는 것이 좋습니다.
application
- dto : request를 application 레이어에서 다룰 수 있도록 하는 매개체입니다.
또, domain 레이어에서 가져온 결과값을 전달하는 매개체가 되기도 합니다.
repsonse/response 데이터를 Application레이어에서 사용할 때 사용됩니다.- service
- exception : business exception
Domain
Domain 계층은 데이터베이스와 밀접한 연관관계를 가지고 있습니다.
VO나 Entity 등 데이터들을 자바 객체로 변환하거나, 그 반대의 경우에 사용하는 클래스들의 집합체입니다.
비즈니스 로직보다는 도메인이 책임을 갖고 있는 도메인 비즈니스 로직이 포함될 수 있고, 편의상 Persistence 계층을 생략하고 repository도 함께 관리할 수 있습니다.
Domain 계층 특징
- 도메인 비즈니스를 알고있고, 애플리케이션 비즈니스를 모른다.
- 하나의 모듈은 하나의 인프라스트럭처에 대한 책임을 갖는다.
- 인프라 연동관리, 도메인 계층 구현
domain과 data 계층의 분리를 꼭 해야하는 것일까?
물론 domain과 data(infra)의 모듈이 나뉘는 것이 이상적입니다.
언제든 인프라 구현체를 바꾸어 사용할 수 있게끔 하기 위해서이죠.
즉, 도메인이 인프라를 모르는 것이 이상적인 아키텍처라고 할 수 있습니다.
하지만 이에 따른 오버헤드와 비용을 생각하지 않을 수 없죠.
다양한 글들을 찾아 읽어보니, 이에 대한 논의는 이미 많이 다루어진 것 같습니다.
실용성을 포기하는 것은 어리석은 일이고, 실제로 인프라가 바뀌는 가능성이 크지 않다고 합니다.
이상적인 코드를 위해 객체지향적 설계를 하다보면 도메인 계층에 수많은 인터페이스가 생성됩니다.
(서비스/인프라의 의존관계 역전이 그 예시가 될 수 있겠습니다)
하나의 infra에는 하나의 domain이라는 책임을 잊지 않는다면, 도메인과 인프라를 같이 사용하는 구조가 편리하게 사용될 수도 있습니다.
하나의 인프라가 하나의 도메인을 책임진다는게 무슨 말일까요?
예를 들어 mysql을 쓰는 도메인과 redis를 쓰는 도메인이 있다고 한다면, 이를 2개로 따로 나누어서 사용하는 겁니다.
2개 도메인 예시
domain-mysql
- entity
- repository
- service
- exception
domain-redis
- entity
- repository
- exception
도메인 비즈니스?
도메인 단위 생성/변경/소멸 라이프사이클
한 도메인이 가지는 정책에 관한 비즈니스이다. 따라서, 애플리케이션의 로직이 바뀌더라도 도메인은 전혀 상관없다!!!
'백엔드 Backend > 기본 개념' 카테고리의 다른 글
final 키워드 사용하기 (0) | 2024.08.08 |
---|---|
SSH Key 동작 원리 (0) | 2024.08.08 |
예외 이해하기 (0) | 2024.08.08 |
멀티 모듈 / MSA 구조 이해하기 (0) | 2024.08.05 |
Http 요청 이해하기 (0) | 2024.08.02 |