docs(DOC): CI/CD 서버 셋팅 가이드 — 배포 파이프라인 검증 완료

- react develop 파이프라인 E2E 검증 완료 (Jenkins Build #3 SUCCESS)
- Jenkinsfile rsync trailing slash 버그 수정 반영 (.next/ → .next)
- 환경별 .env 파일 설정 및 도메인 매핑 정보 추가
- Prometheus localhost 바인딩 반영 (보안)
- 설치 순서 ⑩⑪⑫ 완료 표시, 상태 업데이트

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-24 07:09:09 +09:00
parent a3ef921a4f
commit a11fe745b6

View File

@@ -1,7 +1,7 @@
# CI/CD 서버 셋팅 가이드
> 작성일: 2026-02-23 | 최종 수정: 2026-02-24
> 상태: 설치 완료 (Jenkinsfile 작성 + 실제 배포 테스트 남음)
> 상태: 설치 및 배포 테스트 완료 (react develop 파이프라인 검증 완료)
---
@@ -661,7 +661,7 @@ ExecStart=/usr/local/bin/prometheus \
--config.file=/etc/prometheus/prometheus.yml \
--storage.tsdb.path=/var/lib/prometheus/ \
--storage.tsdb.retention.time=30d \
--web.listen-address=:9090
--web.listen-address=127.0.0.1:9090
Restart=always
[Install]
@@ -859,7 +859,12 @@ pipeline {
### 파이프라인: Next.js React (react/)
**Jenkinsfile** (`react/Jenkinsfile`):
> **검증 완료**: Jenkins Build #3 (develop) — 빌드 + 배포 성공 (241초)
> - rsync source trailing slash 주의: `.next/` (X) → `.next` (O)
> - 개발서버 PM2: `sam-react` (fork), 운영서버 PM2: `sam-front` (cluster)
> - `npm install --prefer-offline` 사용 (package-lock.json이 .gitignore에 포함)
**Jenkinsfile** (`react/Jenkinsfile`) — 실제 배포 검증 완료:
```groovy
pipeline {
@@ -867,7 +872,7 @@ pipeline {
environment {
DEPLOY_USER = 'hskwon'
RELEASE_ID = new Date().format('yyyyMMdd_HHmmss')
RELEASE_ID = new Date().format('yyyyMMdd_HHmmss')
}
stages {
@@ -875,36 +880,49 @@ pipeline {
steps { checkout scm }
}
stage('Build') {
stage('Prepare Env') {
steps {
sh 'npm ci && npm run build'
script {
def envFile = "/var/lib/jenkins/env-files/react/.env.${env.BRANCH_NAME}"
sh "cp ${envFile} .env.local"
}
}
}
// ── main → 운영서버 (배포관리자 수동 push 후 트리거) ──
stage('Deploy Production') {
when { branch 'main' }
stage('Install') {
steps {
sh 'npm install --prefer-offline'
}
}
stage('Build') {
steps {
sh 'npm run build'
}
}
// ── develop → 개발서버 배포 ──
stage('Deploy Development') {
when { branch 'develop' }
steps {
sshagent(credentials: ['deploy-ssh-key']) {
sh """
ssh ${DEPLOY_USER}@211.117.60.189 'mkdir -p /home/webservice/react/releases/${RELEASE_ID}'
rsync -az --delete \
.next/ package.json package-lock.json next.config.* public/ node_modules/ \
${DEPLOY_USER}@211.117.60.189:/home/webservice/react/releases/${RELEASE_ID}/
--exclude='.git' \
--exclude='.env*' \
--exclude='ecosystem.config.*' \
.next package.json next.config.ts public node_modules \
${DEPLOY_USER}@114.203.209.83:/home/webservice/react/
ssh ${DEPLOY_USER}@211.117.60.189 '
ln -sfn /home/webservice/react/shared/.env.local /home/webservice/react/releases/${RELEASE_ID}/.env.local &&
ln -sfn /home/webservice/react/releases/${RELEASE_ID} /home/webservice/react/current &&
cd /home/webservice && pm2 reload sam-front &&
cd /home/webservice/react/releases && ls -1dt */ | tail -n +4 | xargs rm -rf 2>/dev/null || true
'
scp .env.local ${DEPLOY_USER}@114.203.209.83:/home/webservice/react/.env.local
ssh ${DEPLOY_USER}@114.203.209.83 'cd /home/webservice/react && pm2 restart sam-react'
"""
}
}
}
// ── stage → 운영서버 Stage ──
// ── stage → 운영서버 Stage 배포 ──
stage('Deploy Stage') {
when { branch 'stage' }
steps {
@@ -913,34 +931,39 @@ pipeline {
ssh ${DEPLOY_USER}@211.117.60.189 'mkdir -p /home/webservice/react-stage/releases/${RELEASE_ID}'
rsync -az --delete \
.next/ package.json package-lock.json next.config.* public/ node_modules/ \
.next package.json next.config.ts public node_modules \
${DEPLOY_USER}@211.117.60.189:/home/webservice/react-stage/releases/${RELEASE_ID}/
scp .env.local ${DEPLOY_USER}@211.117.60.189:/home/webservice/react-stage/releases/${RELEASE_ID}/.env.local
ssh ${DEPLOY_USER}@211.117.60.189 '
ln -sfn /home/webservice/react-stage/shared/.env.local /home/webservice/react-stage/releases/${RELEASE_ID}/.env.local &&
ln -sfn /home/webservice/react-stage/releases/${RELEASE_ID} /home/webservice/react-stage/current &&
cd /home/webservice && pm2 reload sam-front-stage &&
cd /home/webservice/react-stage/releases && ls -1dt */ | tail -n +3 | xargs rm -rf 2>/dev/null || true
cd /home/webservice && pm2 reload sam-front-stage 2>/dev/null || pm2 start react-stage/current/node_modules/.bin/next --name sam-front-stage -- start -p 3100 &&
cd /home/webservice/react-stage/releases && ls -1dt */ | tail -n +4 | xargs rm -rf 2>/dev/null || true
'
"""
}
}
}
// ── develop개발서버 (CI/CD에서 빌드 후 배포) ──
stage('Deploy Development') {
when { branch 'develop' }
// ── main운영서버 Production 배포 ──
stage('Deploy Production') {
when { branch 'main' }
steps {
sshagent(credentials: ['deploy-ssh-key']) {
sh """
# 빌드 결과물을 개발서버로 전송
rsync -az --delete \
.next/ package.json package-lock.json next.config.* public/ node_modules/ \
${DEPLOY_USER}@114.203.209.83:/home/webservice/react/
ssh ${DEPLOY_USER}@211.117.60.189 'mkdir -p /home/webservice/react/releases/${RELEASE_ID}'
ssh ${DEPLOY_USER}@114.203.209.83 '
cd /home/webservice/react &&
pm2 restart sam-front
rsync -az --delete \
.next package.json next.config.ts public node_modules \
${DEPLOY_USER}@211.117.60.189:/home/webservice/react/releases/${RELEASE_ID}/
scp .env.local ${DEPLOY_USER}@211.117.60.189:/home/webservice/react/releases/${RELEASE_ID}/.env.local
ssh ${DEPLOY_USER}@211.117.60.189 '
ln -sfn /home/webservice/react/releases/${RELEASE_ID} /home/webservice/react/current &&
cd /home/webservice && pm2 reload sam-front &&
cd /home/webservice/react/releases && ls -1dt */ | tail -n +6 | xargs rm -rf 2>/dev/null || true
'
"""
}
@@ -949,12 +972,25 @@ pipeline {
}
post {
success { echo "✅ react 배포 완료 (${env.BRANCH_NAME})" }
failure { echo "❌ react 배포 실패 (${env.BRANCH_NAME})" }
success { echo '✅ react 배포 완료 (' + env.BRANCH_NAME + ')' }
failure { echo '❌ react 배포 실패 (' + env.BRANCH_NAME + ')' }
}
}
```
**환경별 .env 파일** (`/var/lib/jenkins/env-files/react/`):
| 파일 | API URL | Frontend URL |
|------|---------|-------------|
| `.env.develop` | `https://api.codebridge-x.com` | `https://dev.codebridge-x.com` |
| `.env.stage` | `https://stage-api.sam.it.kr` | `https://stage.sam.it.kr` |
| `.env.main` | `https://api.sam.it.kr` | `https://sam.it.kr` |
> **주의사항 (rsync)**:
> - 소스 경로에 trailing slash 사용 금지: `.next/` → 내용만 복사됨, `.next` → 디렉토리째 복사
> - `--delete`와 함께 사용 시 `--exclude`로 `.git`, `.env*` 보호 필수 (개발서버)
> - Release 기반 배포 (stage/main)는 새 디렉토리이므로 exclude 불필요
### 파이프라인: Sales (레거시 PHP)
```groovy
@@ -1154,9 +1190,9 @@ sudo certbot certificates
| ⑦ | Nginx + SSL | 20분 | ⑤⑥ |
| ⑧ | Prometheus + node_exporter | 15분 | ① |
| ⑨ | Grafana | 15분 | ⑧ |
| ⑩ | Jenkins 파이프라인 + Webhook 설정 | 1시간 | ⑥⑦ |
| ⑪ | 백업 자동화 | 15분 | ②-s |
| ⑫ | 최종 점검 + 보안 | 30분 | 전체 |
| ⑩ | Jenkins 파이프라인 + Webhook 설정 | 1시간 | ⑥⑦ |
| ⑪ | 백업 자동화 | 15분 | ②-s |
| ⑫ | 최종 점검 + 보안 | 30분 | 전체 |
**총 예상 시간: 5~6시간**
@@ -1169,4 +1205,4 @@ sudo certbot certificates
- [x] ~~도메인 확정~~ → git.sam.it.kr, ci.sam.it.kr, monitor.sam.it.kr (SSL 발급 완료)
- [ ] **Jenkins 테스트 실행 여부**: CI에서 phpunit/lint 실행 vs 배포만
- [ ] **알림 채널**: Slack, 이메일, 카카오톡 등
- [ ] **개발서버 Gitea bare repo 경로 확인** (hook 설정을 위해)
- [x] ~~개발서버 Gitea bare repo 경로 확인~~`/data/GIT/samproject/<repo>.git/`