[CL] v1 CI CD 문서화 - 100-hours-a-week/6-nemo-wiki GitHub Wiki

1. 개요

v1 에서의 CI/CD는 단일 GCP VM 환경에서 운영되는 3개의 서비스 (BE,FE,AI)를 대상으로 GitHub ActionsPM2 + 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 로 분리된 설정 주입
    • 배포 후 헬스체크 → 배포 성공/실패 여부 알림 전송 (서비스 웹훅 + 클라우드 웹훅)
  • 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 수동 승인 필요 운영 서버, 승인 후 배포 진행
  • 설정 방법

    1. GitHub Settings → Environments → New environment로 prod 환경 생성
    2. Required Reviewers 체크 및 생성
    3. dev 환경 생성은 필요 없음.
  • Workflows 사용 예시

    on:
      workflow_dispatch:
    
    jobs:
      deploy:
        runs-on: ubuntu-latest
        environment:
          name: prod
    

5. 한계 및 회고

5.1. 기존 설계 차이

  1. v1에서는 CI/CD의 중간 저장소 및 배포 관리 방식이 기존 설계와 변경되었습니다.
  • 기존 CI는 GCS를 아티팩트 저장소로 활용해 GitHub Actions → GCS 업로드 → 서버에서 다운로드 하는 방식
  • v1에서는 중간 저장소 없이 서버 내에서 빌드 디렉토리, 로그, 백업 파일등을 관리하는 구조로 변경
  • 단, 백엔드의 경우 빌드 리소스가 많이 들기 때문에 GitHub Action에서 빌드 후 JAR만 서버로 전송하는 방식
  1. 변경 이유

    • 단일 VM 환경에서는 GCS보다 로컬 파일 관리가 빠르고 간단하다고 판단
    • .env, 로그, 빌드 산출물 등을 서버 내에서 일괄 관리하는 것이 배포 흐름상 효율적
    • 초기 MVP 개발은 속도가 중요했기에 서버 중심 배포가 유리했음
  2. 향후 계획

    • v2 이후에는 Docker 기반 컨테이너를 도입
    • GCS, GCR 등을 활용하여 빌드 및 배포 분리아티팩트 버저닝 도입 예정

5.2. 기술적 한계

v1의 CI/CD 구조는 빠르게 MVP를 구축하고 단일 서버 환경에서 안정적으로 배포하기 위한 목적에는 적합했지만,운영 효율성, 확장성, 보안성 측면에서 다음과 같은 기술적 한계가 존재합니다.

  1. CI/CD 흐름 불일치

    항목 한계
    서비스 간 구조 차이 BE는 GitHub Actions에서 JAR 빌드 후 배포, FE/AI는 서버 내 git pull + 빌드 수행 → 관리 복잡
    테스트 자동화 부족 gradle test, pnpm test, pytest 등 자동 테스트 수행 없음
    빌드 이력 없음 GCS 등 외부 저장소를 사용하지 않아 빌드 버전, 타임스탬프 관리 어려움
  2. 확장성 및 이식성 부족

    항목 한계
    단일 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 알림]