hi-hoi

AWS Amplify Next.js 모노레포 빌드 최적화: 40% 시간 단축 (8분 → 5분)

TL;DR

AWS Amplify에서 Next.js 모노레포 빌드 시간이 평균 8분 이상 소요되고 있었습니다.

빌드 로그 분석 결과 주요 병목은 다음 세 가지였습니다.

  • Submodule 인증 과정
  • 전체 의존성 설치
  • node_modules 캐시

이를 개선해 빌드 시간을 8분 → 5분 초반(약 40% 이상)까지 단축했습니다.


문제 상황

회사 프론트엔드 코드는 모노레포 환경으로 관리되고 있습니다.

서비스는 다음과 같은 구조입니다.

  • Next.js 기반 서비스
  • Vite 기반 서비스

AWS Amplify 배포 환경에서 빌드 시간이 예상보다 길어지는 문제가 있었습니다.

서비스평균 빌드 시간
Next.js약 8분
Vite약 5분

파이프라인은 초기 개선 이후 큰 변경 없이 유지되고 있었습니다.

이후 모노레포 구조의 도입과 패키지 매니저의 변경 (npm → pnpm)을 진행했습니다. 이 과정에서 비효율적인 설정이 많이 포함된 상태였습니다.


빌드 병목 분석 및 개선

로그 분석 결과 컴파일이 아닌, 준비 단계에서 낭비되는 시간이 길었습니다.

1. Submodule 인증 구조 개선

기존 구조

기존 Amplify 빌드 파이프라인에서는 Submodule 동기화에 이런 작업들을 진행했습니다.

→ jq 설치

→ Secrets Manager API

→ token fetch

→ https rewrite

→ git submodule sync

왜 이런 불필요하게 보이는 작업들이 필요했던 건지 궁금해서 사내 위키를 찾아봤습니다. 당시에는 다음과 같은 인식이 있었습니다.

"Amplify CI 환경에서는 SSH 인증을 사용할 수 없다."

이 말은 사실이 아닙니다.

Amplify는 최초에 연결된 GitHub 레포지토리에 대해서만 접근 권한을 가지며, 기본적으로는 Submodule로 연결된 다른 GitHub 레포지토리에 접근할 수 없습니다. 여기서 오해가 생겨서 SSH를 https로 치환하는 작업을 했던 것으로 추정됩니다.

Amplify에서 SSH 사용이 불가능한 것이 아니라 접근 권한 범위의 문제였을 것으로 판단해서 이 과정을 개선하려고 했습니다.


해결 방법

이 문제는 Deploy Key 기반 SSH 인증으로 해결할 수 있습니다.

  • Submodule Repository → Deploy Key 등록 (SSH Public Key)

  • Amplify → Private Key 환경 변수 설정 → SSH 기반 Submodule 접근

  • 시크릿 매니저로 관리하던 https 접근 토큰을 삭제

이 방식으로 다음 문제를 모두 해결했습니다.

  • Secrets Manager 호출 제거
  • jq 설치 제거
  • .gitmodules rewrite 제거
  • 로컬 / CI 인증 방식 일치

결과

제거한 작업시간
yum + jq 설치24초
Secrets Manager API13초
https rewrite1초
  • 약 40~50초 시간 개선

2. 모노레포 의존성 설치 최적화

기존 방식

pnpm install --frozen-lockfile

이 명령은 모노레포 전체 패키지를 설치합니다.

개선

빌드 대상 서비스만 설치하도록 변경했습니다.

pnpm install --filter "@inf/web..." --frozen-lockfile

결과

빌드 시간은 약 8~9초 단축되었습니다.

예상보다 체감 성능 개선은 크지 않았습니다.

성능 개선이 크지 않았던 이유

  • 서비스 간 공통 의존성 공유율이 높음
  • pnpm의 하드 링크 구조가 이미 매우 빠름

아래와 같은 장점도 있어서 적절한 의존성 설치는 필요한 작업이라고 생각합니다.

  • Phantom Dependency 방지
  • 빌드 파이프라인 정합성 확보
  • 불필요한 패키지 설치 차단

3. 캐시 전략 개선

기존 방식

