ESP32-S3 Bench Guide
ESP32-S3 N16R8 bench guide: live pinout, lessons, simulators and the bench log.
翻译准备中
尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证制作者的介绍仅有上面的一句话。 更多详情请阅读仓库 README。 仓库 README ↗
正在加载完整 README。
查看完整 README ↗같은 저장소에 별도 앱 OUR STUDIO(
our-studio/, 커플 공동 인스타그램 콘텐츠 작업실)가 있습니다. 독립된 Next.js 앱이며 Vercel 에서 Root Directory 를our-studio로 지정해 따로 배포합니다 — our-studio/README.md.
개인용 의대 AI 공부 웹앱. iPad에서 웹으로 사용(설치 X).
핵심 흐름: 자료 업로드 → 정리본 생성(Claude) → 문제 생성(Gemini) → 문제풀이 → 오답 축적 → AI 과외(GPT)
첫 화면은 "📚 현재 진행 중인 강의" 목록입니다. 정리본 / 문제풀이 / 과외는 최상위 메뉴가 아니라, 강의를 열었을 때 그 강의의 자료를 기반으로 사용하는 하위 학습 기능입니다.
자료 관리는 "강의(Course)" 중심으로 이루어집니다: 강의 → 학습지(강의당 1개) / 수업 기록(날짜·교시별 세션, 각각 강의록+STT) → 정리본·문제풀이·과외. 날짜 기준 달력 View는 전체 수업을 빠르게 훑어보는 보조 화면으로 별도 제공될 예정입니다(Phase D).
배포: https://p-d-r.vercel.app (Vercel, main 브랜치 자동배포 + Supabase 연결 완료)
Phase A — 강의 관리
supabase/migrations/0001_init.sql): courses, study_materials, study_material_mappings, lecture_sessions, summaries, combined_summaries, combined_summary_sessions, questions, question_lecture_sessions, attempts, tutor_sessions, tutor_messages. 이전의 날짜 중심 lectures/lecture_files 테이블은 제거했습니다 (아직 실제 배포 데이터가 없어 무중단 마이그레이션 없이 교체).study_materials, 교체 시 이전 버전 보존), 수업 세션 파일은 강의록 PDF + STT 텍스트 2개뿐입니다./ (홈) — 현재 진행 중인 강의 카드 목록 + + 강의 추가 + 📦 보관된 강의 섹션 (최상위 navigation은 "강의"뿐, 정리본/문제풀이/과외는 여기 없음)/courses/[courseId] — 강의 상세 페이지 (편집/보관·복원/영구 삭제, 🧠 학습 섹션은 아래 세 경로로 연결되는 실제 링크)/courses/[courseId]/summary, /questions, /tutor — 정리본/문제풀이/과외는 강의 안에서만 접근 가능 (지금은 Phase E/F/G placeholder)/api/courses (GET ?status=active|archived, POST 생성), /api/courses/[id] (GET/PATCH/DELETE) — 영구 삭제는 confirm:true 필수 + 관련 Storage 파일을 먼저 정리한 뒤 DB row를 cascade 삭제CourseCard, CourseFormDialog, ConfirmDialogPhase B — 학습지 관리
study_materials(버전 관리, 교체해도 이전 버전+매핑 보존) → worksheet-pdf 버킷에 저장/api/courses/[id]/study-material/init(업로드 자리 마련) → 브라우저가 Supabase로 직접 PUT → /complete(활성화 + 분석 트리거) 3단계로 우회.ANTHROPIC_API_KEY가 설정되어 있으면 업로드 완료 시 Claude가 목차 부분(앞 10페이지, pdf-lib으로 추출)만 읽어 교수/파트/페이지/문제 구간을 분석해 study_material_mappings에 저장 — Claude PDF 입력은 100페이지 제한이 있어서 전체를 보내지 않고, 어차피 구조 정보가 목차에 다 있음 (AI 키가 없으면 조용히 건너뛰고 안내 문구만 표시 — 수동 입력으로 대체 가능)confirmed) 가능, "+ 파트 추가"로 수동 입력도 가능/api/courses/[id]/study-material (GET/DELETE), /study-material/init+/complete (POST, 업로드), /api/study-material-mappings (POST), /api/study-material-mappings/[id] (PATCH/DELETE)Phase C — 수업 세션 관리
/courses/[courseId]/sessions/[sessionId] — 수업 상세: 교수/파트 편집, 삭제, 📄 강의록 + 📝 STT 업로드/교체/삭제 (학습지와 동일하게 브라우저→Supabase 직접 업로드 방식), 🧠 이 수업으로 학습(정리본/문제풀이/과외, 강의 전체 자료를 쓰므로 강의 레벨 페이지로 연결)/api/lecture-sessions (POST), /api/courses/[id]/lecture-sessions (GET 목록), /api/lecture-sessions/[id] (GET/PATCH/DELETE), /api/lecture-sessions/[id]/files/init+/complete (업로드), /api/lecture-sessions/[id]/files (DELETE ?type=)Phase D — 달력 View
/calendar — 월 이동 가능한 달력, 수업이 있는 날짜에 점 표시. 강의별 View(기본 자료 관리)와 달리 이건 전체 강의를 가로질러 날짜 기준으로 훑어보는 보조 화면/calendar/[date] — 그 날짜의 모든 수업을 "N교시 — 강의명 · 파트명" 형태로 나열, 각 항목이 해당 수업 상세로 연결/api/calendar (GET ?month= 날짜별 카운트, ?date= 그 날짜 수업 목록 + 강의명 join)Phase E — 정리본
/courses/[courseId]/summary: 수업 목록에서 체크박스로 선택해 통합 정리본을 만들거나, 각 수업 옆 버튼으로 개별 정리본을 만듭니다. 개별 정리본을 먼저 만들어야 통합을 만들 수 있는 게 아니라, 통합도 항상 원본 자료(강의록+STT+학습지 발췌)에서 직접 생성합니다 (비용 최소화 원칙 그대로 구현).src/lib/ai/summary-prompt.ts). 다만 이 앱은 대화형이 아니라 API 자동 파이프라인이라, "STT 불명확 시 솜솜에게 질문" 같은 대화형 전제만 짧은 안내문으로 보정했습니다(질문 대신 [확인필요] 태그 사용, 야첵 없음, 최종 출력은 태그 텍스트) — 프롬프트 본문 자체는 수정하지 않았습니다.study_material_mappings 페이지 범위만 잘라서(pdf-lib) 보냅니다. 한 요청에 포함되는 전체 페이지가 Claude의 PDF 100페이지 제한을 넘지 않도록 예산을 두고 넘으면 안내 문구와 함께 자릅니다.[YAMA], [TY!!], [증례] 등) 텍스트를 공통 파서(src/lib/summary/parse.ts)로 구조화한 뒤, 세 가지로 렌더링합니다: 웹 뷰어(SummaryViewer, 즉시 확인), .docx(docx 패키지, 마킹표의 색상/박스 그대로), .pdf(pdf-lib + Pretendard 폰트 임베딩, 색상은 동일하지만 박스는 배경색만 — Word보다는 단순한 스타일)./api/lecture-sessions/[id]/summary(개별 생성), /api/courses/[id]/combined-summary(통합 생성, body lectureSessionIds), /api/courses/[id]/summaries(목록), /api/summaries/[id] · /api/combined-summaries/[id](조회/삭제 — 삭제 시 Storage의 docx/pdf도 함께 정리)ANTHROPIC_API_KEY가 없으면 생성 버튼을 눌렀을 때 "Claude API 키가 설정되지 않았습니다"라는 명확한 에러를 보여줍니다 (다른 기능처럼 조용히 건너뛰지 않음 — 정리본 생성은 사용자가 명시적으로 누른 액션이라 결과가 있어야 하므로).src/lib/ai의 범용 provider 추상화(SUMMARY_PROVIDER) 대신 Anthropic SDK를 직접 호출합니다. 학습지 목차 분석도 마찬가지입니다 — 둘 다 스펙상 항상 Claude를 쓰기로 되어 있어 당장은 문제 없지만, SUMMARY_PROVIDER를 바꿔도 이 두 기능에는 반영되지 않습니다.Phase E-1 — 정리본 생성 안정화 (실사용 피드백 반영)
max_tokens 고정값(8192) 탓에 본문 중간에서 응답이 끊겨 마인드맵/출제경향/총평까지 도달하지 못함, (2) Claude가 태그 스펙과 다른 형식([H1]/[H2], "이미지:" 등)을 즉흥적으로 섞어써서 파서가 못 읽고 원문 그대로 노출됨. src/lib/ai/summary-prompt.ts(어댑터 노트만 보정, v3.6 원문은 그대로), src/lib/summary/parse.ts, src/lib/ai/generate-summary.ts에서 고쳤습니다.src/lib/summary/run-round.ts, src/lib/ai/generate-summary.ts의 generateSummaryRound). 한 라운드는 최대 35초(ROUND_WALL_CLOCK_BUDGET_MS, 토큰 수가 아니라 실제 경과 시간 기준 강제 중단)만 Claude를 돌리고, 아직 못 끝냈으면(stop_reason이 max_tokens거나 우리가 직접 abort) 지금까지 쓴 내용을 DB에 저장한 뒤 "generating" 상태로 남겨둡니다.
508 Loop Detected로 차단했습니다 — 서버가 자기 자신을 호출하는 방식 자체가 이 플랫폼에서 안 됩니다./courses/[courseId]/summary/[summaryId], .../summary/combined/[combinedId])가 status가 generating인 동안 POST /api/summary-round를 호출 → 완료를 기다림 → 최신 상태를 다시 불러옴 → 아직 안 끝났으면 반복하는 루프를 돌립니다. 라운드 하나당 최대 60초(Vercel 함수 duration)만 쓰기 때문에 이 안에서 안전하고, 전체 생성 시간에는 더 이상 상한이 없습니다(대신 총 20라운드 안전장치 有).cache_control)으로 캐싱해, 라운드마다 자료를 다시 보내는 비용을 낮췄습니다.POST /api/lecture-sessions/[id]/summary · POST /api/courses/[id]/combined-summary는 이제 status: "generating" 행만 즉시 만들고(202) 생성은 전혀 시작하지 않습니다 — 상세 페이지가 열리는 순간부터 위 브라우저 주도 루프가 라운드 1부터 시작합니다.summaries/combined_summaries에 status(pending/generating/done/error) · error_message · round(진행된 라운드 수) 컬럼 추가 (supabase/migrations/0002_summary_status.sql, 0003_summary_round.sql — SQL Editor에서 순서대로 실행 필요).Phase F — 문제풀이
/courses/[courseId]/questions: 정리본과 같은 방식으로 수업을 체크하고 한 번에 4개 카테고리(야마그대로/야마변형/티야/탈야) 문제를 전부 생성합니다.src/lib/ai/question-prompt.ts):
범위밖 표시만. 복기가 불완전하거나 정답이 의심스러우면 확인필요 + 사유를 남김 — 대화형이 아닌 자동 파이프라인이라 실시간으로 되물을 수 없어서, "먼저 물어보라"는 요청을 이 표시로 대신합니다(정리본의 [확인필요] 태그와 같은 방식).[Q]...[/Q] 태그 텍스트로 받아 파싱하고(src/lib/questions/parse.ts), 60초 함수 실행 제한 때문에 브라우저가 라운드를 하나씩 호출하는 구조(POST /api/question-round)를 그대로 씁니다. 완성되면 그제서야 파싱해서 questions 행으로 저장합니다(도중에 잘린 마지막 [Q] 블록은 버리고 다음 라운드에서 다시 요청).src/lib/ai/session-materials.ts)은 정리본(Claude)과 문제풀이(Gemini)가 공유합니다.content_json에 {stem, choices, answerIndex, explanation, sourceNote, outOfScope}. 확인필요로 표시된 문제는 기존 스키마의 review_status: "pending" + review_notes를 그대로 사용(별도 컬럼 추가 없이 처음부터 이 용도로 설계돼 있었음). 정답 파싱에 실패한 문제도 자동으로 pending 처리.POST /api/attempts)마다 attempts에 기록하고, 오답노트(/courses/[courseId]/questions/wrong)는 가장 최근 시도가 오답인 문제만 보여줍니다 — 다시 맞히면 목록에서 빠집니다./api/courses/[id]/question-batches (POST 생성/GET 목록), /api/question-batches/[id] (GET 상태/DELETE), /api/question-round (라운드 진행), /api/courses/[id]/questions (GET, ?category=), /api/courses/[id]/questions/wrong (GET), /api/attempts (POST)GEMINI_API_KEY가 없으면 생성 시 명확한 에러를 보여줍니다 (정리본과 동일한 원칙).0004_question_batches.sql — question_batches/question_batch_sessions 테이블 추가 + questions.question_batch_id 컬럼 (SQL Editor에서 0001~0004 순서대로 실행).| Phase | 내용 |
|---|---|
| G | 과외 — 채팅형 1:1, OpenAI API, 기존 과외 프롬프트 적용 |
npm install
cp .env.example .env.local # 아래 "환경변수" 참고해 값 채우기
npm run dev
http://localhost:3000 에서 확인. http://localhost:3000/api/health 로 Supabase 연결 상태 확인 가능.
supabase/migrations/ 아래 파일들을 번호 순서대로(0001_init.sql → 0002_summary_status.sql → 0003_summary_round.sql → 0004_question_batches.sql) 실행해 테이블 생성/갱신lecture-pdfstt-txtworksheet-pdfsummary-docxsummary-pdfanon key, service_role key 확인이 앱은 1인 사용을 전제로 모든 테이블에 RLS를 켜두고 공개 정책은 추가하지 않았습니다. 즉 anon key만으로는 테이블을 읽거나 쓸 수 없고, 모든 DB 접근은 Next.js 서버(API route)의 service-role 클라이언트를 통해서만 이루어집니다.
.env.example 참고. Vercel 배포 시 Project Settings → Environment Variables 에 동일하게 등록합니다.
| 변수 | 설명 |
|---|---|
NEXT_PUBLIC_SUPABASE_URL | Supabase 프로젝트 URL |
NEXT_PUBLIC_SUPABASE_ANON_KEY | Supabase anon key |
SUPABASE_SERVICE_ROLE_KEY | Supabase service role key (서버 전용, 절대 노출 금지) |
ANTHROPIC_API_KEY | Claude API key |
GEMINI_API_KEY | Gemini API key |
OPENAI_API_KEY | OpenAI API key |
SUMMARY_PROVIDER | 정리본 생성에 사용할 벤더 (claude | gemini | openai, 기본 claude) |
QUESTION_PROVIDER | 문제 생성에 사용할 벤더 (기본 gemini) |
TUTOR_PROVIDER | 과외에 사용할 벤더 (기본 openai) |
src/
app/
page.tsx # 홈 = 📚 현재 진행 중인 강의 목록 (최상위 navigation)
calendar/
page.tsx # 월 달력 (보조 View)
[date]/page.tsx # 그 날짜의 전체 강의 수업 목록
courses/[courseId]/
page.tsx # 강의 상세 (학습지/수업 기록/학습)
summary/page.tsx # 정리본 허브 (수업 선택 → 개별/통합 생성, 목록)
summary/[summaryId]/page.tsx # 개별 정리본 뷰어
summary/combined/[combinedId]/ # 통합 정리본 뷰어
questions/page.tsx # 문제풀이 허브 (수업 선택 + 생성 + 카테고리별 진입)
questions/[category]/page.tsx # 카테고리별 문제풀이
questions/wrong/page.tsx # 오답노트
tutor/page.tsx # 과외 (Phase G placeholder)
sessions/[sessionId]/page.tsx # 수업 상세 (강의록/STT, 이 수업으로 학습)
api/
health/ # Supabase 연결 확인
calendar/ # 달력용 월별 카운트 / 날짜별 수업 목록
courses/ # 강의 CRUD (GET/POST, GET/PATCH/DELETE [id])
courses/[id]/study-material/ # 학습지 조회/삭제 + init/complete 업로드
courses/[id]/lecture-sessions/ # 강의의 수업 세션 목록 (GET)
courses/[id]/combined-summary/ # 통합 정리본 생성 (POST)
courses/[id]/summaries/ # 강의의 정리본 목록 (개별+통합, GET)
study-material-mappings/ # 매핑 수동 추가/편집/삭제
lecture-sessions/ # 수업 세션 CRUD + files/init·complete 업로드 + summary(개별 생성)
summaries/, combined-summaries/ # 정리본 조회/삭제
components/
course-card.tsx # 강의 카드 (열기/편집/보관·복원/삭제 메뉴)
course-form-dialog.tsx # 강의 추가/편집 폼 모달
session-form-dialog.tsx # 수업 추가/편집 폼 모달
confirm-dialog.tsx # 보관/복원/삭제 확인 모달
coming-soon.tsx # placeholder 화면 (backHref로 강의로 돌아가기 지원)
study-material-section.tsx # 학습지 업로드/교체/삭제 + 매핑 표
mapping-row.tsx # 매핑 표 한 행(읽기/인라인 편집)
lecture-sessions-section.tsx # 수업 기록 목록(날짜별 그룹) + 수업 추가
summary-viewer.tsx # 정리본 태그를 마킹표 색상/박스로 렌더링하는 웹 뷰어
lib/
supabase/ # 브라우저/서버 Supabase 클라이언트 + upload-client(직접 업로드 헬퍼)
ai/ # provider 추상화 + 학습지 목차 분석 + v3.6 프롬프트/정리본 생성
summary/ # 태그 파서, docx/pdf 생성기, Storage 경로, 생성+업로드 orchestration
pdf-utils.ts # PDF 페이지 범위 추출 (pdf-lib)
courses.ts # Course 타입/상태
lecture-sessions.ts # LectureSession 타입/검증/파일 설정
study-materials.ts # StudyMaterial/Mapping 타입
supabase/
migrations/ # DB 스키마 (강의 중심)