ChatGPT 예약 작업이 만든 영어·일본어·TOEIC 학습 자료를 GitHub에 날짜별로 보관하고, D1과 학습 사이트에 자동 반영하는 Cloudflare Worker 앱입니다.
- Vinext/Next 화면과 API를 하나의 Cloudflare Worker로 배포
- ChatGPT 예약 작업으로 매일 영어·일본어, 월–토 TOEIC 자료 생성
study-logs/YYYY/MM/DD/{kind}.md에 사람이 읽는 본문과 검증용 JSON 보관- GitHub Actions가 학습 파일을 검증하고 기존 D1에 멱등 업서트
- D1에 일정, 생성 콘텐츠, 파일 메타데이터, 발송 이력 저장
- R2에 MP3, PDF, 이미지 저장
- 날짜를 선택하면 영어·일본어·TOEIC 전체 자료와 정답을 사이트에 표시
- 지나간 미완료 일정을 최대 7개까지 모아 보여주고, 한 번에 선택한 날짜로 다시 예약
- 수동 API로 Workers AI 생성 및 Telegram 발송 가능
- FSRS로 카드별 다음 복습일 계산
- 소스 코드의
mainpush는 검사 후 Worker 배포, 학습 파일만 바뀐 push는 D1 동기화만 실행
예약 작업의 기준 시간대는 Asia/Seoul입니다.
| 학습 | 한국 시각 | 파일명 |
|---|---|---|
| 영어 | 매일 06:30 | english.md |
| 일본어 | 매일 08:00 | japanese.md |
| TOEIC | 월–토 18:00 | toeic.md |
Cloudflare Cron은 같은 날짜의 자료를 중복 생성하지 않도록 비활성화했습니다. GitHub 보관 형식과 검증 규칙은 docs/chatgpt-study-sync.md에 정리되어 있습니다.
GitHub Actions는 wrangler.jsonc에 연결된 Cloudflare D1을 갱신합니다. 화면과 API는 모두 language-study-log.evolvix.workers.dev Worker에서 제공합니다. 운영 Worker 전체는 Cloudflare Access로 보호하고, 지정된 Google 계정만 화면을 열 수 있습니다. 일정과 개인 학습 기록의 추가·완료·이동·삭제는 검증된 Access JWT와 same-origin 요청을 함께 요구합니다.
| Method | 경로 | 용도 | 인증 |
|---|---|---|---|
GET |
/api/health |
D1 및 바인딩 상태 확인 | 없음 |
GET |
/api/materials?date=YYYY-MM-DD&kind=english |
날짜별 생성 자료 조회 | 없음 |
GET, HEAD |
/api/assets/:id |
R2 파일 조회 | 없음 |
GET |
/api/reviews/due?language=english&limit=20 |
오늘 복습할 카드 조회 | 없음 |
GET |
/api/dashboard |
일정과 개인 학습 기록 조회 | 없음 |
POST, PATCH, DELETE |
/api/dashboard |
일정과 개인 학습 기록 추가·변경·삭제 | Cloudflare Access JWT + same-origin 또는 Bearer 토큰 |
GET |
/api/dashboard/session |
Google Access 로그인 신원 확인 | Cloudflare Access JWT |
POST |
/api/admin/generate |
자료 생성 및 선택적 Telegram 발송 | Bearer 토큰 |
POST |
/api/admin/send/:contentId |
기존 자료 Telegram 재발송 | Bearer 토큰 |
POST |
/api/admin/reviews/:cardId |
복습 평가 저장 | Bearer 토큰 |
PUT |
/api/admin/assets/:kind/:filename |
MP3/PDF/이미지 업로드(최대 20 MiB) | Bearer 토큰 |
POST |
/api/telegram/connect |
최근 /start 사용자와 Telegram 연결 |
Bearer 토큰 |
브라우저에서는 별도 관리자 토큰을 입력하지 않습니다. Cloudflare Access가 Google 로그인을 처리하고, 앱은 Cf-Access-Jwt-Assertion의 서명·발급자·Audience를 검증한 뒤 편집 권한을 부여합니다. ADMIN_TOKEN은 브라우저 로그인용이 아니라 기존 자동화 API의 Bearer 인증 호환용으로만 유지합니다. Worker 전체가 Access로 보호된 운영 환경에서 외부 자동화가 HTTP API를 호출하려면 Cloudflare Access 서비스 인증도 함께 구성해야 합니다.
알림 시각을 반드시 지키는 방식 대신 생성 → 다시 잡기 → 완료의 세 단계로 운영합니다.
- 예약 작업은 정해진 시각에 학습 자료를 생성하고 사이트는 날짜별 자료를 보관합니다.
- 과거 일정이 미완료인 채 남으면 대시보드의
놓친 공부, 다시 잡기에 최근 7개가 표시됩니다. - 전부 만회하려 하지 않고 하나를 골라
이 날짜로 옮기기를 누른 뒤, 실제로 공부한 후 완료 표시나 학습 기록을 남깁니다.
이 방식은 알림을 놓친 사실과 학습 자료의 소실을 분리합니다. 알림은 시작을 돕는 신호일 뿐이고, 사이트는 놓친 작업을 다시 선택할 수 있는 인박스 역할을 합니다.
자료 생성 예시:
curl -X POST https://YOUR_WORKER.workers.dev/api/admin/generate \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-H "Content-Type: application/json" \
-d '{"date":"2026-08-23","kind":"english","sendTelegram":true}'파일 업로드 예시:
curl -X PUT https://YOUR_WORKER.workers.dev/api/admin/assets/english/practice.mp3 \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-H "Content-Type: audio/mpeg" \
--data-binary @practice.mp3복습 평가는 {"rating":"again|hard|good|easy"} 형식으로 전송합니다.
wrangler login후 D1과 R2를 만듭니다.
npx wrangler d1 create language-study-log-db
npx wrangler r2 bucket create language-study-log-assets- 반환된 D1 ID를
wrangler.jsonc의database_id에 기록합니다. - Telegram의
@BotFather에서 개인 봇을 만든 뒤 새 봇과의 채팅에서/start를 한 번 보냅니다. - Cloudflare Access에서 운영 Worker의
All traffic을 보호하고, 정확한 Google 이메일 Allow 정책과 Google Identity Provider를 연결합니다.wrangler.jsonc의ACCESS_TEAM_DOMAIN과ACCESS_AUD는 해당 Access 애플리케이션 값과 일치해야 합니다. - 실제 값이 콘솔 기록이나 Git에 남지 않도록 Wrangler의 대화형 입력으로 Worker 비밀 값을 저장합니다.
ADMIN_TOKEN은 자동화 API 호환용입니다. Bot Token은 채팅이나 저장소에 붙여 넣지 않습니다.
npx wrangler secret put ADMIN_TOKEN
npx wrangler secret put TELEGRAM_BOT_TOKEN- 배포 후 아래 연결 API를 한 번 호출합니다. Worker 전체가 Access로 보호돼 있다면 이 호출에는 허용된 Access 세션 또는 서비스 인증도 필요합니다. Worker는 Telegram에 보관된 가장 최근의 개인
/start메시지를 확인하고 Chat ID를 D1에 저장한 뒤 확인 메시지를 발송합니다. Chat ID를 직접 복사하거나 별도 서비스에 제공할 필요가 없습니다.
curl -X POST https://language-study-log.evolvix.workers.dev/api/telegram/connect \
-H "Authorization: Bearer $ADMIN_TOKEN"연결 상태는 GET /api/telegram/status에서 token, connected 불리언 값으로만 확인할 수 있습니다. 기존 TELEGRAM_CHAT_ID Secret은 필요한 경우 수동 대상 지정용 호환 옵션으로 계속 지원합니다.
- GitHub 저장소 Actions secrets에 아래 값을 등록합니다.
CLOUDFLARE_ACCOUNT_IDCLOUDFLARE_API_TOKEN
설정 전에도 GitHub Actions의 린트·타입·빌드는 실행되며, Cloudflare 배포 단계만 안전하게 건너뜁니다. 학습 파일 D1 동기화는 두 값이 없으면 실패하므로, 예약 작업을 연결하기 전에 설정해야 합니다.
예약 작업 프롬프트에는 이 두 값이나 ADMIN_TOKEN을 넣지 않습니다. GitHub Actions만 저장소 Secret을 읽으며, 예약 작업은 공개 학습 Markdown 한 파일만 수정합니다.
Telegram Bot API 참고 문서:
오픈소스 채택 범위와 이후 구현 순서는 docs/open-source-reference.md에 기록합니다.
npm ci
npm run worker:types
npm run check실제 비밀 값은 .dev.vars에만 두고 커밋하지 않습니다. 형식은 .dev.vars.example을 참고하세요.