Skip to content

필사 모드: 빌드 시스템 & 모노레포 툴 2026 완벽 가이드 - Bazel 8 · Pants 2 · Buck2 · Nx 20 · Turborepo 2 · Moon · Lerna 8 · Rush · pnpm Workspaces 심층 분석

한국어
0%
정확도 0%
💡 왼쪽 원문을 읽으면서 오른쪽에 따라 써보세요. Tab 키로 힌트를 받을 수 있습니다.
원문 렌더가 준비되기 전까지 텍스트 가이드로 표시합니다.

프롤로그 — 빌드 시스템은 왜 다시 뜨거워졌나

2026년 어느 회사의 플랫폼 회의.

주니어: "JS 모노레포라 Turborepo면 충분하지 않나요?"

시니어: "그럼 백엔드 Go랑 데이터팀 Python은 어떻게 한 번에 빌드해?"

주니어: "...아."

이 짧은 대화에 빌드 시스템의 2026년이 들어있다. 한쪽엔 **언어별 도구**(cargo, gradle, npm 스크립트)가 있고, 다른 한쪽엔 **폴리글랏**(Bazel, Buck2, Pants)이 있다. 그리고 그 사이에 `Nx`, `Turborepo`, `Moon` 같은 **태스크 러너 + 캐시** 계열이 끼어든다.

이 글은 2026년 5월 기준의 전체 지형도를 한 번에 정리한다. Bazel 8의 Bzlmod 기본화, Buck2 OSS 안착, Pants 2의 점유율, Nx 20과 Turborepo 2의 경쟁, Moon의 부상, Gradle 8.10 / Maven 4 / sbt 1.10의 자바·스칼라 진영까지. 그리고 한국·일본 빅테크가 실제로 무엇을 쓰는지까지.

1장 · 2026년 빌드 시스템 지도 — 4개 축으로 나누기

빌드 시스템이라는 단어 하나에 너무 많은 것들이 섞여 있다. 정리하는 가장 쉬운 방법은 두 개의 축으로 나누는 것이다.

| 축 1 / 축 2 | 단일 언어 | 폴리글랏 |

| --- | --- | --- |

| 로컬 캐시만 | cargo, npm, go build | GNU Make, just, Task |

| 원격 캐시/실행 | Gradle + Develocity, Nx Cloud, Turborepo Remote Cache | Bazel, Buck2, Pants |

세로축은 **언어 지원 범위**, 가로축은 **캐시·분산 수준**이다. 2026년의 주요 흐름은 오른쪽 아래(폴리글랏 + 원격) 칸이 빠르게 채워지고 있다는 점이다. 그리고 그 칸 안에서도 두 진영이 갈린다 — **Bazel/Buck2/Pants** 진영의 "선언적 그래프 + 해석적 BUILD 파일" 과 **Nx/Turborepo/Moon** 진영의 "JSON/YAML 설정 + 영향 받은 프로젝트만 실행".

선택의 출발점은 단순하다.

1. **단일 언어 + 작은 팀** → 그 언어 기본 툴 (cargo, gradle, npm).

2. **단일 언어 + 큰 모노레포** → 그 언어 기본 + 원격 캐시 (Develocity, Nx Cloud).

3. **JS/TS 위주 + 다중 패키지** → pnpm workspaces / Nx / Turborepo.

4. **폴리글랏 + 큰 규모** → Bazel / Buck2 / Pants.

2장 · 모노레포 vs 폴리레포 — 2026년의 답

이 논쟁은 거의 정리됐다. 답은 "둘 다 쓴다, 다만 모노레포가 기본값이 됐다" 다.

**모노레포의 장점**: atomic 변경 (한 PR로 라이브러리·서비스·테스트 동시 변경), 단일 의존성 그래프, 공유 인프라(빌드·CI·린트), 검색·리팩터링이 IDE 하나로 끝남.

**폴리레포의 장점**: 권한 격리, 빌드 시간 격리, 팀별 자율성, 작은 리포의 단순함.

2026년 절충: **"한 회사 안에 여러 모노레포"**. 예컨대 `platform-monorepo`(인프라·플랫폼), `product-monorepo`(서비스), `data-monorepo`(파이프라인). 각각은 모노레포지만 회사 전체로 보면 폴리레포. Google/Meta/Microsoft 일부 조직이 이 패턴을 쓴다. 작은 회사라면 그냥 하나의 모노레포가 답이다.

`Trunk-based development` + `feature flags` + `change detection`(아래 21장) 이 세 가지가 결합되면 모노레포의 단점 대부분이 사라진다.

3장 · Bazel 8 — 폴리글랏 빌드의 표준

Bazel은 Google이 내부 빌드 시스템 Blaze를 OSS로 푼 것이다. 2026년 5월 현재 안정 버전은 **Bazel 8.x**, LTS는 7.x. 핵심 변화는 **Bzlmod**(MODULE.bazel) 가 기본이 되고 WORKSPACE 모드가 deprecate 된 것이다.

