본문 바로가기

Architecture

클린 아키텍처와 Nest.JS의 모듈 아키텍처

개요

사이드 프로젝트를 하면서 아키텍처에 대한 고민이 많았다. 약 1년 전에 ver.1을 만들었으나 몇 달 전 리팩토링 한차례 진행했다.


그리고 다시금 리팩토링을 진행하고 있다. 사실 이쯤 되면 리팩토링이 아니라 그냥 재작성이 아닐까 싶다.

 

Node.JS를 사용하다 보니 일단 Node.JS스펙을 이용하고 싶었고, 구조화에 대한 기준을 얻고 싶어서 Nest.JS를 사용했다.
저번 리팩토링은 아키텍처와 테스트코드에 초점을 맞추었다.

 

Nest.JS는 모듈 아키텍처를 방법론으로 사용하는 프레임워크이지만 당시 나는 보다 객체지향적으로 만들고 싶었다.
하지만 제대로 된 이해 없이 어떻게 봐줄만 한 결과물이 나오겠는가?


객체지향 아키텍처는 아무래도 클린 아키텍처가 깔끔하겠다는 단순한 생각으로 프로젝트를 진행했다.

클린 아키텍처

간단하게 클린 아키텍처를 말하자면 계층을 분리하여 관심사를 분리하고, 의존성은 저수준(구현)에서 고수준(추상)으로 향해야 한다는 아키텍처이다.


의존성 방향이 저수준에서 고수준으로 향하기 때문에 저수준 구현의 변경이 고수준 정책에 영향을 미치지 못하게 한다는 의도가 담겨있다.

 

그렇다면 의존의 중심이 되는 정책과 그 구현을 분리해서 구성해야 하므로 하므로 제대로 된 클린 아키텍처는 깊은 숙고와 많은 경험이 합쳐져 만들어진다고 생각한다.


제대로 구성하긴 내공이 부족하니 커다란 아키텍처 구조와 의존성 방향을 Domain 계층(고수준 정책)으로 향하게 한다는 의도를 따왔다.


일단 디렉토리 구조와 파일을 계층으로 분할하고 의존성을 설정했다. 누가? Nest.JS가. 프레임워크 Nest.JS에 의존성 주입을 위임해 놓고는 다 된줄 알았다.

 

앞 뒤 자르고 핵심만 추리면 Core - useCase - Controller - infra로 향하는 의존성을 만든줄 알았으나 결과물은 Nest.JS에 주입된 여러개 useCaseModule과 controller, 작성자 조차 햇갈리는 도메인 객체와 ORM의 entity였다.


심지어 도메인은 각 계층에 따로따로 분리되어 있다. Nest.JS가 방향성으로 제시한 도메인을 하나의 모듈로 만들어 활용하는 방법론을 엉망으로 어겼다.


프레임워크를 사용하면서도 프레임워크의 방법론을 무시하고 아키텍처를 구성하려 했던 것이다.

Nest.JS의 모듈 아키텍처

기본적으로 Nest.JS는 여러 모듈의 집합이다. RootModule이 있고 가장 기본이 되는 모듈에 다른 작은 모듈을 주입하는 방식이다.


모듈을 조립하여 어플리케이션을 만드는데, 하위 모듈은 더 하위 모듈로 조립되는 형태이다. 이렇듯 Nest.JS의 아키텍처 단위는 모듈이다.


가령 userController, userService는 똑같이 user를 다루므로 user도메인에 속한다. 그렇다면 userController, userService를 묶고, 더 필요한 것들을 묶어 userModule이 된다. 도메인이 모듈로 캡슐화 된 것이다.

리팩토링 전 후 문제

리팩토링 전은 도메인 단위로 모듈을 구성하지 않았으니 모듈을 이용한 코드 재사용이 불가능 했다. Nest.JS가 추구하는 바와 다르다는 문제도 있다.


리팩토링 후는 도메인 단위로 모듈을 구성했으나 모듈 내부를 클린 아키텍처 형식으로 구성했다. userModule을 예로 들자면 userDomain - userService - userController - userRepository 형식이다.

 

하지만 문제가 또 발생했다. 만약 협업하는 개발자가 있으면 이 구조를 빠르게 파악해서 업무를 진행할 수 있을까? 이미 Nest.JS에서 일반적으로 사용하는 방법과는 달라져 버렸는데?


좋게 표현하자면 굉장히 개성적인 코드 스타일이고 객관적으로 표현하자면 혼자만 알아볼 수 있는 코드다.

반성

개발자 간 협업이 없다는 문제점이 이렇게 드러난다. 동료 개발자가 이해하기 힘든 코드는 결국 좋은 코드가 아니다.


프로젝트의 코드 스타일이 정해져있다면 그걸 따를 수 밖에 없다. 만약 복잡한 도메인을 다뤄야 하는데 코드 구조까지 복잡하다면? 별로 좋은 소리는 안나올거 같다.


나는 좋은 코드를 만들고 싶은 거지 나혼자의 생각에 취한 코드를 만들고 싶은 게 아니다. 좋은 방법을 찾으려는 노력도 중요하지만 결국 기본기와 협업을 염두에 두어야 한다.