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 ↗지무위키(교내 위키) 프론트엔드. 구조와 규칙은 CLAUDE.md에 있다.
Node.js 24가 필요하다 (.nvmrc, CI도 같은 버전을 쓴다).
cp .env.example .env.local # API_BASE_URL을 채운다 (아래 '어느 백엔드에 붙일까')
npm install
npm run dev # http://localhost:3000
| 명령 | 하는 일 |
|---|---|
npm run dev | 개발 서버 |
npm run build, npm start | 프로덕션 빌드와 그 결과 실행 |
npm run lint | ESLint |
npm run typecheck | 라우트 타입을 만든 뒤(next typegen) tsc --noEmit |
PR을 올리면 CI(.github/workflows/ci.yml)가 npm ci → lint → typecheck → build를 차례로 돌리고,
하나라도 실패하면 PR에 실패로 표시된다. 올리기 전에 같은 명령을 로컬에서 돌려 보면 된다.
Feature-Sliced Design을 따른다. src/ 아래 레이어는 위에서 아래로만 의존한다.
| 레이어 | 담는 것 |
|---|---|
app/ | Next.js 라우트. 페이지 파일은 views의 화면을 다시 내보내기만 한다 |
views/ | 한 화면 전체. FSD의 pages인데, src/pages는 Next가 Pages Router로 읽어서 이름을 바꿨다 |
widgets/ | 화면의 한 덩어리 (헤더, 최근 변경, 리비전 타임라인 …) |
features/ | 사용자 동작 단위 (로그인·로그아웃, 라이트/다크 전환) |
entities/ | 도메인 단위의 UI · 타입 · 조회 (문서, 세션) |
shared/ | 어디서나 쓰는 것 (라우트 상수, API 클라이언트, 공용 UI) |
슬라이스 바깥에서는 배럴(index.ts)로만 import 한다. 라우팅 · 스타일 · 컴포넌트 규칙은 CLAUDE.md에 있다.
백엔드는 wntopia/gikipedia-server이고,
호출 코드는 src/shared/api에 모여 있다.
| 환경 변수 | 설명 |
|---|---|
API_BASE_URL | 백엔드 오리진 (예: http://localhost:8080). 서버 전용 값이며 빌드 시점에 프록시 목적지로 고정된다. 비우면 http://localhost:8080으로 빌드되므로 배포 빌드에서는 반드시 넣는다 |
develop 브랜치가 배포되는 스테이지 서버다. 주소는 팀에서 받는다.http://localhost:8080(.env.example의 값)을 넣는다.
MySQL · MongoDB · Redis · SeaweedFS는 백엔드 저장소의 docker-compose.yml로 띄우고, 설정은
application.yaml.example을 참고한다. 로그인까지 쓰려면 아래 '로그인이 동작하려면'의 값을 맞춘다.API_BASE_URL을 바꾸면 개발 서버를 다시 띄운다. 프록시 목적지는 서버를 띄울 때(배포본은 빌드할 때) 고정된다.
로그인은 프론트가 백엔드의 DATAGSM_OAUTH_REDIRECT_URI와 같은 오리진에 떠 있을 때만 끝까지 된다.
지금 팀 개발 서버는 http://localhost:3000/callback으로 맞춰 두었으므로 npm run dev의 기본 포트(3000)를 바꾸지 않는다.
브라우저는 프론트 오리진의 /api/v1/**를 호출하고, next.config.ts의 rewrites가 이를
API_BASE_URL로 넘긴다. 백엔드를 직접 호출(CORS)하지 않고 프록시를 택한 이유는 다음과 같다.
실시간 공동편집 WebSocket(/ws/**)도 같은 rewrites로 백엔드에 넘긴다. 핸드셰이크에 세션 쿠키가 실리려면 같은 오리진이어야
하기 때문이다. 백엔드는 WebSocket의 Origin을 검사하므로 프론트 오리진을 백엔드의 spring.security.cors.allowed-origins에
넣어야 한다 (빠지면 핸드셰이크가 403이고, 편집 화면은 '연결 끊김'에서 다시 연결만 시도한다).
호출 함수는 실행 위치와 쓰임에 따라 셋으로 나뉜다.
| 함수 | import | 용도 |
|---|---|---|
apiFetch | @/shared/api | 브라우저(프록시 경유, 쿠키 포함), 그리고 서버에서 로그인과 무관한 조회 |
serverApiFetch | @/shared/api/server | 서버 컴포넌트에서 현재 사용자로서 호출 (요청 쿠키를 옮겨 싣는다) |
publicServerApiFetch | @/shared/api/server | 서버 컴포넌트에서 로그인과 무관한 공개 데이터를 요청마다 새로 조회 (쿠키를 싣지 않고, 빌드 때는 부르지 않는다) |
서버 컴포넌트에서 apiFetch를 그대로 부르면 정적인 화면은 빌드 때 한 번 조회한 값으로 굳는다. 홈의 최근 변경처럼
바로 반영되어야 하는 값은 publicServerApiFetch로 부른다.
셋 다 the-sdk의 응답 봉투({ status, code, message, data })를 벗겨 data만 돌려주고,
2xx가 아니면 HTTP 상태를 담은 ApiError를 던진다. isApiError(error, 404)처럼 갈라 쓴다.
로그인은 fetch가 아니라 페이지 이동이다. 브라우저가 /api/v1/oauth/datagsm/signin(프록시)으로
이동하면 백엔드가 DataGSM으로 보내고, DataGSM은 로그인이 끝나면 redirect_uri로 돌려보낸다. 세션 쿠키가
프론트 도메인에 있으므로 redirect_uri도 프론트 오리진이어야 한다. 프론트는 /callback으로 돌아온
요청을 code·state째로 백엔드 callback에 넘긴다 (next.config.ts). 백엔드 도메인으로 돌려보내면
쿠키가 따라가지 않아 OAuth state가 올바르지 않습니다로 실패한다.
| 백엔드 환경 변수 | 값 |
|---|---|
DATAGSM_OAUTH_REDIRECT_URI | <프론트 오리진>/callback — DataGSM 클라이언트에도 등록. 글자 하나까지 같아야 통과한다 |
DATAGSM_OAUTH_SCOPE | 비워 두거나 datagsm:self_read |
DATAGSM_OAUTH_SUCCESS_REDIRECT_URI | /signin/callback |
DATAGSM_OAUTH_FAILURE_REDIRECT_URI | /signin?error (기본값 그대로) |
성공·실패 주소는 상대 경로라 브라우저가 프론트 오리진 기준으로 해석한다. 로그인 전에 보던 화면은
백엔드가 기억해 주지 않으므로 프론트가 sessionStorage에 맡겨 두었다가 /signin/callback에서 꺼내 이동한다.
[영역] 내용이다 — 영역은 바뀌는 화면이나 슬라이스 이름
(document, history, edit, search, auth …), 여러 곳에 걸치면 global, CI는 ci/cd.type(scope): 설명이다. type은 add · update · fix · refactor · docs 등이고 설명은 한국어로 쓴다.Closes #번호를 넣는다. PR을 처음 열면 Claude가 diff를 리뷰해
코멘트를 남긴다(.github/workflows/claude-code-review.yml). 다시 리뷰받으려면 PR에 /claude-review 댓글을 단다.