라이선스는 Apache 2.0. 사용처는 Google, X(구 Twitter), Stripe, Pinterest, Spotify, Snap, Dropbox, Coupang, Mercari 등.

핵심 개념.

- **`BUILD.bazel`**: 디렉터리당 한 개, 그 디렉터리의 빌드 타겟 선언.

- **`WORKSPACE` / `MODULE.bazel`**: 리포 루트, 외부 의존성·툴체인 선언.

- **Starlark**: Python 부분집합, 빌드 규칙을 작성하는 언어.

- **rules**: 언어별 규칙 집합 (`rules_go`, `rules_python`, `rules_js`, `rules_rust`, `rules_java`).

- **sandbox**: 모든 액션을 격리된 디렉터리에서 실행, hermetic 보장.

- **remote cache / remote execution**: 액션 결과를 해시로 캐시, 결과 없으면 원격 워커에서 실행.

가장 단순한 Go 바이너리 빌드.

BUILD.bazel

load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")

go_library(

name = "hello_lib",

srcs = ["main.go"],

importpath = "example.com/hello",

)

go_binary(

name = "hello",

embed = [":hello_lib"],

)

bazel build //cmd/hello:hello

bazel test //...

bazel query 'deps(//cmd/hello:hello)' | head

Bzlmod 의존성 선언.

MODULE.bazel

module(name = "myrepo", version = "0.1.0")

bazel_dep(name = "rules_go", version = "0.55.0")

bazel_dep(name = "gazelle", version = "0.41.0")

go_deps = use_extension("@gazelle//:extensions.bzl", "go_deps")

go_deps.from_file(go_mod = "//:go.mod")

use_repo(go_deps, "com_github_pkg_errors")

Bazel의 강점은 **그래프 + 캐시 + 원격 실행**이 깊게 통합되어 있다는 것이다. 약점은 학습 곡선과 BUILD 파일을 손으로 쓰는 부담 (Gazelle 같은 자동 생성기로 완화).

4장 · Buck2 (Meta) — Rust로 다시 쓴 Buck

Buck1은 Meta가 2013년에 만든 Bazel 사촌. 2023년 Meta는 이를 Rust로 처음부터 다시 쓰고 OSS로 풀었다 — **Buck2**. 2026년 현재 Meta 사내 빌드의 표준이고, OSS 사용처도 늘었다.

Bazel과의 비교.

| 항목 | Bazel | Buck2 |

| --- | --- | --- |

| 구현 | Java | Rust |

| 설정 언어 | Starlark | Starlark |

| 액션 그래프 | rule 평가 시 결정 | Dynamic Dependencies로 빌드 중 결정 가능 |

| 원격 실행 | RE API (BuildBuddy, EngFlow) | RE API (BuildBuddy, EngFlow) |

| 라이선스 | Apache 2.0 | Apache 2.0 |

| 주요 사용처 | Google, X, Stripe | Meta, Discord |

가장 큰 차이는 **dynamic dependencies**. Bazel은 BUILD 평가 → action graph → 실행이 분리되어 있어 빌드 도중 그래프가 바뀔 수 없다. Buck2는 일부 노드에서 빌드 중 추가 입력을 선언할 수 있어 OCaml `.ml`/`.mli`처럼 컴파일 결과에 의존하는 의존 관계를 자연스럽게 표현한다.

BUCK

load("@prelude//rules.bzl", "cxx_binary", "cxx_library")

cxx_library(

name = "hello_lib",

srcs = ["hello.cc"],

headers = ["hello.h"],

)

cxx_binary(

name = "hello",

srcs = ["main.cc"],

deps = [":hello_lib"],

)

buck2 build //cpp/hello:hello

buck2 test //...

buck2 cquery 'deps(//cpp/hello:hello)'

Bazel에서 마이그레이션할 가치가 있을까? 보통은 없다. **신규 폴리글랏 모노레포 + Meta 영향권 + 동적 의존성이 정말 필요**한 경우에만 고려.

5장 · Pants 2 — Python 모노레포의 사실상 표준

Pants v1은 2014년 Twitter가 만든 Java/Scala 빌드 시스템이었다. v2부터는 **Toolchain Labs**가 처음부터 다시 만들어 **Python 우선 폴리글랏**으로 포지셔닝한다. 2026년 5월 안정 버전 **Pants 2.27**.

라이선스 Apache 2.0, 사용처 Slack, IBM, Pico, Toolchain.

Pants 2의 차별점.

- **Python-first**: `pytest`, `mypy`, `ruff`, `pyright`, `black`, `flake8` 등 Python 도구 일급 지원.

- **자동 의존성 추론**: import 그래프를 분석해 BUILD 파일에 deps를 자동 추가.

- **Lockfile-aware**: PEP 621/pyproject.toml과 lockfile 통합.