기존 캐시 전략으로 node_modules 전체에 캐시를 사용 중이었습니다.

캐시를 위해서는 압축 → 다운로드 → 압축 해제 → 업로드 과정이 필요합니다.

pnpm의 node_modules 구조는 symlink + hard link 기반입니다. node_modules 전체를 캐시하면 매우 많은 파일 I/O가 발생하고 캐시 과정 자체가 병목이 될 수 있습니다.

실제로 캐시 관련 작업에 약 2분 이상이 소요되고 있었습니다.

개선

  • node_modules 캐시를 제거하고 pnpm store만 캐시하도록 변경했습니다.
  • Amplify 네트워크 속도가 빠르기 때문에 캐시 미사용 전략도 고려했습니다. 서비스별로 세 번 정도 테스트한 결과, 캐시를 사용할 때 미약한 성능 향상이 있었기에 pnpm-store 캐시는 유지했습니다.

결과

빌드 성능은 다음과 같이 개선되었습니다. (배포 오버헤드 제외)

서비스AS-ISTO-BE개선율
BIZ-WEB8분5분 15초34%
BO-WEB5분2분 55초42%
INF-WEB8분5분 10초35%

Phase별 성능 변화

Phase (빌드 단계)AS-ISTO-BE단축 시간주요 원인
사전 준비 & 캐시 추출1분 11초15초-56초무거운 node_modules 캐시 제거
인증 & 의존성 설치1분 40초43초-57초jq 설치 및 API 호출 제거
Build (컴파일)2분 19초2분 18초-1초Next.js 빌드 자체는 동일
캐시 생성 & 업로드1분 47초36초-1분 11초node_modules 압축 제거
순수 스크립트 실행 시간6분 57초4분 8초-2분 49초

참고: 위 표의 시간은 특정 서비스(@inf/web) 한 개의 Amplify 빌드 파이프라인 동작 시간 기준입니다. 컨테이너 프로비저닝, 내부 환경 캐싱, 배포 등은 제외했습니다.


정리

이번 최적화를 통해 다음과 같은 개선이 이루어졌습니다.

Submodule 인증 구조

Secrets Manager 기반 토큰 → Deploy Key 기반 SSH

모노레포 의존성 설치

pnpm install → pnpm install --filter

캐시 전략

node_modules 캐시 → pnpm store 캐시


Appendix: Amplify 설정 예시

  • 실제 Amplify 설정의 구조를 단순화한 예시입니다.
frontend:
  phases:
    preBuild:
      commands:
        # Deploy Key 기반 SSH 인증
        - mkdir -p ~/.ssh
        - printf '%s' "$DEPLOY_KEY_BASE64" > ~/.ssh/key.base64
        - base64 --decode ~/.ssh/key.base64 > ~/.ssh/id_rsa
        - chmod 600 ~/.ssh/id_rsa
        - ssh-keyscan github.com >> ~/.ssh/known_hosts
 
        # Submodule 동기화
        - git submodule sync
        - git submodule update --init --recursive
 
        # pnpm 환경 준비
        - corepack enable pnpm
 
        # 모노레포 의존성 설치 (target service only)
        - pnpm install --filter "@inf/web..." --frozen-lockfile
 
    build:
      commands:
        - pnpm run build
 
  cache:
    paths:
      - ~/.pnpm-store/**/*
      - .next/cache/**

인사이트

이번 작업을 통해 몇 가지 흥미로운 점을 확인할 수 있었습니다.

  • CI/CD 파이프라인은 한 번 구축되면 장기간 방치되기 쉽다
  • node_modules 캐시는 항상 성능 향상을 보장하지 않는다
  • pnpm은 이미 상당히 최적화된 구조를 가지고 있다
  • AWS Amplify에서도 SSH 인증을 충분히 활용할 수 있다

빌드 로그를 기반으로 병목을 분석하고 개선하는 과정에서 많은 인사이트를 얻을 수 있었습니다.

비슷한 환경에서 Amplify CI/CD를 운영하고 있다면 빌드 로그를 한 번 확인해보는 것도 좋은 출발점이 될 것 같습니다.

긴 글 읽어주셔서 감사합니다.