[CL] v1 CI CD 문서화 - 100-hours-a-week/6-nemo-wiki GitHub Wiki
1. 개요
v1
에서의 CI/CD는 단일 GCP VM 환경에서 운영되는 3개의 서비스 (BE,FE,AI)를 대상으로 GitHub Actions와 PM2 + Shell Script 기반으로 자동화 배포 체계를 구성하였습니다.
- 목표: 수작업 배포 부담을 줄이고 배포 흐름 자동화
- 환경: GCP VM (Ubuntu), GitHub, PM2, Discord Webhook
- 적용 서비스
- BE: Spring Boot
- FE: Next.js
- AI: FastAPI + ChromaDB
- 구성 방식
- 코드 Push → GitHub Actions → SSH 접속 → 서버 내
deploy.sh
실행 - 환경별
.env
로 분리된 설정 주입 - 배포 후 헬스체크 → 배포 성공/실패 여부 알림 전송 (서비스 웹훅 + 클라우드 웹훅)
- 코드 Push → GitHub Actions → SSH 접속 → 서버 내
- dev/prod 전략
- develop 브랜치: 완전 자동화 배포
- main 브랜치: 수동 승인 후 배포
2. 공통 CI/CD 아키텍처
v1
에선 3개의 서비스가 모두 비슷한 CI/CD 아키텍처를 따릅니다.
GitHub Actions를 기반으로 CI는 자동화하고, CD는 SSH 및 Shell Script를 통해 서버 내에서 소스 코드를 불러와 빌드 후 실행하는구조입니다. 단, BE의 경우 서버 내에서 빌드하는 작업이 비교적 무겁기 때문에 서버 리소스를 고려하여 GitHub Actions에서 빌드 후 빌드 산출물을 scp
방식을 통해 서버에 전송하는 방식입니다.
구성 요소 | 설명 |
---|---|
CI 도구 | GitHub Actions |
CD 방식 | SSH 접속 후 Shell Script 실행 (deploy.sh ) |
서비스 실행 | PM2 프로세스 매니저 |
환경 관리 | .env 파일 기반 서비스별 환경 분리 |
알림 시스템 | Discord Webhook (배포 성공/실패, 롤백 등) |
배포 스크립트 | deploy.sh , run.sh , rollback.sh , healthcheck.sh , backup.sh |
헬스체크 방식 | API 또는 포트 응답 체크 + 실패 시 알림 전송 |
브랜치 전략 | develop : 자동 배포, main : 수동 승인 이후 배포 |
3. 서비스별 상세 흐름
3.1. BE (Spring Boot)
-
CI/CD 전체 흐름
[GitHub Push (develop or main)] ↓ [GitHub Actions] - Gradle Build - JAR 파일 생성 - scp로 서버 전송 ↓ [SSH 접속 → 서버에서 deploy.sh 실행] ↓ [최신 jar 서버 내 백업] ↓ [PM2로 기존 프로세스 종료 및 새로운 프로세스 실행] ↓ [헬스체크 + Discord Webhook 성공여부 알림]
-
서버 디렉토리 구조
~/nemo/cloud/v1/backend/semi-automated/ ├── backup.sh # 배포 전 백업 ├── deploy-cicd.sh # CI/CD 자동 배포용 (GitHub Actions에서 호출) ├── deploy.sh # 수동 배포용 (서버 내 빌드 및 실행) ├── healthcheck.sh # 헬스체크 및 상태 확인 ├── rollback.sh # 이전 버전으로 롤백 ├── run.sh # PM2 실행 스크립트 └── README.md # 문서 설명
3.2. FE (Next.js)
-
CI/CD 전체 흐름
[GitHub Push (develop or main)] ↓ [GitHub Actions] - SSH 접속 - 서버 내부 진입 - deploy.sh 실행 ↓ [서버 내 git pull → pnpm install → pnpm build] ↓ [PM2로 기존 프로세스 종료 및 새로운 프로세스 실행] ↓ [헬스체크 + Discord Webhook 성공여부 알림]
-
서버 디렉토리 구조
~/nemo/cloud/v1/frontend/semi-automated/ ├── backup.sh # 배포 전 백업 ├── deploy.sh # git pull 및 빌드 + 실행 ├── healthcheck.sh # 헬스체크 및 상태 확인 ├── rollback.sh # 이전 빌드로 롤백 ├── run.sh # PM2 실행 스크립트 └── README.md # 문서 설명
3.3. AI (FastAPI)
-
CI/CD 전체 흐름
[GitHub Push (develop or main)] ↓ [GitHub Actions] - SSH 접속 - 서버 내부 진입 - deploy.sh 실행 ↓ [서버 내 git pull → Python venv 활성화 → pip install] ↓ [PM2로 기존 프로세스 종료 및 새로운 프로세스 실행] ↓ [헬스체크 + Discord Webhook 성공여부 알림]
-
서버 내 디렉토리 구조
~/nemo/cloud/v1/ai/semi-automated/ ├── backup.sh # 배포 전 백업 ├── deploy.sh # git pull 및 빌드 + 실행 ├── healthcheck.sh # 헬스체크 및 상태 확인 ├── rollback.sh # 이전 빌드로 롤백 ├── run.sh # PM2 실행 스크립트 └── README.md # 문서 설명
4. GitHub Actions 설정
4.1. SSH Key
아래와 같이 SSH 키를 생성하면 두 가지 파일이 생성 되는데 각각 알맞게 등록해야 함.
- GitHub Actions에서 사용해야 하는 키는
id_rsa
(비공개 키) - 서버에는
id_rsa.pub
(공개 키)만 등록
# SSH 키 생성 (로컬 PC)
ssh-keygen -t rsa -b 4096 -C "[email protected]"
# 공개 키 등록 (서버에)
cat ~/.ssh/id_rsa.pub
# 비공개 키 등록 (GitHub Secrets에)
cat ~/.ssh/id_rsa
# → PROD_SSH_KEY 또는 DEV_SSH_KEY 로 등록
항목 | 저장 위치 | 설명 |
---|---|---|
id_rsa.pub |
서버 (~/.ssh/authorized_keys ) |
공개 키, GitHub에 등록 ❌ |
id_rsa |
GitHub Secrets (*_SSH_KEY ) |
비공개 키, GitHub에 등록 ✅ |
4.2. Secrets 설정
키 이름 | 설명 |
---|---|
DEV_HOST |
개발 서버 IP 또는 도메인 |
DEV_USER |
개발 서버의 SSH 사용자명 (예: ubuntu ) |
DEV_SSH_KEY |
개발 서버 접속용 SSH 비공개 키 |
키 이름 | 설명 |
---|---|
PROD_HOST |
운영 서버 IP 또는 도메인 |
PROD_USER |
운영 서버의 SSH 사용자명 (예: ubuntu ) |
PROD_SSH_KEY |
운영 서버 접속용 SSH 비공개 키 |
4.3. Environments 설정
환경 이름 | 연결 브랜치 | 승인 조건 | 설명 |
---|---|---|---|
dev |
develop |
없음 | 개발 서버, 자동 배포 |
prod |
main |
수동 승인 필요 | 운영 서버, 승인 후 배포 진행 |
-
설정 방법
- GitHub Settings → Environments → New environment로 prod 환경 생성
- Required Reviewers 체크 및 생성
- dev 환경 생성은 필요 없음.
-
Workflows 사용 예시
on: workflow_dispatch: jobs: deploy: runs-on: ubuntu-latest environment: name: prod
5. 한계 및 회고
5.1. 기존 설계 차이
- v1에서는 CI/CD의 중간 저장소 및 배포 관리 방식이 기존 설계와 변경되었습니다.
- 기존 CI는 GCS를 아티팩트 저장소로 활용해 GitHub Actions → GCS 업로드 → 서버에서 다운로드 하는 방식
- v1에서는 중간 저장소 없이 서버 내에서
빌드 디렉토리
,로그
,백업 파일
등을 관리하는 구조로 변경 - 단, 백엔드의 경우 빌드 리소스가 많이 들기 때문에 GitHub Action에서 빌드 후 JAR만 서버로 전송하는 방식
-
변경 이유
- 단일 VM 환경에서는 GCS보다 로컬 파일 관리가 빠르고 간단하다고 판단
.env
,로그
,빌드 산출물
등을 서버 내에서 일괄 관리하는 것이 배포 흐름상 효율적- 초기 MVP 개발은 속도가 중요했기에 서버 중심 배포가 유리했음
-
향후 계획
- v2 이후에는 Docker 기반 컨테이너를 도입
- GCS, GCR 등을 활용하여 빌드 및 배포 분리 및 아티팩트 버저닝 도입 예정
5.2. 기술적 한계
v1의 CI/CD 구조는 빠르게 MVP를 구축하고 단일 서버 환경에서 안정적으로 배포하기 위한 목적에는 적합했지만,운영 효율성, 확장성, 보안성 측면에서 다음과 같은 기술적 한계가 존재합니다.
-
CI/CD 흐름 불일치
항목 한계 서비스 간 구조 차이 BE는 GitHub Actions에서 JAR 빌드 후 배포, FE/AI는 서버 내 git pull + 빌드 수행 → 관리 복잡 테스트 자동화 부족 gradle test
,pnpm test
,pytest
등 자동 테스트 수행 없음빌드 이력 없음 GCS 등 외부 저장소를 사용하지 않아 빌드 버전, 타임스탬프 관리 어려움 -
확장성 및 이식성 부족
항목 한계 단일 VM 의존 모든 서비스가 한 서버에 밀집되어 있으며, 분산/스케일아웃 어려움 PM2 기반 실행 Node 생태계에 맞춰진 도구로 Spring/FastAPI에선 제한적 활용 도커 미도입 배포 환경 간 이식성, 테스트 환경 재현성 부족
6. 개선 방향 및 다음 단계(v2)
v1에서는 GitHub Actions와 Shell Script 기반 배포 구조로 MVP 단계에 맞는 빠른 배포 구조를 구축했습니다.
하지만, CI/CD 시스템의 일관성과 확장성 측면에서 다음과 같은 개선이 필요하여 v2에서는 이를 중심으로 고도화할 예정입니다.
6.1. 개선 항목
항목 | v1 | v2 개선 방향 |
---|---|---|
배포 단위 | Git → 서버 직접 배포 | Docker 이미지 빌드 → 컨테이너 단위 배포 |
빌드 방식 | 서비스별 상이 (BE: GitHub에서, FE/AI: 서버 내) | 모든 서비스 공통 GitHub Actions에서 빌드 |
아티팩트 저장소 | 없음 (서버 내 백업만 존재) | GCS 또는 Artifact Registry 활용 |
배포 환경 제어 | Shell Script 직접 실행 | Docker Compose 기반 환경 제어 |
롤백 전략 | 수동 rollback.sh |
Docker 이미지 태그를 통한 롤백 가능 구조 |
CI 통합 테스트 | 미적용 | gradle test , pnpm test , pytest 등 GitHub Actions 내 테스트 통합 |
알림 체계 | Discord Webhook 단순 메시지 | 구조화된 메시지 + APM 상태 통합 연계 계획 |
6.2. v2 CI/CD 파이프라인 예고
[GitHub Push]
↓
[GitHub Actions]
- 테스트 실행
- Docker 이미지 빌드
- 이미지 Push (GCR or Artifact Registry)
↓
[서버]
- Docker Pull
- docker-compose up -d
↓
[헬스체크 + Discord 알림]