- **Remote caching**: BuildBuddy, EngFlow 호환.

pants.toml

[GLOBAL]

pants_version = "2.27.0"

backend_packages = [

"pants.backend.python",

"pants.backend.python.lint.ruff",

"pants.backend.python.typecheck.mypy",

"pants.backend.docker",

]

[python]

interpreter_constraints = ["==3.12.*"]

src/python/myapp/BUILD

python_sources(name="lib")

python_tests(name="tests", dependencies=[":lib"])

pex_binary(name="bin", entry_point="myapp.main:main")

pants tailor :: # BUILD 파일 자동 생성

pants lint test check :: # 전체 lint/test/typecheck

pants --changed-since=main test # 변경된 것만

pants package src/python/myapp:bin

Python 모노레포라면 Pants 2가 거의 디폴트 선택지다. mypy/ruff 캐시까지 처리해 주는 게 결정적이다.

6장 · 원격 실행 백엔드 — BuildBuddy / EngFlow / NativeLink

Bazel·Buck2·Pants 모두 **Remote Execution API**(REAPI) 라는 gRPC 표준을 따른다. 캐시(action result, CAS)와 실행(worker)을 분리해서, 클라이언트는 캐시 미스면 원격 워커에 실행을 위임한다.

2026년 주요 백엔드.

| 제품 | 회사 | 특징 |

| --- | --- | --- |

| BuildBuddy | BuildBuddy Inc | 오픈코어, UI 좋음, GCP/AWS SaaS + 셀프호스트 |

| EngFlow | EngFlow | 엔터프라이즈 포커스, Spotify·Tesla 도입 |

| NativeLink | TraceMachina | OSS, Rust, 학습 단계지만 빠름 |

| Buildbarn | OSS | 오픈소스, 직접 운영 |

BuildBuddy 설정 예 (`.bazelrc`).

build --bes_results_url=https://app.buildbuddy.io/invocation/

build --bes_backend=grpcs://remote.buildbuddy.io

build --remote_cache=grpcs://remote.buildbuddy.io

build --remote_executor=grpcs://remote.buildbuddy.io

build --remote_header=x-buildbuddy-api-key=YOUR_API_KEY

이 한 블록만으로 캐시 + 실행 + 빌드 이벤트 스트림(BES, 웹 UI에서 빌드 추적) 이 켜진다. 큰 모노레포에선 빌드 시간이 5~10배 줄어드는 경우가 흔하다.

7장 · Nx 20 — JS/TS 모노레포의 강자

Nx는 Nrwl(현 Nx)가 만든 JS/TS 모노레포 도구다. 2026년 5월 현재 Nx 20.x. 라이선스 MIT, 클라우드 호스팅은 Nx Cloud(유료 SaaS).

Nx의 핵심 가치 두 가지.

1. **로컬·원격 캐시**: 태스크 결과(빌드, 테스트, 린트 출력)를 해시로 캐시.

2. **affected**: git diff 기반으로 변경 영향을 받은 프로젝트만 실행.

npx create-nx-workspace@latest myorg --preset=ts

cd myorg

nx g @nx/react:app web

nx g @nx/node:app api

nx g @nx/js:lib shared

// nx.json

{

"tasksRunnerOptions": {

"default": {

"runner": "nx-cloud",

"options": {

"cacheableOperations": ["build", "lint", "test", "e2e"],

"accessToken": "YOUR_NX_CLOUD_TOKEN"

}

}

},

"namedInputs": {

"default": ["{projectRoot}/**/*"],

"production": ["default", "!{projectRoot}/**/*.spec.ts"]

}

}

nx run-many -t build # 모든 프로젝트 빌드

nx affected -t test # 변경 영향 프로젝트만 테스트

nx graph # 프로젝트 의존성 그래프 시각화

nx release # 버전·changelog·publish

Nx 20의 새 기능: **Atomizer**(테스트 분할), **Custom Conformance Rules**(모노레포 규칙 검사), **Self-Healing CI**(실패한 e2e를 자동 재시도+분석). Lerna 인수 후 통합이 거의 완료되어 Lerna는 Nx의 별칭에 가깝다.

8장 · Turborepo 2 — Vercel의 JS 모노레포 도구

Turborepo는 2021년 Jared Palmer가 만든 모노레포 빌드 시스템. 2022년 Vercel 인수. 2024년 **Turborepo 2.0**에서 핵심 부분이 Rust로 다시 쓰였고, 2026년 현재 2.x가 안정.

Nx와의 비교.

| 항목 | Nx | Turborepo |

| --- | --- | --- |

| 철학 | "스마트한" 워크스페이스 (생성기·플러그인·그래프) | "단순한" 태스크 러너 + 캐시 |

| 설정 | nx.json + project.json | turbo.json |

| 코드 생성 | 풍부한 generator | 거의 없음 |

