[CL] CI(지속적 통합) 파이프라인 구축 설계 - 100-hours-a-week/2-hertz-wiki GitHub Wiki
📚 목차
📄 CI 설계 문서
1. CI 설계 배경
1.1 도입 배경
현재 프로젝트는 프론트엔드(Next.js), 백엔드(Spring Boot), AI 서버(FastAPI) 로 구성되어 있으며,
각 파트는 개별적으로 개발·운영되고 팀원 또한 나뉘어 병렬적으로 작업 중입니다.
이러한 구조에서 다음과 같은 문제가 반복되고 있습니다:
- 코드 병합 시 의존성 충돌
- 테스트 누락 또는 빌드 실패
- 개발 환경 차이로 인한 실행 오류
특히 CI 없이 수동으로 검증하던 방식은 다음과 같은 한계를 드러냈습니다:
- 반복적인 빌드/테스트 수행으로 인한 생산성 저하
- PR 병합 이후 오류 발견으로 인한 피드백 지연
- 테스트 누락이나 실행 실패를 늦게 인지하여 품질 관리에 어려움 발생
1.2 CI 도입의 목적
이러한 문제를 해결하고자, 자동화된 CI 파이프라인을 도입하여 다음을 실현하고자 합니다:
- 모든 개발자가 코드를 병합하기 전, 기초적인 빌드 및 테스트 검증 자동화
- 프론트/백/AI 각 파트에 맞춘 분리된 CI 구성으로 기술 스택별 검증 수행
- GitHub Actions 기반으로 운영 부담이 적은 경량 CI 환경 구축
- 반복 작업을 줄이고, PR 단계에서 오류를 조기에 감지하여
협업 효율성과 코드 품질을 동시에 확보
2. CI 도구 선택
선택 도구: GitHub Actions
선택 배경 및 논리
현재 프로젝트는 GitHub 저장소를 중심으로 관리되고 있으며,
개발 효율성과 운영 편의성을 고려할 때 GitHub Actions는 가장 적합한 선택입니다.
CI 도입의 궁극적인 목적은 “지속 가능한 품질 관리와 협업 자동화의 정착” 이며, GitHub Actions는 이 목적을 충족하는 다음과 같은 강점을 갖고 있습니다.
2.1 선택 이유 및 근거
항목 |
설명 |
즉시 활용 가능 |
GitHub 저장소에 .github/workflows/ 디렉토리만 추가하면 별도 설정 없이 바로 CI 파이프라인 구성 가능 |
외부 의존성 없음 |
Jenkins, GitLab CI처럼 별도 서버나 러너 설치가 필요 없어 초기 진입 비용이 낮음 |
표준 이벤트 지원 |
push , pull_request , release 등 GitHub 중심의 워크플로와 유기적으로 동작 |
보안성 확보 (Secrets 관리) |
GitHub Secrets 를 통해 SSH 키, AWS 인증 정보 등을 안전하게 암호화하여 관리 가능 |
확장성 |
Docker 빌드, AWS S3/ECS 배포, Slack/Discord 알림 등 다양한 액션으로 확장 가능 |
유지보수 용이성 |
워크플로 설정이 코드(YAML)로 관리되므로 Git 기반 협업, 리뷰, 버전 추적이 쉬움 |
3. CI 도입 효과
CI 도입을 통해 기존 Big Bang 배포 방식에서 발생하던 문제를 자동화 기반으로 개선하고, 각 파트별 개발 안정성과 협업 효율성을 강화할 수 있습니다.
특히 PR 병합 이전 단계에서 테스트와 빌드 검증을 통해 문제를 조기 감지하고, 일관된 품질을 유지할 수 있는 기반이 마련됩니다.
3.1 백엔드(Spring Boot)
- Gradle 기반 빌드 및 테스트 자동화
- JUnit 기반 유닛/통합 테스트로 기능 이상 조기 발견
- PR 병합 전 선제적 검증으로 QA 이전 품질 확보
3.2 프론트엔드(Next.js)
- 유닛 테스트 자동 실행 (예: Jest)으로 빠른 피드백 제공
- Pull Request 시점에서 UI/비즈니스 로직 문제 조기 발견
- 빌드 성공 여부 확인을 통한 배포 안정성 확보
- 스토리북 등과 연계한 UI 컴포넌트 테스트 도입 기반 마련
3.3 AI 서버(FastAPI)
- pytest 기반 테스트 자동화로 예측 결과 검증
- 주요 API와 모델 로직 변경 시 회귀 테스트 자동 수행
- 테스트 누락 방지 및 코드 신뢰성 향상
3.4 공통 효과
항목 |
설명 |
개발 생산성 향상 |
반복적인 수작업 최소화 및 자동화 기반 개발 프로세스 정립 |
테스트 누락 방지 |
커밋/PR 시 자동 테스트 실행으로 품질 확보 |
협업 안정성 증가 |
표준화된 워크플로를 통한 팀 간 협업 효율 향상 |
이슈 조기 감지 |
빌드 실패, 의존성 충돌, 기능 오류 등을 초기에 감지 |
일관된 배포 품질 유지 |
배포 전 테스트 및 빌드를 통과한 코드만 병합 가능 |
4. CI 파이프라인 설계
4.1 CI 트리거 조건
조건 |
설명 |
main 브랜치 Push 또는 PR |
전체 파이프라인 실행 |
PR 발생 시 |
정적 분석, 빌드, 테스트까지만 수행, CD는 미포함 |
GitHub Actions 러너 |
ubuntu-latest 환경 사용 |
4.2 브랜치별 목적 요약
브랜치 |
목적 |
특징 요약 |
develop |
기능 통합 및 시나리오 검증 |
통합 테스트 포함, 전체 서비스 흐름 검증 |
main |
최종 품질 인증 및 배포 전 빌드/아티팩트 확보 |
가장 강도 높은 검증, 최종 산출물 생성 |
4.3 파이프라인 구성
4.3.1 프론트엔드 (Next.js)
단계 |
develop 브랜치 |
main 브랜치 |
사용 기술 |
1. 코드 체크아웃 |
O |
O |
actions/checkout |
2. 의존성 설치 |
O |
O |
npm, yarn |
3. 유닛 테스트 |
O |
O |
Jest |
4. 빌드 |
O |
O |
npm run build |
5. 아티팩트 저장 |
X |
O (.next, 정적 파일 등) |
GitHub artifact |
6. 배포 (CD) |
X |
(향후 추가 예정) |
실행: pm2 start npm -- start |
4.3.2 백엔드 (Spring Boot)
단계 |
develop 브랜치 |
main 브랜치 |
사용 기술 |
1. 코드 체크아웃 |
O |
O |
actions/checkout |
2. 의존성 설치 |
O |
O |
Gradle, Java 17 |
3. 유닛 테스트 |
O |
O |
JUnit |
4. 통합 테스트 |
O |
O |
SpringBootTest |
5. 빌드 |
O |
O |
./gradlew build |
6. 아티팩트 저장 |
X |
O (.jar) |
GitHub artifact |
7. 배포 (CD) |
X |
(향후 추가 예정) |
실행: java -jar |
4.3.3 AI 서버 (FastAPI)
단계 |
develop 브랜치 |
main 브랜치 |
사용 기술 |
1. 코드 체크아웃 |
O |
O |
actions/checkout |
2. 의존성 설치 |
O |
O |
pip, requirements.txt |
3. 유닛 테스트 |
O |
O |
pytest |
4. 빌드 |
O |
O |
(optional: Python 패키징) |
5. 아티팩트 저장 |
X |
O (모델 파일, 설정 등) |
GitHub artifact |
6. 배포 (CD) |
X |
(향후 추가 예정) |
실행: uvicorn , pm2 등 |
5. CI 파이프라인
5.1 CI 파이프라인 다이어그램

