콘텐츠로 이동

Local Test and CI Optimization

  1. 로컬에서 완전한 검증 완료 → CI는 배포만 집중
  2. 로컬 테스트 실행 방법 가이드 제공
  3. 신뢰성 보장: 로컬 검증과 CI 검증의 일관성 유지

validate (TypeScript + 테스트 + 빌드 검증)
provision (리소스 프로비저닝 + 검증)
deploy (실제 배포)
  • CI에서 모든 검증을 반복 실행 (시간 소모)
  • 로컬에서 이미 검증했는데 CI에서도 동일한 검증 반복
  • 개발자 경험 저하 (빠른 피드백 부족)

🎯 방안 1: “Trust Local, Verify in CI” 전략 (권장)

섹션 제목: “🎯 방안 1: “Trust Local, Verify in CI” 전략 (권장)”

“로컬에서 검증 완료 → CI는 최소 검증 + 배포 집중”

로컬 개발자
[로컬 검증 완료] ← TypeScript, 테스트, 빌드 검증
[Git Push]
CI (간소화)
[빠른 검증] ← TypeScript만 (빠른 실패 감지)
[리소스 프로비저닝]
[배포]

1. 로컬 검증 스크립트 통합

Terminal window
# package.json에 추가
"precommit": "pnpm run validate:local"
"validate:local": "pnpm run typecheck && pnpm run test && pnpm run build:check"

2. CI 간소화

  • TypeScript 검증: 빠른 실패 감지용 (30초)
  • 테스트: 스킵 또는 선택적 실행
  • 빌드 검증: 배포 전 최종 확인만

3. 검증 신뢰성 보장

  • Git hooks로 로컬 검증 강제
  • CI에서도 최소한의 검증 유지 (안전망)

🎯 방안 2: “Pre-commit Hook + CI Skip” 전략

섹션 제목: “🎯 방안 2: “Pre-commit Hook + CI Skip” 전략”

“Pre-commit hook에서 검증 → CI는 스킵 플래그로 제어”

로컬 개발자
[Git Commit 시도]
[Pre-commit Hook] ← 자동 검증 실행
[검증 실패] → Commit 차단
[검증 성공] → Commit 허용
[Git Push]
CI (검증 스킵)
[배포만 실행]

1. Pre-commit Hook 설정

.husky/pre-commit
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
echo "🔍 Running pre-commit validation..."
pnpm run validate:local || {
echo "❌ Validation failed. Please fix errors before committing."
exit 1
}

2. CI에서 검증 스킵 옵션

.github/workflows/deploy.yml
- name: TypeScript Type Check
run: |
if [ "${{ github.event.head_commit.message }}" =~ "\[skip-ci-validation\]" ]; then
echo "⏭️ Skipping validation (pre-commit verified)"
else
pnpm exec tsc --noEmit --skipLibCheck
fi

🎯 방안 3: “Local CI Script” 전략 (가장 추천)

섹션 제목: “🎯 방안 3: “Local CI Script” 전략 (가장 추천)”

“로컬에서 CI와 동일한 검증 실행 → CI는 배포만”

로컬 개발자
[로컬 CI 스크립트 실행] ← CI와 동일한 검증
[검증 성공]
[Git Push]
CI (검증 최소화)
[빠른 TypeScript 체크] ← 30초
[배포]

1. 로컬 CI 스크립트

scripts/ci-local.sh
#!/bin/bash
set -euxo pipefail
echo "🧪 Running local CI validation..."
# TypeScript 검증
echo "🔍 TypeScript type check..."
pnpm exec tsc --noEmit --skipLibCheck
# 테스트 실행
echo "🧪 Running tests..."
pnpm test
# 빌드 검증
echo "🔨 Build validation..."
pnpm exec wrangler deploy --dry-run --env staging
echo "✅ Local CI validation passed!"

2. CI 간소화

.github/workflows/deploy.yml
validate:
steps:
# 빠른 TypeScript 체크만 (안전망)
- name: Quick TypeScript Check
run: pnpm exec tsc --noEmit --skipLibCheck
timeout-minutes: 2 # 빠른 실패
# 테스트는 스킵 (로컬에서 이미 실행)
- name: Run Tests
run: echo "⏭️ Tests skipped (run locally before push)"
continue-on-error: true