| 캐시 | 로컬 + Nx Cloud | 로컬 + Remote Cache (Vercel 기본 무료, 셀프호스트 가능) |

| 분산 실행 | Nx Agents | 없음 (CI shard로 우회) |

| 언어 | JS/TS 중심, 일부 폴리글랏 | JS/TS 전용 |

| 학습 곡선 | 중상 | 낮음 |

// turbo.json

{

"$schema": "https://turbo.build/schema.json",

"tasks": {

"build": {

"dependsOn": ["^build"],

"outputs": [".next/**", "!.next/cache/**", "dist/**"],

"inputs": ["src/**", "package.json", "tsconfig.json"]

},

"test": { "dependsOn": ["^build"], "outputs": ["coverage/**"] },

"lint": { "outputs": [] },

"dev": { "cache": false, "persistent": true }

}

}

turbo run build # 전체 빌드 (캐시 적중분 skip)

turbo run test --filter=...[origin/main] # 변경분만

turbo run dev --parallel # 개발 서버 병렬

turbo prune --scope=web # 특정 앱만 추려서 Docker 빌드

Turborepo의 가장 큰 무기는 **단순함과 Vercel 통합**. CI에서 `TURBO_TOKEN` + `TURBO_TEAM` 환경변수만 주면 Vercel Remote Cache가 자동으로 켜진다. Next.js·Remix 위주의 팀은 Turborepo가 가장 마찰이 적다.

9장 · Moon (moonrepo) — Rust로 만든 폴리글랏 다크호스

Moon은 2022년 등장한 Rust 기반 빌드 시스템. 만든 사람은 Lerna·Yarn 출신의 Miles Johnson. 라이선스 MIT. JS/TS·Python·Rust·Go·Deno·Bun을 한 도구로 묶는 게 목표.

Nx/Turborepo와 다른 점.

- **언어 무관**: `lang.toml`로 toolchain (Node, Deno, Bun, Rust, Python) 버전 핀.

- **Project graph**: Bazel처럼 디렉터리 단위, 하지만 설정은 YAML.

- **Affected**: Nx와 동일한 컨셉.

- **Mise 통합**: 버전 매니저 Mise와 결합해 toolchain 부트스트랩.

.moon/workspace.yml

projects:

- 'apps/*'

- 'packages/*'

vcs:

manager: 'git'

defaultBranch: 'main'

runner:

cacheLifetime: '7 days'

archivableTargets: ['build', 'test']

apps/web/moon.yml

language: 'typescript'

type: 'application'

dependsOn:

- 'shared'

tasks:

build:

command: 'next build'

outputs: ['.next']

test:

command: 'vitest run'

moon run web:build

moon ci # 변경 영향 받은 모든 태스크

moon dep-graph

Moon은 아직 작지만, **Rust 속도 + 폴리글랏 + YAML 설정** 조합이 매력적이다. Bazel은 부담스럽고 Turborepo는 JS 전용이라 답답한 팀이 노릴 만하다.

10장 · Lerna 8 · Rush · pnpm workspaces — JS 모노레포 3 가지 길

여전히 가벼운 JS 모노레포 옵션이 셋 있다.

**Lerna 8**: 2022년 Nrwl이 인수해 사실상 Nx의 일부가 됐다. 새 프로젝트라면 그냥 Nx를 직접 쓰는 게 낫지만, 기존 Lerna 리포는 Nx 캐시·affected를 그대로 받을 수 있다.

// lerna.json

{ "version": "independent", "npmClient": "pnpm", "useNx": true }

lerna run build --since=origin/main

lerna publish

**Rush (Microsoft Rush Stack)**: pnpm 위에 강한 정책(엄격한 phantom dependency 차단, 변경 파일 검사) 을 얹은 도구. Microsoft, Microsoft Office Online, Azure 일부에서 사용. 큰 JS 모노레포의 엄격함이 필요할 때.

rush install

rush build

rush change # PR 전 변경 파일 작성

rush publish

**pnpm workspaces (9.x)**: 가장 단순. `pnpm-workspace.yaml` + `package.json`의 `workspaces` 필드. 캐시·affected는 없지만 작은 모노레포(20개 미만 패키지) 에 적합.

pnpm-workspace.yaml

packages:

- 'apps/*'

- 'packages/*'

pnpm install

pnpm -r build # 모든 워크스페이스 빌드

pnpm --filter=@org/web build # 특정 패키지만

pnpm --filter='...[origin/main]' test # 변경 영향만 (pnpm 9+)

선택 가이드: **작은 팀 + JS 전용 + 단순 선호** → pnpm workspaces. **중대형 + Vercel 친화** → Turborepo. **중대형 + 풍부한 도구·정책** → Nx. **대형 + 엄격 정책 + MS 친화** → Rush.

11장 · 자바·코틀린 진영 — Gradle 8.10 + Maven 4

JVM은 자체 빌드 도구 생태계가 두텁다. 2026년 5월 기준 안정 버전.

