모노레포와 마이크로서비스

atesi·2023년 9월 8일
0

Retrograde

목록 보기
1/3

이번 시리즈는 Retrograde 토이 프로젝트에 관한 첫번째 이야기로 프로젝트 아키텍처에 관한 생각을 담은 글입니다.

당신은 시작하는 프로젝트 아키텍쳐를 왜 모노레포로 구성했나요?

우선 모노레포 정의를 내려봅니다.

모노레포는 단일 저장소에 여러 서비스를 구성한 것을 말합니다.

처음엔 프론트와 백엔드의 레포를 하나에서 관리하면 빌드 및 배포가 편해질 것이라는 단순한 생각에서 도입을 결정하게 됩니다. 진행하는 토이 프로젝트를 구성하는데 소스를 공유하고 하나의 레포에서 구성한다면 모노레포라고 생각을 하게 됩니다.

맞는 말입니다. 그러나 제가 위의 모노레포 정의에 대해 가장 혼동했던 것은 서비스에 대한 부분입니다. 서비스라고 규정했지만 많은 곳에서 앱 혹은 프로젝트라고 정의하고 있습니다.

대인관계에서 호감도는 만나고 2~3분 안에 결정된다고 합니다. 호감도라는 정보가 저에게는 모노레포의 정보로 변했을 뿐입니다. 토이프로젝트를 시작하기 위해 모노레포의 도입을 시도하는 시점에서 저의 모노레포의 스케일에 대한 정보가 결정되었습니다.

회의 중 프로젝트의 확장에 대해 이야기가 나왔습니다.

"작성한 API를 사용해서 다른 프로젝트를 연결할 수 있나요?"

이 질문에 관한 이런저런 논점을 제외하고 다른 프로젝트에 대한 부분에 초점을 맞춰 봅니다.

선입된 정보를 바꾸려면 많은 시간이 필요합니다. 모노레포의 정의에서 apps, projects, services등 많은 곳에서 용어를 혼용하여 사용하고 있으며 개인적인 확증편향이 발생해 정의에 적힌 서비스에 대한 확장을 배제했습니다. 하나의 모노레포에는 하나의 주제에 대한 서비스를 제공 해야 한다고 해석했습니다.

예를 들어 A라는 To-do 서비스를 구성하는데 하나의 저장소에 프론트와 백엔드가 같은 리소스를 사용하면 모노레포라고 할수 있겠죠. 이 저장소에 B라는 Chat 서비스를 추가하여 리소스를 공유해도 모노레포라고 할 수 있습니다. 당연한 말처럼 보이지만 당시에는 받아들이지 못했습니다.

잘못된 정보를 바로잡았습니다. 다음으로 넘어가겠습니다.

하나의 레포지토리에 여러 프로젝트를 구성하면 모노레포일까요?

코드 콜로케이션(code collocation)과는 다릅니다. 모노레포를 단순히 구현하는 방법의 하나는 코드 콜로케이션입니다. 이는 여러 저장소의 모든 코드를 동일한 저장소에 합친다는 것을 의미합니다.

이 방법은 Monolithic에 가깝다고 볼 수 있습니다. 모든 어플리케이션이 하나의 모듈로 캡슐화되어 서비스를 제공하는 형태입니다.

언뜻 보면 모든 코드가 단일 저장소에 있다는 점에서 혼동 가능성이 있습니다. 그리고 여러 프로젝트가 한 모노리틱에서 구성될 수 있습니다.

모노리스에서는 모든 코드가 한곳에 있으며 기능을 추가하고 구성 요소를 재사용하기가 쉽습니다. 모든 개발자는 필요에 따라 코드의 모든 부분에 기여할 수 있습니다. 무엇보다도 모노리스의 모든 코드는 단일 단위로 테스트되며 모든 구성요소가 패키지 되어 호환성 문제가 해결된 단일 단위로 배포됩니다.

위의 모노리스의 특징 중 모노레포와 명확히 구별되는 점은 개별 프로젝트나 구성 요소를 개별적으로 배포할 수 있다는 점입니다.

다음은 모노레포 도구에 관해 이야기해 보겠습니다.

Nx와 Turbo를 비교함에 모노레포를 처음 접근함에 Nx가 제공해주는 완성된 구조를 이용하는 편이 좋아 보였고 비교적 최근에 만들어진 Turbo에 비해 Nx는 많은 레퍼런스가 존재할 것이라는 판단이 Nx를 이용하게 한 주요한 요인이 되었습니다.

실제로 Nx는 여러 모노레포를 위한 도구 중 가장 많은 편의성을 제공하는 것으로 알려져 있습니다(1)^{(1)}. 그러나 실제로 프로젝트를 진행하면서 사용한 편의성은 아직 많지 않습니다. 많은 편의성을 제공하는 것은 서비스가 무거워진다는 것을 의미하며 완성된 구조를 제공한다는 것은 유연하지 않다는 것을 의미합니다. Nx를 이용하여 프로젝트를 시작했을 때 불필요한 설정 등을 사용해야 한다는 점은 매력적이지 않게 느껴집니다.

어떠한 도구 사용에 당연한 말이지만 '선택에 있어서 절대적인 것은 없다.' 입니다.

다음은 마이크로서비스 입니다. 마이크로서비스는 각각의 서비스를 작은 단위의 독립적인 상태로 구성하는 것을 말합니다.

모노레포에서 마이크로서비스를 구성하면서 가장 고민했던 부분은 패키지 의존성 관리 부분입니다. 단일 package.json을 이용하여 프로젝트의 의존성을 확보하는 모노레포와 각각의 서비스를 독립적인 상태로 유지해야하는 마이크로서비스간 충돌이 필연적으로 발생하게 되었습니다.

실제로 모노레포에 구성된 마이크로서비스를 쿠버네티스 환경에 배포 하기 위해 모노레포가 지향하는 의존성 관리가 마이크로서비스 아키텍처 구축에 있어 발목을 잡았습니다. 독립적으로 배포 하기 위해 각각의 서비스 내에 설정파일을 구성했고 cloudbuild를 이용한 도커파일 빌드 시 상위 디렉토리를 읽을 수 없는 점이 root에 위치한 package.json을 이용한 의존성 관리 기법을 활용하는데 어려움을 겪었습니다.

반대로 제가 구성한 각 마이크로서비스는 ORM으로 Prisma를 사용하고 있습니다. 각 서비스에서 반복적으로 구성할 필요를 줄이고 한곳에서 구성한 Prisma를 각 서비스에서 공유하여 위에 언급한 의존성 문제를 해결한다면 모노레포를 이용한 프로젝트 구성에 힘을 실어 주게 됩니다.




참고
monorepo.tools
Nx DOCS
Monolithic to Microservices Architecture with Patterns & Best Practices
모던 프론트엔드 프로젝트 구성 기법(1)^{(1)}

profile
Action!

0개의 댓글