Turborepo

Turborepo

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๋ฐ ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ ์ฝ”๋“œ๋ฒ ์ด์Šค๋ฅผ ์œ„ํ•œ ๊ณ ์„ฑ๋Šฅ ๋นŒ๋“œ ์‹œ์Šคํ…œ

๋นŒ๋“œ ๊ณผ์ •์—์„œ์˜ ์„ฑ๋Šฅ ํ–ฅ์ƒ์„ ์œ„ํ•ด ๋กœ์ปฌ ์บ์‹œ, ๋ฆฌ๋ชจํŠธ ์บ์‹œ, ๋ณ‘๋ ฌ ์‹คํ–‰ ๋“ฑ์˜ ๊ธฐ๋Šฅ์„ ์‰ฝ๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ์ œ๊ณต

ํŠน์ง•

  • vercel ์—์„œ ์ธ์ˆ˜ํ•œ ๋นŒ๋“œ ์‹œ์Šคํ…œ ๋„๊ตฌ

  • ๋ชจ๋…ธ๋ ˆํฌ ๊ธฐ๋Šฅ๋„ ์ง€์›ํ•˜๋ฉฐ ๋‹ค๋ฅธ ํŒจํ‚ค์ง€ ๋งค๋‹ˆ์ € ์›Œํฌ์ŠคํŽ˜์ด์Šค์™€ ํ•จ๊ป˜ ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

  • ๋ชจ๋…ธ๋ ˆํฌ ํ™˜๊ฒฝ์—์„œ๋„ ์‰ฝ๊ณ  ๋น ๋ฅด๊ฒŒ ๊ฐœ๋ฐœํ•  ์ˆ˜ ์žˆ๋Š” ๋นŒ๋“œ ํ™˜๊ฒฝ์„ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ์ด ๋ชฉํ‘œ

  • ๋ฃจํŠธ ์›Œํฌ์ŠคํŽ˜์ด์Šค ๋˜๋Š” ๊ฐ ์›Œํฌ์ŠคํŽ˜์ด์Šค์— turbo.json ์ด๋ผ๋Š” ํŒŒ์ผ์„ ์ด์šฉํ•ด์„œ ์บ์‹ฑ๊ณผ ํ…Œ์Šคํฌ ์˜ค์ผ€์ŠคํŠธ๋ ˆ์ด์…˜์„ ์„ค์ •ํ•œ๋‹ค.

ํ…Œ์Šคํฌ ์˜ค์ผ€์ŠคํŠธ๋ ˆ์ด์…˜(Task Orchestration)

  • ์˜ค์ผ€์ŠคํŠธ๋ ˆ์ด์…˜์ด๋ž€ ๋‹ค์–‘ํ•œ ๋‹จ๊ณ„๋ฅผ ์ˆ˜๋ฐ˜ํ•˜๋Š” ํ”„๋กœ์„ธ์Šค ๋˜๋Š” ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ์ž๋™ํ™”ํ•˜๋Š” ๋ฐฉ์‹์„ ๋œปํ•จ

  • ์—ฌ๋Ÿฌ ์ž‘์—…์ด๋‚˜ ํƒœ์Šคํฌ๋ฅผ ํšจ๊ณผ์ ์œผ๋กœ ์กฐ์œจํ•˜๊ณ  ์‹คํ–‰

  • ์—ฌ๋Ÿฌ ์ž‘์—…์„ ์ž๋™ํ™”ํ•˜๊ณ , ์ž‘์—… ๊ฐ„์˜ ์˜์กด์„ฑ์„ ๊ด€๋ฆฌํ•˜๋ฉฐ, ์‹คํ–‰ ์ˆœ์„œ๋ฅผ ์ตœ์ ํ™”ํ•˜์—ฌ ๊ฐœ๋ฐœ ํ”„๋กœ์„ธ์Šค๋ฅผ ๋‹จ์ถ•์‹œํ‚จ๋‹ค.