**Gradle 8.10+**: Groovy/Kotlin DSL, 의존성 관리, 멀티 프로젝트. 핵심 캐시 기능 두 가지.

- **build cache**: 태스크 결과 캐시 (로컬 + 원격).

- **configuration cache**: 빌드 설정 단계 결과 캐시 (대형 프로젝트에서 수 초~수십 초 절약).

- **Develocity**(구 Gradle Enterprise): 원격 캐시 + 빌드 스캔 + 테스트 인사이트 SaaS.

// build.gradle.kts

plugins {

java

application

id("org.springframework.boot") version "3.4.1"

}

group = "com.example"

version = "0.1.0"

repositories { mavenCentral() }

dependencies {

implementation("org.springframework.boot:spring-boot-starter-web")

testImplementation("org.springframework.boot:spring-boot-starter-test")

}

tasks.test { useJUnitPlatform() }

./gradlew build --build-cache --configuration-cache

./gradlew :api:test

./gradlew dependencies

**Maven 4** (2025년 GA): pom.xml의 안정성을 유지하면서 빌드 그래프, 병렬화, daemon (`mvnd`)을 강화. Spring 생태계의 거대한 관성으로 여전히 1순위. `mvnd`(Maven Daemon)를 쓰면 JVM 워밍업이 없어 체감 속도가 Gradle 수준에 근접한다.

./mvnw -T 1C clean install # CPU 코어당 1 스레드 병렬

mvnd -T 1C clean install # daemon 모드

JVM 모노레포라면: 신규 프로젝트는 Gradle + Develocity, 기존/SI 프로젝트는 Maven 4 + mvnd가 합리적이다.

12장 · sbt 1.10 · Mill — Scala 진영

Scala는 별도 글에서도 다루지만 빌드 관점에서 짧게.

**sbt 1.10**: Scala의 디폴트, incremental 컴파일이 강점. 학습 곡선이 가파르다는 평이 영원한 불만.

// build.sbt

ThisBuild / scalaVersion := "3.6.0"

lazy val root = (project in file("."))

.settings(

name := "myapp",

libraryDependencies ++= Seq(

"org.typelevel" %% "cats-effect" % "3.5.4",

"org.scalatest" %% "scalatest" % "3.2.19" % Test,

)

)

**Mill (Lihaoyi)**: Scala/Java/JS 빌드를 Scala로 기술. sbt보다 명료하고 빠르다는 평. 메인스트림은 아니지만 신규 Scala 팀이 종종 채택.

// build.mill

package build

object app extends ScalaModule {

def scalaVersion = "3.6.0"

def ivyDeps = Agg(ivy"org.typelevel::cats-effect:3.5.4")

}

Scala 모노레포가 정말 크면 Bazel + `rules_scala` 가 사실상 유일한 답이지만, 그 단계까지 가는 팀은 극소수다.

13장 · C/C++ — CMake 3.31 + Ninja 1.12 / Meson / Bazel

C/C++는 빌드 시스템 춘추전국 시대가 가장 오래 갔다. 2026년의 정리.

**CMake 3.31 + Ninja 1.12**: 사실상 표준. CMake는 빌드 시스템이 아니라 빌드 시스템 **생성기**(Makefile, Ninja, MSBuild 등 생성). Ninja는 그 결과를 가장 빠르게 실행한다.

CMakeLists.txt

cmake_minimum_required(VERSION 3.31)

project(myapp CXX)

set(CMAKE_CXX_STANDARD 23)

add_library(mylib STATIC src/foo.cc src/bar.cc)

target_include_directories(mylib PUBLIC include)

add_executable(myapp src/main.cc)

target_link_libraries(myapp PRIVATE mylib)

cmake -S . -B build -G Ninja

cmake --build build -j

ctest --test-dir build

**Meson + Ninja**: CMake의 사촌, 더 깔끔한 문법(Python 비슷). GNOME, systemd 등에서 사용.

**Bazel + rules_cc**: 대규모 C/C++ 폴리글랏 모노레포의 답. Google·Stripe·Pinterest의 C++ 서비스가 이 경로.

**GNU Make**: 여전히 작은 프로젝트의 1순위. 학습 곡선이 가장 평탄.

14장 · Rust — Cargo workspaces + cargo-nextest

Rust 모노레포는 거의 모든 경우 **Cargo workspaces** 로 충분하다.

Cargo.toml (root)

[workspace]

resolver = "2"

members = ["crates/*", "services/*"]

[workspace.dependencies]

tokio = { version = "1.42", features = ["full"] }

serde = { version = "1.0", features = ["derive"] }

cargo build --workspace

cargo test --workspace

cargo nextest run --workspace # 더 빠른 테스트 러너

cargo metadata --format-version 1 # 의존성 그래프

원격 캐시가 필요하면 `sccache`(Mozilla) 가 표준. S3·GCS·Redis·memcached·로컬 디스크 백엔드 지원.

