NextJS

[architecture]어떻게 시행착오를 코드에 반영할 수 있을까? (multi-zones, MFA)

변기원 2024. 12. 19. 15:48

빠르게 성장하는 스타트업에게 빠르게 만들고, 배포하고, 유저의 반응을 체크하고, 빠르게 개선하는 게 중요하다는 것은 당연하다.

그 순환 사이에 시행착오를 겪으면서 이런 비즈니스를 하는 사람들에게는 이런 기능이 중요하구나, 아 이런 부분은 옵션으로 제공하면 다양한 사용자가 만족할 수 있겠구나, 이런 부분은 추상화가 되어 모듈화 할 수 있겠구나, 같은 깨달음이 생긴다.

스타트업의 개발자로서 성장하는 회사를 만들기 위해 중요한 것은 바로 이 시행착오를 통해 얻은 깨달음을 내 머리에만 넣어두는게 아니라, 코드에 적절히 녹여놔야 한다는 것이다.

입사 후 첫 프로젝트를 하며 물류업계, 특히 의약품 물류업계에 대한 지식이 생겼다. 그리고 TMS, OMS, WMS를 만들면서 이것들을 어느 부분에서 모듈화 해야 하는지 시행착오를 겪으며 깨달음이 생겼다.

하지만 안타깝게도 모놀리식한 프로젝트에서는 너무 편한 나머지 추상화가 이루어지기 전에 대뜸 구현이 되어버린 모양새이다. 누군가 나에게 와서 이번 프로젝트 하며 얻게된 지식을 결과물로 보여주세요. 하면 하나도 보여줄게 없을 것 같다.

25년의 목적은 한번 내지 두 번의 시행착오를 더 겪으며시스템을 모듈화 하고 템플릿화 하려고 한다.

그 결과물로 시행착오 끝에 알게된 지식들이 녹여진 코드가 나와야 한다.

 

그럼

1. 어떻게 해야 시행착오를 코드에 녹일 수 있을까? 
2. 한 서비스 내의 다양한 시스템을 모듈화하려면 어떻게 해야 할까? 이것이 내 고민이다.
이 요구사항을 충족하는 아키텍처를 고민해 보자

 

고민하다 보니 극단적인 두 가지 케이스를 생각해 보게 되었다.

하나는 여러 팀이 거대한 서비스를 만드는 경우이고, 또 다른 하나는 하나의 팀이 비슷한 여러 개의 작은 서비스를 만드는 경우이다.

전자를 예로 들자면 내가 애용하는 서비스인 오늘의집 같은 서비스가 있다. 이것저것 클릭해 보면 메인서비스, store, content, event, o2o 같은 모듈로 나누어진 팀이 존재하는 것 같다. 하나의 서비스 같지만, 도메인이 바뀌면서 하드링크를 이용해서 서비스가 바뀌고 있다. 후자가 바로 나와 같은 상황이다. 단일 프론트엔드 팀이 비슷하고 많은 서비스를 개발하는 팀이다.

그럼 케이스 별로 개발자들에게 어떤 불편함과 욕망이 생길지, 그래서 어떤 대책이 있는지 생각해 봤다.

 

위와 같은 불편함과 욕망이 생길 것이고 그것을 해결한 것이 요즘 많이 나오는 MFA라고 생각한다.

그럼 우리는 어떤 불편함이 있을까?

 

이런 불편함이 생길 것 같다. 그래서 내부에 코어로직과 ui패키지를 갖춘 모노레포를 만들고자 했다.

템플릿이라고 이름을 붙인 이유는 제대로 작성해서 템플릿(보일러 플레이트)처럼 만들고 싶었기 때문이다.

 

가장 처음 나의 목적이었던

1. 어떻게 해야 시행착오를 코드에 녹일 수 있을까? 
2. 서비스 내의 다양한 시스템을 모듈화 하려면 어떻게 해야 할까?

를 반영한 아키텍처를 구현하기 위해 위와 같은 구조를 상상했다. 모노레포 안에 packages/ui , packages/core를 가지고 ui패키지와 코어로직을 구현단계에서부터 추상화를 하여 시행착오를 녹이고자 했다. 모놀리식 한 구조에서는 아무래도 계속 편하게 개발하게 되는데 이것을 처음부터 라이브러리를 하나 개발한다는 느낌으로 가져가도록 구조에서부터 나누고자 했다. 독립된 환경에서 빌드되는 ui라이브러리, hooks라이브러리를 만들기 위해 충분한 고민을 거치며 이곳에서 시행착오를 쌓아가고자 했다.
services내부에서 실제 서비스가 구현되는데 내부에 tms, oms, wms 같은 프로젝트도 역시 독립적으로 Package.json을 가지고 빌드된다. 아마 대부분의 시간을 이곳에서 보내게 될 것이다.

portal은 레이아웃을 결정하고 라우팅 기능만 제공하는 포탈로서 존재한다. 이곳에서 services에서 작성된 실제 결과물을 Import 해서 보여주게 된다. 사용자 접근제어는 middleware를 통한다. 그리고 이것이 제대로 작성되면 보일러플레이트가 되어 Customizing point만 일부 수정이 되어야 한다.라고 생각했다. 그럼 실제로 구현해 보자

