Turborepo vs Nx: 2026년에 멀쩡하게 쓸 수 있는 모노레포 툴은

5명짜리 팀에서 Next.js 앱 3개를 관리하다 보면 언젠가는 터진다. 우리 팀은 공유 컴포넌트 라이브러리, 디자인 토큰 패키지, API 클라이언트를 각각 별도 레포로 관리하고 있었는데, 어느 순간부터 npm linkyalc로 버텨가는 게 한계에 왔다. 버전 맞추다가 반나절 날리고, CI에서 의존성 캐시 날아가면 빌드가 12분씩 걸렸다.

그래서 올해 1월, 2주짜리 스파이크를 계획했다. 1주는 Turborepo, 1주는 Nx. 같은 코드베이스를 마이그레이션해보면서 실제로 어떤 차이가 있는지 직접 겪어보려고.

결론부터 말하면 — 나는 Turborepo를 골랐다. 근데 생각보다 훨씬 아슬아슬한 선택이었다.

Turborepo: 진입이 쉬운 건 맞는데, 그 이후가 문제

Turborepo는 진입 장벽이 낮다. 이건 사실이다. npx create-turbo@latest로 시작하면 10분 안에 기본 파이프라인이 돌아가는 걸 볼 수 있다. turbo.json 설정도 직관적이다:

{
  "$schema": "https://turbo.build/schema.json",
  "tasks": {
    "build": {
      "dependsOn": ["^build"],
      "outputs": [".next/**", "dist/**"]
    },
    "lint": {
      "dependsOn": ["^lint"]
    },
    "test": {
      "cache": false
    }
  }
}

이 정도면 웬만한 Next.js 멀티앱 세팅은 커버된다. 내가 마이그레이션한 레포에서도 기존 package.json 스크립트를 거의 그대로 썼다. 파괴적인 변경이 없다는 게 Turborepo의 가장 큰 강점이다.

Remote caching도 효과적이었다. Vercel Remote Cache를 붙이니까 CI 빌드 시간이 12분에서 3분 40초로 줄었다. 솔직히 말하면, 이건 Turborepo의 기능이라기보다는 “캐시를 제대로 설정했다”의 효과가 크다. Nx도 똑같이 한다.

며칠 쓰다 보니 한계가 보이기 시작했다.

태스크 의존성 그래프의 표현력이 첫 번째 문제다. Turborepo는 태스크를 패키지 단위로만 묶는다. apps/webbuildpackages/uibuild에 의존한다는 건 잘 표현하는데, 더 세밀한 제어 — 특정 파일 변경 시에만 특정 태스크를 재실행한다든가 — 를 하려면 inputs 설정을 꽤 많이 써야 한다. 못 하는 건 아닌데, 규모가 커지면 turbo.json이 슬슬 무거워진다.

두 번째는 코드 생성 기능이 없다는 것. 새 패키지를 추가할 때마다 package.json, tsconfig.json, index.ts를 손으로 복붙해야 한다. 팀이 작을 때는 괜찮은데, 새 팀원이 왔을 때를 생각하면 컨벤션이 흐트러질 게 눈에 보인다.

Next.js 중심 소규모 팀에서 지금 당장 뭔가 돌아가야 한다면 — Turborepo다. 설정 30분이면 된다.

Nx: 강력한데, 처음 3일이 고비

Nx는 다르다. 처음 npx create-nx-workspace@latest 실행했을 때부터 질문이 쏟아진다. Preset은 뭐로 할지, integrated냐 package-based냐, Nx Cloud 쓸지. 나는 Turborepo에서 넘어온 코드베이스를 package-based 모드로 시작하고 나중에 integrated로 옮기려 했는데 — 이게 생각보다 큰 차이다.

integrated 워크스페이스는 Nx가 더 많은 걸 제어한다. project.json이 각 패키지의 태스크를 정의하고, executor가 실제 빌드 명령을 감싼다. 처음엔 왜 이렇게 추상화를 쌓냐고 생각했다. package.json 스크립트로 충분한데.

3일째 되던 날 이해했다.

nx graph 명령어로 태스크 실행 그래프를 시각화했는데, 우리 코드베이스에 순환 의존성이 있다는 걸 발견했다. packages/authpackages/api-client를 임포트하고, packages/api-clientpackages/auth의 타입을 임포트하고 있었던 것. TypeScript는 그냥 컴파일했다. 런타임에도 문제없었다. 근데 실제로 존재하는 순환 의존성이었고, 이게 나중에 번들 사이즈 문제로 나타날 수 있었다. Turborepo였으면 이걸 발견하지 못했을 것 같다.

Nx의 generator 시스템도 실제로 써보면 유용하다. 새 라이브러리를 추가할 때:

nx generate @nx/js:library packages/shared-utils \
  --bundler=rollup \
  --unitTestRunner=vitest \
  --importPath=@myapp/shared-utils

