"use client"; import { useState, useEffect } from "react"; import { aiAssistantApi } from "@/lib/api/aiAssistant"; import type { ApiKeyItem } from "@/lib/api/aiAssistant"; import { Key, Plus, Copy, Trash2, Loader2, Check, Eye, EyeOff, } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { Badge } from "@/components/ui/badge"; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger, } from "@/components/ui/dialog"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@/components/ui/table"; import { toast } from "sonner"; export default function AiAssistantApiKeysPage() { const [loading, setLoading] = useState(true); const [apiKeys, setApiKeys] = useState([]); const [createDialogOpen, setCreateDialogOpen] = useState(false); const [newKeyDialogOpen, setNewKeyDialogOpen] = useState(false); const [newKeyName, setNewKeyName] = useState(""); const [newKey, setNewKey] = useState(""); const [creating, setCreating] = useState(false); const [showKey, setShowKey] = useState(false); const [copied, setCopied] = useState(false); useEffect(() => { loadApiKeys(); }, []); const loadApiKeys = async () => { setLoading(true); try { const res = await aiAssistantApi.get("/api-keys"); setApiKeys(res.data?.data ?? []); } catch { toast.error("API 키 목록을 불러오는데 실패했습니다."); } finally { setLoading(false); } }; const createApiKey = async () => { if (!newKeyName.trim()) { toast.error("키 이름을 입력해주세요."); return; } setCreating(true); try { const res = await aiAssistantApi.post("/api-keys", { name: newKeyName }); setNewKey((res.data?.data as { key?: string })?.key ?? ""); setCreateDialogOpen(false); setNewKeyDialogOpen(true); setNewKeyName(""); loadApiKeys(); toast.success("API 키가 생성되었습니다."); } catch (err: unknown) { const msg = err && typeof err === "object" && "response" in err ? (err as { response?: { data?: { error?: { message?: string } } } }).response?.data ?.error?.message : null; toast.error(msg ?? "API 키 생성에 실패했습니다."); } finally { setCreating(false); } }; const revokeApiKey = async (id: number) => { if (!confirm("이 API 키를 폐기하시겠습니까?")) return; try { await aiAssistantApi.delete(`/api-keys/${id}`); loadApiKeys(); toast.success("API 키가 폐기되었습니다."); } catch { toast.error("API 키 폐기에 실패했습니다."); } }; const copyToClipboard = async (text: string) => { try { await navigator.clipboard.writeText(text); setCopied(true); toast.success("클립보드에 복사되었습니다."); setTimeout(() => setCopied(false), 2000); } catch { toast.error("복사에 실패했습니다."); } }; const baseUrl = typeof window !== "undefined" ? process.env.NEXT_PUBLIC_AI_ASSISTANT_API_URL || "http://localhost:3100/api/v1" : ""; if (loading) { return (
); } return (

API 키 관리

외부 시스템에서 AI Assistant API를 사용하기 위한 키를 관리합니다.

새 API 키 생성 새로운 API 키를 생성합니다. 키는 한 번만 표시되므로 안전하게 보관하세요.
setNewKeyName(e.target.value)} />
API 키가 생성되었습니다 이 키는 다시 표시되지 않습니다. 안전한 곳에 복사하여 보관하세요.
API 키 목록 발급된 모든 API 키를 확인하고 관리합니다. {apiKeys.length === 0 ? (

API 키가 없습니다

새 API 키를 생성하여 시작하세요.

) : ( 이름 상태 사용량 마지막 사용 생성일 작업 {apiKeys.map((key) => ( {key.name}
{key.keyPrefix}...
{key.status === "active" ? "활성" : "폐기됨"} {(key.usageCount ?? 0).toLocaleString()} 토큰 {key.lastUsedAt ? new Date(key.lastUsedAt).toLocaleDateString("ko-KR") : "-"} {new Date(key.createdAt).toLocaleDateString("ko-KR")} {key.status === "active" && ( )}
))}
)}
API 사용 방법 발급받은 API 키를 Authorization 헤더에 포함하여 요청하세요.
            {`curl -X POST ${baseUrl}/chat/completions \\
  -H "Content-Type: application/json" \\
  -H "Authorization: Bearer YOUR_API_KEY" \\
  -d '{"model": "gemini-2.0-flash", "messages": [{"role": "user", "content": "Hello!"}]}'`}
          
); }