Cloudwiki

API 키 발급 목록

제목: CloudStock/API 키 발급 목록

> [[CloudStock]] 프로젝트가 필요로 하는 외부 API 키 발급 체크리스트.
> 발급 후 `wrangler secret put <KEY_NAME>` 으로 Cloudflare Workers에 주입한다.

---

## 개요

| Phase | 키 이름 | 용도 | 비용 | 우선순위 |
|-------|--------|------|------|---------|
| 2 | `FMP_API_KEY` | 미국 종목 EOD 시세 | 무료 250 req/일 (Starter $22/월) | 필수 |
| 2 | `FINNHUB_API_KEY` | 미국 뉴스 (일반 + 종목별 company-news) | 무료 60 req/분 | 필수 |
| 3 | `GEMINI_API_KEY` | 시장 요약 음성 듣기(TTS) — Gemini 3.1 Flash TTS (`gemini-3.1-flash-tts-preview`) | 프리티어 한도 내 $0 | 권장 (미설정 시 음성 듣기만 비활성) |
| 3 | `PERPLEXITY_API_KEY` | 범용 웹 서치 — Phase 3에서는 미사용(향후 옵션) | $5/1,000 req | 미사용 |
| 4 | `KIS_APP_KEY`, `KIS_APP_SECRET` | 한국주식 시세 | 무료 (계좌만 필요) | Phase 4 시작 시 |
| 5 | `NOTIFY_WEBHOOK_URL` | Discord/Telegram 운영 알림 | 무료 | 선택 |

Workers AI Gemma (`GEMMA_MODEL` 기본 `@cf/google/gemma-4-26b-a4b-it`)는 별도 키 불필요 — Cloudflare Worker `env.AI` 바인딩으로 직접 호출. 텍스트 요약(시장 요약 / mover 한줄 요약 / 뉴스 번역)은 모두 Gemma 단일 경로이며, Gemini API 는 시장 요약 음성 듣기(TTS) 전용으로만 사용된다.

`GEMMA_MODEL`·`GLM_MODEL` 평문 vars는 `wrangler.toml [vars]`에 기본값이 있어 secret 주입 불필요. 모델 교체는 wrangler 변수만 수정 후 재배포. 음성 듣기(TTS) 모델은 `worker/routes/tts.ts` 에 고정(`gemini-3.1-flash-tts-preview`).