export RUSTC_WRAPPER=sccache

export SCCACHE_BUCKET=my-sccache-bucket

cargo build --release

sccache --show-stats

대규모 폴리글랏에 Rust가 끼면 Bazel + `rules_rust` 도 선택지지만, 도입 부담이 크다. 회사 단위로 Bazel 표준이 없으면 sccache + Cargo가 사실상 정답.

15장 · Go — go modules + gomonorepo 패턴

Go는 모듈 시스템이 단순해서 모노레포가 자연스럽다. 한 리포에 하나의 `go.mod`를 두고 `internal/`로 패키지 경계를 긋는 게 표준.

myrepo/

go.mod

cmd/

api/main.go

worker/main.go

internal/

auth/

storage/

pkg/

publicapi/

go build ./...

go test ./...

go vet ./...

go test -count=1 -run TestFoo ./internal/auth

캐시·원격 실행이 필요하면 Bazel + `rules_go` + `gazelle` 조합이 가장 성숙. Gazelle는 `BUILD.bazel`을 `go.mod`에서 자동 생성한다.

bazel run //:gazelle

bazel run //:gazelle -- update-repos -from_file=go.mod -to_macro=deps.bzl%go_dependencies

Pinterest·Twitter·Coupang의 Go 서비스가 이 경로다.

16장 · Mise (구 rtx) · just · Task — 가벼운 태스크 러너

빌드 시스템과 별개로, **반복 명령을 짧게 부르는 도구**가 있다. 셸 스크립트·Makefile의 후계자들.

**Mise** (구 rtx): asdf 호환 버전 매니저 + 태스크 러너. Rust로 작성. 한 도구로 Node·Python·Go·Rust·Ruby·Bun 버전을 잠그고 태스크까지 정의.

mise.toml

[tools]

node = "22"

python = "3.12"

go = "1.23"

[tasks.build]

description = "Build all"

run = "pnpm -r build"

[tasks.test]

description = "Run tests"

depends = ["build"]

run = "pnpm -r test"

mise install # 도구 설치

mise run build

mise run test

**just**: Make의 현대판. 깔끔한 문법, 의존성 없음.

justfile

default:

@just --list

build:

pnpm -r build

test: build

pnpm -r test

release version:

git tag v{{version}}

git push origin v{{version}}

**Task** (taskfile.dev): YAML 기반 태스크 러너, Go로 작성.

Taskfile.yml

version: '3'

tasks:

build:

cmds:

- pnpm -r build

test:

deps: [build]

cmds:

- pnpm -r test

이 셋은 **빌드 그래프 도구가 아니라 명령 단축어**다. 대형 모노레포에서도 entry point로 쓰기 좋다 — `just ci` 가 내부적으로 `bazel test //...`나 `nx affected -t test`를 부르는 식.

17장 · 원격 캐시 — Bazel BES vs Nx Cloud vs Turborepo Remote Cache

세 도구의 원격 캐시 방식이 다르다.

| 시스템 | 캐시 키 | 저장 위치 | 백엔드 |

| --- | --- | --- | --- |

| Bazel | action hash (입력 + 명령 + 환경) | CAS (Content Addressable Storage) | BuildBuddy, EngFlow, Buildbarn |

| Nx Cloud | task hash (입력 + 명령 + 환경) | Nx Cloud SaaS or self-host | Nx Cloud (proprietary) |

| Turborepo Remote Cache | task hash | Vercel SaaS or self-host | Vercel, Turborepo Server (OSS) |

**Bazel의 강점**: REAPI 표준, 멀티 백엔드, 캐시 hit이 거의 항상 동작 (sandboxing 덕분).

**Nx Cloud의 강점**: 웹 UI, 실패한 빌드 인사이트, Nx Agents(분산 실행) 통합.

**Turborepo의 강점**: 설정이 가장 단순(환경변수 2개), Vercel CI와 자동 통합.

Self-host 옵션이 모두 있지만, 운영 부담은 BuildBuddy/Buildbarn >> Nx Cloud (Helm chart) >> Turborepo Server (Docker 컨테이너 하나).

18장 · Hermetic builds + content-addressed cache — 재현성의 본질

"빌드가 어제는 됐는데 오늘 안 됨" 의 근본 원인은 **숨어있는 입력**(환경변수, 시스템 라이브러리, 시계, 네트워크). 이걸 해결하는 게 hermetic build와 content-addressed cache.

**Hermetic**: 빌드 액션의 입력을 명시적으로 선언 (소스 + 도구 + 환경변수), 외부 접근 차단 (sandbox). Bazel·Buck2·Pants가 기본으로 한다.

**Content-addressed**: 입력 해시가 같으면 출력도 같다고 가정. 입력이 1바이트라도 다르면 새로 빌드, 같으면 캐시 적중.

input_hash = sha256(sources + tools + env + command)

output: stored under output_hash

