# CI/CD 배포 트러블슈팅 가이드

**작성일**: 2026-07-11  
**버전**: 1.0  
**대상**: QuantEngine 배포 담당자

---

## 1. 배포 실패 진단

### 1.1 Pre-Deployment 실패

**증상**: 배포가 시작되지 않음

```
[ERR] ERROR: SSH key not found
[ERR] ERROR: Build artifact not found
[ERR] ERROR: DB password secret not configured
```

**해결방법**:

| 오류 | 원인 | 해결책 |
|------|------|--------|
| SSH key not found | Gitea Actions에서 SSH 키 미설정 | Gitea Settings > Repository Secrets에서 SSH_KEY 추가 |
| Build artifact missing | 이전 단계(Build) 실패 | merge-to-main.yml의 Stage 4 로그 확인 |
| DB password not configured | Gitea Secrets 미설정 | Gitea Settings > Repository Secrets에서 QUANTENGINE_DB_PASSWORD 추가 |
| Config files missing | deploy/ 디렉토리 미포함 | 소스 코드의 `deploy/` 폴더 확인 |

**빠른 확인**:
```bash
# 로컬에서 필수 파일 확인
ls -la ./deploy/
ls -la deploy_gb.sh
file quantengine.tar.gz  # 파일 크기 1MB 이상 확인
```

---

### 1.2 배포 실패 (Extract Stage)

**증상**:
```
[ERR] FATAL: Failed to extract artifact
[ERR] tar: (standard input): gzip: stdin: unexpected end of file
```

**원인 분석**:
- 빌드 아티팩트 손상
- 부분 다운로드된 파일
- 압축 형식 오류

**해결책**:

1. **빌드 아티팩트 재생성**:
   ```bash
   # 로컬에서 강제 재빌드
   dotnet clean src/dotnet/QuantEngine.Web/QuantEngine.Web.csproj
   dotnet build -c Release
   ```

2. **tar 파일 검증**:
   ```bash
   # 정상 tar 파일인지 확인
   tar -tzf quantengine.tar.gz | head -20
   
   # 파일 크기 확인 (최소 1MB 이상)
   ls -lh quantengine.tar.gz
   ```

3. **재배포 트리거**:
   ```bash
   # 새 커밋 생성 또는 manual dispatch
   git commit --allow-empty -m "rebuild: Force redeployment"
   git push origin main
   ```

---

### 1.3 배포 실패 (Structure Normalization)

**증상**:
```
[ERR] FATAL: QuantEngine.Web.dll not found in deployment
```

**원인**:
- net10.0 구조 정규화 실패
- DLL 파일이 중첩된 폴더에 있음

**해결책**:

1. **배포 디렉토리 구조 확인**:
   ```bash
   ls -lh /home/kjh2064/deployments/quantengine_*/
   ```

2. **수동 구조 정리** (긴급 복구):
   ```bash
   # 가장 최근 배포 확인
   LATEST=$(ls -dt /home/kjh2064/deployments/quantengine_* | head -1)
   
   # net10.0 아래 파일들 이동
   mv $LATEST/net10.0/* $LATEST/
   rmdir $LATEST/net10.0
   
   # 서비스 재시작
   systemctl restart quantengine
   ```

---

### 1.4 헬스 체크 실패

**증상**:
```
[ERR] FAILED: Health check did not pass after 5 attempts
[ERR] Service not responding on http://127.0.0.1:5000/
```

**진단**:

```bash
# 1. 서비스 상태 확인
systemctl status quantengine.service

# 2. 포트 점유 확인
lsof -i :5000 || ss -tlnp | grep 5000

# 3. 서비스 로그 확인
journalctl -u quantengine.service -n 50

# 4. DB 연결 테스트
PGPASSWORD='pvuIp8fWNj+oWfZtciw43GzJ4yU0vwKf' \
  psql -h 127.0.0.1 -U quantengine_app -d quantenginedb -c "SELECT 1;"

# 5. 포트 수동 테스트
curl -v http://127.0.0.1:5000/
```

**공통 해결책**:

| 증상 | 원인 | 해결책 |
|------|------|--------|
| Connection refused | 서비스 시작 안 됨 | `systemctl restart quantengine` |
| Address already in use | 이전 프로세스 남음 | `pkill -f "dotnet.*QuantEngine"` |
| Database error | DB 연결 실패 | appsettings.Production.json 비밀번호 확인 |
| Timeout | 느린 시작 | HEALTH_CHECK_RETRIES 증가 |

---

### 1.5 자동 롤백 실패

