러닝기록 플랫폼 — 멀티유저 · BYO 스토리지 · 제로-DB 아키텍처 (v1)
프로젝트: 자동발행 · 확장 기획 II · 작성일: 2026-07-24 (KST) · 상태: 검토용 기획(안) 목적: 창작자는 플랫폼·콘텐츠만 관리하고, 각 사용자는 자기 데이터·비용·리스크를 갖는 구조를 설계한다. 서버·DB 관리비 없이 누구나 쉽게 적용·관리.
0. 요약 (한 장 정리)
핵심은 "플랫폼이지 데이터베이스가 아니다(Platform, not Database)" 다. 창작자는 정적 웹앱(플랫폼) 하나만 유지하고, 모든 사용자 데이터는 각자의 저장소(구글드라이브 · 노션 · 시트)에 남는다. 창작자 서버는 사용자 데이터를 보관하지도 경유하지도 않는다. 결과적으로 서버·DB 비용 0, 데이터 유출·관리 리스크는 구조적으로 사용자에게 위임되고, 사용자는 웹 URL 하나로 자기 계정을 연결해 바로 쓴다.
추천 구성은 제로-DB 정적 웹앱 + BYO 스토리지 어댑터(1순위 구글드라이브, 2순위 노션) + 티어드 BYO 추출(무료 OCR·수동 + 선택 BYOK AI 비전) 이다. 아래 기술 전제는 모두 공식 문서로 확인했다(§4·§5·본문 각주).
1. 요구사항 재정의
- 창작자(서비스 제공자)는 플랫폼(앱)과 기본 콘텐츠만 관리한다.
- 각 사용자의 실제 데이터는 사용자 자신의 저장소에 저장·관리된다(구글드라이브 / 노션 / 시트 등).
- 창작자는 사용자 데이터를 저장하지도, 서버로 경유하지도 않는다 → 서버·DB 비용 0, 데이터 유출·관리 리스크를 사용자에게 위임.
- 그러면서도 누구나 쉽게 접근·적용·관리할 수 있어야 한다.
2. 설계 원칙 — "반드시 어딘가 있어야 하는 3가지"를 전부 사용자 쪽에
자동화에는 세 가지가 반드시 어딘가에 존재해야 한다. 이 셋을 모두 사용자 소유 영역에 두는 것이 이 아키텍처의 요체다.
| 무엇 | 어디에 (사용자 소유) | 창작자 관여 |
|---|---|---|
| 입력 (캡쳐 이미지) | 사용자의 드라이브 폴더 | 없음 |
| 누적 데이터 (정본) | 사용자의 드라이브 JSON/CSV · 노션 DB · 시트 | 없음 |
| 연산 (이미지→데이터 추출) | 사용자의 브라우저(무료 OCR) · 사용자 AI키(BYOK) · 사용자 Apps Script | 없음 |
세 가지가 모두 사용자 쪽에 있으므로, 창작자는 정적 앱 + 저장소 어댑터 + 템플릿만 유지하면 된다.
3. 레이어 구조 (기존 스키마 v1.0 그대로 재사용)
이전 기획서의 저장소 중립 스키마(레코드 v1.0) 가 이 모델의 결정적 자산이다 — 같은 레코드를 저장소만 바꿔 담는다.
저장소 어댑터 인터페이스(개념): listImages() · readDataset() · writeDataset(records) — 세 메서드만 구현하면 어떤 백엔드든 연결된다. 앱 본체(추출·대시보드)는 어댑터 뒤편을 모른다 → 백엔드 추가가 앱 수정 없이 이뤄진다.
4. 책임·소유 분담 (창작자 vs 사용자)
🛠 창작자가 관리 (플랫폼·콘텐츠)
- 웹앱 코드 · UI · 대시보드 · 추출 로직
- 저장소 어댑터 · 각 백엔드 템플릿
- OAuth 클라이언트 등록(공개 client_id)
- 문서 · 버전 · 배포(무료 정적 호스팅)
- 개인정보처리방침 · 정책 준수
👤 각 사용자가 소유 (데이터·비용·리스크)
- 저장소 계정(구글/노션) · 접근 권한
- 캡쳐 이미지 · 누적 데이터(정본)
- (선택) AI API 키와 그 사용료
- 데이터 백업 · 보존 · 삭제 권한
- 자기 데이터의 보안·프라이버시 통제
토큰과 데이터가 사용자 브라우저 ↔ 사용자 저장소 사이에서만 오가므로, 창작자 서버에는 보관되는 사용자 데이터가 없다(= 유출될 데이터가 애초에 없음).
5. "연산 비용" 문제와 해결 — 티어드 BYO 추출 (핵심)
이미지→데이터 추출은 유일하게 연산이 드는 지점이다. 이 비용을 누가, 어디서 부담하느냐가 "창작자 비용 0"의 성패를 가른다. 답은 전부 사용자 쪽, 3단 티어다.
| 티어 | 방식 | 실행 위치 | 비용 | 정확도 | 대상 |
|---|---|---|---|---|---|
| 무료 | Tesseract.js OCR + 수동 확인·보정 | 사용자 브라우저 | 0원, 키 불필요 | 중 (격자 지표 일부 결측) | 누구나 |
| 정확 (BYOK) | 사용자 AI 키로 비전 추출 | 브라우저(직접) 또는 사용자 스크립트 | 사용자 결제(이미지당 극소액) | 상 (케이던스·심박·고도까지) | 원하는 사용자 |
| 수동 | 폼 입력 | 브라우저 | 0원 | — | 폴백·보정 |
BYOK 브라우저 호출 실현성(확인됨):
- Claude: anthropic-dangerous-direct-browser-access: true 헤더로 브라우저에서 직접 호출 지원 → 프록시 없이 BYOK 가능.[1]
- Gemini: API 키로 브라우저 호출 가능.
- OpenAI: 브라우저 직접 호출은 일반적으로 차단(CORS 미지원) → 프록시 필요하므로 BYOK 1순위에서 제외.
→ 무료 OCR/수동으로 "누구나 쉽게", BYOK 비전으로 "원하면 고정밀". 어느 경우든 창작자 연산비 0.
6. 저장소 어댑터 (BYO 스토리지) 비교
| 백엔드 | 접근 방식 | 검증·백엔드 부담 | 대시보드 | 적합 |
|---|---|---|---|---|
| 구글드라이브 ⭐1순위 | OAuth drive.file + Picker로 폴더 선택 |
비민감 스코프 → 무거운 검증(CASA) 회피, 백엔드 불필요[2] | 앱(우리 대시보드) | 이미지가 이미 드라이브에 있는 사용자 |
| Notion ⭐2순위 | 템플릿 복제 + OAuth(또는 내부토큰) | 공개 OAuth는 토큰 교환에 서버측 secret 필요 → 무상태 함수 or 내부토큰[3] | 노션 뷰 자체 | 노션 사용자 |
| Google Sheets | OAuth 또는 Apps Script 템플릿 | Apps Script는 사용자 계정에서 실행(무료 쿼터) | 앱 or Looker Studio | 시트 친화·앱 없이 |
| 로컬 파일 | 파일 가져오기/내보내기(JSON) | 없음(완전 오프라인) | 앱 | 최대 프라이버시·오프라인 |
핵심 팩트 2가지:
- 구글 drive.file은 비민감(non-sensitive) 스코프로, drive/drive.readonly(restricted)가 요구하는 보안평가·검증 부담을 피한다. Picker로 사용자가 고른 파일/폴더만 앱에 노출 → 저마찰·프라이버시 우수.[2]
- 노션 공개 OAuth는 인증코드→토큰 교환에 client secret(서버측)이 필요해 순수 브라우저만으로는 불가 → 무상태 서버리스 함수(무료) 로 교환만 대행하거나, 사용자가 내부 통합 토큰을 발급해 붙여넣는다. 어느 쪽도 데이터는 저장하지 않는다.[3]
7. 배포 트랙 — "누구나 쉽게" (사용자가 있는 곳에서 만난다)
Track A · 웹앱 + 구글드라이브 (추천 1순위)
- URL 접속 → "구글드라이브 연결"(Picker)
- 앱이 러닝기록 폴더를 읽어 추출
- 정본 JSON을 사용자 드라이브에 기록
- 기존 대시보드로 바로 열람
Track B · 웹앱 + 노션
- 창작자 노션 템플릿 복제
- 연결(무상태 Worker OAuth 또는 내부토큰)
- 레코드를 노션 DB 페이지로 기록
- 노션 뷰(갤러리·캘린더·차트)가 대시보드
Track C · 구글시트 + Apps Script (앱조차 불필요)
- 창작자 시트 템플릿 "사본 만들기"
- 스크립트 승인(사용자 계정에서 실행)
- 스크립트가 드라이브 스캔→추출→행 기록
- 시트 내장 대시보드로 열람
공통 원칙
- 온보딩 3~4스텝 이내
- 토큰·데이터는 사용자 쪽에만
- 같은 스키마 v1.0 → 트랙 간 이동 가능
- 창작자는 트랙별 템플릿·문서만 유지
추천 순서: Track A(우리 대시보드 재사용 + 드라이브 데이터에 가장 부합 + 최저 비용·마찰)로 먼저 검증 → Track B(노션 어댑터) 추가 → Track C는 앱 없이 쓰려는 사용자용 대안.
8. 비용·리스크 위임 구조 (요구의 핵심)
| 항목 | 창작자 | 각 사용자 |
|---|---|---|
| 호스팅 | 무료 정적(예: Cloudflare Pages) — $0[4] | — |
| DB/데이터 저장 | 없음(0) — 보관·경유 안 함 | 자기 저장소 용량 |
| 추출 연산 | 없음(0) | 무료 OCR(0) 또는 BYOK 키 사용료 |
| OAuth | 클라이언트 등록 $0 / (노션용)무상태 함수 무료 | 자기 계정 인증 |
| 도메인 | 선택 · 연 1만원대 | — |
| 데이터 유출 리스크 | 표면 없음(저장 데이터 없음) | 자기 계정·제공자 보안에 귀속 |
| 남는 의무 | 개인정보처리방침 · 구글 limited-use 정책 · 앱코드 보안 | 데이터 백업·보존·삭제 |
→ 사용자 수와 무관하게 창작자 비용은 사실상 고정 ~$0, DB 관리·데이터 유출 리스크는 구조적으로 사용자(및 각자의 클라우드 제공자)에게 귀속된다.
9. 정직한 주의점 (설계 전 반드시 인지)
- "제로 백엔드"는 노션 매끄러운 OAuth에서만 예외 — 공개 OAuth 토큰 교환에 무상태 함수가 필요. 단 데이터는 저장 안 하므로 "제로 DB·제로 데이터보관"은 유지. 완전 무(無)함수를 원하면 노션은 내부토큰 방식.
- 브라우저 AI 호출 편차 — Claude/Gemini는 BYOK 가능, OpenAI는 불가(프록시 필요). BYOK는 키 발급이라는 장벽 → 무료 OCR/수동 티어로 진입장벽 해소.
drive.file의 범위 — 앱은 "사용자가 고르거나 앱이 만든" 파일만 본다. 온보딩에서 Picker로 폴더를 부여하고, 신규 파일은 폴더 권한 + 앱 열 때 스캔으로 처리(백그라운드 서버 불필요, 앱은 사용자가 여는 것이므로 자연스러움).- 미검증 앱 경고 — 비민감 스코프여도 공개 전 기본 OAuth 검증(경량·무료) 권장.
- 비밀키 절대 임베드 금지 — 정적 앱에 창작자 API 키를 넣지 않는다(BYOK만). 공개 OAuth
client_id는 노출돼도 무방,secret은 금지(→ 무상태 함수). - 데이터 이식성 = 셀링포인트 — 스키마 중립이라 백엔드 간 이동 자유(락인 없음). "당신 데이터는 당신 것"을 강점으로.
10. 추천안 (결론)
제로-DB 정적 웹앱 플랫폼 + BYO 스토리지 어댑터(1순위 구글드라이브, 2순위 노션) + 티어드 BYO 추출(무료 OCR·수동 + 선택 BYOK 비전). 창작자는 앱·템플릿만 유지, 데이터·연산·리스크는 사용자 소유. Track A부터 구축.
11. 로드맵
| 단계 | 내용 | 창작자 비용 |
|---|---|---|
| P1 | Track A MVP: Drive Picker + 무료 OCR/수동 + 기존 대시보드 + Drive JSON 정본 | ~$0 |
| P2 | BYOK AI 비전 티어 추가(케이던스·심박·고도 채움, 신뢰도·정합성 검증) | ~$0 |
| P3 | Notion 어댑터(Track B) + 노션 템플릿·뷰 대시보드 | ~$0 |
| P4 | Sheets/Apps Script(Track C), 다중 러닝앱·다국어, 공유/공개 프로필(선택) | ~$0 |
각 단계에서 저장소 중립 스키마·어댑터 인터페이스를 지키면 확장이 앱 본체 수정 없이 진행된다.
12. 결정 필요 (검토 요청)
- 1순위 배포 트랙: Track A(웹앱+구글드라이브) 권장 / B(노션) / C(시트·Apps Script).
- 무료 티어 추출 기본값: OCR 우선 권장 / 수동 우선.
- 노션 OAuth 방식: 무상태 Worker(매끄러움) 권장 / 내부토큰(완전 무함수).
- 호스팅: Cloudflare Pages 권장 / Vercel / Netlify / GitHub Pages.
- 브랜드·도메인: 서비스명/도메인 확정 여부.
각주 (근거)
- [1] Anthropic API — 브라우저 직접 호출용
anthropic-dangerous-direct-browser-access헤더 지원(2024~). - [2] Google Drive API 문서 —
drive.file은 비민감 스코프로 간소 검증, Picker로 사용자 선택 파일만 접근. - [3] Notion API 문서 — 공개 OAuth 토큰 교환은 client secret(서버측) 필요, 내부 통합 토큰은 정적 토큰.
- [4] 2026 무료 정적 호스팅 비교 — Cloudflare Pages 등 무료 티어(대역폭 넉넉).
자동발행 프로젝트 · 확장 기획 II · 스키마 v1.0 연계 · 결정 반영 시 v2로 갱신.