Terminal window
# 모든 테스트 실행
pnpm test
# Watch 모드 (파일 변경 시 자동 재실행)
pnpm test --watch
# 특정 테스트 파일만 실행
pnpm test src/lib/domain.test.ts
# Cloudflare Workers 환경에서 테스트
pnpm test:local
Terminal window
# 타입 체크만 실행
pnpm exec tsc --noEmit --skipLibCheck
# 또는 package.json에 스크립트 추가
# "typecheck": "tsc --noEmit --skipLibCheck"
pnpm run typecheck
Terminal window
# 로컬 모드 (로컬 D1/KV 사용)
pnpm dev:local
# 원격 모드 (Cloudflare 리소스 사용)
pnpm dev:remote
# 특정 환경
wrangler dev --local --env staging
Terminal window
# Health check
curl http://localhost:8787/health
# API 엔드포인트 테스트
curl http://localhost:8787/api/v1/research
curl http://localhost:8787/api/v1/seeds
# Orchestrator 테스트
curl -X POST http://localhost:8787/api/v1/seeds/orchestrate \
-H "Content-Type: application/json" \
-d '{"country": "sg", "category": "news", "date": "2026-01-28"}'
Terminal window
# Staging 환경 dry-run
pnpm exec wrangler deploy --dry-run --env staging
# Production 환경 dry-run
pnpm exec wrangler deploy --dry-run --env production
# Bundle 정보 확인
pnpm exec wrangler deploy --dry-run --env staging > bundle-info.txt
cat bundle-info.txt
# scripts/validate-local.sh 생성 필요
#!/bin/bash
set -euxo pipefail
echo "🔍 Running complete local validation..."
# 1. TypeScript 검증
echo "📝 TypeScript type check..."
pnpm exec tsc --noEmit --skipLibCheck || {
echo "❌ TypeScript errors found"
exit 1
}
# 2. 테스트 실행
echo "🧪 Running tests..."
pnpm test || {
echo "❌ Tests failed"
exit 1
}
# 3. 빌드 검증
echo "🔨 Build validation..."
pnpm exec wrangler deploy --dry-run --env staging || {
echo "❌ Build validation failed"
exit 1
}
echo "✅ All validations passed!"
{
"scripts": {
"validate:local": "bash scripts/validate-local.sh",
"precommit": "pnpm run validate:local"
}
}

validate:
steps:
- name: TypeScript Type Check
run: pnpm exec tsc --noEmit --skipLibCheck # 2-3분
- name: Run Tests
run: pnpm test # 5-10분
- name: Build Validation
run: pnpm exec wrangler deploy --dry-run # 1-2분
validate:
steps:
# 빠른 TypeScript 체크만 (안전망)
- name: Quick TypeScript Check
run: pnpm exec tsc --noEmit --skipLibCheck
timeout-minutes: 2
# 테스트는 스킵 (로컬에서 실행 가정)
- name: Run Tests
run: |
echo "⏭️ Tests skipped"
echo "💡 Run 'pnpm test' locally before pushing"
continue-on-error: true
# 빌드 검증은 유지 (배포 전 최종 확인)
- name: Build Validation
run: pnpm exec wrangler deploy --dry-run --env "$ENV"
timeout-minutes: 3

예상 시간 절약: 5-10분 → 2-3분


validate:
steps:
- name: Check Skip Flag
id: check_skip
run: |
if echo "${{ github.event.head_commit.message }}" | grep -q "\[skip-validation\]"; then
echo "skip=true" >> $GITHUB_OUTPUT
else
echo "skip=false" >> $GITHUB_OUTPUT
fi
- name: TypeScript Type Check
if: steps.check_skip.outputs.skip != 'true'
run: pnpm exec tsc --noEmit --skipLibCheck
- name: Run Tests
if: steps.check_skip.outputs.skip != 'true'
run: pnpm test

사용법:

Terminal window
git commit -m "feat: add new feature [skip-validation]"