cache_key: input_hash → output_hash

Nix도 같은 철학이다 (Bazel과 Nix는 다른 도구지만 같은 아이디어). 재현 가능한 CI/CD가 진짜 가능해진다.

19장 · 컨테이너 빌드 — BuildKit / Buildah / Kaniko / Earthly

빌드 시스템 글이 컨테이너로 끝나는 이유: 2026년 모든 서비스가 OCI 이미지로 배포되고, **빌드 시스템 출력 → 컨테이너 이미지** 변환이 빌드 파이프라인의 마지막 단계다.

| 도구 | 데몬 필요 | 특징 |

| --- | --- | --- |

| Docker BuildKit | 필요(dockerd) | 표준, 캐시 마운트·SBOM·provenance |

| Buildah / Podman build | 불필요 | 데몬리스, Red Hat |

| Kaniko | 불필요 | 컨테이너 안에서 컨테이너 빌드, K8s CI 친화 |

| Earthly | 데몬 사용 | Dockerfile + Makefile 결합, 캐시 강력 |

| ko (Go 전용) | 불필요 | Go 바이너리를 distroless 이미지로 즉시 패키징 |

| Jib (JVM 전용) | 불필요 | Maven/Gradle 플러그인으로 Docker 없이 이미지 빌드 |

Bazel은 `rules_oci`(구 `rules_docker` 후속) 로 OCI 이미지를 hermetic하게 만든다. 이미지 레이어가 입력 해시에 따라 동일하게 재현된다.

BUILD.bazel

load("@rules_oci//oci:defs.bzl", "oci_image")

oci_image(

name = "api_image",

base = "@distroless_base",

entrypoint = ["/api"],

tars = [":api_layer"],

)

20장 · 글로벌 빅테크의 빌드 시스템

| 회사 | 메인 빌드 |

| --- | --- |

| Google | Blaze (Bazel 사내판) |

| Meta | Buck2 |

| Microsoft | Rush + 자체 시스템 |

| Amazon | Brazil (자체) + Cargo / Maven |

| X (구 Twitter) | Bazel (Pants에서 마이그레이션) |

| Pinterest | Bazel (Python/Java/Go) |

| Stripe | Bazel |

| Spotify | Bazel + EngFlow |

| Snap | Bazel |

| Dropbox | Bazel (Python 일부 Pants) |

| Slack | Pants (Python·TS) |

| Vercel | Turborepo |

| Shopify | Bazel (서비스), nx/turborepo (storefront) |

| GitHub | 자체 + Bazel |

| Discord | Buck2 |

폴리글랏 + 대규모는 Bazel/Buck2/Pants 셋으로 수렴한다.

21장 · 한국·일본 사례

**한국**

- **Coupang**: Bazel 광범위 사용. Search·Logistics·iOS/Android 일부 Bazel. C++ 검색 인프라가 Bazel hermetic 위에서 돈다.

- **Toss / Viva Republica**: 프론트엔드 Turborepo. 백엔드는 Gradle 중심.

- **Naver**: 광범위. NHN/Naver Pay 일부 Bazel, 프론트엔드 팀 다수 Turborepo·Nx.

- **Kakao**: Gradle/Maven 중심, 프론트는 Turborepo / pnpm workspaces.

- **Woowa Brothers (배민)**: Gradle + Spring 중심. 프론트는 Nx/Turborepo.

- **당근**: pnpm workspaces + Turborepo가 표준. 일부 Nx 도입.

**일본**

- **Mercari**: Bazel 광범위. Microservices Go/Java를 Bazel + BuildBuddy.

- **LINE Yahoo**: Bazel(LY), Gradle(LINE 일부). 검색·광고 인프라는 Bazel.

- **CyberAgent / Ameba**: Nx + Turborepo. Bazel은 일부 광고 플랫폼.

- **Recruit / Indeed**: Bazel 광범위. Indeed는 monorepo + Bazel 발표 다수.

- **DeNA**: Gradle 중심 + 일부 Bazel.

- **Rakuten**: Gradle + Maven, Bazel 일부.

흥미로운 점: 일본 빅테크의 Bazel 채택률이 한국보다 높다. Mercari·Indeed·LY의 영향.

22장 · 언제 무엇을 쓸 것인가 — 결정 트리

마지막으로 정리.

1. **소규모 JS 팀 (~5명, ~10 패키지)** → `pnpm workspaces` 단독.

2. **중규모 JS/TS 팀 (~30명, ~50 패키지) + Vercel/Next.js 위주** → `Turborepo 2` + Vercel Remote Cache.

3. **중규모 JS/TS 팀 + 풍부한 도구·정책 필요** → `Nx 20` + Nx Cloud.

4. **JS + Python + Go 폴리글랏 모노레포** → `Moon` 또는 `Bazel`.

5. **Python 모노레포 (데이터·ML 팀)** → `Pants 2`.

6. **JVM 신규** → `Gradle 8.10` + Develocity.

