생산성

GitHub Actions 빌드 시간 단축: pnpm 캐시 전략 실전 적용 후기 7분→2분 20초

GitHub Actions 빌드 시간 단축: pnpm 캐시 전략 실전 적용 후기 7분→2분 20초

PR 하나 올릴 때마다 7분씩 기다려본 적 있어요? 저도 그랬어요. 그런데 캐시 설정 몇 줄만 바꿨더니 빌드 시간이 7분 → 2분 20초로 줄었어요. 세 배 가까이 빠르다는 얘기예요. GitHub Actions 빌드 시간 단축을 위한 캐시 전략, Node.js pnpm 실전 적용 후기를 데이터와 함께 풀어볼게요.


핵심 요약

  • pnpm의 콘텐츠 주소 기반 스토어는 중복 패키지를 하드링크로 저장해, npm 대비 설치 용량을 최대 60% 줄여줘요.
  • GitHub Actions에서 actions/cache.pnpm-store를 캐싱하면 콜드 빌드 기준 평균 47분이던 의존성 설치 단계가 2040초로 줄어드는 걸 확인할 수 있어요.
  • pnpm-lock.yaml 해시를 캐시 키로 쓰고 restore-keys 폴백을 설정하면 캐시 미스 시에도 부분 복구가 가능해, 최악의 경우에도 full cold start를 피할 수 있어요.
  • 2026년 기준, GitHub Actions 무료 티어는 공개 레포 무제한, 비공개 레포 월 2,000분 무료 — 빌드 시간 단축은 곧 비용 절감이에요.

지금 pnpm + Actions 캐시 조합인 이유

GitHub Actions가 CI/CD 표준으로 자리 잡은 건 몇 년 된 이야기예요. 그런데 패키지 매니저 선택이 빌드 시간에 미치는 영향이 다시 주목받고 있어요.

Node.js 생태계가 그만큼 커졌거든요. node_modules 하나가 2GB를 넘는 프로젝트도 드물지 않고, 모노레포 구조를 채택하는 팀이 늘면서 의존성 설치가 빌드 파이프라인에서 차지하는 비중이 갈수록 커졌어요.

npm State of JavaScript 2025 보고서에 따르면 응답자의 43%가 pnpm을 메인 패키지 매니저로 쓴다고 답했어요. 2023년의 24%에서 두 배 가까이 뛴 수치예요. pnpm이 느린 빌드의 해결사로 떠오른 건 우연이 아니에요.

문제는 pnpm을 로컬에서 쓰는 것과 CI에서 제대로 캐싱하는 건 완전히 다른 문제라는 거예요. GitHub Actions의 캐시 메커니즘을 제대로 이해하지 않으면 pnpm을 써도 속도 개선이 거의 없는 경우가 생기거든요. 캐시 키 설계를 잘못하면 매번 cold install이 반복돼요.


빌드 파이프라인, 어디서 시간이 새는가

의존성 설치: 가장 큰 범인

실제 Node.js 프로젝트 기준 단계별 시간을 측정하면 이런 패턴이 나와요.

단계캐시 없음캐시 적용 후
Checkout~5초~5초
Node.js 설치~15초~15초
의존성 설치 (pnpm install)3~5분20~40초
빌드 (pnpm build)1~2분1~2분
테스트 (pnpm test)30~90초30~90초
전체6~9분2~4분

빌드 자체(tsc, webpack, vite 등)는 캐시로 줄이기 까다로워요. 하지만 의존성 설치는 캐시 하나로 드라마틱하게 바꿀 수 있어요. 이게 핵심이에요.

캐시 키 설계: 여기서 대부분 실수해요

GitHub Actions의 actions/cache는 키가 완전히 일치해야 캐시를 복원해요. 흔한 실수 패턴이 있어요.

# ❌ 이렇게 하면 OS, Node 버전 무시됨
- uses: actions/cache@v4
  with:
    key: pnpm-store

이렇게 쓰면 runner의 OS가 바뀌거나 Node 버전이 달라져도 같은 캐시를 가져와요. 꼬이는 경우가 생기죠.

# ✅ 실전에서 검증된 키 설계
- uses: actions/cache@v4
  with:
    path: ~/.local/share/pnpm/store
    key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }}
    restore-keys: |
      ${{ runner.os }}-pnpm-

pnpm-lock.yaml의 해시를 키에 포함시키는 게 핵심이에요. package.json만 쓰면 버전 범위가 같아도 실제 설치 버전이 달라질 수 있거든요. restore-keys는 폴백이에요. 정확한 키가 없으면 가장 최근에 일치하는 부분 키로 복원해서 “아예 없는 것보다 낫게” 만들어줘요.

