docs: 콜드메일 다중 확인 루프 트러블슈팅 및 테스트 원칙 보완

- 트러블슈팅 문서 추가: 260121_coldmail_multi_confirm_loop_fix.md
- 계획 문서 archive 이동: 260121_coldmail_multi_confirm_and_summary_fix.md
- 테스트 원칙 보완: 컨테이너 테스트 파일 반영 방법 (docker cp)
- 백엔드 원칙 보완: 테스트 원칙에 컨테이너 반영 추가
This commit is contained in:
Claude-51124 2026-01-21 10:13:06 +09:00
parent d4be579021
commit 9c2df748b3
4 changed files with 205 additions and 0 deletions

View File

@ -363,6 +363,7 @@ utils
## 18. 테스트 원칙
- **실제 테스트 필수**: 코드 수정 후 추측하지 말고 실제로 테스트 (curl, Slack 직접 사용, DB 조회)
- **컨테이너 테스트 파일 반영**: tests 디렉토리는 볼륨 마운트 아님 (빌드 시 COPY). 새 테스트 파일 추가 시 `docker cp [파일경로] [컨테이너명]:/code/tests/` 사용 또는 컨테이너 재빌드
## 19. 리팩토링 시 로직 상실 방지 원칙

View File

@ -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. 테스트 네이밍 및 구조

View File

@ -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 # 에러 확인
```

View File

@ -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` 또는 재빌드 필요