์žฅ์ 

  • ์‚ฌ์šฉ์ž๊ฐ€ ๋นŒ๋“œํ•œ ๋‚ด์šฉ์„ ๊ธฐ์–ตํ•ด์„œ ์ด๋ฏธ ๊ณ„์‚ฐํ•œ ๋‚ด์šฉ์€ ๊ฑด๋„ˆ๋œ€ (ํ…Œ์Šคํฌ ์„ค์ • ๊ธฐ๋ณธ๊ฐ’์ด ์บ์‹ฑ ํ—ˆ์šฉ)

  • ํƒ€์ž„์Šคํƒฌํ”„๊ฐ€ ์•„๋‹Œ ํŒŒ์ผ์˜ ๋‚ด์šฉ์„ ๋ณด๊ณ  ๋นŒ๋“œํ•ด์•ผ ํ•  ๋‚ด์šฉ์„ ํŒŒ์•…ํ•œ๋‹ค.

  • ์‰ฌ๊ณ  ์žˆ๋Š” CPU๋ฅผ ๋‚ญ๋น„ํ•˜์ง€ ์•Š๊ณ , ๋ชจ๋“  ์ฝ”์–ด๋ฅผ ์ตœ๋Œ€๋กœ ์‚ฌ์šฉํ•ด์„œ ๋ณ‘๋ ฌ๋กœ ์‹คํ–‰

  • ์›๊ฒฉ ๋นŒ๋“œ ์บ์‹œ๋ฅผ ํŒ€์› ๋ฐ CI/CD์™€ ๊ณต์œ ํ•˜์—ฌ ๋นŒ๋“œ ์†๋„๋ฅผ ๋†’ํž ์ˆ˜ ์žˆ๋‹ค.

  • ์ž‘์—… ๊ฐ„์˜ ๊ด€๊ณ„๋ฅผ ์ •์˜ํ•˜์—ฌ turborepo๊ฐ€ ๋นŒ๋“œ ํ•ญ๋ชฉ๊ณผ ์‹œ๊ธฐ๋ฅผ ์ตœ์ ํ™”ํ•  ์ˆ˜ ์žˆ๋‹ค.

์ฃผ์š” ๊ธฐ๋Šฅ

Running Tasks

ํ…Œ์Šคํฌ ์ˆ˜ํ–‰

turbo run test // ๊ฐ ์›Œํฌ์ŠคํŽ˜์ด์Šค์˜ 'run test' ์Šคํฌ๋ฆฝํŠธ ์‹คํ–‰

turbo run test --filter=ํŠน์ •์›Œํฌ์ŠคํŽ˜์ด์Šค // ํ•ด๋‹น ์›Œํฌ์ŠคํŽ˜์ด์Šค์˜ ์Šคํฌ๋ฆฝํŠธ ์‹คํ–‰

Task Dependencies

์˜์กด ๊ด€๊ณ„์— ๋”ฐ๋ผ ํ…Œ์Šคํฌ ์‹คํ–‰ + ๋ณ‘๋ ฌ ์‹คํ–‰

turbo run lint test build // lint, test, build ๊ฐ ํ…Œ์Šคํฌ๊ฐ€ ๋ชจ๋‘ ๋ณ‘๋ ฌ๋กœ ์‹คํ–‰๋จ
  • ์˜์กด ๊ด€๊ณ„์— ๋”ฐ๋ผ ๋จผ์ € ์ˆ˜ํ–‰๋˜์–ด์•ผ ํ•  ๊ฒƒ๋“ค์„ ํŒ๋‹จํ•˜์—ฌ ์ž‘์—…์ด ์ง„ํ–‰๋จ

  • ์˜์กด๊ด€๊ณ„๋งŒ ์ž˜ ์„ ์–ธํ•ด์ค€๋‹ค๋ฉด ํ„ฐ๋ณด๋ ˆํฌ๊ฐ€ ์•Œ์•„์„œ ์ž˜ ๊ณ„์‚ฐํ•˜์—ฌ ์ฒ˜๋ฆฌํ•ด์ฃผ๊ธฐ ๋•Œ๋ฌธ์— ์†๋„ ์ธก๋ฉด์—์„œ ์ผ๋ฐ˜ ํŒจํ‚ค์ง€ ๋งค๋‹ˆ์ €๋ณด๋‹ค ๋น ๋ฅด๊ฒŒ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค.