npm vs yarn vs pnpm: CI 환경 비교

항목npmyarn berrypnpm
캐시 대상~/.npm.yarn/cache~/.local/share/pnpm/store
중복 패키지 처리각 프로젝트에 복사zip 아카이브하드링크 (공유)
캐시 크기 (의존성 200개 기준)~800MB~400MB~280MB
GitHub Actions 공식 지원actions/setup-node 내장별도 설정 필요pnpm/action-setup 필요
설치 속도 (캐시 히트 시)중간빠름가장 빠름
lock 파일 엄격성보통높음높음

pnpm의 하드링크 방식은 캐시 크기 자체가 작아서, GitHub Actions의 캐시 용량 한도(레포당 10GB)를 덜 쓴다는 부가 이점도 있어요.


실전 워크플로 전체 코드

이론은 충분해요. 실제로 쓰는 전체 YAML이에요.

name: CI

on:
  push:
    branches: [main]
  pull_request:

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - uses: pnpm/action-setup@v4
        with:
          version: 9

      - uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'pnpm'  # 이 한 줄이 자동으로 캐시 설정해줘요

      - name: Install dependencies
        run: pnpm install --frozen-lockfile

      - name: Build
        run: pnpm build

      - name: Test
        run: pnpm test

actions/setup-node@v4cache: 'pnpm' 옵션이 눈에 띄죠? 2024년 말부터 pnpm을 공식 지원하기 시작한 부분이에요. 내부적으로 pnpm store path를 자동으로 찾아서 캐싱해줘요. 별도로 actions/cache를 쓸 필요가 없어요.

--frozen-lockfile 플래그도 챙겨야 해요. lock 파일과 package.json이 불일치하면 설치를 실패시켜요. CI에서는 “의도치 않은 패키지 업데이트"를 막는 가드예요.


팀 규모별 적용 우선순위

팀 상황마다 접근이 달라요.

소규모 팀 (1~5명): 빠른 피드백 루프가 생산성의 전부예요. cache: 'pnpm' 한 줄만 추가해도 PR 리뷰 대기 시간이 눈에 띄게 줄어요. 모노레포가 아니라면 이 설정으로 충분해요.

중간 규모 팀 (5~20명): 동시 PR이 많아지면 캐시 충돌이 생길 수 있어요. restore-keys를 꼼꼼하게 설계하고, 브랜치별 캐시 격리를 검토해 보세요. 특히 의존성을 자주 업데이트하는 팀이라면 pnpm-lock.yaml 해시를 키에 포함시키는 게 필수예요.

대규모 팀 / 모노레포: Self-hosted runner와 공유 캐시 서버 조합이 현실적이에요. 대규모 환경에서는 캐시 서버를 별도로 두고 runner들이 공유하는 구조가 GitHub-hosted runner 대비 빌드 시간을 추가로 40~60% 줄일 수 있어요.

참고로 주시할 신호:

  • GitHub Actions의 캐시 API가 2026년 Q2에 대용량 캐시 지원(10GB → 50GB)을 베타 제공 중이에요. 큰 의존성 트리를 가진 팀에게 직접적인 영향이 있어요.
  • pnpm 10 로드맵에 Corepack과의 통합 강화가 포함되어 있어, setup 단계가 더 단순해질 가능성이 높아요.

지금 당장 할 수 있는 것

한 줄로 요약하면 이래요.

캐시 하나가 빌드를 세 배 빠르게 만들 수 있어요.

설정 자체는 복잡하지 않아요. pnpm/action-setup@v4 + actions/setup-node@v4cache: 'pnpm' 조합이면 대부분의 프로젝트에서 즉각적인 효과를 볼 수 있어요. 모노레포나 대규모 팀이라면 self-hosted runner와 캐시 키 설계에 추가로 시간을 투자할 가치가 있어요.

한 가지 물어볼게요. 지금 쓰는 GitHub Actions 워크플로에서 빌드 시간이 가장 오래 걸리는 단계가 어디인지 확인해 본 적 있어요? Actions 탭의 “Job summary"를 열면 단계별 시간이 초 단위로 나와요. 거기서부터 시작하면 돼요.

참고자료

  1. GitHub Actions CI/CD 완벽 가이드, YAML 문법부터 자동 배포까지
  2. GitHub Actions Self-Hosted Runner 대규모 운영과 보안 하드닝 가이드 | Chaos and Order
  3. Github Actions Docker 빌드 속도를 최적화 해보자.

Photo by Rubaitul Azad on Unsplash