From 9c2df748b3ae6c30eecab206a83831330e247f5a Mon Sep 17 00:00:00 2001 From: Claude-51124 Date: Wed, 21 Jan 2026 10:13:06 +0900 Subject: [PATCH] =?UTF-8?q?docs:=20=EC=BD=9C=EB=93=9C=EB=A9=94=EC=9D=BC=20?= =?UTF-8?q?=EB=8B=A4=EC=A4=91=20=ED=99=95=EC=9D=B8=20=EB=A3=A8=ED=94=84=20?= =?UTF-8?q?=ED=8A=B8=EB=9F=AC=EB=B8=94=EC=8A=88=ED=8C=85=20=EB=B0=8F=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=9B=90=EC=B9=99=20=EB=B3=B4?= =?UTF-8?q?=EC=99=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 트러블슈팅 문서 추가: 260121_coldmail_multi_confirm_loop_fix.md - 계획 문서 archive 이동: 260121_coldmail_multi_confirm_and_summary_fix.md - 테스트 원칙 보완: 컨테이너 테스트 파일 반영 방법 (docker cp) - 백엔드 원칙 보완: 테스트 원칙에 컨테이너 반영 추가 --- .../311_백엔드_구조_원칙.md | 1 + .../315_테스트_작성_원칙.md | 15 +++ ..._coldmail_multi_confirm_and_summary_fix.md | 95 +++++++++++++++++++ .../260121_coldmail_multi_confirm_loop_fix.md | 94 ++++++++++++++++++ 4 files changed, 205 insertions(+) create mode 100644 journey/plans/archive/260121_coldmail_multi_confirm_and_summary_fix.md create mode 100644 journey/troubleshooting/260121_coldmail_multi_confirm_loop_fix.md diff --git a/book/300_architecture/311_백엔드_구조_원칙.md b/book/300_architecture/311_백엔드_구조_원칙.md index 581cf22..71312ac 100644 --- a/book/300_architecture/311_백엔드_구조_원칙.md +++ b/book/300_architecture/311_백엔드_구조_원칙.md @@ -363,6 +363,7 @@ utils ## 18. 테스트 원칙 - **실제 테스트 필수**: 코드 수정 후 추측하지 말고 실제로 테스트 (curl, Slack 직접 사용, DB 조회) +- **컨테이너 테스트 파일 반영**: tests 디렉토리는 볼륨 마운트 아님 (빌드 시 COPY). 새 테스트 파일 추가 시 `docker cp [파일경로] [컨테이너명]:/code/tests/` 사용 또는 컨테이너 재빌드 ## 19. 리팩토링 시 로직 상실 방지 원칙 diff --git a/book/300_architecture/315_테스트_작성_원칙.md b/book/300_architecture/315_테스트_작성_원칙.md index 9c1850f..1f64685 100644 --- a/book/300_architecture/315_테스트_작성_원칙.md +++ b/book/300_architecture/315_테스트_작성_원칙.md @@ -131,6 +131,21 @@ pytest tests/test_*.py -v grep -l "import pytest\|@pytest" tests/test_*.py ``` +### 컨테이너 테스트 파일 반영 + +**배경**: tests 디렉토리는 볼륨 마운트가 아님 (Dockerfile에서 `COPY ./tests /code/tests`로 빌드 시만 복사) + +**새 테스트 파일 추가 시**: +```bash +# 방법 1: docker cp (빠름, 재빌드 불필요) +docker cp tests/test_new_feature.py rb8001:/code/tests/ + +# 방법 2: 컨테이너 재빌드 (확실함) +docker compose down && docker compose up -d --build +``` + +**주의**: 호스트에서 테스트 파일 수정 후 컨테이너에 반영 안 되는 문제 주의 + --- ## 7. 테스트 네이밍 및 구조 diff --git a/journey/plans/archive/260121_coldmail_multi_confirm_and_summary_fix.md b/journey/plans/archive/260121_coldmail_multi_confirm_and_summary_fix.md new file mode 100644 index 0000000..2b9708c --- /dev/null +++ b/journey/plans/archive/260121_coldmail_multi_confirm_and_summary_fix.md @@ -0,0 +1,95 @@ +# 콜드메일 다중 확인 루프 및 요약 메시지 개선 + +**작성일**: 2026-01-21 +**관련 파일**: `rb8001/app/services/workflows/coldmail_workflow.py` + +--- + +## 문제 상황 + +1. **다중 이메일 확인 시 1개만 처리**: 오다가다, 에듀온 2개 모두 "맞음" 클릭 → 에듀온만 처리됨 +2. **요약 메시지 부적절**: `None억원 (신뢰도 0%)` 표시 → IR 분석 안 된 건 의미 없는 정보 + +--- + +## 아키텍처 (현재 vs 개선) + +### 현재 (버그) + +``` +wait_confirmation (interrupt) + ↓ 버튼 클릭 1회 +confirm → send → END ← 워크플로우 종료, 나머지 대기 이메일 유실 +``` + +- 현재 엣지: `confirm → send` (L352, 고정 엣지) + +### 개선 (루프) + +``` +wait_confirmation (interrupt) + ↓ 버튼 클릭 +confirm + ↓ 남은 대기 있으면 + ↓ → wait_confirmation (다시 interrupt) + ↓ 없으면 +send → END +``` + +--- + +## 필요 작업 + +### Phase 1: 다중 확인 루프 구현 (TDD) + +1. **Red**: `tests/test_coldmail_workflow_multi_confirm.py` 작성 + - 2개 이상 waiting_confirmation 시나리오 + - 첫 번째 confirm 후 다시 wait_confirmation으로 루프 확인 +2. **Green**: 코드 수정 + - `route_after_confirm()` 함수 추가 (L311 이후) + - `waiting_confirmation` 남아있으면 `"wait_confirmation"` 반환 + - 없으면 `"send"` 반환 + - L352 `confirm → send` 고정 엣지를 조건부 엣지로 변경 +3. **Refactor**: 필요 시 정리 + +### Phase 2: 요약 메시지 개선 (TDD) + +1. **Red**: 테스트 케이스 추가 + - `median`이 None인 경우 표시 문구 검증 +2. **Green**: `send_node` 수정 (L260-279) + - `median`이 None이면 `"등록 완료 (IR 분석 대기)"` 표시 +3. **Refactor**: 필요 시 정리 + +--- + +## 예상 변경 범위 + +| 파일 | 변경 내용 | +|------|----------| +| coldmail_workflow.py L311~ | `route_after_confirm()` 함수 추가 | +| coldmail_workflow.py L352 | `confirm → send` 조건부 엣지로 변경 | +| coldmail_workflow.py L260-279 | `send_node` 요약 포맷 수정 (median None 처리) | +| tests/test_coldmail_workflow_multi_confirm.py | 다중 확인 루프 테스트 (신규) | + +--- + +## 검증 절차 + +### 단위 테스트 +```bash +cd /home/admin/ivada_project/rb8001 +docker exec rb8001 pytest tests/test_coldmail_workflow_multi_confirm.py -v +``` + +### E2E 테스트 (실제 Slack) +1. 콜드메일 2건 이상 대기 상태 생성 +2. Slack에서 첫 번째 "맞음" 클릭 → 다시 interrupt 대기 확인 +3. 두 번째 "맞음" 클릭 → 요약 메시지 전송 확인 + +### 배포 후 확인 +```bash +git push origin main +# Gitea Actions 완료 대기 +docker ps | grep rb8001 # 재시작 확인 +docker logs rb8001 --tail 50 # 에러 확인 +``` diff --git a/journey/troubleshooting/260121_coldmail_multi_confirm_loop_fix.md b/journey/troubleshooting/260121_coldmail_multi_confirm_loop_fix.md new file mode 100644 index 0000000..2add027 --- /dev/null +++ b/journey/troubleshooting/260121_coldmail_multi_confirm_loop_fix.md @@ -0,0 +1,94 @@ +# 콜드메일 다중 확인 루프 및 요약 메시지 개선 + +**날짜**: 2026-01-21 +**작성자**: happybell80 +**관련 파일**: `rb8001/app/services/workflows/coldmail_workflow.py` + +--- + +## 문제 상황 + +1. **다중 이메일 확인 시 1개만 처리**: 오다가다, 에듀온 2개 모두 "맞음" 클릭 → 에듀온만 처리됨 +2. **요약 메시지 부적절**: `None억원 (신뢰도 0%)` 표시 → IR 분석 안 된 건 의미 없는 정보 + +--- + +## 원인 분석 + +### 문제 1: 워크플로우 종료 +- `confirm → send` 고정 엣지로 인해 첫 확인 후 바로 요약 전송 → 종료 +- 나머지 `waiting_confirmation` 유실 + +### 문제 2: median None 처리 누락 +- `send_node`에서 `median`이 None인 경우 처리 로직 없음 +- `f"- {company}: {median}억원"` → `None억원` 표시 + +--- + +## 해결 방법 + +### Phase 1: 다중 확인 루프 + +```python +# route_after_confirm() 함수 추가 +def route_after_confirm(state: ColdmailState) -> str: + if state.get("waiting_confirmation"): + return "wait_confirmation" + else: + return "send" + +# confirm → send 고정 엣지를 조건부 엣지로 변경 +workflow.add_conditional_edges( + "confirm", + route_after_confirm, + { + "wait_confirmation": "wait_confirmation", + "send": "send" + } +) +``` + +### Phase 2: 요약 메시지 개선 + +```python +# median이 None이면 IR 분석 대기 표시 +if median is None: + summary_lines.append(f"- {company}: 등록 완료 (IR 분석 대기)") +elif is_hold: + ... +else: + summary_lines.append(f"- {company}: {median}억원 (신뢰도 {conf_pct}%)") +``` + +--- + +## 변경 내용 + +| 파일 | 변경 | +|------|------| +| coldmail_workflow.py L311-325 | `route_after_confirm()` 함수 추가 | +| coldmail_workflow.py L365-372 | `confirm → send` 조건부 엣지로 변경 | +| coldmail_workflow.py L267-269 | `send_node` median None 처리 추가 | +| tests/test_coldmail_workflow_multi_confirm.py | 5개 테스트 케이스 추가 | + +--- + +## 검증 + +### 단위 테스트 +```bash +docker exec rb8001 pytest tests/test_coldmail_workflow_multi_confirm.py -v +# 5 passed +``` + +### 배포 +- `git push origin main` → Gitea Actions 자동 배포 +- `docker ps | grep rb8001` → 재시작 확인 완료 + +--- + +## 교훈 + +1. **LangGraph 루프 패턴**: 조건부 엣지로 동일 노드 재진입 가능 (고정 엣지 대신 `route_after_*` 함수 사용) +2. **None 값 처리 필수**: 외부 데이터(IR 분석 결과 등)는 None 가능성 항상 고려 +3. **테스트 컨테이너 반영**: tests 디렉토리는 볼륨 마운트 아님 → `docker cp` 또는 재빌드 필요