DOCS/journey/troubleshooting/250917_네이버웍스_캘린더_API_연동_가이드.md
Claude-51124 22557e7132 docs: 오래된 트러블슈팅 아카이브 및 구조 정리
- 7-8월 초기 구축 문서 12개를 _archive/troubleshooting/2025_07-08_initial_setup/로 이동
- book/300_architecture/390_human_in_the_loop_intent_learning.md를 journey/research/intent_classification/로 이동 (개발 여정 문서)
- 빈 폴더 제거 (journey/assets/*)
2025-11-17 14:06:05 +09:00

12 KiB

네이버웍스 API 연동 가이드

[구현 완료] 2025-09-17 네이버웍스 OAuth 로그인 구현 성공

구현 현황 (2025-09-17 완료)

구현 완료 사항

  • auth-server:
    • Phase 1 로그인 ( 2025-09-17)
      • /auth/naverworks/login 작동
      • /auth/naverworks/callback 작동
      • ID Token 파싱 방식 구현 (userinfo API 대체)
      • 이메일 기반 사용자 통합 (Gmail/Slack과 동일 계정)
    • Phase 2 Passport ( 2025-09-17)
      • /auth/naverworks/passport/install 작동
      • /auth/naverworks/passport/callback 작동
      • /auth/naverworks/passport/status 작동
      • naverworks_token 테이블 생성 및 관리
  • Frontend: OAuth 로그인 구현 완료
    • login-dialog.tsx에 네이버웍스 버튼 추가
    • auth-context.tsxloginWithNaverWorks() 구현
    • 콜백 처리 (#auth= 형식)
  • .env 설정: 서버 환경변수 설정 완료
    • NAVER_WORKS_CLIENT_ID
    • NAVER_WORKS_CLIENT_SECRET
    • NAVER_WORKS_TENANT_ID
  • skill 서비스: Phase 3 예정

확인된 OAuth 엔드포인트 패턴

📍 Google (Gmail) OAuth - 구현됨

API 엔드포인트:

  • /auth/gmail/login - 로그인 시작
  • /auth/gmail/callback - OAuth 콜백
  • /auth/gmail/passport/ - Passport 로그인 시작
  • /auth/gmail/passport/callback - Passport 콜백
  • /auth/gmail/passport/status - Passport 상태 확인

📍 Slack OAuth - 구현됨

API 엔드포인트:

  • /auth/slack/login/ - 로그인 시작
  • /auth/slack/login/callback - OAuth 콜백
  • /auth/slack/passport/install - Passport 설치
  • /auth/slack/passport/callback - Passport 콜백
  • /auth/slack/passport/status/{workspace_id} - Passport 상태

📍 NAVER WORKS OAuth - 구현 완료

Phase 1 - 로그인 엔드포인트 ( 완료):

  • /auth/naverworks/login - 로그인 시작
  • /auth/naverworks/callback - OAuth 콜백

Phase 2 - Passport 엔드포인트 ( 완료):

  • /auth/naverworks/passport/install - Passport 설치/권한 부여
  • /auth/naverworks/passport/callback - Passport 콜백
  • /auth/naverworks/passport/status - Passport 상태 확인

Phase 3 - 토큰 갱신 엔드포인트 (구현 필요):

  • 결정 필요: /auth/naverworks/refresh 또는 /api/auth/naverworks/refresh
  • 파일 생성 필요: naverworks_refresh.py
  • Refresh Token Rotation 처리 필요

외부 OAuth URL:

  • Authorization: https://auth.worksmobile.com/oauth2/v2.0/authorize
  • Token: https://auth.worksmobile.com/oauth2/v2.0/token
  • Userinfo (OIDC): https://www.worksapis.com/v1.0/oidc/userinfo
  • API Base: https://www.worksapis.com/v1.0/

1. 로빙(RO-BEING) 앱 설정 현황

  • 앱 이름: Ro-being
  • 소속: company-x.partners

1.1. 인증 정보

  • Client ID: [환경변수 NAVERWORKS_CLIENT_ID 참조]
  • Client Secret: [환경변수 NAVERWORKS_CLIENT_SECRET 참조]
    • ⚠️ 경고: 이 값은 외부에 노출되어서는 안 되며, Git 등 버전 관리 시스템에 포함하지 마십시오. Vault 또는 암호화된 환경 변수를 통해 안전하게 관리해야 합니다.

  • Service Account: [환경변수 NAVERWORKS_SERVICE_ACCOUNT 참조]

1.2. 토큰 설정

  • Access Token 유효기간: 1시간
  • Refresh Token Rotation: On (보안 강화)

1.3. OAuth 설정

  • 구성원 계정 인증 Redirect URL (콘솔 설정):
    • https://auth.ro-being.com/auth/naverworks/callback (일반 로그인)
    • https://auth.ro-being.com/auth/naverworks/passport/callback (Passport 로그인)
  • OIDC Logout Redirection:
    • https://example.com (기본값 유지)
  • 활성화된 Scopes:
    • openid, profile, email (OIDC 사용자 식별용)
    • calendar (캘린더 읽기/쓰기)
    • contact (주소록 읽기/쓰기)
    • file (드라이브 파일 접근)
    • mail (메일 읽기/보내기)
    • task (업무 관리)
    • user (조직 내 사용자 정보 조회)

2. 인증 방식

네이버웍스 API를 사용하기 위해서는 먼저 Access Token을 발급받아야 합니다. 현재 앱 설정에 따라 아래 두 가지 방식 모두 사용 가능합니다.

  1. 구성원 계정으로 인증 (OAuth 2.0 / OIDC): 사용자가 직접 로그인하여 자신의 데이터에 대한 접근을 허용하는 방식입니다. (예: "내 캘린더 일정 조회")
  2. 서비스 계정으로 인증 (JWT): 사용자 로그인 없이, 시스템(로빙)이 조직 전체의 데이터에 접근할 때 사용합니다. (예: 주기적인 데이터 동기화)

3. API 사용 예시 및 주요 엔드포인트

3.1. 캘린더 (Calendar API)

  • 스코프: calendar

  • 주요 엔드포인트:

    • GET /v1.0/users/{userId}/calendar/events: 특정 사용자의 일정 목록 조회
    • POST /v1.0/users/{userId}/calendar/events: 새 일정 생성
    • PUT /v1.0/users/{userId}/calendar/events/{eventId}: 기존 일정 수정
  • 요청 예시: 새 일정 생성 POST https://www.worksapis.com/v1.0/users/{userId}/calendar/events

    {
      "subject": "Team Meeting",
      "start": {
        "date": "2025-09-18",
        "time": "10:00:00"
      },
      "end": {
        "date": "2025-09-18",
        "time": "11:00:00"
      },
      "attendees": [
        {
          "email": "member1@example.com",
          "isOptional": false
        }
      ]
    }
    

3.2. 주소록 (Contact API)

  • 스코프: contact, user
  • 주요 엔드포인트:
    • GET /v1.0/contacts: 고객/거래처 연락처 목록 조회
    • POST /v1.0/contacts: 새 연락처 생성
    • GET /v1.0/users/{userId}: 조직 내 사용자 정보 조회

3.3. 메일 (Mail API)

  • 스코프: mail
  • 주요 엔드포인트:
    • POST /v1.0/users/{userId}/mail: 메일 발송
    • GET /v1.0/users/{userId}/mail/mailfolders/{folderId}/children: 메일 목록 조회 (folderId=0: 받은메일함)

4. 로빙 연동 아키텍처

4.1. 시크릿 관리 (온프레미스 2서버 환경)

  • 원칙: 영구 시크릿(Client Secret, Private Key)은 게이트웨이 서버에만 중앙 집중식으로 보관합니다.
  • 구현: 게이트웨이 서버에서 HashiCorp Vault 또는 암호화된 파일 시스템(600 권한)을 사용하여 Client ID/Secret을 관리하고, 컨테이너에는 읽기 전용(:ro)으로 마운트합니다.
  • 로빙/스킬 서버: 게이트웨이를 통해 발급된 단기 Access Token만 받아 사용하며, 영구 시크릿을 보관하지 않습니다.

4.2. 인증 흐름 및 토큰 관리

  • JWT 키 관리 (JWKS): 게이트웨이는 JWT 서명에 사용하는 공개키 목록을 /.well-known/jwks.json 엔드포인트를 통해 노출하여, 다른 서비스들이 토큰을 안전하게 검증하고 키 교체에 대응할 수 있도록 합니다.
  • 토큰 흐름: 로빙/스킬 서버는 외부 API를 직접 호출하는 대신, 게이트웨이에 API 호출을 위임하고 필요한 단기 토큰을 받아 사용합니다.

5. 구현 필요 사항

5.1 파일 생성/수정 목록

생성 완료

  • auth-server/app/providers/naverworks.py: OAuth 2.0 인증 플로우 구현
  • auth-server/app/providers/naverworks_passport.py: Passport 시스템 구현

생성 예정 (Phase 3)

  • skill-naverworks/: NAVER WORKS API 전용 스킬 서비스 (포트 8511)

수정 완료

  • auth-server/app/main.py: naverworks 라우터 등록
    • naverworks.router (prefix="/auth/naverworks")
    • naverworks_passport.router (prefix="/auth/naverworks/passport")
  • auth-server/.env: NAVERWORKS_* 환경변수 설정 완료
  • nginx-infra: /auth/naverworks 라우팅 설정

DB 스키마

  • Phase 1: 로그인 구현 (현재):

    • 기존 user 테이블만 사용
    • oauth_provider="naverworks"
    • oauth_id={userinfo.sub}
    • 이메일 기반 사용자 통합: Gmail/Slack과 동일 이메일이면 같은 User 레코드 사용
  • Phase 2: Passport 구현 ( 완료):

    • naverworks_token 테이블: token_data JSONB에 access_token/refresh_token 저장
    • 테이블 구조: user_id(PK), domain_id, account_id, token_data(JSONB), oauth_config, scopes, metadata, expiry, is_equipped, created_at, updated_at
    • 메일/캘린더 API 접근용

5.2 구현 플로우 (Slack 패턴 참조)

OAuth 로그인 엔드포인트

  • GET /auth/naverworks/login/: State 생성 → Redis 저장 → OAuth 리다이렉트
  • GET /auth/naverworks/callback: State 검증 → Token 교환 → Userinfo 조회 → User 매핑 → JWT 발급
    • 주의: 표준 OAuth 2.0은 GET 콜백 사용 (Slack OIDC의 POST form_post와 다름)

Redis Keys

  • oauth:state:{state}: CSRF 방지용 state 저장 (TTL 300s)
  • auth:temp:{temp_code}: Frontend 전달용 임시 코드 (TTL 60s)
  • naverworks:service:token: Service Account 토큰 캐싱 (TTL 3600s)

Slack OAuth 참조 파일

  • 구현 패턴: auth-server/app/providers/slack.py
  • Gmail passport: auth-server/app/providers/gmail_passport.py
  • JWT 생성: auth-server/app/core/auth.py의 create_access_token()

5.3 결정/확인 필요 사항

결정사항 (확정)

  • Redirect URL 도메인: auth.ro-being.com 사용 (Gmail/Slack과 통일)
  • Private Key 처리:
    • 2025-09-17: Git 임시 commit 후 서버 전송
    • 서버 저장: Base64 인코딩하여 .env의 NAVERWORKS_PRIVATE_KEY_BASE64에 저장
    • Git에서 삭제 완료 (보안상 Git 저장 금지)
  • NAVER WORKS 토큰 테이블: naverworks_token (team 스키마 아래, 단수형)

확인 완료

  • OIDC userinfo 필드: sub (사용자 ID), email (이메일)
  • Service Account JWT 서명: RS256 알고리즘 (RSA 2048 bits)
  • 에러 응답 형식: JSON {"error", "error_description", "error_uri"}
  • response_mode: 기본 query 사용 (form_post 불필요)

6. Frontend 수정 계획 ( 구현 완료)

6.1 로그인 버튼 추가

  • 위치: frontend-customer/src/components/login-dialog.tsx (실제 파일명)
  • 아이콘: /assets/integrations/naverworks-icon.svg (파일 존재 확인됨)
  • 동작: /auth/naverworks/login 리다이렉트
  • 상태: 구현 완료

6.2 Auth Context 수정

  • 위치: frontend-customer/src/contexts/auth-context.tsx
  • 함수 추가: loginWithNaverWorks() (context value에 추가 필요)
  • AUTH_SERVER_URL: import.meta.env.VITE_AUTH_SERVER_URL || 'https://auth.ro-being.com' 사용
  • 패턴: Gmail/Slack과 동일한 OAuth 플로우
  • redirect_uri 인코딩: encodeURIComponent(window.location.origin) 필수
  • 상태: 구현 완료

6.3 Skills Panel (Passport 연동)

  • 위치: frontend-customer/src/components/skills-items-panel.tsx
  • sessionStorage key: naverworks_oauth_return_url
  • 엔드포인트: /auth/naverworks/passport/install?user_id={userId}
  • 상태: 구현 완료

6.4 Callback 처리

  • URL hash (#auth=임시코드)에서 임시 코드 추출 (기존 코드 패턴)
  • /auth/verify POST 호출로 JWT 획득
  • localStorage 'auth_token' 키로 저장 (주의: 일부 서비스는 'token'도 체크)
  • 성공시 URL 정리: window.history.replaceState() 사용
  • 실패시 에러 처리: window.location.hash = '' 및 로그
  • 상태: 구현 완료

6.5 UI/UX

  • 버튼 스타일: Google/Slack과 동일한 디자인 사용
  • 버튼 텍스트: "NAVER WORKS로 계속하기"
  • 연동 상태 표시 필요
  • 상태: 구현 완료

7. 수정 이력

  • 2025-09-17: Phase 1 로그인 구현 완료
  • 2025-09-17: Phase 2 Passport 구현 완료
  • 2025-09-18: 테이블명 수정 (naverworks_tokens → naverworks_token)
  • 2025-09-18: 문서 업데이트 - Passport 구현 완료 상태 반영

8. 참고 자료