Summary
AnkiConnect 연결 실패 시 원인을 3단계로 진단(네트워크/포트/애드온)하고, 서버 시작 로그 + API 에러 응답 + 웹 UI 배너로 사용자에게 구체적 원인을 알려주는 개선. 현재는 5초 타임아웃 후 504 TimeoutError만 반환하여 Tailscale 꺼짐/Anki 미실행/AnkiConnect 비활성을 구분할 수 없음.
Context
- 현 상태:
ankiConnect() 함수(client.ts:47-81)에서 fetch 실패 시 TimeoutError 또는 AnkiConnectError만 반환. 에러 메시지는 "AnkiConnect 응답 시간 초과. Anki가 실행 중인지 확인하세요"로 고정
- 문제점: MiniPC(100.79.80.95:8765)에 Tailscale VPN으로 연결하는 구조에서, Tailscale 꺼짐 vs Anki 미실행 vs AnkiConnect 애드온 비활성의 구분이 불가능. 서버 시작 시에도 진단 없이 경고만 출력
- 트리거: Tailscale 꺼진 상태에서
bun dev 실행 → 서버 시작은 되지만 모든 API 호출이 5초 타임아웃 → 웹 UI에서 무한 로딩 스피너만 표시
Affected Files
| File |
Role |
Required Change |
packages/core/src/anki/diagnostics.ts |
신규 |
3단계 연결 진단 함수 (diagnoseAnkiConnect) |
packages/core/src/anki/client.ts |
AnkiConnect 클라이언트 |
에러 메시지에 URL/포트 정보 + 에러 코드 기반 분기 추가 |
packages/core/src/index.ts |
Core export |
diagnostics export 추가 |
packages/server/src/index.ts |
서버 엔트리 |
시작 시 diagnoseAnkiConnect() 호출 + /api/health 확장 |
packages/web/src/lib/api.ts |
API 클라이언트 |
health 응답 타입에 ankiConnect 필드 추가 |
packages/web/src/hooks/useAnkiStatus.ts |
신규 |
health 엔드포인트 30초 폴링 훅 |
packages/web/src/components/AnkiStatusBanner.tsx |
신규 |
연결 끊김 시 상단 경고 배너 |
packages/web/src/components/layout/Layout.tsx |
레이아웃 |
AnkiStatusBanner 배치 |
Proposed Changes
Notes
- 서버 시작 시 AnkiConnect 연결 불가해도 서버는 계속 실행 (MiniPC 배포 시 Anki 재시작 대기 필요)
- Bun의
Bun.connect() TCP 소켓으로 네트워크 vs 앱 레벨 구분 가능
ANKI_CONNECT_URL 환경변수에서 hostname/port 파싱: new URL(process.env.ANKI_CONNECT_URL || "http://localhost:8765")
Summary
AnkiConnect 연결 실패 시 원인을 3단계로 진단(네트워크/포트/애드온)하고, 서버 시작 로그 + API 에러 응답 + 웹 UI 배너로 사용자에게 구체적 원인을 알려주는 개선. 현재는 5초 타임아웃 후
504 TimeoutError만 반환하여 Tailscale 꺼짐/Anki 미실행/AnkiConnect 비활성을 구분할 수 없음.Context
ankiConnect()함수(client.ts:47-81)에서fetch실패 시TimeoutError또는AnkiConnectError만 반환. 에러 메시지는 "AnkiConnect 응답 시간 초과. Anki가 실행 중인지 확인하세요"로 고정bun dev실행 → 서버 시작은 되지만 모든 API 호출이 5초 타임아웃 → 웹 UI에서 무한 로딩 스피너만 표시Affected Files
packages/core/src/anki/diagnostics.tsdiagnoseAnkiConnect)packages/core/src/anki/client.tspackages/core/src/index.tspackages/server/src/index.tsdiagnoseAnkiConnect()호출 +/api/health확장packages/web/src/lib/api.tspackages/web/src/hooks/useAnkiStatus.tspackages/web/src/components/AnkiStatusBanner.tsxpackages/web/src/components/layout/Layout.tsxProposed Changes
packages/core/src/anki/diagnostics.ts신규 —diagnoseAnkiConnect()함수 구현getVersion()HTTP 호출 (실패 → "AnkiConnect 애드온 확인")packages/core/src/anki/client.ts수정 — catch 블록에서 에러 코드(ETIMEDOUT/ECONNREFUSED) 기반으로 구체적 메시지 + ANKI_CONNECT_URL 정보 포함packages/server/src/index.ts수정 —runStartupTasks()에diagnoseAnkiConnect()추가 (성공: "✅ AnkiConnect 연결 확인 (v6, 45ms)", 실패: 단계별 경고 메시지)packages/server/src/index.ts수정 —GET /api/health응답에ankiConnect: AnkiConnectStatus필드 추가packages/web/src/hooks/useAnkiStatus.ts신규 —useAnkiStatus()훅 (30초 폴링)packages/web/src/components/AnkiStatusBanner.tsx신규 — 단계별 배너 (빨강: 네트워크, 주황: Anki 미실행, 노랑: 애드온)packages/web/src/components/layout/Layout.tsx수정 —AnkiStatusBanner를 메인 콘텐츠 상단에 배치Notes
Bun.connect()TCP 소켓으로 네트워크 vs 앱 레벨 구분 가능ANKI_CONNECT_URL환경변수에서 hostname/port 파싱:new URL(process.env.ANKI_CONNECT_URL || "http://localhost:8765")