5.2 브랜치 전략

6. 스크립트
백엔드
# .github/workflows/backend-ci.yml
name: Backend CI
on:
pull_request:
branches: [ main, develop ] # PR이 main 또는 develop 브랜치로 열릴 때 트리거
jobs:
backend-ci:
runs-on: ubuntu-latest # GitHub Actions의 실행 환경(OS)
steps:
# 1. 소스 코드 체크아웃
- name: Checkout repository
uses: actions/checkout@v3
# 2. Java 17 설치 (Spring Boot 3.x 기준)
- name: Set up JDK
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'
# 3. Gradle 캐시 적용 (빌드 시간 단축)
- name: Cache Gradle
uses: actions/cache@v3
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: gradle-${{ runner.os }}-
# 4. 단위 테스트 실행 (JUnit 기반)
- name: Run Unit Tests
run: ./gradlew test
# 5. 애플리케이션 빌드 (JAR 생성)
- name: Build Spring Boot Application
run: ./gradlew build
# 6. 통합 테스트 실행 (존재하는 경우)
- name: Run Integration Tests
run: ./gradlew integrationTest
continue-on-error: false # integrationTest task가 없으면 실패하지 않게 설정 가능
# 7. 빌드 결과(.jar) 아티팩트로 저장
- name: Upload JAR Artifact
uses: actions/upload-artifact@v3
with:
name: springboot-jar
path: build/libs/*.jar
# 8. Discord로 CI 결과 전송 (성공/실패 상관없이 항상 실행)
- name: Notify Discord
if: always()
run: |
STATUS="${{ job.status }}" # success / failure
curl -H "Content-Type: application/json" \
-X POST \
-d "{\"username\": \"Backend CI\", \"content\": \"📦 Backend CI 결과: **${STATUS}**\n🔗 [${{ github.repository }}@${{ github.ref_name }}](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})\"}" \
${{ secrets.DISCORD_WEBHOOK_URL }}
프론트엔드
# .github/workflows/frontend-ci.yml
name: Frontend CI
on:
pull_request:
branches: [ main, develop ] # PR 발생 시 CI 트리거
jobs:
frontend-ci:
runs-on: ubuntu-latest # Node.js 환경 제공
steps:
# 1. 코드 체크아웃
- name: Checkout repository
uses: actions/checkout@v3
# 2. Node.js 설치 (Next.js 13/14 권장 버전)
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
# 3. 의존성 설치 (CI 캐시 최적화된 npm ci 사용)
- name: Install dependencies
run: npm ci
# 4. 유닛 테스트 실행 (Jest 기반)
- name: Run Unit Tests (Jest)
run: npm run test
# 5. 앱 빌드 (.next 디렉토리 생성)
- name: Build Next.js App
run: npm run build
# 6. 빌드 결과 아티팩트 업로드 (.next 폴더)
- name: Upload .next Build Artifact
uses: actions/upload-artifact@v3
with:
name: nextjs-app
path: .next
# 7. Discord 알림 전송 (성공/실패 관계없이 항상 실행됨)
- name: Notify Discord
if: always()
run: |
STATUS="${{ job.status }}" # success / failure
curl -H "Content-Type: application/json" \
-X POST \
-d "{\"username\": \"Frontend CI\", \"content\": \"🖥️ Frontend CI 결과: **${STATUS}**\n🔗 [${{ github.repository }}@${{ github.ref_name }}](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})\"}" \
${{ secrets.DISCORD_WEBHOOK_URL }}
AI (fastAPI +AI model)
# .github/workflows/fastapi-ai-ci.yml
name: FastAPI + AI Model CI
on:
pull_request:
branches: [ main, develop ] # main, develop 브랜치로 PR 발생 시 CI 실행
jobs:
fastapi-ai-ci:
name: FastAPI Server Test and Model Validation
runs-on: ubuntu-latest # GitHub Actions에서 사용하는 가상 환경 (우분투)
steps:
# 1. GitHub 리포지토리 코드 체크아웃
- name: Checkout Repository
uses: actions/checkout@v3
# 2. Python 3.10 설치
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.10'
# 3. 의존성 설치
- name: Install Dependencies
run: |
python -m pip install --upgrade pip # pip 최신화
pip install -r requirements.txt # 프로젝트 기본 의존성 설치
pip install pytest # 테스트 프레임워크 설치
# 4. 유닛 테스트 실행
- name: Run Unit Tests (pytest)
run: |
pytest tests/ # tests 디렉토리 내 테스트 실행
# 5. AI 모델 파일 존재 여부 확인
- name: Validate AI Model File (optional)
run: |
if [ -f "./models/my_model.pt" ]; then
echo "✅ 모델 파일 존재 확인 완료"
else
echo "❌ 모델 파일 누락" && exit 1 # 없으면 CI 실패 처리
fi
# 6. 모델 파일을 GitHub Actions 아티팩트로 저장 (다음 워크플로에서 활용 가능)
- name: Save Artifacts (AI Model)
if: success()
uses: actions/upload-artifact@v4
with:
name: ai-model
path: ./models/my_model.pt
# 7. Discord Webhook으로 CI 결과 알림 전송 (성공/실패 여부 상관없이 항상 실행됨)
- name: Notify Discord (always)
if: always()
run: |
STATUS="${{ job.status }}" # CI 성공/실패 상태
curl -H "Content-Type: application/json" \
-X POST \
-d "{\"username\": \"CI Bot\", \"content\": \"📢 FastAPI + AI Model CI 실행 결과: **${STATUS}**\n🔗 [${{ github.repository }}@${{ github.ref_name }}](${{
github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})\"}" \
${{ secrets.DISCORD_WEBHOOK_URL }}