// frontend/components/settings/DataTab.tsx — 데이터 내보내기 + API 토큰 + 시스템 정보(읽기전용) "use client"; import { useState } from "react"; import { Button } from "@/components/Button"; import { Icon } from "@/components/Icon"; import { settingsApi } from "@/lib/settings/api"; import { useSystemConfig, useTokens } from "@/lib/hooks/useSettings"; import type { ToastFn } from "./SettingsClient"; const MODE_LABEL: Record = { mock: "데모(mock)", real: "실연동", csv: "CSV", ics: "iCal", healthkit: "HealthKit", clipper: "클리퍼", imap: "IMAP", }; const DOMAIN_LABEL: Record = { calendar: "일정", mail: "메일", chat: "채팅", finance: "금융", health: "건강", knowledge: "지식", }; export function DataTab({ toast }: { toast: ToastFn }) { const { data: sys } = useSystemConfig(); const { data: tokens, refresh } = useTokens(); const [exporting, setExporting] = useState(false); const [tokenName, setTokenName] = useState(""); const [created, setCreated] = useState<{ name: string; token: string } | null>(null); const onExport = async () => { setExporting(true); try { const blob = await settingsApi.exportData(); const url = URL.createObjectURL(blob); const a = document.createElement("a"); a.href = url; a.download = "ari-export.zip"; document.body.appendChild(a); a.click(); a.remove(); URL.revokeObjectURL(url); toast("내보내기를 시작했어요", "green"); } catch { toast("내보내기에 실패했어요", "coral"); } finally { setExporting(false); } }; const onCreate = async () => { const name = tokenName.trim() || "API 토큰"; try { const t = await settingsApi.createToken(name); if (t.token) setCreated({ name: t.name, token: t.token }); setTokenName(""); await refresh(); toast("토큰을 발급했어요", "green"); } catch { toast("토큰 발급에 실패했어요", "coral"); } }; const onRevoke = async (id: string) => { try { await settingsApi.revokeToken(id); await refresh(); toast("토큰을 폐기했어요", "faint"); } catch { toast("폐기에 실패했어요", "coral"); } }; const onCopy = async (text: string) => { try { await navigator.clipboard.writeText(text); toast("클립보드에 복사했어요", "blue"); } catch { toast("복사에 실패했어요", "amber"); } }; const activeTokens = (tokens ?? []).filter((t) => !t.revoked); return (

데이터 · 보안

내 데이터를 내보내거나, API 토큰을 관리하고, 시스템 구성을 확인해요.

{/* 데이터 내보내기 */}
데이터 내보내기 작업·인박스·일정·메일 등 내 데이터를 ZIP으로 받아요.
{/* API 토큰 */}

API 토큰

외부에서 아리 API에 접근할 때 사용해요.
setTokenName(e.target.value)} />
{created && (
새 토큰 — 지금만 보여요
{created.token}
)} {activeTokens.length === 0 ? (
발급된 토큰이 없어요.
) : (
    {activeTokens.map((t) => (
  • {t.name} {t.id} · {new Date(t.created_at).toLocaleDateString("ko-KR")}
  • ))}
)}
{/* 시스템 정보 (읽기 전용) */}

시스템

환경변수(.env)로 관리 · 읽기 전용
환경
{sys?.env ?? "—"}
인증
{sys ? (sys.auth_enabled ? "켜짐" : "꺼짐(데모)") : "—"}
백그라운드 워커
{sys ? (sys.worker_enabled ? "켜짐" : "꺼짐(수동)") : "—"}
데이터베이스
{sys?.database ?? "—"}
동기화 주기
{sys ? `${sys.sync_interval_minutes}분` : "—"}
웹 검색
{sys?.web_search_provider ?? "—"}
{sys && (
{Object.entries(sys.connector_modes).map(([domain, mode]) => ( {DOMAIN_LABEL[domain] ?? domain} {MODE_LABEL[mode] ?? mode} ))}
)}
); }