CI 설정하기(Setting up CI)
대상 독자: 개발자와 관리자(Developers and Admins)
출처: 문서
본문
대상 독자: 개발자와 관리자(Developers and Admins)
Backstage에 CI가 왜 중요한가
Backstage 인스턴스는 살아있는 프로젝트예요. 플러그인을 추가하고, 구성을 커스터마이즈하고, 의존성을 업데이트하다 보면 미묘한 방식으로 문제가 생길 수 있어요. 한 패키지의 TypeScript 오류, 백엔드 시작을 막는 구성 오타, 더 이상 빌드되지 않는 Docker 이미지 같은 것들이죠. 지속적 통합(CI)은 이런 문제를 프로덕션에 도달하기 전에 모든 풀 리퀘스트에서 잡아내요.
Backstage를 위한 좋은 CI 파이프라인은 다음을 검증해요.
-
코드가 컴파일되고 린트 검사를 통과함
-
모노레포의 모든 패키지에서 테스트가 통과함
-
구성 파일이 유효함
-
배포 아티팩트(보통 Docker 이미지)가 성공적으로 빌드됨
무엇을 검사할까
이 검사들은 어떤 CI 시스템을 쓰든 적용돼요. 대부분 Backstage CLI가 제공하는 명령에 매핑돼요.
린트(Lint)
yarn backstage-cli repo lint
모노레포의 모든 패키지에 걸쳐 ESLint를 실행해요. 코드 품질 문제, 사용되지 않는 임포트, 스타일 위반을 잡아요. 사용 가능한 옵션은 repo lint를 참고하세요.
타입 검사(Type checking)
yarn tsc:full
--skipLibCheck false와 --incremental false로 TypeScript 컴파일러를 실행해 프로젝트 전체에 걸쳐 완전한 타입 검사를 수행해요. 이것은 기본 yarn tsc보다 더 엄격하고, 증분 빌드가 놓칠 수 있는 타입 오류를 잡아요.
테스트(Tests)
yarn backstage-cli repo test
모든 패키지의 테스트 스위트를 실행해요. Backstage CLI가 어떤 테스트 러너를 쓸지 자동으로 감지하고 모노레포 특화 구성을 처리해요. 사용 가능한 옵션은 repo test를 참고하세요.
폐기된 API 사용(Deprecated API usage)
yarn backstage-cli repo list-deprecations
폐기된 Backstage API 사용에 대해 코드를 스캔해요. 버전 업그레이드를 준비할 때 특히 유용하지만, CI에서 실행하면 새 코드가 폐기된 패턴을 도입하지 않음을 보장해요. 사용 가능한 옵션은 repo list-deprecations를 참고하세요.
빌드(Build)
yarn build:all
Dockerfile이 필요로 하는 백엔드 번들을 포함해 모노레포의 모든 패키지를 빌드해요. CI에서 빌드를 실행하면 타입 검사만으로는 드러나지 않을 수 있는 컴파일 오류, 누락된 의존성, 깨진 임포트를 잡아요. 사용 가능한 옵션은 repo build를 참고하세요.
구성 검증(Configuration validation)
yarn backstage-cli config:check --lax --strict \
--config app-config.yaml \
--config app-config.production.yaml
구성 파일을 구성 스키마에 대해 검증해요. --lax 플래그는 환경 변수가 해석되지 않은 채로 남아 있게 허용하고(프로덕션 시크릿이 없는 CI에서 유용), --strict는 구성 구조가 스키마와 일치하는지 보장해요. 여러 개의 --config 플래그를 넘기면 기본 구성과 함께 프로덕션 구성을 검증할 수 있어요. 사용 가능한 옵션은 config:check를 참고하세요.
Docker 빌드(선택 사항)
yarn build-image
Docker 이미지가 성공적으로 빌드되는지 검증해요. 이 스크립트는 올바른 빌드 컨텍스트와 Dockerfile 경로로 docker build를 실행해요. 패키징 시점에만 드러나는 호환되지 않는 의존성 같은 문제를 잡아요. 이 단계는 yarn build:all의 사전 빌드된 백엔드 번들을 기대해요.
이 단계는 선택 사항이에요. Docker 빌드는 느릴 수 있어서, 어떤 팀은 모든 풀 리퀘스트보다는 기본 브랜치에 머지되거나 예약된 시점에만 실행하는 것을 선호해요.
GitHub Actions
create-app으로 Backstage 인스턴스를 만들었다면 .github/workflows/ci.yml에 GitHub Actions 워크플로우가 포함돼요. 매 풀 리퀘스트마다 위의 모든 검사를 실행해요.
워크플로우가 단계별로 무엇을 하는지는 다음과 같아요.
Node.js 및 Yarn 설정
워크플로우는 Node.js 24.x를 설치하고 node_modules와 전역 Yarn 캐시를 모두 캐시해요. 이후 실행에서는 락파일이 바뀌지 않았다면 yarn install --immutable이 몇 초 만에 끝나요.
CI 단계
파이프라인은 이 단계들을 순서대로 실행해요.
-
Lint -- 모든 패키지에 걸쳐 코드 품질 검사
-
Type checking -- 완전한 TypeScript 컴파일
-
Deprecations -- 폐기된 API 사용에 플래그 표시
-
Tests -- 전체 테스트 스위트 실행
-
Build -- 모든 패키지 빌드 (
yarn build:all) -
Config check -- 기본과 프로덕션 구성을 함께 검증
-
Docker build -- 컨테이너 이미지 빌드 검증
테스트는 전체 빌드 전에 실행돼 가장 흔한 실패 모드에 대해 더 빠른 피드백을 줘요. Dockerfile이 사전 빌드된 백엔드 번들을 기대하므로 빌드는 Docker 빌드 전에 실행돼요.
워크플로우 커스터마이즈
일반적인 수정 사항:
-
여러 Node.js 버전에서 테스트하도록 매트릭스 전략을 추가 (템플릿은 Node.js 22와 24를 지원해요).
-
기본 브랜치에 머지할 때 Docker 이미지를 레지스트리에 푸시하는 배포 단계를 추가.
-
포함된 Playwright 구성을 사용해 엔드투엔드 테스트를 추가 (
yarn test:e2e).
다른 CI 시스템
같은 검사가 어떤 CI 시스템에서든 동작해요. 파이프라인 구문만 바뀔 뿐이에요.
GitLab CI
stages:
- validate
- build
- test
default:
cache:
key:
files:
- yarn.lock
paths:
- node_modules/
- .yarn/cache/
variables:
CI: 'true'
NODE_OPTIONS: '--max-old-space-size=8192'
lint:
stage: validate
script:
- yarn install --immutable
- yarn backstage-cli repo lint
type-check:
stage: validate
script:
- yarn install --immutable
- yarn tsc:full
build:
stage: build
script:
- yarn install --immutable
- yarn build:all
test:
stage: test
script:
- yarn install --immutable
- yarn backstage-cli repo test
Jenkins
pipeline {
agent {
docker {
image 'node:24-slim'
}
}
environment {
CI = 'true'
NODE_OPTIONS = '--max-old-space-size=8192'
}
stages {
stage('Install') {
steps {
sh 'yarn install --immutable'
}
}
stage('Lint') {
steps {
sh 'yarn backstage-cli repo lint'
}
}
stage('Type check') {
steps {
sh 'yarn tsc:full'
}
}
stage('Build') {
steps {
sh 'yarn build:all'
}
}
stage('Test') {
steps {
sh 'yarn backstage-cli repo test'
}
}
stage('Config check') {
steps {
sh 'yarn backstage-cli config:check --lax --strict --config app-config.yaml --config app-config.production.yaml'
}
}
}
}
Azure DevOps
참고: YAML pr: 트리거는 저장소가 GitHub 또는 Bitbucket Cloud에 호스팅될 때만 동작해요. Azure Repos Git을 사용한다면, 이 파이프라인을 풀 리퀘스트에서 실행하도록 빌드 검증을 위한 브랜치 정책을 구성하세요.
trigger:
- main
pool:
vmImage: 'ubuntu-latest'
variables:
CI: 'true'
NODE_OPTIONS: '--max-old-space-size=8192'
steps:
- task: NodeTool@0
inputs:
versionSpec: '24.x'
displayName: use node.js
- script: yarn install --immutable
displayName: yarn install
- script: yarn backstage-cli repo lint
displayName: lint
- script: yarn tsc:full
displayName: type checking
- script: yarn backstage-cli repo list-deprecations
displayName: deprecations
- script: yarn build:all
displayName: build
- script: yarn backstage-cli repo test
displayName: tests
- script: yarn backstage-cli config:check --lax --strict --config app-config.yaml --config app-config.production.yaml
displayName: config check
GitHub Actions와의 주요 차이점
-
캐싱: GitHub Actions에는 내장 캐시 액션이 있어요. 다른 시스템은 캐시 경로와 키를 수동으로 구성해야 해요.
-
Docker-in-Docker: 어떤 CI 시스템은 파이프라인 안에서
docker build를 실행하려면 추가 구성이 필요해요. Docker 지원에 대해서는 플랫폼 문서를 확인하세요. -
환경 변수: 파이프라인 환경에
CI=true와NODE_OPTIONS=--max-old-space-size=8192를 설정하세요.CI변수는 Jest 같은 도구에서 결정적 동작을 보장하고, 메모리 한도는 아래에서 설명해요.
환경 변수
생성된 워크플로우에는 두 가지 환경 변수가 설정돼요.
-
CI=true-- Jest 같은 도구에서 CI 특화 동작을 활성화(예: 변경된 테스트만이 아니라 모든 테스트 실행)하고 대화형 프롬프트를 막아요. -
NODE_OPTIONS=--max-old-space-size=8192-- Node.js 힙 메모리 한도를 8GB로 늘려요. 모노레포 전체에 걸친 TypeScript 컴파일과 번들링은, 특히 플러그인을 많이 추가할수록 기본 메모리 한도를 초과할 수 있어요. 이 설정은yarn tsc:full과yarn build:all중 메모리 부족 크래시를 막아요.