CI/CD 스터디 04: Build, Test, Quality Gate

Build, lint, unit/integration test, coverage, test artifact, 품질 게이트를 CI 파이프라인에서 어떻게 배치할지 정리합니다.

CI는 코드를 자동으로 빌드하는 기능이 아니라, 운영에 올리면 안 되는 변경을 최대한 앞에서 걸러내는 품질 게이트입니다.

품질 게이트의 목적

좋은 CI는 모든 테스트를 많이 돌리는 것이 아니라, 변경 위험을 빠르게 분류합니다. format/lint는 수십 초 안에 실패해야 하고, unit test는 개발자에게 즉시 피드백을 줘야 하며, integration/e2e test는 운영 장애를 만들 수 있는 흐름을 검증해야 합니다.

  • format: 코드 스타일 논쟁을 자동화로 제거합니다.
  • lint/static check: 잠재 오류, 미사용 변수, 위험 API 사용을 찾습니다.
  • unit test: 함수와 모듈 단위 회귀를 빠르게 잡습니다.
  • integration test: DB, queue, external adapter 같은 경계를 검증합니다.
  • build: artifact 또는 container image가 실제로 만들어지는지 확인합니다.
  • quality gate: coverage, vulnerability, policy 결과를 merge/deploy 조건으로 연결합니다.

로컬에서 먼저 재현하기

CI에서만 실패하는 테스트는 디버깅 비용이 큽니다. 따라서 파이프라인 명령은 로컬에서도 거의 같은 순서로 실행 가능해야 합니다.

# Node.js 예시
npm ci
npm run format:check
npm run lint
npm test
npm run build

# Python 예시
python3 -m venv .venv
. .venv/bin/activate
pip install -r requirements.txt
python -m pytest -q
python -m compileall .

# Maven 예시
mvn -B -ntp test
mvn -B -ntp package

# Go 예시
go test ./...
go build ./...

테스트 리포트와 artifact

테스트가 실패했을 때 로그만 남기면 원인 분석이 느립니다. JUnit XML, coverage report, browser screenshot, e2e trace 같은 산출물을 artifact로 남기면 실패를 재현하기 쉽습니다.

test:
  stage: test
  image: python:3.12-slim
  script:
    - pip install -r requirements.txt
    - pytest --junitxml=reports/junit.xml --cov=app --cov-report=xml:reports/coverage.xml
  artifacts:
    when: always
    reports:
      junit: reports/junit.xml
      coverage_report:
        coverage_format: cobertura
        path: reports/coverage.xml
    paths:
      - reports/
    expire_in: 14 days

GitHub Actions 품질 게이트 예시

jobs:
  quality:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: "22"
          cache: npm
      - run: npm ci
      - run: npm run lint
      - run: npm test -- --ci
      - run: npm run build
      - name: Upload test reports
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: test-reports
          path: reports/

게이트 강도 조절

브랜치/이벤트권장 게이트이유
feature branchformat, lint, unit test개발자 feedback 속도가 중요합니다.
pull/merge requestunit, integration, build, policymain에 들어가기 전 회귀를 막습니다.
main push전체 test, image build, scan, staging deploy배포 가능한 산출물을 만듭니다.
release tag재빌드 또는 digest pin 검증, production approval운영 변경 이력을 고정합니다.

실무 판단 기준

  1. 항상 먼저 실패해야 하는 검사는 앞쪽 job에 둡니다.
  2. 느린 e2e test는 모든 commit보다 main 또는 nightly로 분리할 수 있습니다.
  3. 테스트가 flaky하면 재시도보다 원인 분류가 먼저입니다. flaky test는 신뢰를 갉아먹습니다.
  4. coverage 숫자만 보지 말고, 운영 장애를 만들었던 경로가 test로 고정됐는지 확인합니다.
  5. 품질 게이트 실패는 우회보다 기록과 예외 만료일이 중요합니다.

참고 문서

BGM EVER