docs: add README and technical analysis report
- README.md: project overview, quick start, usage guide, API reference, directory structure, environment variables, security notes - report.html: comprehensive Korean technical report covering architecture, tech stack, feature analysis, API spec, data flow, security, deployment, and roadmap Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
203
README.md
203
README.md
@@ -0,0 +1,203 @@
|
||||
# ESP32 Web Flasher
|
||||
|
||||
브라우저에서 ESP32 계열 마이컴에 펌웨어를 플래시하는 Docker 기반 웹 애플리케이션입니다.
|
||||
별도 소프트웨어 설치 없이 Chrome/Edge 브라우저와 USB 케이블만으로 펌웨어를 구워 넣을 수 있습니다.
|
||||
|
||||
## 주요 특징
|
||||
|
||||
- **Web Serial API** — 드라이버·CLI 도구 없이 브라우저 직접 시리얼 통신
|
||||
- **esp-web-tools v10** (Espressif 공식) — 안정적인 웹 컴포넌트 기반 플래싱
|
||||
- **다중 바이너리 지원** — bootloader / partition table / application 개별 또는 병합 바이너리
|
||||
- **펌웨어 관리** — 업로드·목록·삭제, UUID 기반 REST API
|
||||
- **실시간 로그** — 색상 구분 시리얼 모니터 내장
|
||||
- **Docker Compose** — 단일 명령으로 백엔드(Node.js) + 프론트엔드(Nginx) 기동
|
||||
|
||||
## 지원 칩
|
||||
|
||||
| 칩 패밀리 | 지원 여부 |
|
||||
|----------|---------|
|
||||
| ESP32-S3 | ✓ 권장 (내장 USB-OTG 지원) |
|
||||
| ESP32-S2 | ✓ |
|
||||
| ESP32-C3 | ✓ |
|
||||
| ESP32 | ✓ |
|
||||
|
||||
## 브라우저 호환성
|
||||
|
||||
| 브라우저 | 지원 |
|
||||
|--------|------|
|
||||
| Chrome 89+ | ✓ |
|
||||
| Edge 89+ | ✓ |
|
||||
| Firefox | ✗ (Web Serial 미지원) |
|
||||
| Safari | ✗ (Web Serial 미지원) |
|
||||
|
||||
> **참고:** HTTP(localhost 제외)에서는 Web Serial API가 동작하지 않습니다. 외부 배포 시 HTTPS가 필수입니다.
|
||||
|
||||
## 빠른 시작
|
||||
|
||||
### 사전 요구사항
|
||||
|
||||
- Docker Engine 20.10+
|
||||
- Docker Compose v2+
|
||||
- Chrome 89+ 또는 Edge 89+
|
||||
|
||||
### 실행
|
||||
|
||||
```bash
|
||||
git clone https://gitea.byunc.com/byun/webflash.git
|
||||
cd webflash
|
||||
docker compose up -d --build
|
||||
```
|
||||
|
||||
브라우저에서 `http://localhost:3100` 접속
|
||||
|
||||
### 중지
|
||||
|
||||
```bash
|
||||
docker compose down
|
||||
```
|
||||
|
||||
펌웨어 데이터까지 삭제하려면:
|
||||
|
||||
```bash
|
||||
docker compose down -v
|
||||
```
|
||||
|
||||
## 사용 방법
|
||||
|
||||
### 1단계 — 시리얼 연결 확인
|
||||
|
||||
1. ESP32를 USB 케이블로 PC에 연결
|
||||
2. **포트 연결** 버튼 클릭 → 브라우저 포트 선택 대화상자에서 포트 선택
|
||||
3. VID/PID가 표시되고 Espressif(0x303A) 장치 여부 확인
|
||||
|
||||
### 2단계 — 펌웨어 업로드
|
||||
|
||||
**펌웨어 업로드** 탭에서:
|
||||
|
||||
- 이름, 버전, 칩 패밀리 입력
|
||||
- `.bin` 파일 드래그&드롭 또는 클릭하여 선택
|
||||
- 병합 바이너리(merged.bin): 펌웨어 하나만 업로드
|
||||
- 분리 파일: bootloader(0x0000) + partitions(0x8000) + app(0x10000)
|
||||
- **서버에 업로드** 클릭
|
||||
|
||||
### 3단계 — 플래시
|
||||
|
||||
**플래시** 탭에서:
|
||||
|
||||
1. 목록에서 펌웨어 선택
|
||||
2. **ESP32S3 플래시 실행** 버튼 클릭
|
||||
3. esp-web-tools 대화상자에서 포트 선택 후 플래시 진행
|
||||
|
||||
## 플래시 파일 준비
|
||||
|
||||
### Arduino IDE에서 내보내기
|
||||
|
||||
```
|
||||
Sketch → Export Compiled Binary
|
||||
→ 스케치 폴더에 .bin 파일 생성
|
||||
```
|
||||
|
||||
### 병합 바이너리 생성 (권장)
|
||||
|
||||
```bash
|
||||
esptool.py --chip esp32s3 merge_bin \
|
||||
-o merged.bin \
|
||||
0x0 bootloader.bin \
|
||||
0x8000 partitions.bin \
|
||||
0x10000 app.bin
|
||||
```
|
||||
|
||||
### PlatformIO 사용 시
|
||||
|
||||
```bash
|
||||
pio run # 개별 바이너리 빌드
|
||||
pio run --target mergebin # 병합 바이너리 생성
|
||||
```
|
||||
|
||||
## 프로젝트 구조
|
||||
|
||||
```
|
||||
webflash/
|
||||
├── backend/
|
||||
│ ├── Dockerfile # Node.js 20 Alpine 이미지
|
||||
│ ├── package.json
|
||||
│ └── server.js # Express REST API 서버
|
||||
├── frontend/
|
||||
│ ├── Dockerfile # Nginx Alpine 이미지
|
||||
│ ├── nginx.conf # 리버스 프록시 설정
|
||||
│ ├── index.html # 단일 페이지 앱 (한국어 UI)
|
||||
│ ├── css/style.css # 다크 테마 스타일
|
||||
│ └── js/app.js # Web Serial API 로직
|
||||
└── docker-compose.yml
|
||||
```
|
||||
|
||||
## REST API
|
||||
|
||||
| 메서드 | 경로 | 설명 |
|
||||
|--------|------|------|
|
||||
| `GET` | `/api/health` | 헬스 체크 |
|
||||
| `GET` | `/api/firmware` | 펌웨어 목록 조회 |
|
||||
| `POST` | `/api/firmware/upload` | 펌웨어 업로드 |
|
||||
| `GET` | `/api/firmware/:id/manifest` | esp-web-tools 매니페스트 생성 |
|
||||
| `DELETE` | `/api/firmware/:id` | 펌웨어 삭제 |
|
||||
| `GET` | `/firmware/files/:filename` | 바이너리 파일 서빙 |
|
||||
|
||||
### 업로드 요청 예시
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:3100/api/firmware/upload \
|
||||
-F "name=My Firmware" \
|
||||
-F "version=1.0.0" \
|
||||
-F "chipFamily=ESP32-S3" \
|
||||
-F "firmware=@app.bin" \
|
||||
-F "bootloader=@bootloader.bin" \
|
||||
-F "partitions=@partitions.bin"
|
||||
```
|
||||
|
||||
### 매니페스트 응답 예시
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "My Firmware",
|
||||
"version": "1.0.0",
|
||||
"new_install_prompt_erase": true,
|
||||
"builds": [{
|
||||
"chipFamily": "ESP32-S3",
|
||||
"parts": [
|
||||
{ "path": "/firmware/files/xxxx-bootloader.bin", "offset": 0 },
|
||||
{ "path": "/firmware/files/xxxx-partitions.bin", "offset": 32768 },
|
||||
{ "path": "/firmware/files/xxxx-app.bin", "offset": 65536 }
|
||||
]
|
||||
}]
|
||||
}
|
||||
```
|
||||
|
||||
## 환경 변수
|
||||
|
||||
| 변수 | 기본값 | 설명 |
|
||||
|------|--------|------|
|
||||
| `PORT` | `3000` | 백엔드 포트 |
|
||||
| `NODE_ENV` | `production` | 실행 환경 |
|
||||
| `ALLOWED_ORIGIN` | `*` | CORS 허용 오리진 |
|
||||
|
||||
## 기술 스택
|
||||
|
||||
| 영역 | 기술 |
|
||||
|------|------|
|
||||
| 백엔드 | Node.js 20, Express 4, Multer, UUID |
|
||||
| 프론트엔드 | Vanilla JS, HTML5, CSS3 |
|
||||
| 웹 서버 | Nginx Alpine (리버스 프록시) |
|
||||
| 플래싱 | esp-web-tools v10, Web Serial API |
|
||||
| 컨테이너 | Docker, Docker Compose |
|
||||
| 저장소 | 파일 시스템 + JSON 메타데이터 |
|
||||
|
||||
## 보안 고려사항
|
||||
|
||||
- 파일 업로드는 `.bin` 확장자 및 8 MB 크기 제한
|
||||
- XSS 방지를 위한 HTML 이스케이프 처리
|
||||
- 외부 배포 시 HTTPS 적용 필수
|
||||
- ESP32 Flash Encryption 활성화 권장 (펌웨어 덤프 방지)
|
||||
|
||||
## 라이선스
|
||||
|
||||
MIT
|
||||
|
||||
Reference in New Issue
Block a user