# NAVER WORKS → Slack 연동 [1/3] 기본 구성

## 날짜: 2025-09-19 (완료: 2025-09-10)
## 작성자: Claude (51123 서버 관리자) / happybell80
## 관련 서비스: rb8001, skill-email, skill-slack, auth-server, robeing-gateway
## 상태: ✅ 구현 완료 및 테스트 성공

## 관련 문서
- [2/3 일일 브리핑](./250919_naverworks_slack_02_daily_briefing.md)
- [3/3 콜드메일 리스트업](./250919_naverworks_slack_03_cold_mail_list.md)

---

## 1. 현재 구현 상태 (2025-01-09 확인)

### 구현 완료
- **auth-server**:
  - `naverworks.py`, `naverworks_passport.py` 파일 존재
  - NAVER WORKS OAuth 환경변수 설정 (CLIENT_ID, CLIENT_SECRET, REDIRECT_URI, TENANT_ID)
  - 토큰 갱신: POST `/auth/naverworks/passport/refresh` 동작
- **skill-email (포트 8501)**:
  - `services/naverworks_provider.py` NaverWorksProvider 클래스 구현
  - 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 파라미터 없음, UUID 변환 누락 (list 경로)
- **skill-slack**: rb8001과 미연동 (직접 WebClient 사용)
- **24시간 필터**: 어디에도 구현 안 됨
- **토큰 갱신**: 자동 호출 없음 (수동 함수만 존재)

### 잘못된 전제 정정
- ❌ "skill-naverworks(8511) 구현 완료" → ✅ skill-email(8501) 멀티 프로바이더로 통합
- ❌ "Service Account 설정 완료" → ✅ 사용자 OAuth 토큰 기반 (SA는 Phase 3 계획)
- ❌ 별도 skill-naverworks 필요 → ✅ skill-email의 provider 파라미터로 처리

---

## 2. 기본 구성 구현 사항

### 2.1 rb8001 수정 - 자동 Provider 감지
- `app/skills/email_integration.py`에 DB 기반 자동 분기 로직 추가
- 사용자의 메일 계정을 DB에서 조회하여 자동 선택
- 분기 로직:
  ```
  1. DB에서 user_id로 메일 계정 조회
  2. Gmail만 있음 → provider=gmail
  3. NaverWorks만 있음 → provider=naverworks
  4. 둘 다 있음 → 사용자에게 선택 요청
  5. 둘 다 없음 → 메일 계정 설정 안내
  ```
- 명시적 키워드("네이버웍스", "Gmail")는 오버라이드용

### 2.2 skill-email 수정 - 안전성 개선
- NaverWorksProvider.DEFAULT_USER_ID 제거
- account_id 누락 시 400/422 에러 반환
- 모든 요청에 UUID 검증 로직 추가

---

## 3. 정확한 구현 경로

### 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": "네이버웍스 메일 확인"
  }
}
```

**프론트엔드 요청 경로**:
```
Frontend → Gateway → rb8001 → skill-email → rb8001 → skill-slack → Slack
```

Gateway → rb8001 전달 정보:
- Headers: `X-User-Id`, `X-Source`: "frontend"
- Body: `{"text": "메시지", "user_id": "UUID", "context": {}}`

### 3.2 현재 사용 가능한 엔드포인트

**skill-email (포트 8501)**:
- GET `/messages?provider=naverworks&user_id={uuid}` - 메일 목록 조회
- POST `/send` - 메일 발송 (provider 필드 포함)

**skill-slack (포트 8502)**:
- POST `/api/v1/send` - Slack 메시지 전송
  - 필수: channel, text
  - 선택: token, thread_ts, blocks

### 3.3 수정 필요 위치

**rb8001/app/skills/email_integration.py**:
- 262행: GET `/messages` 호출 시 provider 파라미터 누락
- 현재 코드: `params={"user_id": user_id, "limit": 5}` (Gmail만 조회)
- 필요한 수정: provider=naverworks 파라미터 추가

**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 헤더 없음 (요청 출처 구분 불가)


---

## 4. 확인된 사실과 구현 체크리스트

### 코드 분석 결과 (2025-01-09)
- **skill-slack**: 8502 포트 엔드포인트 구현됨, rb8001은 직접 WebClient 사용 중 (미연동)
- **provider 구분**: 미구현, 기본 Gmail만 동작 (rb8001/app/skills/email_integration.py:260-266)
- **24시간 필터**: 목록 API는 날짜 파라미터 미지원 → 클라이언트(receivedTime) 기준 필터 적용
- **토큰 갱신**: NaverWorks는 auth-server 위임, 자동 호출 없음
- **UUID 변환**: list 경로에서 변환 없음 (263행 user_id는 입력 그대로 전달)

### 구현 완료 사항 (2025-09-10)
**P0 (완료)**:
- ✅ skill-slack thread_ts 버그 수정 (messages.py:36-48)
- ✅ skill-slack API Key 인증 추가 (/send, /update)

**P1 (완료)**:
- ✅ Gateway X-Source 헤더 추가 (main.py:552, 240)
- ✅ rb8001 provider 로직 구현 (email_integration.py:70-130)
- ✅ skill-email 24시간 로컬 필터(응답 후 receivedTime 비교)
- ✅ skill-email DEFAULT_USER_ID 제거 (31행 삭제)
- ✅ skill-email 401 에러 시 토큰 갱신 (194-210행)

**P2 (완료)**:
- ✅ send_naverworks_to_slack() 함수 구현 (email_integration.py:433-524)
- ✅ slack_handler.py 키워드 연결 (213-228행)

### 테스트 결과
- ✅ "네이버웍스 메일 확인" 명령어 정상 작동
- ✅ 24시간 이내 메일 조회 성공
- ✅ 메일 없을 시 안내 메시지 표시
- ⚠️ 메일 있을 시 이중 전송 가능성 (send_naverworks_to_slack + slack_handler)
- 📝 skill-slack은 메일이 있을 때만 호출됨 (없으면 직접 응답)


---

## 5. 주요 파일 위치와 역할

### rb8001 (포트 8001)
- **app/skills/email_integration.py**: Gmail 스킬 통합 (네이버웍스 추가 필요)
- **app/router/slack_handler.py**: Slack 이벤트 처리 (현재 직접 호출)

### 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 필드 포함)


---

## 6. 결정 사항 (2025-01-09)

### 구현 결정
1. **Provider 선택**: 키워드 우선 → DB 조회 → 둘 다 있으면 질문
2. **24시간 필터**: skill-email에서 응답 후 receivedTime 기준 클라이언트 필터 처리
3. **토큰 갱신**: 401 에러 후 재시도 (1회)
4. **UUID 변환**: Gateway에서 모두 변환
5. **skill-slack 전환**: 단계적 (새 기능부터)
6. **메일 표시**: 5개 요약 + "더보기" 버튼
