DOCS/troubleshooting/250919_naverworks_slack_01_base_configuration.md
happybell80 39abdee278 docs: 이중 전송 가능성 및 skill-slack 호출 조건 명시
- 메일 있을 시 이중 전송 가능성 경고 추가
- skill-slack은 메일이 있을 때만 호출됨 명시

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-20 00:54:50 +09:00

8.7 KiB

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

날짜: 2025-09-19 (완료: 2025-01-10)

작성자: Claude (51123 서버 관리자) / happybell80

관련 서비스: rb8001, skill-email, skill-slack, auth-server, robeing-gateway

상태: 구현 완료 및 테스트 성공

관련 문서


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 (원본 그대로):

{
  "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시간 필터: 미구현, orderBy만 있음 (skill-email/services/naverworks_provider.py:167)
    • NaverWorks API는 searchDateType, startSearchDate, endSearchDate 파라미터 지원
  • 토큰 갱신: NaverWorks는 auth-server 위임, 자동 호출 없음
  • UUID 변환: list 경로에서 변환 없음 (263행 user_id는 입력 그대로 전달)

구현 완료 사항 (2025-01-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시간 필터 (naverworks_provider.py:173-179)
  • 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에서 API 파라미터 처리 (startSearchDate, endSearchDate)
  3. 토큰 갱신: 401 에러 후 재시도 (1회)
  4. UUID 변환: Gateway에서 모두 변환
  5. skill-slack 전환: 단계적 (새 기능부터)
  6. 메일 표시: 5개 요약 + "더보기" 버튼