**증상**:
```
[ERR] CRITICAL: Rollback failed - previous deployment not found
```

**원인**:
- 이전 배포가 삭제됨
- 배포 디렉토리 정리로 인한 손실

**예방**:
```bash
# 배포 히스토리 확인
ls -ldt /home/kjh2064/deployments/quantengine_* | head -10

# 수동 롤백 (긴급)
PREV_DEPLOY="/home/kjh2064/deployments/quantengine_YYYYMMDD_HHMMSS"
ln -sfn $PREV_DEPLOY /home/kjh2064/quantengine_active
systemctl restart quantengine
```

---

## 2. 배포 수동 관리

### 2.1 수동 배포 트리거

```bash
# Gitea Actions에서 Manual Dispatch
# 또는 CI/CD에서 commit → main 푸시

git commit --allow-empty -m "deploy: Manual trigger"
git push origin main
```

### 2.2 현재 배포 상태 확인

```bash
# 활성 배포 확인
readlink /home/kjh2064/quantengine_active

# 배포 디렉토리 목록
ls -lht /home/kjh2064/deployments/quantengine_* | head -5

# 서비스 상태
systemctl status quantengine.service

# 최근 로그
journalctl -u quantengine.service -f
```

### 2.3 즉시 롤백

```bash
# 1. 이전 배포 선택
DEPLOYMENTS=$(ls -dt /home/kjh2064/deployments/quantengine_*)
PREV=$(echo "$DEPLOYMENTS" | head -2 | tail -1)

# 2. 롤백 실행
ln -sfn $PREV /home/kjh2064/quantengine_active

# 3. 서비스 재시작
systemctl restart quantengine

# 4. 확인
systemctl status quantengine.service
curl http://127.0.0.1:5000/
```

---

## 3. 성능 최적화

### 3.1 배포 시간 단축

```bash
# 배포 캐시 검증
du -sh /home/kjh2064/deployments/

# 오래된 배포 수동 정리 (유지: 3개)
ls -dt /home/kjh2064/deployments/quantengine_* | tail -n +4 | xargs rm -rf
```

### 3.2 헬스 체크 타임아웃 조정

`.gitea/workflows/deploy-prod.yml`에서:
```yaml
env:
  HEALTH_CHECK_RETRIES: "5"        # 재시도 횟수
  HEALTH_CHECK_DELAY: "3"          # 재시도 간격 (초)
```

---

## 4. 모니터링 & 알림

### 4.1 Telegram 알림 설정

```bash
# Gitea Settings > Repository Secrets에서 설정
TELEGRAM_BOT_TOKEN=<your_token>
TELEGRAM_CHAT_ID=<your_chat_id>
```

### 4.2 배포 로그 위치

```bash
# 최근 배포 로그
journalctl -u quantengine.service -n 100

# 배포 정보 확인
cat /home/kjh2064/deployments/quantengine_*/(.deployment_info)
```

---

## 5. 자주 묻는 질문 (FAQ)

**Q: 배포는 되었는데 변경사항이 반영되지 않음**
```bash
# 1. 캐시 확인
curl -H "Cache-Control: no-cache" https://quant.taxbaik.com/

# 2. 서비스 재시작
systemctl restart quantengine

# 3. 브라우저 캐시 삭제 후 재접속
```

**Q: "appsettings.Production.json not found" 오류**
```bash
# 파일이 자동 생성되므로 정상
# 만약 없다면:
cat > /home/kjh2064/quantengine_active/appsettings.Production.json << 'EOF'
{
  "ConnectionStrings": {
    "DefaultConnection": "Host=127.0.0.1;Database=quantenginedb;Username=quantengine_app;Password=<PASSWORD>;Search Path=quantengine;"
  }
}
EOF
systemctl restart quantengine
```

**Q: 데이터베이스 연결이 계속 실패**
```bash
# 비밀번호 확인
grep "Password=" /home/kjh2064/quantengine_active/appsettings.Production.json

# DB 직접 테스트
PGPASSWORD='pvuIp8fWNj+oWfZtciw43GzJ4yU0vwKf' \
  psql -h 127.0.0.1 -U quantengine_app -d quantenginedb -c "SELECT version();"
```

---

## 6. 연락처 & 지원

- **배포 담당**: kjh2064
- **긴급 롤백**: systemctl restart quantengine
- **로그 위치**: /var/log/journalctl, /home/kjh2064/deployments/*/logs/
- **모니터링**: https://quant.taxbaik.com/Admin/Monitoring

---

**마지막 업데이트**: 2026-07-11  
**다음 업데이트 예정**: 버그 수정 후
