계층형 아키텍처 패턴 (Layered Architecture Pattern)
계층형 아키텍처 패턴(Layered Architecture Pattern)은 계층을 분리해서 관리하는 아키텍처 패턴이고, 현재 가장 흔하게 사용되고 있는 아키텍처 패턴 중 하나입니다.
단순하고 대중적이면서 비용도 적게 들어 모든 애플리케이션의 사실상 표준 아키텍처입니다.
어떤 아키텍처 패턴을 도입할지 확신이 없을 때에는 계층형 아키텍처 패턴은 좋은 선택지가 될 수 있습니다.
계층형 아키텍처 패턴은 어떤 경우든 계층을 분리해서 유지하고, 각 계층이 자신의 바로 아래 계층에만 의존하게 만드는 것이 목표입니다.
계층화의 핵심은 각 계층은 응집도(Cohesion)가 높으면서, 다른 계층과는 낮은 결합도(Coupling)를 가지고 있어야합니다.
여기서 상위 계층은 하위 계층을 사용할 수 있지만, 하위 계층은 자신의 상위 계층에 누가 있는지 알 수 없고, 사용할 수 조차 없도록 구성해야 합니다.
예를 들어 데이터 액세스 계층 (Data Access Layer)은 비즈니스 로직 계층 (Business Logic Layer)에 어떤 코드들이 있는지 알 수 조차 없고, 사용하면 안 됩니다.
일반적으로 계층형 아키텍처 패턴의 경우 규모가 작은 애플리케이션의 경우 3개, 크고 복잡한 경우는 그 이상의 계층으로 구성됩니다.
저희가 알아볼 아키텍처 패턴은 3 계층 아키텍처(3-Layered Architecture)입니다.
3계층 아키텍처에서 구성되는 각각의 계층(Layer)은 아래와 같습니다.
- 프레젠테이션 계층 (Presentation Layer)
- 비즈니스 로직 계층 (Business Logic Layer)
- 데이터 액세스 계층 (Data Access Layer)
계층형 아키텍처 패턴의 장점
- 관심사를 분리하여 현재 구현하려 하는 코드를 명확하게 인지할 수 있습니다.
- 각 계층별로 의존성이 낮아 모듈을 교체하더라도 코드 수정이 용이합니다.
- 각 계층별로 단위 테스트를 작성할 수 있어 테스트 코드를 조금 더 용이하게 구성할 수 있습니다.
3 계층 아키텍처 (3-Layered Architecture)
- Controller : 애플리케이션의 가장 바깥 부분, 요청/응답을 처리함.
- 클라이언트의 요청을 처리한 후 서버에서 처리된 결과를 반환해주는 역할을 합니다.
- Service : 애플리케이션의 중간 부분, 실제 중요한 작동이 많이 일어나는 부분
- 아키텍처의 가장 핵심적인 비즈니스 로직이 수행되는 부분입니다.
- Repository : 어플리케이션의 가장 안쪽 부분, DB와 맞닿아 있음.
- 실제 데이터베이스의 데이터를 사용하는 계층입니다.
3-Layered Architecture에서는 아래의 플로우를 기반으로 로직이 수행됩니다.
- 클라이언트(Client)가 요청(Request)을 보냅니다.
- 요청(Request)을 URL에 알맞은 컨트롤러(Controller)가 수신받습니다.
- 컨트롤러(Controller)는 넘어온 요청을 처리하기 위해 서비스(Service)를 호출합니다.
- 서비스(Service)는 필요한 데이터를 가져오기 위해 저장소(Repository)에게 데이터를 요청합니다.
- 서비스(Service)는 저장소(Repository)에서 가져온 데이터를 가공하여 컨트롤러(Controller)에게 데이터를 넘깁니다.
- 컨트롤러(Controller)는 서비스(Service)의 결과물(Response)을 클라이언트(Client)에게 전달해 줍니다.
Controller
컨트롤러(Controller) 란?
컨트롤러(Controller)란 클라이언트의 요청을 처리한 후 서버에서 처리된 결과를 반환해주는 역할을 합니다.
컨트롤러(Controller)는 추가적으로 아래의 역할을 가지고 있습니다.
- 클라이언트의 요청(Request)을 수신합니다.
- 요청(Request)에 들어온 데이터 및 내용을 검증합니다.
- 서버에서 수행된 결과를 클라이언트에게 반환(Response)합니다.
프레젠테이션 계층(Presentation Layer) 이란?
3 계층 아키텍처 패턴에서는 프레젠테이션 계층(Presentation Layer)이라고 표현되며, 대표적으로는 컨트롤러(Controller)로 사용됩니다. 사용자(클라이언트)가 서버에 요청(Request)을 하게 되면 가장 먼저 만나게 되는 계층입니다.
- 하위 계층(서비스 계층, 저장소 계층)에서 발생하는 예외(Exception)를 처리합니다.
- 클라이언트가 전달한 데이터에 대해 유효성을 검증하는 기능을 수행합니다.
- 클라이언트의 요청을 처리한 후 서버에서 처리된 결과를 반환합니다.
Service
서비스 계층(Service Layer)이란?
서비스 계층(Service Layer)이란 비즈니스 로직 계층(Business logic layer)이라고도 불립니다. 아키텍처의 가장 핵심적인 비즈니스로직을 수행하고 실제 사용자(클라이언트)가 원하는 요구사항을 구현하는 계층입니다.
- 프레젠테이션 계층(Presentation Layer)과 데이터 액세스 계층(Data Access Layer) 사이에서 중간 다리 역할을 하며 서로 다른 두 계층이 직접 통신하지 않게 만들어 줍니다.
- 서비스(Service)는 데이터가 필요할 때 저장소(Repository)에게 데이터를 요청합니다.
- 애플리케이션의 규모가 커지면 커질수록 서비스의 역할 및 코드 또한 점점 더 커지게 됩니다.
- 애플리케이션의 핵심적인 비즈니스 로직을 수행하여 클라이언트들의 요구사항을 반영하여 원하는 결과를 반환해주는 계층입니다.
서비스 계층의 장점
각각의 유스 케이스(Use Case)와 워크플로우(Workflow)를 명확히 정의할 때 도움이 됩니다.
- 저장소(Repository)에게 얻을 필요가 있는 데이터가 무엇인지 이해할 수 있습니다.
- 어떤 사전 검사와 현재 상태 검증을 필수적으로 해야 하는 것인지 이해할 수 있습니다.
- 어떤 내용을 저장해야 하는지 이해할 수 있습니다.
→ 유스 케이스(Use Case)에 대해 자세히 알고 싶다면 여기를 클릭하세요!
- 비즈니스 로직을 API 뒤에 감췄기 때문에 서비스 계층의 코드를 자유롭게 리팩터링 할 수 있습니다.
- 저장소 패턴(Repository Pattern) 및 가짜 저장소(Fake Repository)와 조합하면 높은 수준의 테스트를 작성할 수 있습니다.
서비스 계층의 단점
- 서비스 계층 또한 다른 추상화 계층에 불과합니다.
- 서비스 계층에 너무 많은 기능을 넣으면 빈약한 도메인 모델(Anemic Domain Model)과 같은 안티 패턴이 생길 수 있습니다.
Repository
저장소 계층(Repository Layer) 이란?
저장소 계층(Repository Layer)이란 데이터 액세스 계층(Data Access Layer)이라고도 불립니다. 대표적으로 Database와 관련된 작업을 수행하는 계층입니다.
- 모든 데이터가 Memory상에 존재하는 것처럼 가정해 데이터 접근과 관련된 세부 사항을 감춥니다
- 대표적인 저장소 계층의 메서드
- add() : 새 원소를 저장소에 추가합니다.
- get() : 이전에 추가한 원소를 저장소에서 가져옵니다.
- 저장소 계층을 구현했을 때 데이터를 저장하는 방법을 더 쉽게 변경할 수 있고, 테스트 코드 작성 시 가짜 저장소(Mock Repository)를 제공하기가 더 쉬워집니다.
- 애플리케이션의 다른 계층에서는 저장소의 세부 사항이 어떤 방식으로 구현되어 있더라도 영향을 받지 않습니다.
- → 객체 지향의 개념 중에서 추상화(Abstraction)와 관계가 있습니다.
- 저장소 계층은 데이터 저장소를 간단히 추상화한 것으로 이 패턴을 사용하면 모델 계층과 데이터 계층을 분리할 수 있습니다.
저장소 계층의 장점
- 모델과 인프라에 대한 사항을 완전히 분리했기 때문에 단위 테스트(Unit test)를 위한 가짜 저장소(Fake Repository)를 쉽게 만들 수 있습니다.
- 도메인 모델을 미리 작성하면 처리해야 할 비즈니스 문제에 더 잘 집중할 수 있다.
- 접근 방식을 바꾸고 싶을 때 외래키나 마이그레이션 등을 염려하지 않고 모델에 반영할 수 있다.
- 객체를 테이블에 매핑하는 과정을 원하는 대로 제어할 수 있어서 DB 스키마를 단순화할 수 있다.
- 저장소 계층에 ORM을 사용하면 필요할 때 MySQL과 Postgres와 같이 DB를 서로 바꾸기 쉬워집니다.
저장소 계층의 단점
- 저장소 계층이 없더라도 ORM이 어느 정도 (모델과 저장소의) 결합을 완화시켜 줍니다.
- ORM 매핑을 수동으로 하려면 개발 코스트가 더욱 소모됩니다.
- → 여기서 설명하는 ORM은 저희가 이전에 사용한 Sequelize와 같은 라이브러리를 말합니다.
전체적인 그림
'Language > Node.js' 카테고리의 다른 글
[JEST] 테스팅 프레임워크 JEST (0) | 2022.12.29 |
---|---|
[JEST] 테스트 코드 (0) | 2022.12.29 |
아키텍처 패턴 (Architecture Pattern) (0) | 2022.12.27 |
도메인 (Domain) (0) | 2022.12.27 |
객체 지향 설계 5원칙 (SOLID) (1) | 2022.12.27 |