> Phase 3 단순화 (2026-05-22): 원래 기획의 Kimi K2.6 + Perplexity 조합은 작업 성격(고정 입력 → 한국어 요약)과 deterministic mover 선정 때문에 불필요해 Gemini→Gemma 단일 폴백으로 통합. 자세한 배경은 [[CloudStock#s-1.9]] 참고.

---

## Phase 2 — 미국 EOD 데이터

### FMP (Financial Modeling Prep)

미국 종목 시총·등락률·거래량 일별 스냅샷. `/stable/batch-quote` 엔드포인트로 다중 티커 일괄 조회.

- **발급처**: https://site.financialmodelingprep.com/
- **가입 후 경로**: Dashboard → API Keys → Free Plan으로 시작
- **요금제**:
  - Free: 250 req/일 (본 프로젝트 일 1회 호출이라 충분)
  - Starter: $22/월 (연 결제 $264) — 250 req/일 초과 시
- **secret 주입**:
  ```bash
  npx wrangler secret put FMP_API_KEY
  # 발급받은 키 붙여넣기
  ```
- **호출 확인**: `https://financialmodelingprep.com/stable/batch-quote?symbols=AAPL,MSFT&apikey=<KEY>`
- **MCP 옵션 (Phase 3에서 도입 검토)**: FMP는 공식 MCP 서버 `https://financialmodelingprep.com/mcp?apikey=<KEY>`를 동일 키·동일 free tier로 제공한다. Phase 2 cron 배치는 결정적 호출이라 REST가 단순하고 충분하지만, Phase 3에서 Kimi K2.6 등 AI가 시장 분석 중 추가 데이터를 동적으로 조회해야 할 때 `agents` SDK의 `this.addMcpServer("fmp", "https://financialmodelingprep.com/mcp?apikey=...")` 한 줄로 도구 인벤토리를 LLM에 노출할 수 있다.

### Finnhub

미국 일반 뉴스 헤드라인. `/api/v1/news?category=general`로 상위 5건.

- **발급처**: https://finnhub.io/
- **가입 후 경로**: Dashboard → API Keys
- **요금제**: Free 60 req/분 (본 프로젝트 일 1회 호출이라 무료로 충분)
- **secret 주입**:
  ```bash
  npx wrangler secret put FINNHUB_API_KEY
  ```
- **호출 확인**: `https://finnhub.io/api/v1/news?category=general&token=<KEY>`

---

## Phase 3 — AI 요약 파이프라인

### Gemini API (Google AI Studio)

오늘의 시장 요약을 음성으로 듣는 **TTS(`/api/tts`) 전용**. 화면에 렌더된 요약 본문을 Gemini 3.1 Flash TTS(`gemini-3.1-flash-tts-preview`)로 합성해 재생한다. (과거 텍스트 요약 1차 경로였으나 2026-05-23 제거됐고, 같은 키가 이제 음성 합성에 재사용된다 — [[CloudStock#s-1.9]] 참고.)

- **발급처**: https://aistudio.google.com/
- **가입 후 경로**: 좌측 메뉴 → "Get API key" → Create API key in new project
- **요금제**: 프리티어 한도 내 $0. 음성 합성은 사용자가 "음성 듣기" 버튼을 누를 때만(on-demand) 호출되므로 사용량이 적다.
- **secret 주입**:
  ```bash
  npx wrangler secret put GEMINI_API_KEY
  ```
- **음성 / 모델**: 음성은 `Charon`(informative 톤), 모델 슬러그(`gemini-3.1-flash-tts-preview`)는 `worker/routes/tts.ts` 에 고정. 응답은 24kHz/16bit/mono PCM(base64)이라 워커가 WAV 헤더를 씌워 data URL 로 브라우저에 반환한다.
- **미설정 시**: `/api/tts` 가 503 을 반환하고 대시보드의 "음성 듣기" 버튼만 동작하지 않는다 (요약 텍스트·시세 등 나머지 기능은 정상).
- **호출 확인**: `curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-3.1-flash-tts-preview:generateContent" -H "x-goog-api-key: <KEY>" -H "Content-Type: application/json" -d '{"contents":[{"parts":[{"text":"안녕하세요"}]}],"generationConfig":{"responseModalities":["AUDIO"],"speechConfig":{"voiceConfig":{"prebuiltVoiceConfig":{"voiceName":"Charon"}}}}}'`

### Perplexity Search API (미사용, 향후 옵션)

원래 기획(`CloudStock §4`)에서 "범용 웹 서치"용으로 검토했으나 Phase 3 구현 단계에서 제외. 종목별 Finnhub `/company-news`로 mover 요약 컨텍스트가 충분하고, 시장 요약은 Finnhub general news + FMP 통계로 deterministic하게 처리 가능하다고 판단.

향후 도입 시:
- **발급처**: https://docs.perplexity.ai/
- **요금제**: $5 / 1,000 검색
- **secret 주입**: `npx wrangler secret put PERPLEXITY_API_KEY`

Phase 3에서는 발급 불필요. `worker/types.ts`의 `Env`에 `PERPLEXITY_API_KEY?: string` 타입 정의만 남겨두고 호출 코드는 없다.

---

## Phase 4 — 한국주식

### KIS Open API (한국투자증권)

KOSPI/KOSDAQ 종목 시세. 평일 장중 매시간 갱신용.

- **발급처**: https://apiportal.koreainvestment.com/
- **사전 조건**: 한국투자증권 계좌 보유 (없으면 비대면 개설)
- **가입 후 경로**:
  1. 회원가입 + 본인인증
  2. 앱 등록 → APP_KEY / APP_SECRET 발급
  3. 모의투자/실전 환경 선택 (본 프로젝트는 시세만 조회하므로 모의로도 충분)
- **요금제**: 무료 (계좌 유지만 필요)
- **레이트 리밋**: 실전 초당 20건 (슬라이딩 윈도우), self-throttle 15/sec 권장
- **secret 주입**:
  ```bash
  npx wrangler secret put KIS_APP_KEY
  npx wrangler secret put KIS_APP_SECRET
  ```
- **운영 주의**:
  - 계좌 3개월 미거래 시 휴면 자동 전환 → 월 1회 모의 거래 자동화 권장
  - access_token 24h TTL → D1 `token_cache` 테이블로 캐시
  - 2026.03.20 신규 고객 초당 호출 제한 변경 공지 → 발급 후 본인 한도 재확인

---

## Phase 5 (선택) — 운영 알림

### Discord 또는 Telegram 웹훅

cron 실패, 일일 비용 초과 등 운영 이벤트를 푸시 알림으로 받기.

- **Discord**: 채널 설정 → 통합 → 웹훅 생성 → URL 복사
- **Telegram**: BotFather로 봇 생성 → `getUpdates`로 chat_id 확인 → `https://api.telegram.org/bot<TOKEN>/sendMessage?chat_id=<ID>&text=...` 형식
- **secret 주입**:
  ```bash
  npx wrangler secret put NOTIFY_WEBHOOK_URL
  ```

---

## 발급 체크리스트

Phase 2 가동에 필요한 최소:
- [x] FMP_API_KEY
- [x] FINNHUB_API_KEY

Phase 3 (구현 완료, 2026-05-22):
- [x] GEMINI_API_KEY  ← 음성 듣기(TTS) 전용. 미설정 시 음성 버튼만 비활성, 등록 권장
- [ ] ~~PERPLEXITY_API_KEY~~  ← Phase 3에서는 사용하지 않음

Phase 4 시작 전:
- [ ] KIS 계좌 (없으면 개설)
- [ ] KIS_APP_KEY
- [ ] KIS_APP_SECRET

선택:
- [ ] NOTIFY_WEBHOOK_URL

---

## 시크릿 일괄 주입 스크립트

발급이 끝나면 한 번에:

```bash
# Phase 2 — 최소 가동
npx wrangler secret put FMP_API_KEY
npx wrangler secret put FINNHUB_API_KEY

# Phase 3 — 음성 듣기 (TTS, Gemini 3.1 Flash TTS)
npx wrangler secret put GEMINI_API_KEY    # 미설정 시 음성 버튼만 비활성, 등록 권장
# npx wrangler secret put PERPLEXITY_API_KEY  ← Phase 3에서는 미사용

# Phase 4 추가 시
npx wrangler secret put KIS_APP_KEY
npx wrangler secret put KIS_APP_SECRET

# 등록된 시크릿 확인
npx wrangler secret list
```

`AGENT_ENABLED`·`GEMMA_MODEL`·`GLM_MODEL`은 평문 환경변수로 `wrangler.toml [vars]`에 들어가 있으므로 secret put 불필요 (저장소가 private이라 무관). 모델 교체는 wrangler 변수 수정 후 재배포.