https://github.com/kiwonbyun/architecture-test1

 

GitHub - kiwonbyun/architecture-test1

Contribute to kiwonbyun/architecture-test1 development by creating an account on GitHub.

github.com

위 레포에서 실제로 구현해 봤다. 문제점이 있었는데, 독립적으로 빌드된 3개의 Nextjs프로젝트는 portal프로젝트와 프론트엔드 서버 측에서 적절히 통합될 수 없었다. 그래서 모든 services들이 100% 클라이언트 컴포넌트로 작성되었고, 그렇다면 이것은 서비스가 될 수 없고 일종의 ui템플릿이 될 수밖에 없었다. 대부분의 서비스 구현은 portal에서 하게 될 것이고, 그럼 보일러플레이트처럼 사용할 수 없다. 탈락

https://github.com/kiwonbyun/architecture-test2

 

GitHub - kiwonbyun/architecture-test2

Contribute to kiwonbyun/architecture-test2 development by creating an account on GitHub.

github.com

그럼 packages만 꺼내고 website에서 모놀리식 하게 구현을 하되, 각 서비스의 독립된 환경은 폴더구조와 타입모듈을 사용해서 구분하고자 했다. 하지만 역시 강제할 방법이 없기 때문에 언제든 스코프가 침범되고 상태가 넘나들면서 종속성이 생길 수 있다. 탈락

 

그럼 대체 어떻게 서비스 간 독립된 환경을 보장할 수 있을까?

그것이 바로 MFA의 주된 역할이기도 하다. 내가 MFA에 대해 설명할 때 이런 큰 부분을 간과한 것이다.

우리 조직은 MFA에 적합하진 않지만 개발하고자 하는 제품이 서비스 간 독립된 환경을 요구하기 때문에 MFA가 의미를 가질 수 있다고 생각했다. 그래서 nextjs 프로젝트를 마이크로 프론트엔드로 구성해보고자 했다. module-federation방식으로 해보고자 했으나 Nextjs app라우터 지원이 안된다. 그렇다고 13 버전으로 돌아가서 pages라우터를 사용할 순 없다. 우리 팀은 app라우터 기반에서 작업하면서 코드 컨벤션을 맞춰왔고 지속적으로 학습해 왔기 때문이다. 그럼 module-federation방식 말고 어떻게 app라우터를 사용하면서 MFA를 만들 수 있을까?

현재 찾은 답은 Multi-zones 방식으로 프로젝트를 구성하는 것이다. 일종의 마이크로 프론트엔드이다. 완벽한 마이크로 프론트엔드라고 할 순 없지만 Nextjs기반에서는 마이크로 프론트엔드 아키텍처를 요구하는 사람들의 불편함을 해소해 줄 수 있는 방법이다.

말로 하면 이해가 잘 안 되는데 비교를 해보면 알 수 있다.

 

멀티존과 마이크로 프론트엔드의 공통점

1. 여러 개의 독립적인 애플리케이션을 하나의 웹사이트로 통합한다.

2. 각 zone은 독립적으로 개발, 배포가 가능하다.


멀티존과 마이크로 프론트엔드의 차이점
1. 멀티존은 모든 프로젝트가 Nextjs를 사용해야만 한다. 마이크로 프론트엔드는 무엇을 사용하든 통합할 수 있다.

2. 멀티존은 라우팅 기반 통합방식을 사용한다. 마이크로 프론트엔드는 module-federation, web component등 다양한 통합방식이 가능하다.

이러한 공통점과 차이점이 있기 때문에 Nextjs 기반에서 마이크로 프론트엔드 아키텍처를 요구하는 사람들의 불편함을 해소해 줄 수 있는 방법이라고 표현한 것이다. 결국 우리 팀은 Next.js를 사용하고 싶어 하며, 완벽히 독립된 환경을 통합해서 사용할 수 있다는 요구사항을 만족하기 때문에 Multi-zones방식을 사용하기로 했다,

https://github.com/kiwonbyun/architecture-test3

 

GitHub - kiwonbyun/architecture-test3

Contribute to kiwonbyun/architecture-test3 development by creating an account on GitHub.

github.com


위 레포가 구현테스트이다. next.js의 rewrites 기능을 활용한 라우팅기반 통합을 테스트 한 레포지토리이다.

각 프로젝트는 3001, 3002, 3003 포트에서 독립적으로 실행되기 때문에 완전히 분리된 환경을 가진다. 즉, 개발단계부터 컨텍스트가 분리되기 때문에 고객별 커스터마이징에 걱정이 없다. 각 시스템이 의존성 없이 따로 잘 동작한다고 확신할 수 있다.

또한 모노레포 워크스페이스 안에서 packages/ui 와 packages/core를 작성해 가며 제품을 고도화하기 때문에 라이브러리를 개발하듯 추상화를 거치며 시행착오를 녹여볼 생각이다.