[CL] v1 배포 문서화 - 100-hours-a-week/6-nemo-wiki GitHub Wiki
1. 완전 수동 배포 방식 (Manual Deployment)
1.1. 개요
완전 수동(Bang-Bang) 배포 방식은 각 서비스에 대해 직접 서버에 접속해 모든 명령어를 수동으로 입력하거나 단일 스크립트 파일을 실행하는 구조입니다.
1.2. 공통 디렉토리 구조
manual-scripts/
├── deploy-frontend.sh # FE 배포 스크립트
├── deploy-backend.sh # BE 배포 스크립트
└── deploy-ai.sh # AI 배포 스크립트
6-nemo-*/
├── .env # 환경 변수
├── 소스코드 디렉토리 및 설정 파일
└── (서비스별 빌드 결과물 혹은 가상환경)
1.3. 공통 배포 절차
- GCP VM 접속
- GCP 콘솔 또는 SSH 툴을 사용해 서버 접속
sudo su -ubuntu
명령어로ubuntu
계정 전환
chmod +x deploy-*.sh
로 실행 권한 부여- PM2 상태 및 로그 확인
pm2 status
pm2 logs [프로세스명]
1.4. BE (Spring Boot)
- 배포 스크립트 요약
- 브랜치 기반 소스
clone
및pull
./gradlew clean bootJar -x test
pm2 start "java -jar ..." --name nemo-backend
- 헬스체크:
curl http://localhost:8080/actuator/health
- 브랜치 기반 소스
- 주요 포인트
- JAR 경로:
build/libs/nemo-server-0.0.1-SNAPSHOT.jar
- 서버에서 직접 빌드
- JAR 경로:
- BE 배포 깃허브 링크
1.5. FE (Next.js)
- 배포 스크립트 요약
- 브랜치 기반 소스
clone
및pull
pnpm install
pnpm build
pm2 start pnpm --name nemo-frontend -- start
- 헬스체크:
curl http://localhost:3000
- 브랜치 기반 소스
- 주요 포인트
- ESLint 설정 문제 발생 시
eslint.config.mjs
수정 (트러블 슈팅 링크)
- ESLint 설정 문제 발생 시
- FE 배포 깃허브 링크
1.6. AI (FastAPI)
- 배포 스크립트 요약
- 브랜치 기반 소스
clone
및pull
python3 -m venv venv && source venv/bin/activate
pip install -r requirements.txt
pm2 start venv/bin/uvicorn ...
- 헬스체크:
curl http://localhost:8000
- 브랜치 기반 소스
- 주요 포인트
PYTHONPATH=./src
설정 필요- 가상환경 활성화/비활성화 명시적 수행
- AI 배포 깃허브 링크
1.7. 한계 및 개선 필요성
완전 수동 배포 방식은 초기 개발 환경에서는 간단하게 사용할 수 있으나, 운영 환경으로 넘어가면서 아래와 같은 뚜렷한 한계가 발생했습니다:
한계점 | 설명 | 개선 방향 (스크립트 기반 배포) |
---|---|---|
1. 롤백 전략 부재 | 배포 실패 시 수동으로 이전 상태 복구 필요 | rollback.sh 스크립트 도입으로 간편 롤백 가능 |
2. 단일 파일/단일 흐름의 비유연성 | 하나의 스크립트에 모든 흐름이 담겨 있어 특정 단계만 실행하기 어려움 | backup.sh , deploy.sh , healthcheck.sh , rollback.sh , run.sh 등으로 기능 분리 |
3. 알림 미지원 | 배포 성공/실패 여부를 다른 파트와 공유할 수 없음 → 커뮤니케이션 비용 증가 | Discord Webhook 연동으로 배포 상태 실시간 공유 |
4. 디렉토리 이동 반복 | 매번 서비스별 디렉토리 진입 후 명령어/스크립트 실행해야 함 | 서비스 별 배포 명령어를 alias 로 등록하여 단축 실행 가능 (예: deploy-be ) |
5. 운영 중 헬스체크 부재 | 배포 당시에는 확인하지만, 이후에는 장애를 자동 인지하기 어려움 | healthcheck.sh + crontab 으로 주기적 헬스체크 및 실패 시 알림 기능 도입 |
1.8. 결론
위와 같은 문제들은 운영 안정성과 반복 배포 효율성에 직접적인 영향을 주었습니다.
이에 따라 스크립트 기반 배포 구조를 새롭게 도입하여 다음과 같은 효과를 기대할 수 있습니다.
- 배포 속도 단축 및 휴먼 에러 감소
- 이슈 발생 시 빠른 롤백 대응
- 타 팀과의 협업 시 배포 상태 투명성 확보
- 운영 중 장애 조기 인지 가능
다음 장에서는 이 개선을 반영한 개선된 배포(Semi-Automated) 방식을 설명합니다.
2. 개선된 배포 방식 (Semi-Automated Deployment)
2.1. 개요
수동 배포의 비효율성을 개선하고, 배포-실행-롤백-헬스체크-백업까지 반복 작업을 스크립트로 자동화한 구조입니다.
- 클라우드 파트가 아니더라도 팀원 누구나 서버 접속 후 정해진 alias 명령어로 주요 작업을 수행할 수 있습니다.
- 디스코드 웹훅을 통해 배포 결과 및 헬스체크 상태를 실시간 공유합니다.
- 깃허브 링크
2.2. 공통 디렉토리 구조
~/nemo/
├── [서비스명]/
│ ├── [서비스 소스]/
│ ├── [백업 디렉토리]/
│ └── .env
└── cloud/
└── v1/
└── [서비스명]/
└── semi-automated/
├── deploy.sh
├── run.sh
├── rollback.sh
├── backup.sh
└── healthcheck.sh
2.3 공통 alias 등록 (BE 예시)
echo 'alias be-deploy="bash ~/nemo/cloud/v1/backend/semi-automated/deploy.sh"' >> ~/.bashrc
echo 'be-rollback() { bash ~/nemo/cloud/v1/backend/semi-automated/rollback.sh \"$1\"; }' >> ~/.bashrc
echo 'alias be-health="bash ~/nemo/cloud/v1/backend/semi-automated/healthcheck.sh"' >> ~/.bashrc
echo 'alias be-run="bash ~/nemo/cloud/v1/backend/semi-automated/run.sh"' >> ~/.bashrc
echo 'alias be-backup="bash ~/nemo/cloud/v1/backend/semi-automated/backup.sh"' >> ~/.bashrc
source ~/.bashrc
2.4. 명령어 매핑
서비스에 따라 ai-
, be-
, fe-
접두어로 구분됩니다.
명령어 | 설명 |
---|---|
[서비스]-deploy |
전체 배포 수행 |
[서비스]-rollback |
최신 백업 롤백 or 파일 지정 롤백 |
[서비스]-run |
PM2로 서비스 재시작 |
[서비스]-backup |
소스 또는 빌드 백업 |
[서비스]-health |
헬스체크 수행 및 결과 출력 |
2.5. 크론탭 설정
# 실행 권한 부여
chmod +x ~/nemo/cloud/v1/[서비스]/semi-automated/*.sh
# 크론탭 등록 (개발: 5분 주기, 운영: 1분 주기)
crontab -e
*/5 * * * * /home/ubuntu/nemo/cloud/v1/[서비스]/semi-automated/healthcheck.sh
*/1 * * * * /home/ubuntu/nemo/cloud/v1/[서비스]/semi-automated/healthcheck.sh
# 로그 확인
cat /var/log/syslog | grep CRON
2.6. 디스코드 알림
# 디스코드 웹훅
send_discord_notification() {
local message="$1"
for webhook_url in "$WEBHOOK_CLOUD_URL" "$WEBHOOK_BACKEND_URL"
do
curl -H "Content-Type: application/json" \
-X POST \
-d "{\"content\": \"$message\"}" \
"$webhook_url"
done
}
# 배포 알림
sleep 60
if bash "$SCRIPT_DIR/healthcheck.sh"; then
send_discord_notification "✅ [배포 성공: $BRANCH] $SERVICE_NAME 배포 완료!"
else
send_discord_notification "❌ [배포 실패: $BRANCH] $SERVICE_NAME 배포 실패!"
exit 1
fi
# 헬스체크 알림
if [ "$STATUS" -eq 200 ]; then
echo "✅ [$SERVICE_NAME] 서버 정상 작동 (HTTP 200)"
else
echo "❌ [$SERVICE_NAME] 서버 비정상 (HTTP $STATUS)"
send_discord_alert "🚨 [헬스체크 실패: $BRANCH] $SERVICE_NAME 비정상 상태 감지!"
exit 1
fi
# 알림 메시지
✅ [배포 성공: dev] nemo-frontend 배포 완료!
❌ [배포 실패: dev] nemo-frontend 배포 실패!
✅ [롤백 성공: dev] nemo-frontend 롤백 완료! (Rollback Point: 20250516-2259)
❌ [롤백 실패: dev] nemo-frontend 롤백 실패! (Rollback Point: 20250516-2259)
🚨 [헬스체크 실패: dev] nemo-frontend 비정상 상태 감지!
2.7 롤백 전략
- 주요 설계 원칙
- 백업 기준: 배포 시마다
.jar
(BE) 또는.tar.gz
(FE/AI) 파일을 백업 디렉토리에 저장 - 백업 유지 개수: 최대 7개 버전까지만 보관 (
oldest-first
방식으로 자동 삭제) - 파일명 규칙:
서비스명-YYYYMMDD-HHMM.jar
형식으로 타임스탬프 포함
- 백업 기준: 배포 시마다
- 롤백 스크립트 작동 방식
-
fe-rollback
/be-rollback
/ai-rollback
-
인자 없이 실행 시 → 가장 최근 백업 파일로 롤백
-
인자 전달 시 →
YYYYMMDD-HHMM
포맷을 기반으로 해당 백업 파일로 롤백fe-rollback # 최신 백업으로 롤백 fe-rollback 20240531-2300 # 특정 시점으로 롤백
-
2.8. 한계 및 개선 필요성
스크립트 기반 배포(Semi-Automated)는 수동 배포의 반복 작업과 실수 가능성을 줄였지만, 여전히 다음과 같은 운영 및 협업상의 한계가 존재했습니다.
-
CI/CD 파이프라인이 부재하여, 배포 및 롤백 시 서버에 수동 접속이 필요했고
이로 인해 타 파트와의 커뮤니케이션 비용이 지속적으로 발생함
-
각 스크립트 파일 내부에서
PORT
,BRANCH
,WEBHOOK
등 환경변수를 개별 관리하여환경 설정을 한눈에 파악하거나 일관되게 유지하기 어려웠음
이를 해결하기 위해 다음과 같은 리팩토링을 진행했습니다.
-
.env
파일을 기준으로 모든 환경 설정을 중앙 집중화하여 관리 -
FE/BE/AI 각각의 서비스 디렉토리에 흩어져 있던 스크립트를
cloud 레포로 통합해 유지보수성과 구조적 일관성을 확보 (3장)
-
2.9. 결론
주요 개선 사항은 다음과 같습니다.
- 배포, 재시작, 롤백, 헬스체크, 백업을 기능별 스크립트로 분리하여 역할 명확화
alias
등록을 통해 클라우드 파트 뿐만 아니라 다른 파트 개발자도 명령어 기반 운영 가능- Discord Webhook 연동으로 배포 상태 및 헬스체크 실패 알림을 실시간 공유
crontab
을 통한 헬스체크 주기 자동화 및 장애 조기 인지 체계 구현- 백업 + 롤백 전략 도입으로 배포 실패 시 빠른 복구 지원
이 구조는 이후 단계에서 CI/CD 파이프라인으로 자연스럽게 전환할 수 있는 기반이 되었으며, 서비스 안정성과 협업 효율성을 동시에 확보하는 중요한 전환점이었습니다.
3. 스크립트 구조 리팩토링 및 관리 방식 개선
3.1. 개선 배경
초기에는 각 서비스 디렉토리 내부(~/nemo/backend/scripts/
)에서 배포 스크립트를 서버에서 직접 생성/수정하여 관리하였습니다.
이러한 구조로 인해 다음과 같은 문제가 발생했습니다.
- 경로 중복 및 환경 의존성으로 인한 코드 중복
PORT
,SERVICE_NAME
,BRANCH
등이 각 스크립트마다 하드코딩- dev/prod 간 구조 불일치로 인해 환경별 관리 어려움
- 서버 내 수작업 변경으로 인해 이력 추적 불가, 협업 어려움
3.2. 개선 방향: Cloud 레포 기반 통합 관리 구조 도입
모든 배포 스크립트를 cloud
레포로 통합하여 중앙 집중화된 버전 관리 체계를 도입하였으며,
.env
파일을 통해 환경별 설정을 분리하고 스크립트 재사용성을 극대화하였습니다.
-
통합 디렉토리 구조
cloud/v1/backend/semi-automated/ ├── backup.sh ├── deploy.sh ├── deploy-cicd.sh ├── healthcheck.sh ├── rollback.sh ├── run.sh └── README.md
-
공통 환경 구성 (.env 예시)
SERVICE_NAME=nemo-backend BRANCH=develop PORT=8080 REPO_URL=https://github.com/100-hours-a-week/6-nemo-be.git BACKUP_DIR=$HOME/nemo/backend/jar-backups SCRIPT_DIR=$HOME/nemo/cloud/v1/backend/semi-automated APP_DIR=$HOME/nemo/backend/backend-service JAR_PATH=$APP_DIR/build/libs/nemo-server-0.0.1-SNAPSHOT.jar HEALTHCHECK_URL=http://localhost:$PORT/actuator/health
3.3. Before & After 비교
run.sh
예시-
Before (서비스 디렉토리 내, 직접 관리)
#!/bin/bash set -euo pipefail SERVICE_NAME="nemo-backend" ROOT_DIR="$HOME/nemo/backend" PORT=8080 JAR_FILE="$ROOT_DIR/backend-service/build/libs/nemo-server-0.0.1-SNAPSHOT.jar" ENV_FILE="$ROOT_DIR/.env" # 환경 변수 로드 if [ -f "$ENV_FILE" ]; then set -a source "$ENV_FILE" set +a fi echo "🚀 PM2로 백엔드 서버 실행 중..." pm2 start java --name "$SERVICE_NAME" -- \ -Duser.timezone=Asia/Seoul \ -jar "$JAR_FILE" \ --server.port=$PORT pm2 save
-
After (Cloud 레포 내, 중앙 관리)
#!/bin/bash set -euo pipefail ENV_FILE="$HOME/nemo/backend/.env" # 환경 변수 로드 if [ -f "$ENV_FILE" ]; then set -a source "$ENV_FILE" set +a fi echo "🚀 PM2로 백엔드 서버 실행 중..." pm2 start java --name "$SERVICE_NAME" -- \ -Duser.timezone=Asia/Seoul \ -jar "$JAR_FILE" \ --server.port=$PORT pm2 save
-
3.4. 리팩토링 효과 요약
항목 | 리팩토링 전 | 리팩토링 후 |
---|---|---|
스크립트 위치 | 서비스별 디렉토리 (~/nemo/backend/scripts ) |
Cloud 레포 (cloud/v1/backend/semi-automated ) |
환경 변수 | 스크립트 내 하드코딩, 중복 선언 | .env 기반 통일 관리 |
dev/prod 전환 | 구조 불일치, 별도 유지 필요 | 동일 스크립트 재사용 + .env 만 분기 |
변경 이력 | 수동 수정 → 이력 추적 불가 | Git으로 버전 관리 및 PR 협업 가능 |
협업 가능성 | 개인 작업 중심 | 팀 단위 유지보수 가능 |
3.5. 핵심 요약
cloud
레포를 통해 스크립트의 통합 관리 체계 확보.env
기반 구조로 운영 환경(dev/prod) 분리 용이- 변경 이력을 Git으로 관리하여 협업 생산성 및 신뢰성 향상
- 각 서비스가 동일한 구조로 배포 흐름을 공유 → 유지보수/확장성 극대화