Code Generation

์ฝ”๋“œ(์›Œํฌ์ŠคํŽ˜์ด์Šค) ์ƒ์„ฑ

turbo gen workspace // ๋นˆ ์›Œํฌ์ŠคํŽ˜์ด์Šค ์ƒ์„ฑ

turbo gen workspace --name @jtwjs/ui

Remote Caching

ํ•œ์ชฝ์—์„œ ๋ฆฌ๋ชจํŠธ์— ์บ์‹ฑ์„ ํ•ด๋‘๋ฉด CI/CD ์ชฝ์—์„œ ์บ์‹ฑ๋œ ๋‚ด์šฉ์„ ํ™œ์šฉํ•ด์„œ ์†๋„๊ฐ€ ํ–ฅ์ƒ๋จ

turbo login
turbo link // ๋ฒ„์…€ ํด๋ผ์šฐ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด ์‰ฝ๊ฒŒ ๊ตฌํ˜„

pnpm ์‹ค์Šต

turborepo๋Š” ๋ชจ๋“  ํŒจํ‚ค์ง€ ๋งค๋‹ˆ์ €๋ฅผ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜์ง€๋งŒ pnpm ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ๊ถŒ์žฅํ•œ๋‹ค.

pnpm ํ™˜๊ฒฝ ์„ธํŒ…

mkdir turborepo-example
cd turborepo-example
pnpm init
corepack prepare pnpm@8.11.0 --activate
code .
// pnpm-workspace.yaml
packages:
  - 'packages/*'
  - 'apps/*'
mkdir apps
cd apps
pnpx create-next-app@latest
cd ..

Turbo install

pnpm -w add turbo -D // ํŒจํ‚ค์ง€ ์ „์—ญ์— devDependencies๋กœ turbo ์„ค์น˜

workspace ์ถ”๊ฐ€

mkdir packages
pnpm exec turbo gen workspace --name my-utils

typescript ์ถ”๊ฐ€

pnpm --filter my-utils add typescript -D
pnpm --filter my-utils exec tsc --init
 // tsconfig.json
 {
   compileOptions: {
    //...
    "declaration": true, // ํƒ€์ž… ์ •์˜ ํŒŒ์ผ ์ƒ์„ฑํ•˜๋„๋ก ์„ค์ •
    "outDir": "./dist" // ์ปดํŒŒ์ผ๋œ js ํŒŒ์ผ์„ ์ €์žฅํ•˜๋Š” ๋””๋ ‰ํ† ๋ฆฌ ์„ค์ •
   },
   include: ["src/**/*"]
 }
 // package.json
{
  "name": "jtw-utils",
  "version": "0.0.0",
  "main": "dist/index.js",
  "types": "dist/index.d.ts",
  "scripts": {
    "build": "tsc"
  },
  "devDependencies": {
    "typescript": "^5"
  }
}
pnpm --filter my-utils build

workspace ์˜์กด์„ฑ ์ถ”๊ฐ€

// apps package.json
"dependencies": {
  //...
  "my-utils": "workspace:*"
},
pnpm i  

turbo ๋ช…๋ น์–ด ์‚ฌ์šฉํ•˜๊ธฐ

