Skip to content

[AiCredential] 본인 AI API 키(BYOK) 등록·관리 화면 #54

Description

@Danto7632

🔥 Issue 개요

백엔드에 BYOK(Bring Your Own Key) AI 크리덴셜 API 가 추가된다(Dvely_springboot PR #245, Issue #242). 사용자가 자기 공식 AI API 키를 등록하면, 그 키로 Claude Code / Codex 코딩 에이전트가 격리 컨테이너에서 실행되고 사용량은 사용자 계정으로 직접 청구된다.

FE 는 이 키를 등록·확인·삭제하는 화면이 필요하다. 엔드포인트 3개는 이미 구현·테스트 완료 상태다.

왜 구독 연동이 아닌가 — 구독(Claude Pro/Max, ChatGPT Plus) 자격증명을 제3자 제품에 임베딩하는 것은 Anthropic 이 공식 금지하고 OpenAI 도 지원하지 않는다. 사용자에게 "구독 계정 연결" 로 안내하면 안 되고, "본인 API 키 등록" 이라는 표현이 정확하다.

🎯 목표

  • 설정 화면에서 벤더별 본인 API 키를 등록·교체·삭제할 수 있다
  • 등록된 키는 마스킹된 형태로만 표시된다
  • 키 미등록 상태로 코딩 에이전트를 쓰려 할 때 등록 화면으로 유도된다

✅ 작업 범위

포함 범위

  • AI 크리덴셜 관리 UI (목록 / 등록·교체 / 삭제)
  • AI_CREDENTIAL_NOT_REGISTERED 에러 처리 → 키 등록 화면 유도
  • 등록 시 입력 검증 안내(공백·제어문자 포함 키는 400)

제외 범위 (지금 하지 말 것)

  • CLAUDE_CODE / CODEX 를 AI 제공자 선택지에 노출하지 말 것. 코딩 에이전트는 아직 채팅/CODE 플로우에 배선되지 않은 휴면 상태이고, GET /api/v1/agent/ai-providers 목록에도 나오지 않는다. 지금 선택지로 넣으면 400 이 난다. 배선 완료 시 별도 이슈로 요청한다.
  • 사용량·비용 표시 (백엔드 미제공)

📋 API 계약

전부 Authorization: Bearer {accessToken} 필요.

1) 목록 조회

GET /api/v1/ai-credentials
→ 200 [
  {
    "aiProviderCredentialId": 1,
    "provider": "ANTHROPIC",
    "maskedApiKey": "sk-ant****",
    "label": "개인 계정",
    "createdAt": "2026-09-05T10:00:00",
    "updatedAt": "2026-09-05T10:00:00"
  }
]

본인이 등록한 것만 반환된다(소유자는 토큰에서만 결정되며 요청 파라미터가 없다).

2) 등록 / 교체

PUT /api/v1/ai-credentials/{provider}
{ "apiKey": "sk-ant-api03-...", "label": "개인 계정" }   // label 은 선택(nullable, 최대 64자)
→ 200  (위 목록과 동일한 객체 1개)

등록과 교체가 같은 동작이다(PUT). 벤더당 키 하나이므로, 이미 등록돼 있으면 새 키로 교체된다. "이미 등록됨" 409 같은 건 없다 — 유출 직후 교체가 한 번의 호출로 끝나야 하기 때문.

3) 삭제

DELETE /api/v1/ai-credentials/{provider}
→ 204
→ 404  (등록돼 있지 않음)

{provider}

벤더만 받는다: ANTHROPIC · OPENAI · GLM

CLAUDE_CODE / CODEX 로 등록을 시도하면 400 이고, 응답 메시지가 어느 벤더로 등록해야 하는지 알려준다. 이유: Claude Code 는 Anthropic 키를, Codex 는 OpenAI 키를 쓰므로 사용자는 벤더당 키를 한 번만 넣으면 된다. UI 에서도 "Claude Code 용 키" / "Codex 용 키" 로 나누지 말고 벤더 단위로 하나씩 두는 게 맞다.

🎨 UI 참고 사항

  • 평문 키는 어떤 응답에도 없다. 등록 직후 응답에도 마스킹된 값만 온다. "복사하기" 같은 기능은 만들 수 없다.
  • maskedApiKey앞 6자만 남긴 형태(sk-ant****). 뒤 4자를 보여주는 흔한 관례와 다른데, 꼬리가 실제 키 엔트로피라 의도적으로 가린 것이다. 그대로 표시하면 된다.
  • 등록 폼에는 키 발급처 링크를 함께 두면 좋다 — Anthropic: https://platform.claude.com , OpenAI: https://platform.openai.com/account/api-keys
  • 비용이 사용자 계정으로 청구된다는 점을 등록 화면에 명시하는 편이 좋다.

⚠️ 에러 처리

상황 응답 FE 처리
키 미등록 상태로 코딩 에이전트 사용 400 AI_CREDENTIAL_NOT_REGISTERED 키 등록 화면으로 유도. 서버가 운영자 키로 대신 채워주지 않는다(제공사 약관상 사용자를 대신한 결제·중개 금지)
키에 공백/제어문자 포함 400 붙여넣기 시 개행이 섞인 경우가 흔하다. 입력값 trim 후 전송하고, 그래도 400 이면 메시지 노출
실행 모드(CLAUDE_CODE 등)로 등록 시도 400 위 "provider 값" 참고 — 발생하지 않도록 UI 를 벤더 단위로 구성
미등록 항목 삭제 404 목록 갱신 후 안내

✅ 완료 기준

  • 목록·등록·교체·삭제 동작 확인
  • 마스킹된 키만 화면에 노출되는지 확인
  • AI_CREDENTIAL_NOT_REGISTERED 유도 플로우 확인
  • 백엔드 PR #245 머지 후 dev 서버에서 연동 확인

📌 참고

  • 백엔드: Dvely/Dvely_springboot Issue #242 / PR #245
  • API 문서: docs/FRONTEND_API_GUIDE.md §4.12 (해당 PR 에 포함)
  • 설계 배경: docs/byok-coding-agent-design.md
  • 백엔드 머지 전에는 dev 서버에 엔드포인트가 없다. PR #245 머지 후 착수하거나, 그 전에는 목업으로 진행.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions