-
카카오클라우드 - 클라우드 개발자 교육 22주차 후기 (4/20 - 4/24)bootcamp 2026. 4. 24. 20:22
발표는 끝났고, 운영이 시작됐다 — 배포 자동화·보안 핫픽스·추천 신호 다층 흡수
이번 주 한 눈에
| 영역 | 핵심 산출물 |
| 인프라 / DevOps | 5개 레포 `cd-prod.yml` 운영 자동 배포 구축 · `scripts/deploy-prod.sh` · 운영서버 4-VM 재구축 매뉴얼 신설 · 운영 Nginx OAuth2 404 핫픽스 |
| 보안 | OCR SSRF 방어 · 10MB 스트리밍 제한 · debug EP 운영 가드 · PaddleOCR 싱글턴 race fix · `/ocr-events/analyze` 인증 필수화 · 결제 웹훅 서명 검증 재설계 |
| Chat Agent 품질 | CBF 약한 신호 다층 흡수 (reviews ∪ watch_history UNION + likes 0.7× + wishlist 0.4× + clicked_rec 0.5×) · 추천 편수 사용자 요청 존중 · info 의도 첫 턴 폴백 · 이미지 단독 첨부 422 hotfix · image-aware 재질문 |
| 결제 | Toss 콘솔 직접 취소 동기화 — `refundOrder` 선조회 구조 개편 · 관리자 "PG 재조회" 버튼 신설 · 웹훅 핸들러 `syncFromPg` 위임 일원화 |
| 관리자 AI 에이전트 v3 | v2 Write tool·HITL·risk_gate 전면 제거 → Read 54 + Draft 10 + Navigate 12 = **76 tool** ReAct 루프 재설계 · SSE `form_prefill`/`navigation` 2 이벤트 추가 |
| 고객센터 챗봇 v3.3 | vLLM 1.2B 분류 → ES Nori BM25 top-5 + 점수 임계값 분기 + Solar 경계 분류로 재구성. 정상 경로 LLM 호출 횟수 절반 이하 |
| 팀 협업 | 민수 OCR 영수증 인증 + 한나 좋아요 토글/리뷰 삭제 머지 반영 → 5개 레포 PR 생성 |게스트 쿼터 검증 + 팀원 PR 전수 리뷰 (4/21~22)
8주차 발표가 끝난 직후라 월요일은 "안전하게 운영으로 가져갈 수 있는 상태"를 만드는 날로 잡았어요.
두 가지를 정리:
비로그인 체험 1회 무료 실측
- `mongle_guest` HMAC HttpOnly 쿠키 + IP 이중 방어 (`chat:guest_used:{guestId}` + `chat:guest_used_ip:{ip}` TTL 365일)
- 쿠키 삭제 후 재접속·IP 고정 시나리오·다른 브라우저 동일 IP 3가지로 우회 시도 → 모두 차단 확인
- 소진 후 SSE `error: GUEST_QUOTA_EXCEEDED` → Client `LoginRequiredModal` 자동 노출
팀원 조직레포 PR/머지 전수 리뷰
팀원 4명 × 5개 레포의 열린 PR/최근 머지 전부 읽어봤어요. 정한나의 recommend v2 `review_repository.py` 에서 SQL 문자열 동적 치환 경로가 발견돼 화이트리스트(`_ALLOWED_TABLES`) + 런타임 컬럼 존재 검사로 보강하도록 피드백 남김. 민수 OCR 코드는 다음날 머지 반영에서 본격 점검.운영 CI/CD 자동 배포 구축 (4/23)
18주차 Q&A 때 "운영 배포는 어떻게 해요?" 에 "로컬 빌드 → rsync → VM2 `docker load` → compose up. 자동화는 다음 스프린트 과제" 라고 답변한 그 다음 스프린트가 바로 이번 주였어요.
핵심 결정 — GHCR 이미지 빌드 → VM pull
| 옵션 | 장점 | 단점 | 선택 |
| **A) GHCR 빌드 → VM pull** | VM 에서 빌드 X, SHA 태그 롤백 쉬움 | GHCR 권한/로그인 세팅 필요 | ✅ |
| B) rsync + VM 빌드 | 스테이징과 동일 패턴 | **VM2 디스크 94% / Agent 1.1GB 로드 실패 전례(4/16)** | ✗ |
4/16 운영 배포 때 VM2 디스크가 94% 까지 차서 Agent 이미지 로드가 실패한 사건이 결정적. VM 에서 빌드하지 않는 쪽으로 확정.
5개 레포 `cd-prod.yml` 구조
GitHub Actions (push: main)
├─ test (gradle/pytest/lint)
├─ build & GHCR push (backend/agent/recommend) → tag: {sha} + latest
└─ deploy (ssh + ProxyJump)
VM1 bastion (210.109.15.187, 공인)
└─ VM2 app (10.20.0.11) — docker pull + compose up -d + 헬스체크
- Client/Admin 은 VM1 Nginx 에 정적 서빙이라 dist artifact → VM1 rsync → `nginx -s reload`
- Backend/Agent/Recommend 는 VM2 사설망이라 **VM1 bastion ProxyJump 필수**
- Concurrency key `cd-prod-<svc>` — 동일 서비스 배포 직렬화
- 이미지 태그 **2종 동시 push**: `{sha}` (롤백용) + `latest` (compose 참조)
자동 롤백 트릭 — `:latest` 포인터
deploy job 이 배포 직전 컨테이너의 **이미지 ID** 를 `docker inspect` 로 기억 → 헬스체크 실패하면 `docker tag <prev_id> ...:latest` 1줄로 이전 이미지 복귀. compose 는 항상 `:latest` 만 참조하니까 SHA 를 `:latest` 로 덮어쓰면 `docker compose up -d --no-deps --force-recreate` 만으로 교체됨.
대안 중에 "compose image 에 SHA 직접 박기" 도 있었지만 배포마다 compose 수정 + commit 필요해서 기각. 불변 SHA + 가변 포인터 조합이 **compose 수정 없는 교체 + SHA 추적** 을 양립시키는 유일한 방법.
수동 배포/롤백 CLI — `scripts/deploy-prod.sh`
./scripts/deploy-prod.sh all # 전체
./scripts/deploy-prod.sh backend # 단일 서비스 :latest 재풀
./scripts/deploy-prod.sh backend abc1234 # SHA 롤백
첫 구현 때 `declare -A SERVICES` 의 메타를 `:` 구분자로 파싱하다가 health URL(`http://localhost:8080/health`) 의 `:` 때문에 split 실패. 구분자를 **`|`** 로 바꿔서 해결. 외부 입력이 아닌 상수라도 구분자 충돌 가능성은 반드시 체크해야 한다는 교훈.
관리자 AI 에이전트 v3 재설계"AI 가 직접 쓰게 하면 안 되겠다"
3종 Tool 분류 (Read / Draft / Navigate)
| 분류 | Backend 호출 | 반환 payload | Client 동작 |
| Read | GET 직접 | `AdminApiResult.data` | narrator 가 자연어 서술 |
| Draft | 없음 | `{target_path, draft_fields, action_label, summary}` | SSE `form_prefill` → "해당 화면으로 열기" 버튼 → `navigate(path, {state: {draft}})` |
| Navigate | GET (검색) | `{target_path\|None, label, context_summary, candidates?}` | SSE `navigation` → "이동" 버튼. 단건/다건 분기 |AI 가 실수로 데이터를 바꿀 수 없고, HITL/confirm_keyword 복잡도가 사라지며, UX 는 "AI 가 초안·링크를 주고 관리자가 최종 저장/실행" 으로 명확해짐.
결제 사고 두 건 근본 해결
유저(관리자)가 Toss 개발자센터 콘솔에서 결제 1건을 직접 취소 → 몽글픽 관리자 페이지 확인 → 상태가 여전히 `COMPLETED`. 관리자가 "환불" 버튼 클릭 → 500 에러.
교훈
공식 문서를 한 번 더 확인했으면 피할 수 있었던 유령 구현. 외부 시스템 통합은 "있을 것 같은" API 를 구현하지 말고 실제 스펙을 읽어야 함. 단일 진실 원본 원칙 — 관리자 "PG 재조회" 버튼과 웹훅 핸들러가 정확히 같은 로직 수행 → 유지보수 1개 경로로 단순화.

——————————————————————————
본 후기는 [카카오엔터프라이즈x스나이퍼팩토리] 카카오클라우드로 배우는 AIaaS 마스터 클래스 3기(B-log) 리뷰로 작성 되었습니다.'bootcamp' 카테고리의 다른 글
카카오클라우드 - 클라우드 개발자 교육 21주차 후기 (4/13 ~ 4/17) (1) 2026.04.20 카카오클라우드 - 클라우드 개발자 교육 20주차 후기(4/6 ~ 4/10) (0) 2026.04.20 카카오클라우드 - 클라우드 개발자 교육 19주차 후기(3/30 ~ 4/3) (0) 2026.04.20 카카오클라우드 - 클라우드 개발자 교육 18주차 후기 (0) 2026.03.29 카카오클라우드 - 클라우드 개발자 교육 17주차 후기 (0) 2026.03.29