pnpm exec turbo build --filter=my-utils // pnpm๊ณผ ๋‹ฌ๋ฆฌ turbo๋Š” '='๋ฅผ ๋ถ™ํžˆ๋Š”๊ฒƒ์— ์ฃผ์˜
  • turbo.json ์„ ๋งŒ๋“ค๊ณ  task๋ฅผ ์ •์˜ ํ•ด์ฃผ์–ด์•ผ ํ„ฐ๋ณด ๋ช…๋ น์–ด๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

// turbo.json
{
  "$schema": "https://turbo.build/schema.json",
  "pipeline": { // pipline์€ ์ผ์ข…์˜ task line
    "build": {}
  }
}
  • ์‹คํŒจํ–ˆ๋˜ ๋ช…๋ น์–ด๋ฅผ ๋‹ค์‹œ ์ž…๋ ฅํ•ด๋ณด๋ฉด ์ •์ƒ์ ์œผ๋กœ ์‹คํ–‰๋˜๋Š”๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

  • ๋‘ ๋ฒˆ์งธ ์‹คํ–‰๋ถ€ํ„ฐ๋Š” cache ๋˜์–ด ์ˆ˜ํ–‰์‹œ๊ฐ„์ด 980ms -> 50ms๋กœ ๋‹จ์ถ•๋œ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

๋ชจ๋“  ์›Œํฌ์ŠคํŽ˜์ด์Šค ๋ช…๋ น์–ด ์‹คํ–‰

  • --filter ๋ฅผ ์ž‘์„ฑํ•˜์ง€ ์•Š์œผ๋ฉด ๋ชจ๋“  ์›Œํฌ์ŠคํŽ˜์ด์Šค๋ฅผ ๋Œ๋ฉด์„œ ์Šคํฌ๋ฆฝํŠธ ์‹คํ–‰

pnpm exec turbo build

build outputs ์„ค์ •

{
  "$schema": "https://turbo.build/schema.json",
  "pipeline": {
    "build": {
      "outputs": ["./next/**", "!.next/cahce/**", "dist/**"]
    }
  }
}

build ๊ด€๊ณ„ ์„ค์ •ํ•˜๊ธฐ

  • dependsOn ์„ค์ •์„ ํ†ตํ•ด ๋นŒ๋“œํ•  ๋•Œ ์˜์กดํ•˜๊ณ  ์žˆ๋Š” ๊ฒƒ๋“ค์— ๊ด€๊ณ„๋ฅผ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

  • app์˜ ์ฝ”๋“œ๋งŒ ๋ณ€๊ฒฝ๋œ๋‹ค๋ฉด ์˜์กดํ•˜๋Š” ๊ฒƒ๋“ค์€ ์บ์‹ฑ๋œ ๊ฒƒ์„ ์‚ฌ์šฉํ•˜๊ณ  ์˜์กดํ•˜๋Š” ๊ฒƒ๋“ค์— ๋ณ€๊ฒฝ์‚ฌํ•ญ์ด ์ƒ๊ธด๋‹ค๋ฉด ์บ์‹ฑ์—†์ด ๋‹ค์‹œ ๋นŒ๋“œ๊ฐ€ ์ผ์–ด๋‚œ๋‹ค.

{
  "$schema": "https://turbo.build/schema.json",
  "pipeline": {
    "build": {
      "dependsOn": ["^build"], // ์•ž์—  "^" ๊บฝ์‡ ๋ฅผ ๋ถ™ํžˆ๋ฉด ์˜์กดํ•˜๊ณ  ์žˆ๋Š” ๋ชจ๋“  ๊ฒƒ์„ ๋นŒ๋“œํ•œ๋‹ค๋Š” ์–˜๊ธฐ
      "outputs": ["./next/**", "!.next/cahce/**", "dist/**"]
    }
  }
}