7. **JVM 레거시/SI** → `Maven 4` + `mvnd`.

8. **Rust 모노레포** → `Cargo workspaces` + `sccache` + `cargo-nextest`.

9. **Go 모노레포** → 단일 `go.mod` + 필요시 Bazel + Gazelle.

10. **C/C++** → `CMake + Ninja` (작은 팀) 또는 `Bazel` (대규모).

11. **Scala** → `sbt` 또는 `Mill`, 정말 크면 `Bazel + rules_scala`.

12. **거대 폴리글랏 + 원격 실행 필수** → `Bazel` + BuildBuddy/EngFlow, 또는 `Buck2`.

가장 흔한 실수는 "유행 따라 Bazel 도입했다가 6개월 뒤 후회" 다. **현재 팀의 빌드 시간이 정말 병목이고**, **그 병목이 원격 캐시/실행으로 해결되며**, **유지보수 인력이 있다** 는 세 조건이 맞을 때만 폴리글랏 빌드 시스템을 고려해라. 그렇지 않으면 그 언어의 기본 도구가 거의 항상 옳다.

참고 자료

- Bazel 공식 문서 — https://bazel.build/

- Bazel Bzlmod (MODULE.bazel) — https://bazel.build/external/module

- Buck2 공식 — https://buck2.build/

- Buck2 GitHub — https://github.com/facebook/buck2

- Pants 2 문서 — https://www.pantsbuild.org/

- Nx 공식 문서 — https://nx.dev/

- Nx Cloud — https://nx.app/

- Turborepo 공식 — https://turbo.build/repo

- Turborepo 2 발표 — https://vercel.com/blog/turborepo-2-0

- Moon (moonrepo) — https://moonrepo.dev/

- Lerna 공식 — https://lerna.js.org/

- Rush Stack — https://rushjs.io/

- pnpm Workspaces — https://pnpm.io/workspaces

- Yarn Workspaces — https://yarnpkg.com/features/workspaces

- Gradle 공식 — https://gradle.org/

- Develocity (구 Gradle Enterprise) — https://gradle.com/develocity/

- Apache Maven — https://maven.apache.org/

- mvnd (Maven Daemon) — https://github.com/apache/maven-mvnd

- sbt — https://www.scala-sbt.org/

- Mill — https://mill-build.org/

- CMake — https://cmake.org/

- Ninja — https://ninja-build.org/

- Meson — https://mesonbuild.com/

- BuildBuddy — https://www.buildbuddy.io/

- EngFlow — https://www.engflow.com/

- NativeLink — https://www.nativelink.com/

- Buildbarn — https://github.com/buildbarn

- Mise (구 rtx) — https://mise.jdx.dev/

- just — https://github.com/casey/just

- Task (taskfile.dev) — https://taskfile.dev/

- Cargo Workspaces — https://doc.rust-lang.org/cargo/reference/workspaces.html

- cargo-nextest — https://nexte.st/

- sccache — https://github.com/mozilla/sccache

- Remote Execution API (REAPI) — https://github.com/bazelbuild/remote-apis

- BuildKit — https://github.com/moby/buildkit

- rules_oci — https://github.com/bazel-contrib/rules_oci

- Mercari Engineering / Bazel — https://engineering.mercari.com/en/blog/

에필로그 — "빌드는 결국 그래프"

빌드 시스템 30년의 핵심을 한 줄로 요약하면 **"입력 → 출력의 방향 그래프, 그래프의 노드를 최대한 재사용해라"** 다. Make가 했던 일을 Bazel은 sandboxing + 원격 실행으로, Turborepo는 JS만의 단순한 형태로, Pants는 Python 친화적으로 다시 쓰고 있다.

도구는 바뀌어도 **"내 빌드의 입력을 정확히 안다, 출력을 캐시한다, 같은 입력이면 다시 안 한다"** 는 원칙은 그대로다. 2026년의 폴리글랏 빌드 시스템은 이 원칙을 **여러 언어·여러 머신**에 걸쳐 적용한다. 작은 팀이라면 그 원칙을 가장 가까이서 구현한 도구(pnpm + Turborepo, Cargo, Gradle)로 충분하고, 큰 팀은 어쩌면 Bazel을 피할 수 없을지도 모른다.

마지막으로 한 가지 — 빌드 시스템의 성공은 **"누가 BUILD 파일을 유지보수하느냐"** 에 달려 있다. 도구가 아니라 사람의 문제다. Bazel을 도입하든 Nx를 도입하든, **빌드 인프라 전담자 1~2명**이 없으면 절반 정도만 성공한다. 그 인력 예산이 없다면, 그 회사에 맞는 빌드 시스템은 더 단순한 도구일 가능성이 높다.

현재 단락 (1/483)

2026년 어느 회사의 플랫폼 회의.

작성 글자: 0원문 글자: 18,588작성 단락: 0/483