# zio-server CI/CD 파이프라인 가이드 > **서버**: zio-server | **IP**: zioinfo.co.kr > **작성일**: 2026-05-30 --- ## 1. CI/CD 아키텍처 ``` ┌─────────────────────────────────────────────────────────┐ │ 개발자 로컬 PC │ │ 코드 수정 → git commit → git push gitea main:main │ └──────────────────────┬──────────────────────────────────┘ │ HTTP push (포트 3000) ▼ ┌─────────────────────────────────────────────────────────┐ │ Gitea (zioinfo.co.kr:3000) │ │ zio/zioinfo-web 저장소 → 웹훅 트리거 │ └──────────────────────┬──────────────────────────────────┘ │ POST http://localhost:9999/ ▼ ┌─────────────────────────────────────────────────────────┐ │ ZioInfo Deploy Server (포트 9999) │ │ /opt/zioinfo/deploy_server.py │ │ │ │ ① git pull (소스 최신화) │ │ ② npm ci && npm run build (React SPA 빌드) │ │ ③ mvn clean package (Spring Boot JAR 빌드) │ │ ④ cp app.jar /opt/zioinfo/app/ │ │ ⑤ cp static/* /var/www/zioinfo/ │ │ ⑥ systemctl restart zioinfo │ └──────────────────────┬──────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────┐ │ Spring Boot (포트 8082) │ │ /opt/zioinfo/app/app.jar │ │ DB: /opt/zioinfo/app/data/zioinfo.db (SQLite) │ └──────────────────────┬──────────────────────────────────┘ │ proxy_pass ▼ ┌─────────────────────────────────────────────────────────┐ │ Nginx (포트 80) │ │ /var/www/zioinfo/ → React SPA 정적 파일 │ │ /api/ → localhost:8082 프록시 │ └─────────────────────────────────────────────────────────┘ │ ▼ http://zioinfo.co.kr (서비스 엔드포인트) ``` --- ## 2. 로컬 개발 환경 설정 ### 2-1. Git remote 설정 (최초 1회) ```bash # 현재 remote 확인 git remote -v # Gitea remote 추가 cd C:\GUARDiA\workspace\zioinfo-web git remote add gitea http://zio:Zio%40Admin2026%21@zioinfo.co.kr:3000/zio/zioinfo-web.git # 설정 확인 git remote -v # gitea http://zio:...@zioinfo.co.kr:3000/zio/zioinfo-web.git (fetch) # gitea http://zio:...@zioinfo.co.kr:3000/zio/zioinfo-web.git (push) # origin https://github.com/... (fetch) ← GitHub (기존) ``` ### 2-2. 코드 배포 ```bash # 1. 변경 사항 커밋 git add . git commit -m "feat: 기능 설명" # 2. Gitea에 push → 자동 빌드·배포 시작 git push gitea main:main # 3. 배포 진행 상황 확인 (SSH 접속 후) ssh root@zioinfo.co.kr "tail -f /var/log/zioinfo/deploy.log" ``` --- ## 3. 배포 서버 구성 ### 3-1. 파일 위치 | 파일 | 경로 | 설명 | |------|------|------| | 배포 스크립트 | `/opt/zioinfo/deploy_server.py` | 웹훅 수신 + 빌드·배포 실행 | | 소스 코드 | `/opt/zioinfo/src/` | Gitea 클론 경로 | | 실행 JAR | `/opt/zioinfo/app/app.jar` | 배포된 Spring Boot JAR | | 정적 파일 | `/var/www/zioinfo/` | 배포된 React 빌드 결과물 | | 배포 로그 | `/var/log/zioinfo/deploy.log` | 빌드·배포 과정 기록 | ### 3-2. systemd 서비스 ```ini # /etc/systemd/system/zioinfo-deploy.service [Unit] Description=ZioInfo CI/CD Webhook Server After=network.target [Service] User=root ExecStart=/usr/bin/python3 /opt/zioinfo/deploy_server.py Restart=always RestartSec=5 [Install] WantedBy=multi-user.target ``` ```bash # 서비스 관리 systemctl status zioinfo-deploy systemctl restart zioinfo-deploy journalctl -u zioinfo-deploy -n 20 --no-pager ``` ### 3-3. 웹훅 보안 배포 서버는 HMAC-SHA256으로 요청을 검증합니다. ```python # 검증 키: zioinfo-deploy-2026 # Gitea 웹훅 설정의 Secret 값과 동일 ``` --- ## 4. Gitea 웹훅 설정 ### 4-1. 현재 웹훅 확인 ```bash # API로 웹훅 목록 조회 curl -s http://localhost:3000/api/v1/repos/zio/zioinfo-web/hooks \ -u "zio:Zio@Admin2026!" | python3 -m json.tool # 브라우저에서 확인 # http://zioinfo.co.kr:3000/zio/zioinfo-web/settings/hooks ``` ### 4-2. 웹훅 재등록 (필요 시) ```bash # 기존 웹훅 삭제 curl -s -X DELETE http://localhost:3000/api/v1/repos/zio/zioinfo-web/hooks/1 \ -u "zio:Zio@Admin2026!" # 새 웹훅 등록 (Python) python3 << 'EOF' import urllib.request, json, base64 data = json.dumps({ "type": "gitea", "active": True, "config": { "url": "http://localhost:9999/", "content_type": "json", "secret": "zioinfo-deploy-2026" }, "events": ["push"] }).encode() cred = base64.b64encode(b"zio:Zio@Admin2026!").decode() req = urllib.request.Request( "http://localhost:3000/api/v1/repos/zio/zioinfo-web/hooks", data=data, headers={"Content-Type": "application/json", "Authorization": f"Basic {cred}"}) resp = urllib.request.urlopen(req) d = json.loads(resp.read()) print(f"Webhook ID: {d.get('id')}") EOF ``` --- ## 5. 배포 이력 및 롤백 ### 5-1. 배포 이력 확인 ```bash # Gitea 커밋 이력 curl -s "http://localhost:3000/api/v1/repos/zio/zioinfo-web/commits?limit=10" \ -u "zio:Zio@Admin2026!" | python3 -c " import json, sys commits = json.load(sys.stdin) for c in commits: print(c['sha'][:8], c['commit']['message'][:60], '|', c['commit']['author']['date'][:10]) " # 서버 소스 로컬 이력 ssh root@zioinfo.co.kr "git -C /opt/zioinfo/src log --oneline -10" ``` ### 5-2. 특정 버전으로 롤백 ```bash ssh root@zioinfo.co.kr # 이전 커밋으로 체크아웃 cd /opt/zioinfo/src git log --oneline -5 # 커밋 해시 확인 git checkout <커밋해시> # 원하는 버전으로 변경 # 빌드 및 재배포 cd frontend && npm ci && npm run build cd ../backend && mvn clean package -DskipTests -q cp target/zioinfo-web-*.jar /opt/zioinfo/app/app.jar cp -r src/main/resources/static/. /var/www/zioinfo/ systemctl restart zioinfo # 최신 버전으로 복구 git checkout main ``` --- ## 6. Jenkins 파이프라인 (심화 설정) > Jenkins 초기 설정 완료 후 사용 가능 ### 6-1. Jenkinsfile 위치 ``` workspace/zioinfo-web/Jenkinsfile (홈페이지 파이프라인) itsm/Jenkinsfile (GUARDiA ITSM 파이프라인) ``` ### 6-2. 홈페이지 Jenkinsfile 주요 단계 ```groovy pipeline { agent any stages { stage('Frontend Build') { /* npm ci + npm run build */ } stage('Backend Build') { /* mvn clean package */ } stage('Test') { /* mvn test */ } stage('Deploy') { when { branch 'main' } /* JAR 복사 + 정적파일 배포 + systemctl restart */ } } } ``` ### 6-3. Jenkins Job 수동 트리거 ```bash # Jenkins API로 빌드 트리거 (초기 설정 완료 후) CRUMB=$(curl -s -u admin:Admin@2026! \ http://localhost:8080/crumbIssuer/api/json | python3 -c \ "import json,sys; print(json.load(sys.stdin)['crumb'])") curl -u admin:Admin@2026! -X POST \ http://localhost:8080/job/zioinfo-web/build \ -H "Jenkins-Crumb: $CRUMB" ``` --- ## 7. 트러블슈팅 ### 7-1. push 후 자동 배포가 안 될 때 ```bash # 1. 웹훅 서버 상태 확인 systemctl is-active zioinfo-deploy # 2. 웹훅 서버 로그 journalctl -u zioinfo-deploy -n 20 --no-pager # 3. 수동 트리거 테스트 curl -s -X POST http://localhost:9999/ \ -H "Content-Type: application/json" -d '{}' # 4. 배포 로그 실시간 확인 tail -f /var/log/zioinfo/deploy.log ``` ### 7-2. 빌드 실패 시 ```bash # 빌드 로그에서 오류 확인 grep -i "error\|failed\|fail" /var/log/zioinfo/deploy.log | tail -20 # npm 빌드 오류 재현 cd /opt/zioinfo/src/frontend npm ci --legacy-peer-deps npm run build # Maven 빌드 오류 재현 cd /opt/zioinfo/src/backend mvn clean package -DskipTests ``` ### 7-3. Spring Boot 재시작 실패 ```bash # 상세 로그 확인 journalctl -u zioinfo --since "5 minutes ago" --no-pager tail -50 /var/log/zioinfo/spring.log # 포트 충돌 확인 (8082) ss -tlnp | grep 8082 kill -9 # 기존 프로세스 강제 종료 # 수동 실행 (디버깅) java -jar /opt/zioinfo/app/app.jar --server.port=8082 ``` --- ## 8. GUARDiA ITSM 배포 > GUARDiA는 별도 Jenkinsfile 기반 파이프라인 사용 ### 8-1. 수동 배포 ```bash # Gitea에서 최신 코드 반영 cd /opt/guardia/app git pull http://zio:Zio%40Admin2026%21@localhost:3000/zio/guardia-itsm.git main # 패키지 업데이트 /opt/guardia/venv/bin/pip install -r requirements.txt -q # 서비스 재시작 systemctl restart guardia sleep 3 && systemctl is-active guardia # 헬스체크 curl -s http://localhost:8001/docs -o /dev/null -w "HTTP %{http_code}" ``` --- *문서 버전: 1.0 | 최종 수정: 2026-05-30*