From 6bd22f0a3f206e780f2f6823b6c6e8e33c9d5618 Mon Sep 17 00:00:00 2001 From: happybell80 Date: Sat, 20 Sep 2025 00:18:26 +0900 Subject: [PATCH] =?UTF-8?q?docs:=20NaverWorks-Slack=20=EC=97=B0=EB=8F=99?= =?UTF-8?q?=20=EA=B5=AC=ED=98=84=20=EC=99=84=EB=A3=8C=20=EB=AC=B8=EC=84=9C?= =?UTF-8?q?=20=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 코드 분석 결과 반영 (51124 서버 확인) - 구현 결정 사항 정리 (6가지 핵심 결정) - 우선순위별 구현 체크리스트 (P0, P1, P2) - 실제 데이터 흐름 15단계 상세 기록 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- ..._naverworks_slack_01_base_configuration.md | 293 ++++++++---------- 1 file changed, 129 insertions(+), 164 deletions(-) diff --git a/troubleshooting/250919_naverworks_slack_01_base_configuration.md b/troubleshooting/250919_naverworks_slack_01_base_configuration.md index d5d62dd..2435dc9 100644 --- a/troubleshooting/250919_naverworks_slack_01_base_configuration.md +++ b/troubleshooting/250919_naverworks_slack_01_base_configuration.md @@ -1,9 +1,9 @@ # NAVER WORKS → Slack 연동 [1/3] 기본 구성 -## 날짜: 2025-09-19 -## 작성자: Claude (51123 서버 관리자) -## 관련 서비스: rb8001, skill-email, auth-server -## 상태: 기본 구조 구현 필요 +## 날짜: 2025-09-19 (수정: 2025-01-09) +## 작성자: Claude (51123 서버 관리자) / happybell80 +## 관련 서비스: rb8001, skill-email, skill-slack, auth-server +## 상태: 기본 구조 부분 구현 ## 관련 문서 - [2/3 일일 브리핑](./250919_naverworks_slack_02_daily_briefing.md) @@ -11,8 +11,7 @@ --- - -## 1. 현재 구현 상태 (코드 분석 기준) +## 1. 현재 구현 상태 (2025-01-09 확인) ### 구현 완료 - **auth-server**: @@ -24,16 +23,19 @@ - GET `/messages` 엔드포인트 (provider 파라미터 지원) - POST `/send` 엔드포인트 - registry.register("naverworks", NaverWorksProvider()) 등록됨 +- **skill-slack (포트 8502)**: + - POST `/api/v1/send` 토큰 파라미터 지원 (2025-01-09) + - 멀티 워크스페이스 지원 가능 - **NAVER WORKS Mail API**: - ✅ 올바른 엔드포인트 확인: `/mail/mailfolders/{folderId}/children` - ✅ mailAddress null 문제 해결 (API 사용에 영향 없음) - ✅ 9,192개 메일 정상 조회 확인 -### 미구현/불일치 -- **rb8001**: provider=naverworks 미지정 → 기본 Gmail만 사용 -- **skill-email**: `/mail-summary` 엔드포인트 없음 (문서에만 제안) -- **식별자**: Slack ID → UUID 변환이 send에만 부분 적용 -- **보안 위험**: NaverWorksProvider.DEFAULT_USER_ID 하드코딩 존재 +### 미구현/문제점 +- **rb8001**: provider 파라미터 없음, UUID 변환 누락 (list 경로) +- **skill-slack**: rb8001과 미연동 (직접 WebClient 사용) +- **24시간 필터**: 어디에도 구현 안 됨 +- **토큰 갱신**: 자동 호출 없음 (수동 함수만 존재) ### 잘못된 전제 정정 - ❌ "skill-naverworks(8511) 구현 완료" → ✅ skill-email(8501) 멀티 프로바이더로 통합 @@ -64,186 +66,149 @@ --- -## 3. 오케스트레이션 구조와 skill-slack 통합 +## 3. 정확한 구현 경로 -### 3.1 rb8001 오케스트레이션 흐름 -``` -Slack 요청 → rb8001 (중앙 오케스트레이터) - ├→ skill-email (메일 데이터 조회) - ├→ 필터링/분석 (rb8001 내부) - ├→ skill-slack (Slack 포맷팅) - └→ Slack 응답 +### 3.1 전체 데이터 흐름 (토큰 갱신 포함) + +**시나리오**: 슬랙에서 "네이버웍스 메일 확인" 메시지를 보내면 최근 24시간 이내 받은 메일 전체가 슬랙 채널에 표시 + +**상세 흐름**: +1. 슬랙 "네이버웍스 메일 확인" → Gateway +2. Gateway가 slack_user_mapping에서 UUID 조회 → X-User-Id 헤더 +3. Gateway가 slack_workspace에서 봇 토큰 조회 → X-Slack-Bot-Token 헤더 +4. Gateway가 X-Source: "slack" 헤더 추가 +5. Gateway → rb8001 (헤더 + 메시지) +6. rb8001이 X-Source 확인 → slack 요청임을 인지 +7. rb8001 → skill-email:8501/messages?provider=naverworks&user_id={uuid} +8. skill-email이 naverworks_token에서 액세스 토큰 조회 +9. 토큰 만료 체크 → 만료시 auth-server:8000/auth/naverworks/passport/refresh 호출 +10. auth-server가 naverworks_token 테이블 업데이트 → 새 토큰 반환 +11. NaverWorks API 호출 → 24시간 이내 메일 전체 반환 +12. rb8001이 메일 데이터를 슬랙 메시지 형식으로 포맷팅 (blocks, markdown) +13. rb8001 → skill-slack:8502/api/v1/send (channel, text, blocks, token) +14. skill-slack이 슬랙 API 형식에 맞게 최종 포맷팅 +15. skill-slack → 슬랙 채널에 메일 표시 + +**Gateway → rb8001 전달 정보**: + +Headers: +- `X-User-Id`: UUID (Slack user를 UUID로 변환) +- `X-Slack-Bot-Token`: 봇 토큰 (Gateway가 DB에서 조회) +- `X-Source`: "slack" (요청 출처 구분) +- `X-Slack-Signature`: Slack 서명 +- `X-Slack-Request-Timestamp`: 타임스탬프 + +Body (원본 그대로): +```json +{ + "team": {"id": "T0925SXPS4D"}, + "event": { + "user": "U0928DT3MDW", + "channel": "C07V9F3V21V", + "text": "네이버웍스 메일 확인" + } +} ``` -**rb8001의 역할:** -- 사용자 의도 파악 -- 스킬 조합 결정 -- 데이터 가공 및 필터링 -- 최종 응답 전송 - -### 3.2 skill-slack 현재 구조 및 추가 역할 - -**실제 파일 구조 (포트 8502):** +**프론트엔드 요청 경로**: ``` -skill-slack/ -├── app/ -│ ├── main.py # FastAPI 앱, API 버전 설정 -│ ├── api/ -│ │ └── endpoints/ -│ │ ├── messages.py # /messages/send, /messages/update -│ │ ├── summarize.py # /summarize -│ │ └── digest.py # /digest -│ ├── services/ -│ │ ├── slack_service.py # SlackService 클래스 -│ │ ├── message_formatter.py # 메시지 포맷 헬퍼 -│ │ └── summarize_service.py # 요약 서비스 -│ ├── models/ -│ │ └── slack_models.py # BaseSkillRequest 등 Pydantic 모델 -│ └── core/ -│ └── config.py # Settings 설정 +Frontend → Gateway → rb8001 → skill-email → rb8001 → skill-slack → Slack ``` -**기존 엔드포인트 (모두 `/api/v1` prefix):** -| 엔드포인트 | 역할 | 현재 상태 | Request Body | -|-----------|------|-----------|--------------| -| POST `/api/v1/messages/send` | Slack 메시지 전송 | ✅ 구현됨 | BaseSkillRequest + message | -| POST `/api/v1/messages/update` | 메시지 업데이트 | ✅ 구현됨 | BaseSkillRequest + ts + message | -| POST `/api/v1/summarize` | 대화 요약 | ✅ 구현됨 | BaseSkillRequest + messages | -| POST `/api/v1/digest` | 스레드 다이제스트 | ✅ 구현됨 | BaseSkillRequest + thread_ts | +Gateway → rb8001 전달 정보: +- Headers: `X-User-Id`, `X-Source`: "frontend" +- Body: `{"text": "메시지", "user_id": "UUID", "context": {}}` -**BaseSkillRequest 구조:** -```python -class BaseSkillRequest(BaseModel): - team_id: str - user_id: str - channel_id: str - thread_ts: Optional[str] = None -``` +### 3.2 현재 사용 가능한 엔드포인트 -**추가 필요 엔드포인트:** -| 엔드포인트 | 역할 | 입력 | 출력 | -|-----------|------|------|------| -| POST `/api/v1/format/mail-list` | 메일 목록을 Slack 블록으로 변환 | BaseSkillRequest + mails | Block Kit JSON | -| POST `/api/v1/format/cold-mail` | 콜드메일 테이블 포맷 생성 | BaseSkillRequest + cold_mails | Table Block | -| POST `/api/v1/format/briefing` | 일일 브리핑 포맷 생성 | BaseSkillRequest + briefing_data | Briefing Block | +**skill-email (포트 8501)**: +- GET `/messages?provider=naverworks&user_id={uuid}` - 메일 목록 조회 +- POST `/send` - 메일 발송 (provider 필드 포함) -### 3.3 skill-email 파일별 역할 (최소 변경 원칙) -| 파일 경로 | 역할 | 구현 내용 | 예상 코드 줄 수 | -|-----------|------|-----------|----------------| -| `main.py` | 앱 실행, 라우터 등록 | 기존 엔드포인트 유지, 새 라우터만 추가 | +5줄 추가 | -| `routers/naverworks_mail.py` (신규) | HTTP 요청 처리 | `/cold-mail-list`, `/daily-briefing` 엔드포인트 | 30-40줄 | -| `services/naverworks_mail_service.py` (신규) | 비즈니스 로직 | 콜드메일 필터링, 브리핑 생성 로직 | 100-150줄 | -| `services/naverworks_provider.py` | NAVER WORKS API 연동 | 기존 파일 활용, 메서드만 추가 | +50줄 추가 | -| `repositories/mail_cache_repository.py` (신규) | DB CRUD 작업 | 메일 캐시 저장/조회 SQL | 50-60줄 | -| `models/mail_cache.py` (신규) | DB 테이블 정의 | SQLAlchemy ORM 모델 (mail_cache 테이블) | 15-20줄 | -| `schemas/naverworks_schemas.py` (신규) | API 입출력 형식 | Pydantic 모델 (Request/Response) | 30-40줄 | -| `core/slack_formatter.py` (신규) | Slack 포맷터 | 메일→Slack 블록 변환 | 50-70줄 | +**skill-slack (포트 8502)**: +- POST `/api/v1/send` - Slack 메시지 전송 + - 필수: channel, text + - 선택: token, thread_ts, blocks -### 3.4 데이터 계층 구분 -| 계층 | 파일 종류 | 역할 | 비유 | -|------|-----------|------|------| -| **Model** | `models/*.py` | DB 테이블 구조 정의 (SQLAlchemy ORM) | 창고 선반 설계도 (내부용) | -| **Schema** | `schemas/*.py` | API 요청/응답 형식 (Pydantic) | 손님 주문서 양식 (외부용) | -| **Repository** | `repositories/*.py` | DB 접근 로직 (CRUD) | 창고 관리 직원 | -| **Database** | `db/session.py` | DB 연결 관리 | 창고 출입문 열쇠 | +### 3.3 수정 필요 위치 -#### 데이터 흐름 예시 -``` -1. API 요청 → Schema (검증) -2. Service → Repository (DB 작업 요청) -3. Repository → Model (ORM으로 DB 테이블 접근) -4. Model → Database (실제 SQL 실행) -5. 결과 → Schema (응답 포맷) → API 응답 -``` +**rb8001/app/skills/email_integration.py**: +- 262행: GET `/messages` 호출 시 provider 파라미터 누락 +- 현재 코드: `params={"user_id": user_id, "limit": 5}` (Gmail만 조회) +- 필요한 수정: provider=naverworks 파라미터 추가 -### 3.5 rb8001 파일별 역할 -| 파일 경로 | 역할 | 구현 내용 | -|-----------|------|-----------| -| `app/main.py` | 메시지 라우팅 | Slack 메시지 수신 및 처리 | -| `app/skills/email_integration.py` | 이메일 스킬 통합 | NaverWorks 지원 추가 | -| `app/services/scheduler.py` | 스케줄러 | 일일 브리핑 자동 실행 | -| `app/schemas/skill_schemas.py` | 스킬 요청/응답 형식 | SkillRequest, SkillResponse | +**rb8001/app/router/slack_handler.py**: +- 274행: `local_client.chat_postMessage()` 직접 호출 +- 311행: `WebClient(token=custom_token)` 직접 생성 +- skill-slack 사용 안 함 + +**robeing-gateway/app/main.py**: +- 553, 560, 611, 615행: X-User-Id, X-Slack-Bot-Token 헤더 설정 +- X-Source 헤더 없음 (요청 출처 구분 불가) -### 3.6 auth-server 파일별 역할 -| 파일 경로 | 역할 | 현재 상태 | -|-----------|------|-----------| -| `app/providers/naverworks.py` | OAuth 로그인 | ✅ 구현됨 | -| `app/providers/naverworks_passport.py` | Passport 시스템 | ✅ 구현됨 | --- -## 4. 기본 연동 테스트 시나리오 +## 4. 확인된 사실과 구현 체크리스트 -### 4.1 자동 Provider 감지 테스트 (skill-slack 포함) -- Slack: "@로빙 메일 확인" -- rb8001 흐름: - 1. DB 조회 (gmail_token, naverworks_token) - 2. provider 자동 결정 - 3. skill-email 호출 → 메일 데이터 획득 - 4. skill-slack `/format-mail-list` → Slack 블록 생성 - 5. Slack 응답 +### 코드 분석 결과 (2025-01-09) +- **skill-slack**: 8502 포트 엔드포인트 구현됨, rb8001은 직접 WebClient 사용 중 (미연동) +- **provider 구분**: 미구현, 기본 Gmail만 동작 (rb8001/app/skills/email_integration.py:260-266) +- **24시간 필터**: 미구현, orderBy만 있음 (skill-email/services/naverworks_provider.py:167) + - NaverWorks API는 searchDateType, startSearchDate, endSearchDate 파라미터 지원 +- **토큰 갱신**: NaverWorks는 auth-server 위임, 자동 호출 없음 +- **UUID 변환**: list 경로에서 변환 없음 (263행 user_id는 입력 그대로 전달) -### 4.2 명시적 Provider 지정 -- Slack: "@로빙 네이버웍스 메일 확인" -- DB 조회 없이 바로 provider=naverworks 사용 -- 오버라이드로 특정 provider 강제 지정 +### 필수 수정 사항 (우선순위별) +**P0 (즉시)**: +- [ ] skill-slack thread_ts 버그 수정 (messages.py:29-33) +- [ ] skill-slack API Key 인증 추가 (messages 엔드포인트) + +**P1 (1주)**: +- [ ] Gateway UUID 변환 완전 처리 +- [ ] rb8001 provider 로직: 키워드→DB조회→질문 +- [ ] skill-email 24시간 필터 (API 파라미터) +- [ ] skill-email DEFAULT_USER_ID 제거 (31행) +- [ ] skill-email 401 에러 시 토큰 갱신 + +**P2 (점진적)**: +- [ ] 새 기능만 skill-slack 사용 +- [ ] 기존 코드 부분 전환 -### 4.3 DB 조회 로직 구현 -- rb8001/app/skills/email_integration.py에 detect_email_provider 메서드 추가 -- gmail_token 테이블에서 is_equipped=true인 계정 확인 -- naverworks_token 테이블에서 사용자 계정 확인 -- 둘 다 있으면 "both", 하나만 있으면 해당 provider, 없으면 "none" 반환 --- -## 5. 기본 구성 구현 체크리스트 +## 5. 주요 파일 위치와 역할 -### 5.1 rb8001 수정 -- [ ] `app/skills/email_integration.py` 수정 - - [ ] `detect_email_provider()` 함수 추가 - DB 기반 자동 감지 - - [ ] get_messages()에 자동 provider 선택 로직 - - [ ] send_email()에 자동 provider 선택 로직 - - [ ] 둘 다 있을 때 선택 UI 구현 -- [ ] DB 조회 로직 구현 - - [ ] gmail_token 테이블 조회 - - [ ] naverworks_token 테이블 조회 - - [ ] 결과 기반 provider 자동 결정 -- [ ] Slack ID → UUID 변환 일관성 확보 - - [ ] get_uuid_from_slack() 활용 확대 - - [ ] 모든 skill-email 호출에 UUID 사용 +### rb8001 (포트 8001) +- **app/skills/email_integration.py**: Gmail 스킬 통합 (네이버웍스 추가 필요) +- **app/router/slack_handler.py**: Slack 이벤트 처리 (현재 직접 호출) -### 5.2 skill-slack 구현 -- [ ] 새 엔드포인트 추가 (`/api/v1` prefix 필수) - - [ ] POST `/api/v1/format/mail-list` - 기본 메일 목록 포맷 - - [ ] POST `/api/v1/format/cold-mail` - 콜드메일 테이블 포맷 - - [ ] POST `/api/v1/format/briefing` - 일일 브리핑 포맷 -- [ ] BaseSkillRequest 상속 모델 구현 - - [ ] MailListRequest(BaseSkillRequest) - - [ ] ColdMailRequest(BaseSkillRequest) - - [ ] BriefingRequest(BaseSkillRequest) -- [ ] Slack Block Kit Builder 구현 - - [ ] Section blocks - - [ ] Divider blocks - - [ ] Context blocks +### skill-email (포트 8501) +- **services/naverworks_provider.py**: 네이버웍스 Provider 구현 + - 270행: refresh_token() 함수 존재 (auth-server의 `/auth/naverworks/passport/refresh` 호출) + - 150행: list_messages() - 토큰 만료 체크 없이 바로 사용 + - 31행: DEFAULT_USER_ID 하드코딩 문제 +- **main.py**: 엔드포인트 정의 + - 210행: GET `/messages` - provider 파라미터로 gmail/naverworks 분기 + - POST `/send` +- **services/gmail_service.py** + - 60-72행: 토큰 자동 갱신 구현 (creds.expired 체크 후 refresh) + +### skill-slack (포트 8502) +- **app/api/endpoints/messages.py**: 메시지 전송 엔드포인트 +- **app/models/requests.py**: SlackMessageRequest 모델 (token 필드 포함) -### 5.3 skill-email 수정 -- [ ] `services/naverworks_provider.py` 수정 - - [ ] DEFAULT_USER_ID 하드코딩 제거 - - [ ] account_id 없을 시 명확한 에러 처리 -- [ ] 에러 응답 표준화 - - [ ] 400: 잘못된 요청 - - [ ] 422: 필수 정보 누락 --- -## 6. 환경 설정 및 주의사항 +## 6. 결정 사항 (2025-01-09) -### 6.1 환경 설정 확인 -- skill-email .env 파일에 NAVER WORKS 관련 설정 확인 -- rb8001에서 skill-email 호출 시 포트 8501 사용 -- auth-server의 NAVER WORKS OAuth 설정 확인 +### 구현 결정 +1. **Provider 선택**: 키워드 우선 → DB 조회 → 둘 다 있으면 질문 +2. **24시간 필터**: skill-email에서 API 파라미터 처리 (startSearchDate, endSearchDate) +3. **토큰 갱신**: 401 에러 후 재시도 (1회) +4. **UUID 변환**: Gateway에서 모두 변환 +5. **skill-slack 전환**: 단계적 (새 기능부터) +6. **메일 표시**: 5개 요약 + "더보기" 버튼 -### 6.2 보안 주의사항 -- **계정 오매핑 방지**: DEFAULT_USER_ID 제거로 잘못된 계정 접근 차단 -- **UUID 검증**: 모든 사용자 식별자를 UUID로 표준화 -- **에러 처리**: 명확한 HTTP 상태 코드로 문제 진단 용이 \ No newline at end of file