개발을 하면서 `어떤 코드 아키텍처가 좋은걸까` 고민을 하는 경우가 많습니다. 결론부터 말하자면, 사실 완벽한 아키텍처는 없습니다.
팀이 선호하는 방향에 맞춰서 가는 것, 컨벤션을 따르는 것이 중요하죠. 그래도 개인적인 기준을 세우는 것은 필요하다고 생각합니다.
그래서 이번에는 코드 아키텍처에 대해 고민해보셨으면 합니다.
Code Architecture 에 대해 고민해보기
코드 아키텍처는 어떻게 코드를 구성할 지에 대한 규칙입니다. 쉽게 말해 다 같이 개발을 하기에 이런 종류의 코드들은 이 Directory에 모아놓자고 하는 것입니다.
이번 글에서는 Layer와 Hexagonal Architecture를 가볍게 꺼내보려고 합니다. 구체적인 이야기를 하기에는 너무 길어질 것 같아서 제외하였습니다.
Layer Architecture
Layer Architecture는 일반적으로 Controller - Service - Repository 의 구조로 코드를 관리하게 됩니다.
- Controller : API를 정의하는 부분
- Service : 비지니스 로직을 정의하는 부분
- Repository : DB와 연결되는 부분
Hexagonal Architecture
Hexagonal Architecture는 Port & Adapter 라고 부르기도 하는 데, 비지니스 로직을 중심에 두고 API나 DB 접근하는 부분을 밖으로 빼서 관리하게 합니다.
- Application : API를 정의하는 부분
- Domain : 비지니스 로직을 정의하는 부분
- Persistence : DB와 연결되는 부분
무엇이 차이점일까?
저는 이 두 아키텍처의 가장 큰 차이점은 의존성이라고 생각합니다.
"의존성이 명시적으로 표현되어 있는가"
`의존성` 이라는 게, 정말 중요합니다. 우리가 흔히 말하는 SOLID 도 의존성을 최소한으로 유지하기 위한 규칙입니다. 어떻게 보면 코드 아키텍처는 SOLID를 잘 따르기 위해 만들어진 것이라고 무방하죠.
서비스를 안정적으로 운영하기 위해서는 의존성을 최소한으로 유지되는 것이 유리하기 합니다. A를 고쳤는데 B도 고쳐야하고, C도 손봐야한다면 그만큼 어지러운 일도 없습니다.
하지만 이 의존성을 완전히 제거하는 것은 불가능합니다. 그래서 최소한으로 유지하는 것이 목표인 것이죠. 그렇다면 어디에 의존성을 두어야 하는 가를 고민해서 만들어진 것이 바로 헥사고날 아키텍처입니다.
헥사고날 아키텍처는 도메인 영역에 어떠한 의존성도 두지 않습니다. 따라서 비지니스 로직이 다른 영역으로 부터 오염받지 않을 수 있습니다. 반대로 다른 영역이 도메인 영역에 대해 의존성이 존재하죠. 그래서 도메인 영역이 변경되면 모든 곳에서 변경이 일어납니다.
반면에, Layer Architecture 는 의존성을 상대적으로 덜 고려합니다. 개발자에게 의존성 관리를 맡겨둔 것이죠. 그렇기 때문에 비지니스 로직이 오염이 될 가능성이 존재하죠.
의존성이 어떻게 존재한다는 걸까?
프레임워크와 ORM, 외부 라이브러리 등 외부에 존재하는 코드들은 모두 의존성이라고 보시면 됩니다. 일단, ORM의 예시를 들어보죠.
Layer architecture 에서 ORM을 사용한다면 아래와 같이 ORM의 정책이 Entity에 존재하게 됩니다.
A라는 Entity 아래에 B와 1대1 관계임을 표현하기 위해서 `@OneToOne` 을 사용했습니다. A는 비지니스 로직을 표현하기 위한 모델인데 그와 관계없는 ORM 때문에 코드가 변경된 것이죠. 이 Entity는 결국 Service Layer에도 영향을 주게 됩니다.
비지니스 로직을 먼저 생각하고 풀어나가야하는데, ORM의 정책이 먼저 고려된 결과입니다.
반면, Hexagonal Architecture에서는 두 개의 모델을 사용합니다.
ORM의 정책을 Persistence에만 존재하게 하고, 비지니스 로직을 위한 영역은 의존성이 없도록 합니다. 따라서 도메인 로직을 먼저 생각하고 추후에 DB와 관련된 정책을 적용해도 무방한 것이죠.
적절한 아키텍처를 선택하세요
위의 예시만 보면, Hexagonal Architecture가 Layer Architecture보다 좋은 것 같지만 꼭 그렇지는 않습니다. Hexagonal 은 의존성을 지키기 위해서 의미없는 코드들이 많아지게 됩니다.
예를 들어, 위에서 예시로 했던 Domain.A와 Persistence.A 처럼 사실상 같은 코드들이 많아지게 됩니다. 같은 내용을 작성하고 변환하는 로직도 작성해야 하기 때문에 생각보다 공수가 많이 듭니다. 반면에, Layer의 경우에는 불필요한 로직들이 없습니다.
"무조건 이 아키텍처가 좋다!" 하는 것은 없습니다. 아키텍처를 얼마나 적절하게 사용할 수 있느냐가 중요하고 각 아키텍처에 대해서 각자만의 기준이 있다고 생각합니다.
추천할만한 책
이 글은 어떤 아키텍처를 소개하려고 쓰는 글은 아닙니다. 단지 어떤 상황에서 이 아키텍처가 좋을까 고민해보셨으면 하는 의미에서 적었습니다. 그래서 각 아키텍처에 대한 설명이 부족했습니다. 이런 저런 아키텍처에 대한 설명을 하기 위해서는 너무 오랜 시간이 필요하기 때문에, 이미 잘 설명이 된 책을 소개하고자 합니다.
1. 클린 아키텍처 by Robert C. Martin
클린 아키텍처라는 개념을 처음 알아보기에 좋은 책입니다. 비교적 난이도가 있는 책이라서 처음 읽을 때는 '그렇구나' 하면서 읽으시면 좋을 것 같습니다.
2. 만들면서 배우는 클린 아키텍처 by Tom Hombergs
위에서 소개한 클린 아키텍처를 보다 쉽게 설명하는 책입니다.
댓글
의견을 남겨주세요