개인의 기록
  • 소개
  • 프로젝트
  • 글
  • 링크

© 2026 newgirok

← YouTube Shorts 자동화

모노레포 설계 — 왜 turborepo를 골랐나

2026년 5월 17일
turborepopnpmmonorepo

유튜브 쇼츠 자동화 파이프라인을 만들기로 했다.

아이디어는 단순했다. 스크립트 생성 → TTS → 자막 → 영상 렌더 → 업로드. 딱 다섯 단계.

근데 막상 설계하다 보니까, 이게 정말 하나의 레포로 관리될 수 있는 구조인가?

스크립트는 Gemini API, TTS는 별도 서비스, 렌더링은 ffmpeg 물린 워커, 웹 대시보드는 또 따로. 각각이 독립적으로 배포되는 서비스들이다. 이걸 한 레포에 때려박으면 나중에 분명 후회한다.

이미 알고 있었다.

왜 모노레포인가

핵심은 타입 공유였다.

Job 타입 하나가 바뀌면 스크립트 워커, 렌더 워커, 웹 앱이 전부 같이 바뀌어야 한다. 이걸 각자 레포로 관리하면? npm publish 하고, 버전 올리고, 각 레포에서 업데이트하고...

생각만 해도 머리가 아팠다.

모노레포를 쓰면 이게 단번에 해결된다. 패키지끼리 로컬 참조로 연결되니까 타입 하나 바꾸면 빌드 시점에 전부 잡힌다. 아, 이거다 싶었다.

툴 선택지는 두 가지였다.

  • nx — 기능 많고 플러그인 생태계 탄탄. 근데 설정이 무거움.
  • turborepo — 캐싱이랑 병렬 빌드에 집중. 가볍고 빠름.

빌드 캐싱이 핵심이었다. 렌더 워커 코드만 바꿨는데 스크립트 워커까지 다시 빌드하면 낭비 아닌가. turborepo로 정했다.

패키지 매니저는 pnpm. workspace 기능이 npm보다 깔끔하고, 디스크 공간도 덜 잡아먹는다.

이 커밋에서 잡은 것들

.changeset/config.json   — 버전 관리 전략
.eslintrc.js             — 공통 린트 규칙
.gitignore
package.json             — 루트 워크스페이스
pnpm-workspace.yaml      — apps/*, packages/* 구조 정의
tsconfig.base.json       — 공통 TS 설정
turbo.json               — 빌드 파이프라인 정의

turbo.json에서 파이프라인을 이렇게 잡았다.

{
  "pipeline": {
    "build": {
      "dependsOn": ["^build"],
      "outputs": ["dist/**"]
    },
    "dev": {
      "cache": false,
      "persistent": true
    }
  }
}

^build는 "내 패키지가 의존하는 것들 먼저 빌드해"라는 뜻이다. 의존성 그래프를 자동으로 따라가준다.

pnpm-workspace.yaml은 단순하다.

packages:
  - "apps/*"
  - "packages/*"

apps/에는 실제 서비스들(web, api, workers), packages/에는 공통 모듈(db 스키마, 타입 정의, 유틸)이 들어갈 예정.

이 시점엔 코드가 하나도 없다. 뼈대만 세운 거다.

근데 이 선택이 나중에 워커 6개 돌릴 때 진짜 빛을 발했다. 타입 하나 바꾸면 전부 에러가 잡혔고, 오히려 안심이 됐으니까.

처음 설계 잘 해두면 이런 게 돌아온다.

다음 글 →Gemini 렌더링 — 씬 기반 파이프라인 구축