# [트러블슈팅] CLAUDE 코드 작성 원칙 정렬 체크리스트 (2025-10-23)

본 문서는 현재 코드가 CLAUDE 원칙(FP 100%, 하드코딩 0%, 계층 분리, UUID 중심, 비동기 안전)에 어긋나는 지점을 정리하고, 수정 시 참고할 구체 체크리스트를 제공합니다. 실제 코드 수정은 포함하지 않습니다.

- 비동기 이벤트 루프 생성 금지 위반
  - rb8001/app/core/emotion/emotion_classifier.py:52 — 동기 `predict()`가 `asyncio.new_event_loop()` 사용. 비동기 API 통일 또는 안전 래핑 필요.
- Slack SDK 동기 호출 사용(요청 루프 블로킹)
  - rb8001/app/router/slack_handler.py:177, 299, 314 등 — `WebClient` 동기 호출. AsyncWebClient 전환 및 `await` 적용 필요.
  - rb8001/app/skills/dm_skill.py:97, 176, 520 등 — DM 전송·메시지 업데이트 동기 호출 제거.
- 라우터 계층의 직접 DB 접근(계층 분리 위반)
  - rb8001/app/router/slack_handler.py:13, 73-85, 198-206 — `SessionLocal`과 SQL 직접 실행. 팀 UUID 매핑 로직을 서비스/레포지토리로 이동.
  - rb8001/app/skills/dm_skill.py:421-459 — 사용자 키워드 조회의 DB 접근을 서비스→state로 이관.
  - rb8001/app/services/naverworks_file_processor.py:12, 26-39 — 팀 UUID 조회 DB 접근 분리.
  - rb8001/app/router/message_router.py:20-23 — 최근 대화 조회는 서비스 헬퍼를 통해 state 호출만 수행하도록 정리.
- 하드코딩된 URL/포트 제거 필요(환경설정 일원화)
  - rb8001/app/router/slack_handler.py:64 — `http://localhost:8508/api/upload` → `settings.SKILL_RAG_FILE_URL` 기반 구성.
  - rb8001/app/router/slack_handler.py:366 — `http://localhost:8508/api/search` → 설정 사용.
  - rb8001/app/skills/dm_skill.py:134, 168, 362 — `SKILL_EMAIL_URL`, 뉴스 검색 `localhost` 기본값 제거 → 설정만 사용.
  - rb8001/app/commands/skill_commands.py:16-17 — `http://localhost:8502/8505` 기본값 제거 → 전역 설정 사용.
  - rb8001/app/skills/email_integration.py:366 — `llm_callback`에 `http://localhost:8001` 하드코딩 제거 → 게이트웨이/자기 호스트 설정 사용.
  - rb8001/app/skills/startup_news_skill.py:20-34 — Mistral API URL/모델 환경설정화.
  - rb8001/app/commands/skill_commands.py:279-285 — Tavily API URL 설정화.
  - auth-server/app/api/slack_router.py:125 — 컨테이너 라우팅 `http://localhost:{port}` 설정화.
  - skill-email/services/naverworks_provider.py:33-34 — 사설 IP 기본값 제거, 환경필수화.
- UUID 중심 식별 일관화
  - rb8001/app/skills/dm_skill.py:125-136, 168-175 — 이메일 조회에 Slack ID 직접 사용 금지. 매핑 후 UUID만 전달.
  - rb8001/app/router/slack_handler.py:282-287 — 로깅/컨텍스트에서도 UUID 우선 유지 점검.
- 동기 HTTP 호출 제거/비동기화
  - rb8001/app/memory/embedding_client.py:28-33 — `requests.post` 동기 호출을 비동기(`httpx.AsyncClient`)로 전환 또는 실행자 활용.
- JSONB 저장 규칙 준수(::jsonb 캐스팅)
  - rb8001/app/services/startup_valuation.py:475-486 — `metadata` 저장 시 `json.dumps(...)` + `$7::jsonb` 캐스팅 반영 필요.

권장 진행 순서: (1) URL/설정 일원화 → (2) 라우터 DB 접근 분리 → (3) Slack/HTTP 비동기화 → (4) UUID 일관화 → (5) JSONB 캐스팅 정리.

## 권장: LangGraph로 동적 플로우 관리
- 복잡한 처리 흐름을 정적 파이프라인이 아닌 “상태 있는 그래프(노드/에지)”로 모델링하고, 런타임 조건에 따라 분기·병합을 결정합니다.
- 그래프 상태와 체크포인트를 영속화해 노드 단위 부분 재시도·중단 지점 재개·아이템별 독립 실패 허용을 구현합니다(시간제한/동시성/백오프 정책 포함).
- 관측성(각 노드 입력/출력/지연/에러)을 표준화하여 트레이싱/로깅을 일관화하고, 실패 시 보상 경로(대안 노드)로 자동 전환합니다.

## 적용 내역 업데이트 (rb8001 제외)
- auth-server
  - 컨테이너 이벤트 전달 URL을 `CONTAINER_BASE_URL`로 외부화 (app/api/slack_router.py)
  - CORS 도메인 ENV `CORS_ALLOW_ORIGINS`(CSV) 지원 (app/main.py)
  - NAVER WORKS redirect 기본값을 `FRONTEND_ORIGIN`으로 치환 (app/providers/naverworks.py)
  - DATABASE_URL 기본 사설 IP 제거 (app/providers/naverworks_passport.py)
- skill-email
  - ROBEING_MONITOR_URL 기본값을 서비스명 기반으로 조정, API Provider가 ENV 사용 (main.py, services/api_credentials_provider.py)
  - AUTH_SERVER_URL/DB 기본 사설 IP 제거 (services/naverworks_provider.py)
- skill-slack
  - 로빙 URL 매핑을 ENV(`ROBEING_URLS_JSON` 또는 `ROBEING_URL_TEMPLATE`/`ROBEING_DEFAULT_PORT_BASE`)로 구성 가능 (app/services/slack_data_client_impl.py)
- skill-publish
  - 게시 뉴스 URL을 settings(`PUBLISHED_NEWS_URL`)에서 일원화 (app/services/post_formatter.py)
- skill-embedding
  - 임베딩 서비스 기본 URL을 ENV(`SKILL_EMBEDDING_URL`)로 일원화 (http_embedding_function.py)
- robeing-gateway
  - 헬스체크 스크립트가 `GATEWAY_URL`을 인식하도록 변경 (scripts/health_check.sh)

참고: nginx-infra, frontend-customer의 기본 도메인/프록시 패턴은 운영 전략에 따라 별도 템플릿화 검토 필요(이번 변경 범위 밖).