์›Œํฌ์ŠคํŽ˜์ด์Šค ๊ฐ„ ๋นŒ๋“œ ์˜ต์…˜์„ ๋‹ค๋ฅด๊ฒŒ ์„ค์ •ํ•˜๊ธฐ

  • ๋ฃจํŠธ์— ์กด์žฌํ•˜๋Š” turbo.json ์œผ๋กœ ํ•œ๊ณณ์—์„œ ๊ด€๋ฆฌํ•œ๋‹ค๋ฉด # ์„ ํ†ตํ•ด ์›Œํฌ์ŠคํŽ˜์ด์Šค๊ฐ„ ๋นŒ๋“œ ์˜ต์…˜์„ ๋‹ค๋ฅด๊ฒŒ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ์›Œํฌ์ŠคํŽ˜์ด์Šค๊ฐ€ ๋งŽ์•„์ง€๋ฉด ๋ณต์žกํ•ด์ง„๋‹ค.

  • ๋‘ ๋ฒˆ์งธ ๋ฐฉ๋ฒ•์œผ๋กœ, ๊ฐ ์›Œํฌ์ŠคํŽ˜์ด์Šค ๊ฐ„์— turbo.json์„ ์ž‘์„ฑํ•˜์—ฌ ์˜ต์…˜์„ ๋‹ค๋ฅด๊ฒŒ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Turborepo์—์„œ ์ถ”๊ฐ€๋˜๋Š” ๊ธฐ๋Šฅ๋“ค์„ ์‚ดํŽด๋ณด๋ฉด ์›Œํฌ์ŠคํŽ˜์ด์Šค ์ƒ์† ๊ธฐ๋Šฅ(์˜ˆ: turbo.json ์ƒ์† ๋“ฑ)์˜ ์ฒ˜๋ฆฌ ์š”์†Œ๊ฐ€ ์ ์  ๋” ์ถ”๊ฐ€๋˜๋Š” ์ถ”์„ธ๋ผ ํ•ด๋‹น ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ์ถ”์ฒœ

// root์— ์กด์žฌํ•˜๋Š” turbo.json
{
  "$schema": "https://turbo.build/schema.json",
  "pipeline": {
    "my-app#build": {
      "dependsOn": ["^build"],
      "outputs": ["./next/**", "!.next/cahce/**"]
    },
    "my-utils#build": {
      "dependsOn": ["^build"],
      "outputs": ["dist/**"]
    }
  }
}

์›Œํฌ์ŠคํŽ˜์ด์Šค ๊ฐœ๋ฐœ ์„œ๋ฒ„ ๋„์šฐ๊ธฐ

pnpm exec turbo dev --filter=my-app
  • ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ turbo.json ์— dev ๊ด€๋ จํ•œ ์ •์˜๊ฐ€ ๋˜์–ด์žˆ์ง€ ์•Š์•„ ํ•ด๋‹น ๋ช…๋ น์–ด๊ฐ€ ์‹คํŒจํ•˜์—ฌ turbo.json ์— ์ถ”๊ฐ€๋กœ ์ •์˜ํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค.

  • ๊ฐœ๋ฐœ ์„œ๋ฒ„ ์‹คํ–‰์€ ์บ์‹ฑ์ด๋˜๋ฉด ์•ˆ๋˜๋ฏ€๋กœ cache ์˜ต์…˜์„ false๋กœ ์„ค์ •

  • ๊ณ„์† ์‹คํ–‰ํ•ด์•ผํ•˜๋Š” ๊ฒƒ๋“ค์€ turborepo์—์„œ cache: false, persistent: true ์„ค์ •์„ ์ถ”๊ฐ€ํ•  ๊ฒƒ์„ ๊ถŒ์žฅํ•œ๋‹ค.

{
  "$schema": "https://turbo.build/schema.json",
  "pipeline": {
    "my-app#build": {
      "dependsOn": ["^build"],
      "outputs": ["./next/**", "!.next/cahce/**"]
    },
    "jtw-utils#build": {
      "dependsOn": ["^build"],
      "outputs": ["dist/**"]
    },
    "my-app#dev": {
      "cache": false,
      "persistent": true
    }
  }
}

Ref

Remote Cache

Graph

Last updated