# Jenkins CI/CD 셋업 가이드 > **작성일**: 2026-02-22 > **상태**: 설계 확정 > **대상**: SAM 프로젝트 개발팀장 --- ## 1. Jenkins 이해하기 ### 1.1 Jenkins란 Jenkins는 오픈소스 자동화 서버다. 코드를 Push하면 자동으로 빌드, 테스트, 배포를 수행한다. ### 1.2 현재 수동 vs 자동화 비교 ``` 현재: 개발자 → git push → SSH 접속 → git pull → composer install → 재시작 (수동, 5~10분) 목표: 개발자 → git push → Jenkins 자동 감지 → 빌드/테스트/배포 (자동, Slack 알림) ``` ### 1.3 핵심 용어 | 용어 | 설명 | |------|------| | **Job** | 하나의 작업 단위 (예: `sam-api-deploy`) | | **Pipeline** | Stage를 순서대로 실행하는 흐름 | | **Stage / Step** | Pipeline의 단계 / 단계 내 개별 명령 | | **Credential** | Jenkins에 저장하는 비밀 정보 (SSH 키, 토큰) | | **Webhook** | Gitea가 Push 이벤트를 Jenkins에 알려주는 HTTP 호출 | --- ## 2. 사전 준비 | 항목 | 값 | |------|------| | IP | `114.203.209.83` | | CPU/RAM | 2코어 / 3.8GB | | Gitea | `http://114.203.209.83:3000` | > **경고: RAM이 부족하므로 Swap 추가가 필수다.** ### 2.1 Swap 4GB 추가 ```bash sudo fallocate -l 4G /swapfile sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab free -h # 확인 ``` ### 2.2 Java 17 + 방화벽 ```bash sudo apt update && sudo apt install -y openjdk-17-jdk java -version # 17.x.x 확인 sudo ufw allow 8080/tcp # Jenkins 웹 UI 포트 ``` --- ## 3. Jenkins 설치 ### 3.1 패키지 설치 ```bash curl -fsSL https://pkg.jenkins.io/debian-stable/jenkins.io-2023.key | sudo tee \ /usr/share/keyrings/jenkins-keyring.asc > /dev/null echo "deb [signed-by=/usr/share/keyrings/jenkins-keyring.asc] \ https://pkg.jenkins.io/debian-stable binary/" | sudo tee \ /etc/apt/sources.list.d/jenkins.list > /dev/null sudo apt update && sudo apt install -y jenkins sudo systemctl start jenkins && sudo systemctl enable jenkins ``` ### 3.2 초기 설정 ```bash sudo cat /var/lib/jenkins/secrets/initialAdminPassword # 초기 비밀번호 ``` 1. `http://114.203.209.83:8080` 접속 → 비밀번호 입력 2. **Install suggested plugins** 선택 → 설치 대기 (3~5분) 3. 관리자 계정 생성 (Username: `admin`) 4. Jenkins URL: `http://114.203.209.83:8080/` → **Save and Finish** --- ## 4. 필수 플러그인 설치 **Jenkins 관리 → Plugins → Available plugins** 에서 설치한다. | 플러그인 | 역할 | 필수 | |---------|------|------| | **Git plugin** | 소스 코드 체크아웃 | 🔴 | | **Pipeline** | Jenkinsfile 지원 | 🔴 | | **SSH Agent** | SSH 키로 운영 서버 배포 | 🔴 | | **Generic Webhook Trigger** | Gitea Push 이벤트 수신 | 🔴 | | **Slack Notification** | 배포 결과 Slack 알림 | 🟡 | | **NodeJS** | React 빌드용 Node.js | 🟡 | > **참고**: Git plugin, Pipeline은 suggested plugins에 포함되어 이미 설치되었을 수 있다. NodeJS 설정: **Jenkins 관리 → Tools → NodeJS installations → Add NodeJS** → Name: `NodeJS-20`, Version: `20.x` --- ## 5. Credential 설정 ### 5.1 SSH 키 생성 (Jenkins → 운영 서버) ```bash # Jenkins 서버에서 실행 sudo su - jenkins ssh-keygen -t ed25519 -C "jenkins@sam" -f ~/.ssh/id_ed25519 -N "" cat ~/.ssh/id_ed25519.pub # 이 값을 운영 서버에 등록 exit # 운영 서버에서 실행 (공개키 등록) echo "ssh-ed25519 AAAA... jenkins@sam" >> /home/deploy/.ssh/authorized_keys ``` ### 5.2 Jenkins Credential 등록 **Jenkins 관리 → Credentials → (global) → Add Credentials** | Credential | Kind | ID | 내용 | |-----------|------|-----|------| | SSH 키 | SSH Username with private key | `prod-server-ssh` | `~jenkins/.ssh/id_ed25519` 비밀키 | | Gitea 토큰 | Username with password | `gitea-token` | Gitea 사용자명 + API 토큰 | | Slack URL | Secret text | `slack-webhook` | Slack Incoming Webhook URL | ```bash # SSH 비밀키 확인 (Jenkins에 붙여넣기) sudo cat /var/lib/jenkins/.ssh/id_ed25519 ``` ``` ❌ Jenkinsfile에 비밀번호/토큰/키를 하드코딩 금지 ✅ 모든 비밀 정보는 Jenkins Credential에 등록 후 credentials('ID')로 참조 ``` --- ## 6. Gitea Webhook 연동 ### 6.1 Jenkins Pipeline Job 생성 1. **New Item** → 이름: `sam-api-deploy` → **Pipeline** 선택 2. **Build Triggers**: Generic Webhook Trigger 체크, Token: `sam-api` 3. **Pipeline**: Pipeline script from SCM → Git - URL: `http://114.203.209.83:3000/SamProject/sam-api.git` - Credentials: `gitea-token` - Branch: `*/main` - Script Path: `Jenkinsfile` ### 6.2 전체 Job 목록 | Job 이름 | 저장소 | 브랜치 | Token | |---------|--------|--------|-------| | `sam-api-deploy` | `sam-api.git` | `*/main` | `sam-api` | | `sam-mng-deploy` | `sam-manage.git` | `*/master` | `sam-mng` | | `sam-react-deploy` | `sam-react-prod.git` | `*/master` | `sam-react` | | `sam-sales-deploy` | `sam-sales.git` | `*/main` | `sam-sales` | ### 6.3 Gitea Webhook 설정 각 저장소: **Settings → Webhooks → Add Webhook → Gitea** | 항목 | 값 | |------|------| | Target URL | `http://114.203.209.83:8080/generic-webhook-trigger/invoke?token=sam-api` | | Content Type | `application/json` | | Trigger On | **Push Events** | | Branch filter | `main` | **Test Delivery** → 응답 200이면 성공 --- ## 7. Jenkinsfile 작성 가이드 ### 7.1 기본 구조 ```groovy pipeline { agent any environment { KEY = 'value' } stages { stage('단계명') { steps { sh 'command' } } } post { success { slackSend channel: '#sam-deploy', message: "성공" } failure { slackSend channel: '#sam-alerts', message: "실패" } } } ``` ### 7.2 SAM 저장소별 Jenkinsfile > 상세 코드는 `plans/production-deployment-plan.md` 4.4절 참조 | 저장소 | Stage 흐름 | 특이사항 | |--------|-----------|---------| | **sam-api** | Checkout → Lint → Test → Deploy | `migrate --force` 포함 | | **sam-manage** | Checkout → Lint → Build Assets → Deploy | 마이그레이션 없음 | | **sam-react-prod** | Checkout → Install → Lint → Build → Package → Deploy | `tar.gz`로 전송 | | **sam-sales** | Deploy | 간소화 (git pull + composer) | ### 7.3 배치 방법 각 저장소 **루트**에 `Jenkinsfile` 생성 → `git add Jenkinsfile && git commit -m "chore: Jenkinsfile 추가"` → push --- ## 8. 트러블슈팅 ### 8.1 빌드 실패 Jenkins 대시보드 → Job → 빌드 번호 → **Console Output** 에서 에러 로그 확인 ### 8.2 SSH 권한 오류 (`Permission denied`) ```bash sudo su - jenkins && ssh deploy@운영서버IP # 수동 테스트 # 운영 서버에서 authorized_keys 등록 확인 chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys ``` ### 8.3 메모리 부족 ```bash # Jenkins 힙 메모리 제한: /etc/default/jenkins에 JAVA_ARGS="-Xmx512m" 추가 sudo systemctl restart jenkins # Job 설정 → Discard old builds → 최대 빌드 수: 10 ``` ### 8.4 Webhook 미동작 ```bash # 수동 트리거 테스트 curl -X POST "http://114.203.209.83:8080/generic-webhook-trigger/invoke?token=sam-api" # Gitea: Webhooks → Recent Deliveries → 응답 코드 확인 (200=정상, 403=Token 불일치) ``` ### 8.5 React 빌드 OOM ```bash # Jenkinsfile에서 메모리 증가 sh 'export NODE_OPTIONS="--max-old-space-size=2048" && npm run build' # 실패 시 로컬(WSL)에서 react/deploy.sh 사용 ``` > **경고: 개발 서버에서 React 빌드 실패 시 로컬에서 `deploy.sh`를 사용한다.** --- ## 관련 문서 - [운영 환경 배포 계획서](../plans/production-deployment-plan.md) - Jenkinsfile 상세, 브랜치 전략 - [.env 동기화 절차](production-env-sync.md) - 환경 변수 분리 - [Docker 환경 스펙](../specs/docker-setup.md) - 현재 개발 환경 --- **최종 업데이트**: 2026-02-22