오늘은 Layered Architecture Pattern 즉 계층형 아키택쳐에 관한 til이다
1. 계층형 아키텍처 패턴 (Layered Architecture Pattern)
계층형 아키텍쳐란?
시스템을 여러 계층으로 분리하여 관리하는 아키텍처 패턴이다. 현재 가장 널리 채택되고 있는 아키텍처 패턴 중 하나이다
계층형 아키텍쳐를 사용하는 목표는 각 계층을 명확하게 분리해서 유지하고, 각 계층이 자신의 바로 아래 계층에만 의존하게 만드는 것이다.
일반적으로 계층형 아키텍처 패턴의 경우 규모가 작은 어플리케이션의 경우 3개의 계층, 크고 복잡한 경우는 그 이상의 계층으로 구성된다.
이번에 사용한 패턴은 3계층 아키텍쳐 패턴이다.
2. 3계층 아키텍쳐 패턴
- 프레젠테이션 계층 (Presentation Layer)
- 비즈니스 로직 계층 (Business Logic Layer)
- 데이터 엑세스 계층 (Data Access Layer) | 영속 계층(Persistence Layer)
이렇게 3계층으로 분리해서 얻을 수 있는 장점으로는
- 관심사를 분리하여 현재 구현하려하는 코드를 명확하게 인지할 수 있다.
- 각 계층은 서로 독립적이며, 의존성이 낮아 모듈을 교체하더라도 코드 수정이 용이하다.
- 각 계층별로 단위 테스트를 작성할 수 있어 테스트 코드를 조금 더 용이하게 구성할 수 있다.
3-Layered Architecture는 주로 아래의 3가지 계층으로 구성된다.
- 컨트롤러(Controller) : 어플리케이션의 가장 바깥 부분, 요청/응답을 처리
- 클라이언트의 **요청(Request)**을 수신 한 후 서버에서 처리된 결과를 **반환(Response)**해주는 역할
- 서비스(Service) : 어플리케이션의 중간 부분, API의 핵심적인 동작이 많이 일어나는 부분
- 아키텍처의 가장 핵심적인 비즈니스 로직이 수행
- 저장소(Repository) : 어플리케이션의 가장 안쪽 부분, 데이터베이스와 맞닿아 있음.
- 실제 데이터베이스와 통신
// 게시글 생성
router.post('/posts', async (req, res) => {
const { title, content, password } = req.body;
const post = await prisma.posts.create({
data: {
title,
content,
password,
},
});
return res.status(201).json({ data: post });
});
위와 같은 라우터가 있다고 가정해보자 3 계층 아키텍쳐는 해당 라우터를 3가지의 계층으로 나누는 것이다.
// prisma client 인스턴스 가져옴
import prisma from '../prisma/prisma.js';
class PostsRepository {
// orm는 오직 PostsService만 접근하도록 private(#) 설정
#orm;
// PostsRepository가 생성될 때 사용할 Orm을 받게 함.
constructor(orm) {
this.#orm = orm;
}
// 게시글 생성
createPost = async ({ title, content, password }) => {
// 생성될 때 받은 orm을 이용하여 db 접근
return await this.#orm.posts.create({
data: { title, content, password },
});
}
}
이런 식으로 PorsRepository.js 파일을 만들어서 prisma를 받아와 포스트를 테이블에 생성하는 역할을 임명한다.
import PostsRepository from '../repositories/posts.repository.js';
class PostsService {
#repository;
constructor(repository) {
this.#repository = repository;
}
createPost = async (postData) => {
return await this.#repository.createPost(postData);
}
}
// 생성 시 PostService가 사용할 Repository(PostsRepository)를 넣어서 생성
// PostsService 인스턴스 생성 후 반환
export default new PostsService(PostsRepository);
그리고 PostsService.js 파일을 만들어 PorsRepository를 임포트하고 해당 클래스 안에 postData를 인자로 받아 this.#repository.createPost(postData); 매서드를 실행시킨다.
// PostsService : posts.service.js 에서 생성해서 반환 된 인스턴스
import PostsService from "../services/Posts.service.js";
class PostsController{
// service는 오직 PostsController만 접근하도록 private(#) 설정
#service;
// PostsController가 생성될 때 PostsService를 받게 함.
constructor(service) {
this.#service = service;
}
// 게시글 생성
createPost = async (req, res) => {
// Client로 부터 받은 데이터를 가공
const { title, content, password } = req.body;
// PostService를 이용하여 게시글 생성 요청
const post = await this.#service.createPost({ title, content, password });
// PostService가 반환한 결과를 Client에게 전달
return res.status(201).json({ data: post });
}
}
마지막으로 PostsController .js 파일을 만들어 PostsService 를 임포트하고 해당 클래스 안에 마지막으로 req 값을 지정하여 직전에 만들었던 PostsService.createPost 매서드를 사용하여 로직을 진행한다 PostsService.createPost가 호출되면
PostsService.js 파일 안에있는 createPost = async (postData) => { return await this.#repository.createPost(postData); }
가 실행되는 것이다! 한 마디로 안으로 들어갈 수록 껍질을 벗긴다라고 생각하면 이해하기 쉽다!
이번 백 오피스 프로젝트가 내일부터 시작되는데 이러한 3계층 아키텍쳐 패턴을 잘 활용하여 완성해보도록 힘써보겠다!
'내일배움캠프 TIL' 카테고리의 다른 글
Joi라이브러리 사용법과 사용하는 이유 본캠프 TIL 01/09 (0) | 2025.01.09 |
---|---|
OSI 7계층에서 네트워크 계층 본캠프 TIL 01/08 (0) | 2025.01.08 |
프로젝트 SA 작성 본캠프 TIL 01/06 (1) | 2025.01.06 |
프로젝트 트러블슈팅 본캠프 TIL 01/03 (0) | 2025.01.03 |
팀 발표와 kpt 회고록 본캠프 TIL 01/02 (1) | 2025.01.02 |