이 한 줄이 package.json, tsconfig.json, project.json, 기본 index.ts, vitest 설정까지 다 만들어준다. 팀 전체가 같은 generator를 쓰면 자연스럽게 컨벤션이 통일된다.

다만 학습 곡선이 진짜 가파르다. executorgenerator의 차이, project.json vs package.json 중 어디에 태스크를 정의해야 하는지, affected 커맨드가 어떤 기준으로 변경 사항을 판단하는지 — 이것들을 이해하는 데 이틀이 걸렸다. 문서가 없는 게 아니라 너무 많아서 어디서부터 읽어야 할지 모르는 그 상황.

내가 예상 못 한 것들: 버전 버그와 가격 정책 변화

Turborepo를 1주 쓰고 Nx로 넘어가면서 몇 가지 예상과 다른 점들이 있었다.

Turborepo가 Vercel에 인수된 이후 방향성이 조금 바뀌었다. v2.x로 오면서 --filter 플래그가 훨씬 직관적이 됐고, watch 모드도 안정화됐다. 근데 개발 활동을 보면 Vercel 생태계 최적화 쪽에 집중하는 느낌이 든다. Next.js 앱 위주 팀에게는 당연히 좋은데, 우리처럼 Vite + Express + Next.js가 섞인 팀에게는 편향된 느낌이 없지 않다.

Nx는 반대로 방향이 너무 넓다. React Native, Angular, Rust 플러그인까지 있다. 처음엔 이게 장점인 줄 알았는데, 그만큼 각 플러그인의 품질이 들쭉날쭉하다. @nx/next 플러그인은 잘 됐는데, @nx/vite 쪽은 설정 충돌로 두 시간 날렸다. GitHub Issues 뒤져보니 [email protected]에서 Vite 5.x랑 충돌하는 버그가 있었다. 패치는 20.4.3에서 났는데, 나는 20.4.1을 쓰고 있었던 것 — 금요일 오후에 발견했고, 버전 올리고 퇴근을 두 시간 늦게 했다.

Nx Cloud 가격 정책도 달라졌다. 2025년 말부터 소규모 팀에는 free tier가 있는데, CI/CD 병렬 실행 수에 제한이 생겼다. 팀이 커지면 어차피 유료로 가야 한다. Turborepo Remote Cache도 Vercel 플랫폼에 묶이는 건 마찬가지지만, 셀프 호스팅 옵션(turbo-remote-cache 같은 오픈소스 서버)이 더 간단하다. Nx 셀프 호스팅은 문서가 있긴 한데 설정이 만만치 않다.

그런데 — 이건 솔직히 예상 못 했는데 — nx affected 커맨드의 정교함은 진짜 인상적이었다. 변경된 파일을 기준으로 영향받는 패키지만 빌드하고 테스트하는 건 Turborepo도 하는데, Nx가 더 세밀하다. 레포가 커질수록 이 차이가 CI 비용으로 직결된다.

결국 Turborepo를 골랐다, 이유는 하나

나는 Turborepo로 갔다. 우리 팀 규모와 코드베이스 복잡도에서 Nx의 추가 학습 비용이 얻는 이점보다 크다고 판단했다.

5명 팀, Next.js 앱 위주, 공유 패키지 7개 — 이 스케일에서 Nx의 generator나 executor 추상화는 오버엔지니어링에 가깝다. Nx 그래프 시각화가 멋지긴 했는데, 순환 의존성은 ESLint import/no-cycle 룰로도 잡을 수 있다. Nx를 써야 할 결정적인 이유를 못 찾았다.

다만 이 결정은 “영원히 Turborepo”가 아니다. 팀이 10명을 넘어가거나, 백엔드 Node.js 서비스까지 같은 모노레포에 넣어야 하는 상황이 오면 다시 볼 것 같다. Nx 21이 올해 중반에 나온다는 로드맵이 있는데, project.json 없이도 작동하는 모드를 강화한다고 한다. 그게 제대로 되면 진입 장벽이 많이 낮아질 것 같아서 관심 있게 지켜보고 있다.

팀이 5-7명이고 Next.js 위주라면, Turborepo로 충분하다. 지금 당장 돌아가는 게 필요한 팀에겐 이게 맞다. 반대로 팀이 10명을 넘어가거나 프레임워크가 뒤섞여 있고, 신규 입사자가 왔을 때 컨벤션 교육이 반복적으로 문제가 된다면 — 그 고통이 Nx 초반 학습 비용보다 크다.

100명짜리 조직에서 Turborepo를 억지로 쓰고 있다면 그건 넘어가야 할 시점이 지난 거고, 스타트업 4명이 Nx 설정하느라 이틀 쓰고 있다면 그것도 문제다. 둘 다 2026년 기준으로 충분히 쓸 만하다. 뭘 골라도 크게 틀리지 않는다. 다만 툴을 고르기 전에 팀 규모와 6개월 후 팀 규모를 먼저 써놓고, 그 숫자를 보면서 결정하면 된다.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top