ESP32-S3 Bench Guide
ESP32‑S3 N16R8 벤치 가이드: 실시간 핀아웃, 강의, 시뮬레이터 및 벤치 로그
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
🎨 SORO | 학생 연간 이벤트 공모전 포털 (Students Annual Contest Portal) 상상력을 현실로! SORO는 학생들을 위해 매달 새롭게 열리는 6대 연간 창의 공모전 및 이벤트 접수 포털입니다. 복잡한 프레임워크나 빌드 과정 없이 HTML5, Vanilla JavaScript, CSS3 로만 만들어졌고, 백엔드는 Firebase(인증·Firestore·Storage)를 씁니다. 처음에는 Google Sheets + Apps Script 로 만들었지만, 한 학급이 동시에 접속하면 로그인에 1분 넘게 걸리는 문제가 있었습니다. Apps Script 가 소유자 계정에서 요청을 하나씩 처리하기 때문이며, 코드 최적화로는 넘을 수 없는 한계였습니다(실측: 25명 동시 접속 시 최악 64초). 2026년 8월 Firebase 로 옮겼습니다.README 전문 보기 ↗
상상력을 현실로!
SORO는 학생들을 위해 매달 새롭게 열리는 6대 연간 창의 공모전 및 이벤트 접수 포털입니다.
복잡한 프레임워크나 빌드 과정 없이 HTML5, Vanilla JavaScript, CSS3 로만 만들어졌고, 백엔드는 Firebase(인증·Firestore·Storage)를 씁니다.처음에는 Google Sheets + Apps Script 로 만들었지만, 한 학급이 동시에 접속하면 로그인에 1분 넘게 걸리는 문제가 있었습니다. Apps Script 가 소유자 계정에서 요청을 하나씩 처리하기 때문이며, 코드 최적화로는 넘을 수 없는 한계였습니다(실측: 25명 동시 접속 시 최악 64초). 2026년 8월 Firebase 로 옮겼습니다.
Radial Gradient Hover)이 적용되어 있습니다.각 공모전의 접수 상태는 관리자가 직접 열고 닫습니다. 날짜로 자동 개폐하지 않는 것은 의도된 운영 방식입니다 — 자동으로 열리고 닫히면 실제 운영에서 여러 문제가 있었습니다.
| 공모전 | ID | 내용 |
|---|---|---|
| 키링 공모전 🎨 | keyring | 아크릴 키링 도안 이미지 |
| 안전 사고 예방 컷툰 📖 | cuttoon | 4컷 만화 원고 |
| 온라인 도서관 📚 | library | 책 제목·저자와 독서 엽서(캘리그라피) |
| 디지털 필사 ✍️ | transcription | 손글씨 이미지 또는 직접 타이핑 |
| 픽셀아트 👾 | pixelart | 도트 그래픽 (내장 에디터 제공) |
| 소로 사운드 앨범 🎵 | sound_album | 음원 업로드 |
| Zep quiz 🕹️ | zepquiz_1~_6 | 회차제. 잠금이 아니라 "접수 중인 회차" 하나로 관리합니다 |
젭퀴즈만 구조가 다릅니다. 다른 공모전은 contest_lock_<ID> 로 열고 닫지만, 젭퀴즈는 zepquiz_active_round 에 적힌 회차 하나만 접수를 받습니다. 전부 닫으려면 존재하지 않는 회차인 0 을 지정합니다(관리자 화면의 🔒 젭퀴즈 잠금 버튼).
?backend=sheets 를 붙이면 예전 Apps Script 백엔드로 그 탭에서만 전환됩니다. 이전 직후 문제가 생겼을 때를 대비해 남겨 둔 길이며, 평소에 쓸 일은 없습니다.migration/firestore.rules)이 직접 막습니다.| 구분 | 기술 스택 | 설명 |
|---|---|---|
| Frontend | HTML5, Vanilla JavaScript (ES6+) | 빌드/컴파일 과정 없이 브라우저에서 직접 초고속 실행되는 경량 구조 |
| Styling | Pure Vanilla CSS3 | CSS 변수(Custom Properties), Flexbox/Grid 레이아웃, 모던 트랜지션 |
| 인증 | Firebase Authentication | 학생 계정. 이메일은 학년/반/번호/이름을 해시한 @soro.local 주소를 씁니다 |
| 데이터베이스 | Cloud Firestore | 계정 프로필, 제출물, 감상 반응, 공모전 설정 |
| 파일 저장소 | Firebase Storage | 학생 작품 이미지·음원. 문서에는 주소만 저장합니다 |
| 초기화 API | Vercel Functions + Firebase Admin SDK | 학생이 직접 요청하면 즉시 비밀번호 초기화 |
| Hosting | Vercel Ready | 정적 라우팅 및 리소스 브라우저 캐싱 구조 설계 최적화 |
soro/
├── index.html # 레이아웃, 모달·드로어 마크업, Firebase 모듈 로더
├── style.css # 노이즈 텍스처, 테마, 드로어 모션
├── app.js # 화면 로직 + 공모전 데이터셋
│ # ※ 파일 뒷부분에 Apps Script 백엔드 코드가
│ # 주석으로 들어 있습니다. 고친 뒤에는 반드시
│ # script.google.com 에 붙여넣고 재배포해야
│ # 실제로 반영됩니다.
├── firebase-backend.js # Firestore·Auth·Storage 를 다루는 백엔드 (ES 모듈)
├── api/reset-password.mjs # 학생용 비밀번호 초기화 HTTP 진입점
├── server/ # Firebase 관리자 인증·초기화 처리 (서버 전용)
├── tests/ # 실제 학생 계정을 건드리지 않는 자동 검사
├── package.json # Firebase Admin SDK 의존성과 검사 명령
├── migration/ # Sheets → Firebase 이전 도구와 보안 규칙
│ ├── firestore.rules # 데이터 접근 규칙 (권한의 실제 방어선)
│ ├── storage.rules # 작품 파일 접근 규칙
│ ├── DESIGN.md # 이전 설계와 판단 근거
│ └── *.mjs # 내보내기·변환·적재·검증 스크립트
├── 작업내역.md # 모든 변경 기록. 무엇을 왜 고쳤는지 남겨 둡니다
├── vercel.json # 정적 파일 캐시·경로 설정
└── README.md # 이 문서
현재 기본 Firebase 모드의 비밀번호 초기화에서는 이 코드를 사용하지 않습니다. 아래 내용은 ?backend=sheets로 이전 시스템을 사용하는 경우에만 해당합니다.
app.js 파일 뒤쪽에 주석으로 들어 있는 Apps Script 코드는 문서용 사본입니다. 여기를 고치고 배포해도 실제 서버 동작은 그대로입니다. 반드시 구글 시트 → 확장 프로그램 → Apps Script 에 붙여넣고, 배포 → 배포 관리 → 편집(연필) → 새 버전 → 배포 를 해야 반영됩니다.
⚠️ "새 배포" 가 아니라 기존 배포의 "새 버전" 이어야 합니다. 새 배포를 만들면 주소가 바뀌어 사이트가 백엔드를 찾지 못합니다.
users/{uid} 문서의 admin 이 true(boolean) 여야 관리자로 인정됩니다. 학번을 비교하던 예전 방식은 브라우저에서 조작할 수 있어 바꿨습니다.
보안 규칙이 "본인이 자기 문서에 admin 을 붙이는 것" 을 막습니다. 학생이 스스로 관리자가 되는 걸 막는 장치인데, 선생님에게도 똑같이 적용됩니다. 그래서 처음 한 번은 Firebase 콘솔에서 직접 넣어야 합니다(Firestore → users → 해당 문서 → 필드 추가 → admin / boolean / true). 넣은 뒤 로그아웃 후 다시 로그인해야 반영됩니다 — 관리자 토큰은 로그인할 때 발급됩니다.
data에 저장됩니다관리자 화면에서 설정한 사은품 지급 상태와 심사 후보 별표는 Firestore submissions/{submissionId} 문서의 data.prizeStatus / data.isStarred에 영구 저장됩니다. 2026년 9월 4일 이전 코드가 문서 최상위에 잘못 저장한 prizeStatus / isStarred도 호환 읽기로 복원됩니다. 해당 항목을 다시 누르면 올바른 data 안으로 저장되고 잘못된 최상위 필드는 자동으로 제거됩니다.
학생이 학년/반/번호/이름을 입력하면 Vercel의 /api/reset-password가 Firebase에서 계정을 찾아 즉시 임시 비밀번호를 발급합니다. 그 비밀번호로 로그인하면 새 비밀번호를 직접 정합니다. 선생님은 학생별 요청을 승인하거나 처리할 필요가 없습니다.
_passwordResetLimits에 트랜잭션으로 기록하고, 초기화 이력은 기존 passwordResets에 남깁니다. Firestore의 기존 기본 차단 규칙을 그대로 사용합니다.학적 정보만으로 초기화하는 운영 방식은 유지됩니다. 이 정보를 아는 사람도 요청할 수 있으므로, 무작위 임시 비밀번호가 별도의 본인 인증을 대신하지는 않습니다.
soro-migration-test의 서비스 계정 JSON 키를 준비합니다. 해당 계정에는 Firebase Authentication 사용자 변경과 Firestore 읽기·쓰기 권한이 필요합니다.FIREBASE_SERVICE_ACCOUNT_JSON이라는 Secret에 JSON 전체를 넣습니다. 운영은 Production에 설정합니다. 운영 키를 시험용 다른 프로젝트에 넣지 않습니다.서비스 계정 키는 브라우저 파일·GitHub·채팅에 붙이지 않습니다. .env.example에는 변수 이름만 있으며 .env*와 서비스 계정 파일은 Git에서 제외했습니다. 키를 바꾸면 Vercel 재배포가 필요합니다.
로컬 검사는 Node.js 24에서 npm ci 후 npm test로 실행합니다. 실제 계정 초기화는 하지 않습니다. Python/Live Server 같은 정적 서버는 /api를 실행할 수 없으므로 API 동작 확인에는 Vercel 배포나 vercel dev가 필요합니다.
그림과 음원은 Firebase Storage 에 올리고, Firestore 문서에는 주소만 저장합니다. 경로는 submissions/<공모전ID>/<학생uid>/<항목>.<확장자> 로 고정되어 있어 다시 제출하면 같은 자리를 덮어씁니다.
이전 초기에는 이 단계가 빠져 base64 를 문서에 통째로 넣었고, 엽서 한 장(0.89~1.13MB)이 Firestore 문서 한도(1MiB)를 넘어 저장이 통째로 실패했습니다. 게다가 오류 문구가 "현재 접수 기간이 아닌 공모전입니다" 로 나와 학생은 원인을 알 수 없었습니다. 지금은 실패 원인을 구분해 알리고, 파일 업로드가 실패하면 저장을 진행하지 않습니다.
asset/backgrounds/)온라인 도서관의 엽서 배경입니다. 학생이 테마를 고르면 그 안에서 무작위로 한 장이 뽑히고, 그릴 때마다 색감이 다르게 입혀집니다.
새 배경을 추가할 때: 4:3 가로, 1200×900 이상. 엽서 캔버스가 800×600이라 세로 사진을 넣으면 가운데만 잘려 보입니다.
파일을 넣은 뒤 app.js 의 CALLIGRAPHY_THEMES_IMAGES 목록에 경로를 추가해야 실제로 쓰입니다.
⚠️ 파일 이름의 앞부분은 테마를 뜻하지 않습니다. 테마가 잘못 붙어 있던 사진들을 맞는 테마로 옮겼기 때문에, 예를 들어
forest목록에sky_1.jpg(잎사귀 사진)가 들어 있습니다. 이름을 바꾸면 변경 기록을 따라가기 어려워져 그대로 두었습니다.
⚠️ 목록에 없는 파일도 폴더에는 남아 있습니다. 중복이거나 테마와 무관한 사진(게임 컨트롤러, 서류가방 든 사람 등)을 목록에서만 뺐습니다. 지우지 않은 것은 나중에 판단이 바뀔 수 있어서입니다.
배경 종류: 2026년 9월 기준 하늘·숲·바다·공간·종이/추상 테마별로 30장씩, 총 150장입니다. 같은 사진이 뽑혀도 결과가 서로 달라 보이도록 그릴 때마다 색조·채도·밝기를 조금씩 바꾸고, 여섯 가지 색감 중 하나를 덧입히고, 절반은 좌우를 뒤집고, 가장자리 어둡기를 무작위로 줍니다.
index.html 의 ?v= 값을 올려야 브라우저가 새 파일을 받습니다. 관리자 화면을 열어 둔 채 배포하면 옛 코드가 계속 돌므로, 강력 새로고침(윈도우 Ctrl+Shift+R, 맥 Cmd+Shift+R)이 필요합니다.
이 저장소를 로컬 컴퓨터로 복제(Clone)하거나 다운로드한 후, 브라우저에서 직접 실행할 수 있습니다.
# 1. 저장소 클론
git clone <repository-url>
# 2. 프로젝트 폴더 진입
cd soro
# 3. 로컬 서버 실행 (또는 index.html 더블클릭)
# VS Code를 사용하신다면 'Live Server' 확장 프로그램 실행을 권장합니다.
본 프로젝트는 vercel.json 파일이 사전 최적화되어 있으므로 별도의 빌드 커맨드 설정 없이 즉시 배포할 수 있습니다.
.vercel.app 고유 주소가 생성됩니다!