2022년 12월 팀 모노레포 관리 도구로 도입한 Nx(v15.3.x)를 6개월 넘게 사용한 후기를 공유합니다.
장점은 이미 앞선 시리즈에서 다루었기에 사용하면서 불편했던 점 위주로 서술합니다. Nx의 공식문서도 참고하시면 좋습니다.
Nx 초기 환경 구축 당시, 각 패키지 별로 독립적으로 의존성 버전 관리를 할 경우 파편화되기 쉽고 추후 유지보수하기 힘들다는 점을 고려하여 integrated repos로 구성했습니다.
Nx는 single version policy를 매우 권장합니다. 종속성의 버전 마이그레이션 시 한 번에 할 수 있으며, 실질적인 코드 공유가 가능하기 때문입니다. 만약 모노레포 내 두 패키지가 다른 버전의 React를 사용한다면, 두 패키지가 공유하는 코드에는 React의 무슨 버전을 기준으로 작성해야 할까요? 기준을 정한다해도 런타임 에러가 발생하기 쉽습니다. 또한 root node_modules에 설치된 종속성과 특정 패키지의 node_modules에 설치된 종속성의 버전이 다른 경우, 로컬 개발 시 문제가 없었지만 종속성이 번들링된 버전인 상용 환경에서 문제가 발생하기도 합니다.
하지만 저희 팀의 경우 독립적인 의존성 관리가 필요했습니다. 이미 패키지간 의존성 버전이 매우 상이했기 때문입니다. 이로 인해 특정 패키지에서 최신 버전의 라이브러리를 사용하고 싶은 경우에도 (e.g., react v18) 다른 프로젝트로 인해 버전 업그레이드를 못하는 경우가 잦았습니다. 물론 이는 Nx의 문제라기보단 표준화해야할 것과 독립적이어야할 것에 대한 구분을 명확하게 하지 않고, 모노레포 구축한 점이 근본적인 문제입니다. Nx 역시 package-based repos로 구성할 수 있었기에 저희 팀은 integrated repos에 package-based 프로젝트를 포함하는 hybrid 방식으로 구성을 변경하였습니다.
Nx는 프레임워크 성격이 강하고, Nx가 유도한 사용법 그대로 사용해야 했습니다.
affected
명령어를 사용해 변경사항에 대해 영향받는 패키지를 자동으로 선별해주고, 빌드 속도를 단축시켜줍니다. 별도 설정 없이 빌드 시간을 단축시켜주는 점은 굉장히 편리했으나, nx는 편리한 기능을 plugins를 통해서 지원하고 plugin을 사용하기 위해선 package.json
대신 project.json
을 통해 프로젝트 설정을 해야 합니다. vscode extension을 제공하고, executors와 generators를 포함하는 Nx plugins를 사용할 수 있다는 점은 DX를 향상시켰습니다.
하지만 Integrated repos로 구성하는 경우, Nx는 project.json에서 Nx executors를 사용하여 tasks(e.g., build, test)를 정의해야 합니다. 문제는 Nx executors를 사용할 경우 디버깅이 까다로워집니다. 설정값과 실행하는 커맨드가 숨겨져 있기 때문입니다. 물론 executor를 사용하더라도 커맨드를 커스텀할 수 있고 특정 프레임워크 플러그인(e.g., @nx/react)의 generators를 사용하지 않고 패키지를 생성하면 설정값이 있는 그대로 드러납니다. 다만 이처럼 일일이 커스텀한다면 굳이 Nx plugins를 사용해야할 필요가 없다고 생각합니다.
The cache restoration Turborepo provides is likely to be fast enough for a lot of small and mid-size repos.