jobs:
validate:
# 빠른 검증만
steps:
- name: TypeScript Check
run: pnpm exec tsc --noEmit --skipLibCheck
provision:
# validate와 병렬 실행 가능
needs: [] # 의존성 제거
deploy:
needs: [validate, provision] # 둘 다 완료 후 배포

항목현재최적화 (방안 A)최적화 (방안 C)
TypeScript 검증✅ CI (2-3분)✅ CI (2분)✅ CI (2분)
테스트 실행✅ CI (5-10분)⏭️ 로컬만⏭️ 로컬만
빌드 검증✅ CI (1-2분)✅ CI (1-2분)✅ CI (1-2분)
프로비저닝✅ CI (2-3분)✅ CI (2-3분)✅ 병렬 (2-3분)
총 소요 시간10-18분5-7분5-7분
시간 절약-50-60%50-60%

Phase 1: 로컬 검증 스크립트 추가 (즉시 적용)

섹션 제목: “Phase 1: 로컬 검증 스크립트 추가 (즉시 적용)”
  1. scripts/validate-local.sh 생성

    • TypeScript 검증
    • 테스트 실행
    • 빌드 검증
  2. package.json 스크립트 추가

    {
    "scripts": {
    "validate:local": "bash scripts/validate-local.sh",
    "typecheck": "tsc --noEmit --skipLibCheck"
    }
    }
  3. README에 로컬 검증 가이드 추가

  1. CI 검증 최소화

    • TypeScript만 유지 (빠른 실패 감지)
    • 테스트는 스킵 또는 선택적
    • 빌드 검증은 유지
  2. 시간 단축 확인

    • CI 실행 시간 모니터링
    • 필요 시 추가 최적화
  1. Husky 설정

    • Pre-commit hook으로 자동 검증
    • 검증 실패 시 commit 차단
  2. 개발자 경험 향상

    • 빠른 피드백
    • CI 실패 감소

  • TypeScript 검증

    Terminal window
    pnpm exec tsc --noEmit --skipLibCheck
  • 테스트 실행

    Terminal window
    pnpm test
  • 빌드 검증

    Terminal window
    pnpm exec wrangler deploy --dry-run --env staging
  • 로컬 서버 테스트 (선택사항)

    Terminal window
    pnpm dev:local
    # 다른 터미널에서
    curl http://localhost:8787/health
Terminal window
# scripts/validate-local.sh 실행
pnpm run validate:local

1. 환경 일관성 유지

Terminal window
# 로컬에서 CI와 동일한 Node.js 버전 사용
nvm use 20 # 또는 .nvmrc 파일 사용
# 로컬에서 CI와 동일한 pnpm 버전 사용
pnpm --version # 9.x 확인

2. Docker로 로컬 CI 재현 (고급)

Dockerfile.ci
FROM node:20
RUN npm install -g pnpm@9
WORKDIR /app
COPY . .
RUN pnpm install --frozen-lockfile
RUN pnpm test

3. CI에서 최소 검증 유지 (안전망)

  • TypeScript 검증은 항상 실행
  • 빠른 실패로 잘못된 코드 배포 방지

  • 빠른 피드백: 로컬에서 즉시 검증
  • CI 시간 단축: 50-60% 시간 절약
  • 신뢰성 향상: 로컬 검증 후 배포
  • 리소스 절약: CI 실행 시간 감소
  • 비용 절감: GitHub Actions 시간 단축
  • 배포 속도: 빠른 배포 사이클

가장 추천하는 방식: 방안 A (CI 검증 최소화)

섹션 제목: “가장 추천하는 방식: 방안 A (CI 검증 최소화)”

이유:

  1. 구현 간단: 기존 CI 구조 최소 변경
  2. 신뢰성 유지: TypeScript 검증으로 안전망 제공
  3. 시간 절약: 50-60% CI 실행 시간 단축
  4. 개발자 경험: 로컬 검증 후 안심하고 배포

구현 순서:

  1. scripts/validate-local.sh 생성
  2. package.jsonvalidate:local 스크립트 추가
  3. CI에서 테스트 단계 스킵 또는 선택적 실행
  4. 모니터링 및 조정

예상 소요 시간: 1-2시간


작성 일시: 2026-01-28
우선순위: High
구현 난이도: Low-Medium