ESP32-S3 Bench Guide
ESP32-S3 N16R8 bench guide: live pinout, lessons, simulators and the bench log.
우리 학교 시험 범위에 맞춘 AI 의학 문제 무한 생성. KMLE 기반 풀 + 학교별 필터 + 강의자료 업로드.
Translation pending
EducationTypeScript · JavaScriptGitHub @lecturelink0-hashOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
lecturelink homepage
Translation pending
Taken from the repository README
Loading the full README. The saved excerpt is shown below.
의료 교육 특화 AI 학습 인프라의 백엔드 + API 레이어. • Checkpoint 1 — 프로젝트 구조 + DB 스키마 + 타입 정의 • Checkpoint 2 — Supabase 클라이언트 + 인증 + 사용자 / 코호트 API • Checkpoint 3 — Anthropic 클라이언트 + 문항 생성 파이프라인 • Checkpoint 4 — 추천 엔진 (bandit) + 임베딩 + 풀이 기록 • Checkpoint 5 — "시험 범위 아니에요" 피드백 + 코호트 학습 • Checkpoint 6 — Track A 파일 업로드 + Private 문항 생성 • Checkpoint 7 — 결제 (토스페이먼츠) + 사용량 캡 • Checkpoint 8 — Next.js 프론트엔드 (Tailwind v4 + 인증 + 4개 핵심 페이지) • Checkpoint 9 (P0)Read the full README ↗
의료 교육 특화 AI 학습 인프라의 백엔드 + API 레이어.
| 계층 | 기술 |
|---|---|
| Framework | Next.js 15 (App Router) |
| DB · Auth · Storage | Supabase (PostgreSQL + pgvector) |
| AI | Google Gemini — 기본 모델 gemini-2.5-flash (생성·검증·Vision·OCR). AI_PROVIDER=anthropic 시 Anthropic Claude Sonnet 4.6 + Haiku 4.5 |
| Hosting | Vercel |
| Type System | TypeScript 5.6 (strict) |
| Validation | Zod |
backend/
├── app/ # Next.js App Router
│ └── api/ # API 엔드포인트 (Checkpoint 2+에서 추가)
├── lib/
│ ├── ai/ # AI 클라이언트(기본 gemini-2.5-flash), 프롬프트 (Checkpoint 3)
│ ├── db/ # Supabase 클라이언트 (Checkpoint 2)
│ ├── types/
│ │ ├── database.ts # DB row 타입 (스키마 1:1)
│ │ └── domain.ts # 비즈니스 도메인 타입
│ └── utils/ # 공통 유틸리티
├── supabase/
│ └── migrations/
│ └── 00001_initial_schema.sql # 초기 DB 스키마
├── .env.example # 환경변수 명세
├── .gitignore
├── next.config.js
├── package.json
├── tsconfig.json
└── README.md
| 테이블 | 역할 |
|---|---|
schools | 학교 마스터 |
subjects | 과목 (호흡기·순환기·...) |
sub_topics | sub-topic (호흡 생리·폐쇄성 폐질환·...) + 위험 영역 플래그 |
users | 사용자 (Supabase auth 확장) |
cohorts | 학교 + 학년 + 학기 + 과목 단위 |
questions | 문항 풀 (Curated / Community / Beta 3단 tier) |
cohort_sub_topic_scores | 학교 코호트 학습의 핵심 — sub-topic별 포함 점수 |
user_attempts | 풀이 기록 |
out_of_scope_feedback | "시험 범위 아니에요" 클릭 |
user_weak_areas | 약점 자동 분류 결과 |
user_uploads / private_questions | Track A (내 강의 노트) |
subscriptions / usage_quotas | 결제 및 사용량 캡 |
CPX 화면과 로그인 프록시는 Next.js 앱에 포함되며, Gemini Live 환자·신체진찰·채점 엔진은 services/cpx에서 같은 저장소의 Docker 서비스로 배포합니다. 따라서 별도의 비공개 CPX 소스 저장소가 필요하지 않습니다.
/cpx — 음성·텍스트 문진, 1차 chibi 환자, 부위별 신체진찰, 채점 결과/cpx/history — Supabase에 저장된 사용자별 완료 기록services/cpx — 197개 증례와 53개 루브릭을 포함한 FastAPI 서비스supabase/migrations/00022_cpx_sessions.sql — 사용자별 CPX 기록 및 RLS배포 순서는 services/cpx/README.md를 따릅니다.
questions.embedding 을 vector(1536) → vector(1024) 로 재생성합니다 (OpenAI text-embedding-3-small → Voyage voyage-3 기준). 운영 DB 에 기존 임베딩 데이터가 있는 상태에서 적용하면 컬럼 자체가 drop+add 되므로 모든 기존 임베딩이 소실됩니다. 안전한 경로:
questions.embedding 전수 export, (b) 적용 후 VOYAGE_API_KEY 로 Voyage voyage-3 (1024-dim) 으로 재계산 + 재삽입 동반 필요.match_questions RPC 가 pgvector 차원 불일치 에러로 실패합니다.open_images.embedding 도 vector(1024) 로 정의돼 있어 00004 와 동일한 Voyage voyage-3 (env: VOYAGE_EMBED_MODEL, VOYAGE_EMBED_DIM=1024) 기준이어야 일관됩니다. 다른 모델/차원으로 인제스트하면 match_open_images RPC 가 동일한 사유로 실패합니다.pg_cron 확장이 필요합니다. Supabase managed 에서는 대시보드 → Database → Extensions 에서 활성화 후 적용하세요..rpc(...) 호출을 추가하기 전에 반드시 서버 API 라우트 + createAdminClient 경유로 설계하세요.lib/types/database.ts — 앱이 import 하는 wrapper (수동 관리). Database 인터페이스 + alias (PlanTier, GradeLevel, UserRow, ...) + helper(Insert<T>, Update<T>) 정의.lib/types/database.generated.ts — npm run db:types 가 생성하는 raw 출력 (Docker + Supabase 로컬 필요). 직접 수정 금지.db:types 는 database.generated.ts 에만 쓰므로 wrapper(database.ts) 가 덮어쓰지 않습니다. 앱 코드는 항상 @/lib/types/database 에서 import 합니다.
전환 전에 docs/database-type-transition-checklist.md 를 먼저 읽으세요. wrapper ↔ migrations ↔ 실 사용 코드의 사전 점검 결과와 예상 수정 후보가 정리돼 있습니다.
아래 검증 순서는 본 README 하단 "⚠️ tsc --noEmit 와 .next/types 의 관계" 원칙을 따릅니다. .next 가 없는 상태에서 단독 tsc --noEmit 을 먼저 돌리면 TS6053 이 나므로, 반드시 build:clean 으로 .next/types 를 만든 뒤 tsc --noEmit 을 실행하세요.
npm run db:types (또는 원격: npm run db:types:linked) 실행.lib/types/database.generated.ts 가 새로 생겼는지 확인.
ls -l lib/types/database.generated.ts
lib/types/database.ts 에서 "MANUAL Database 시작/끝" 주석으로 감싼 export interface Database { ... } 블록을 통째로 제거하고, 같은 위치(또는 파일 상단 import 영역) 에 다음 한 줄을 추가:
export type { Database } from './database.generated';
alias / helper 정의는 그대로 둔다.export type PlanTier = Database['public']['Enums']['plan_tier'];
export type UserRow = Database['public']['Tables']['users']['Row'];
SubscriptionStatus 는 DB 가 enum 이 아닌 text 컬럼이라 derive 불가. literal union 그대로 유지하고 Database.Enums.subscription_status 매핑은 제거 — 체크리스트 1번 항목 참고..next/types 가 함께 생성된다.
npm run build:clean
node node_modules/typescript/bin/tsc --noEmit
tsconfig.json 의 include 에 .next/types/**/*.ts 가 포함돼 있습니다(Next.js 가 라우트 / 페이지 별 타입을 거기서 emit). 다음 순서를 지키지 않으면 TS6053 등이 발생합니다.
.next 가 없는 상태에서 단독 tsc --noEmit 실행 금지 — .next/types/... 파일을 찾지 못해 실패합니다.rm -rf .next → next build → (필요하면) tsc --noEmit.
next build 가 끝나면 .next/types 가 다시 만들어져 standalone tsc --noEmit 도 통과합니다..next/types 가 이미 존재할 때만 의미가 있습니다(한 번이라도 next build 또는 next dev 가 돈 뒤). 한 줄 단위 수정 검증, IDE 보조 검사 용도 정도로 사용하세요.스크립트:
npm run build — .next 캐시를 보존하며 빌드 (가장 흔한 경로).npm run build:clean — .next 를 지우고 다시 빌드. CI / 의심나는 캐시 상태 점검 시 사용.npm run typecheck — tsc --noEmit. .next/types 존재 전제. clean 상태라면 먼저 build:clean 한 번 돌린 뒤 실행하세요.1단계 보정(00012 ~ 00016) + RPC 권한 잠금 + 입력 검증까지 마친 뒤, 다음 명령을 이 순서대로 실행합니다.
# 1) 마이그레이션 적용 (로컬 또는 원격 Supabase)
# - 로컬:
npx supabase db reset # 처음부터 다시 적용
# 또는
npx supabase migration up # 새 마이그레이션만 적용
# - 원격:
npx supabase db push
# 2) DB 타입 자동 생성 — database.generated.ts 에 출력.
# database.ts(wrapper) 는 덮어쓰지 않으므로 alias 정의가 보존된다.
npm run db:types # 로컬 Supabase 사용
# 또는
npm run db:types:linked # `supabase link` 로 연결된 원격 프로젝트 사용
# 3) generated 파일 확인 + wrapper 와 정합성 점검
ls -l lib/types/database.generated.ts # 파일이 생성됐는지
git diff lib/types/database.ts # wrapper 가 그대로인지 (변경 0줄 기대)
# 필요 시 위 "Generated 로 전환하는 방법" 절차로 wrapper 의 MANUAL 블록을 generated 로 교체.
# 4) clean 빌드 — .next/types 가 함께 생성된다.
# standalone `tsc --noEmit` 을 먼저 돌리지 말 것 (TS6053).
npm run build:clean
# 5) 빌드 후 타입 체크 — 0 오류여야 함. "never" 잔존 시 schema ↔ wrapper alias 불일치.
node node_modules/typescript/bin/tsc --noEmit
각 단계 사이 점검:
db:push 후 Supabase Studio → Database → Functions 에서 EXECUTE 권한이 service_role 로 잠겨 있는지(또는 is_admin 만 authenticated 에 grant 돼 있는지) 확인.db:types 후 lib/types/database.generated.ts 가 새로 생겼는지, lib/types/database.ts 가 절대 수정되지 않았는지 확인.build:clean 출력의 "✓ Compiled successfully" + 32 route 가 모두 나오는지 확인. 실패 시 마이그레이션 / wrapper 불일치 가능성.tsc --noEmit 에서 "never" 패턴 오류가 0 으로 정리되지 않으면 wrapper alias 가 generated schema 와 어긋난 것이므로, 위 "Generated 로 전환하는 방법" 4번 단계대로 alias 를 derive 로 바꾼다.next build / build:clean 직전에 npm install 이 한 번도 실행되지 않은 환경이면 npm ci 로 lockfile 기준 설치..env.example → .env.local 복사 후 키 입력npm installnpx supabase link --project-ref <ref>npx supabase db pushnpm run dev # 개발 서버 (.next/types 자동 생성)
npm run build # 캐시 보존 빌드
npm run build:clean # rm -rf .next 후 빌드 (CI / 캐시 의심 시)
npm run typecheck # tsc --noEmit (.next/types 존재 전제)
npm run db:types # Supabase 타입 → lib/types/database.generated.ts
npm run db:reset # DB 리셋 (로컬)
⚠️
tsc --noEmit단독 실행 직전에.next가 비어 있으면 TS6053 (.next/types/...not found) 가 납니다. clean 검증을 원하면 반드시npm run build:clean을 먼저 돌린 뒤tsc --noEmit을 실행하세요.
npm run build:clean 출력에 다음 두 줄이 항상 표시됩니다.
<w> [webpack.cache.PackFileCacheStrategy] Serializing big strings (101kiB) impacts deserialization performance ...
<w> [webpack.cache.PackFileCacheStrategy] Serializing big strings (231kiB) impacts deserialization performance ...
✓ Compiled successfully 와 32 routes 가 정상 출력되는지만 확인하세요.코드 변경이 아니라 외부 리소스/시크릿 / DB 마이그레이션이 필요한 항목입니다. 운영 배포 전에 순서대로 확인하세요.
npx supabase db push (또는 로컬: npx supabase db reset).00004_embedding_dim.sql 적용 시 임베딩 재계산 동반 필요 (위 "마이그레이션 경고" 참조).pg_cron 확장이 활성화돼 있어야 00011_automation_cron_triggers.sql 가 통과 (Supabase Dashboard → Database → Extensions).open_images Storage bucket 생성/권한
open_images (lib/open-images/select.ts 의 OPEN_IMAGES_BUCKET 상수).TOSSPAYMENTS_WEBHOOK_SECRET (필수). 토스 대시보드의 webhook secret 과 동일한 값.200 OK 를 반환하지만, 내부적으로 서명 검증이 실패해 이벤트 처리는 침묵 무시되고 ops_alerts 에 "구성 누락" critical 알림이 남는다. 결제 상태 변경(승인·취소·환불)이 DB 에 반영되지 않으니 운영 알림을 반드시 모니터링.https://<host>/api/webhooks/toss 로 등록.lib/queue/process-upload.ts):
QSTASH_TOKEN — Upstash QStash 콘솔의 publish token.QSTASH_TARGET_URL — 예: https://<host>/api/queue/process-upload.maxDuration = 300, 즉 Vercel 5분 가정)을 넘으면 업로드가 실패하기 시작한다./api/queue/process-upload):
QSTASH_CURRENT_SIGNING_KEY, QSTASH_NEXT_SIGNING_KEY — Upstash 콘솔의 signing key 쌍. 키 로테이션 시 둘 모두 채워두면 무중단 교체 가능.MAX_DAILY_AI_COST_USD (예: 50). 일일 합산 비용이 캡을 넘으면 /api/questions/generate 사전 차단.MAX_QUESTIONS_PER_REQUEST (선택, 기본 50) 도 함께 점검.ANTHROPIC_TIMEOUT_MS (선택, 기본 = 60초) — Anthropic SDK 호출 timeout. 외부 API hang 으로 서버 함수가 묶이는 것을 방지. SDK 자체 retry 는 끄고 의 한 곳으로 일원화돼 있다.60000lib/ai/client.tswithRetrynode scripts/ingest-open-images.mjs \
--source roco_v2 \
--manifest data/roco.jsonl \
--dry-run --skip-embedding
--skip-embedding 을 제거하고 VOYAGE_API_KEY 를 설정 (실제 비용 발생, dry-run 이라 DB insert 는 여전히 없음).--dry-run / --skip-embedding 모두 제거하고 실제 인제스트 (SUPABASE_SERVICE_ROLE_KEY, VOYAGE_API_KEY 환경변수 필요).node scripts/ingest-open-images.mjs --help 로 확인.npm run build:clean — ✓ Compiled successfully + 32 routes 정상 출력 확인.node node_modules/typescript/bin/tsc --noEmit — 0 오류.node scripts/test-open-images-flow.mjs — 전 항목 pass (open-images 흐름 정합성).node scripts/eval-ocr.mjs --help — 스크립트 로드 정상 (실 OCR 평가는 골든셋 준비 후).