8.0 KiB
8.0 KiB
id, title, category, status, source_trust_level, verification_status, created_at, updated_at, tags, tech_stack, applied_in, aliases
| id | title | category | status | source_trust_level | verification_status | created_at | updated_at | tags | tech_stack | applied_in | aliases | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| web-webtransport-hid-usb | WebTransport / WebHID / WebUSB / WebSerial | Coding | draft | B | conceptual | 2026-05-09 | 2026-05-09 |
|
|
|
WebTransport / WebHID / WebUSB
Browser 가 native-like 영역. WebTransport (HTTP/3 stream), WebHID (game controller, MIDI), WebUSB (firmware flash), WebSerial (Arduino).
📖 핵심 개념
- WebTransport: WebSocket 보다 빠름 (HTTP/3, UDP).
- WebHID: human interface device.
- WebUSB: 임의 USB.
- WebSerial: serial port.
💻 코드 패턴
WebTransport
const transport = new WebTransport('https://server.example.com/wt');
await transport.ready;
// Bidirectional stream
const stream = await transport.createBidirectionalStream();
const writer = stream.writable.getWriter();
await writer.write(new TextEncoder().encode('hello'));
await writer.close();
const reader = stream.readable.getReader();
const { value } = await reader.read();
console.log(new TextDecoder().decode(value));
→ HTTP/3 + QUIC. Multiple stream 가 1 connection.
Datagram (unreliable, fast)
const writer = transport.datagrams.writable.getWriter();
await writer.write(new Uint8Array([1, 2, 3]));
const reader = transport.datagrams.readable.getReader();
const { value } = await reader.read();
→ UDP-like. Game / WebRTC alternative.
WebTransport server (Node)
// 일부 server library 만 지원
import { Http3Server } from '@fails-components/webtransport';
const server = new Http3Server({ port: 4433, host: '0.0.0.0' });
server.startServer();
const sessions = await server.sessionStream('/wt');
for await (const session of sessions) {
// ... handle
}
→ HTTP/3 stack 필요. Bun / Node 가 부분 지원.
WebHID (game controller)
const devices = await navigator.hid.requestDevice({
filters: [{ vendorId: 0x054c }], // Sony
});
const device = devices[0];
await device.open();
device.addEventListener('inputreport', (e) => {
const { data, reportId } = e;
// Parse report (game controller state)
});
MIDI controller
const access = await navigator.requestMIDIAccess();
for (const input of access.inputs.values()) {
input.onmidimessage = (e) => {
const [status, note, velocity] = e.data;
// Note on, note off, ...
};
}
WebUSB (firmware update)
const device = await navigator.usb.requestDevice({
filters: [{ vendorId: 0x2341 }], // Arduino
});
await device.open();
await device.selectConfiguration(1);
await device.claimInterface(0);
// Send
await device.transferOut(1, new TextEncoder().encode('hello'));
// Receive
const r = await device.transferIn(2, 64);
console.log(new Uint8Array(r.data!.buffer));
→ Sketch upload, firmware flash.
WebSerial (Arduino, ESP32)
const port = await navigator.serial.requestPort();
await port.open({ baudRate: 9600 });
const writer = port.writable!.getWriter();
await writer.write(new TextEncoder().encode('led on\n'));
const reader = port.readable!.getReader();
while (true) {
const { value, done } = await reader.read();
if (done) break;
console.log(new TextDecoder().decode(value));
}
Web Bluetooth
const device = await navigator.bluetooth.requestDevice({
filters: [{ services: ['heart_rate'] }],
});
const server = await device.gatt!.connect();
const service = await server.getPrimaryService('heart_rate');
const char = await service.getCharacteristic('heart_rate_measurement');
await char.startNotifications();
char.addEventListener('characteristicvaluechanged', (e) => {
const value = (e.target as any).value;
console.log('heart rate:', value.getUint8(1));
});
Web NFC (Android)
if ('NDEFReader' in window) {
const ndef = new NDEFReader();
await ndef.scan();
ndef.onreading = ({ message }) => {
for (const r of message.records) {
console.log(r.recordType, r.data);
}
};
}
→ Android Chrome 만.
Permission
모든 = user gesture (click) 필수.
사용자 가 device picker 에서 grant.
HTTPS 만.
Use case
WebTransport: WebSocket 의 modern, low-latency game / streaming.
WebHID: Game controller, MIDI, custom HID.
WebUSB: Hardware programmer, firmware tool.
WebSerial: Arduino IDE in browser, debugging.
Web Bluetooth: IoT, fitness tracker.
Web NFC: Tag reader, payment (Android).
Browser support
WebTransport: Chrome 97+, FF / Safari 가 부분.
WebHID: Chrome 89+, Edge.
WebUSB: Chrome 61+. FF / Safari 가 안 (security 우려).
WebSerial: Chrome 89+.
Web Bluetooth: Chrome 56+.
Web NFC: Chrome Android 81+.
→ 대부분 Chrome / Edge / Opera 만.
Permission Policy
<!-- iframe 가 사용 -->
<iframe allow="hid; usb; serial; bluetooth"></iframe>
Reconnect
// USB
navigator.usb.addEventListener('connect', (e) => {
// device 가 다시 connected
});
navigator.usb.addEventListener('disconnect', (e) => {});
// 같은 device 가 자동 reconnect 안 됨 — 사용자 picker 다시.
Persistent permission
// 이전 grant 된 device list
const devices = await navigator.hid.getDevices();
for (const d of devices) {
if (!d.opened) await d.open();
}
→ User 가 picker 안 다시 — handle 가 영구.
함정
- Chrome 만 = userbase 한계.
- HID parsing 어려움 (binary).
- Connection drop 자주.
- Sandbox 안에서만 (system file system 안 됨).
- HTTPS only.
Native vs Web
Web:
- Distribution easy
- 자동 update
- 작은 surface (특정 device 만)
Native:
- 큰 권한
- Performance
- 모든 device
→ 작은 use case = Web. 큰 = Native.
WebGPU (powerful)
const adapter = await navigator.gpu.requestAdapter();
const device = await adapter!.requestDevice();
// ... shader, pipeline, render
→ GPU 사용. ML / 3D.
File over USB (e.g. ADB)
// Chrome OS 의 Android device debug
const device = await navigator.usb.requestDevice({
filters: [{ classCode: 0xff, subclassCode: 0x42 }], // ADB
});
→ Chrome OS 의 Android Studio web 같은 것.
Audio / video device
// MediaDevices API (다름)
const stream = await navigator.mediaDevices.getUserMedia({
audio: { deviceId: '...' },
video: { deviceId: '...' },
});
→ Camera, microphone, screen share.
WebRTC vs WebTransport
WebRTC:
- Peer-to-peer
- DTLS + SRTP
- 복잡 setup (signaling, ICE)
WebTransport:
- Client-server
- HTTP/3 + QUIC
- Simple
→ Game / streaming = WebTransport. Conferencing = WebRTC.
Browser WASM 가 native-like
+ 위 device API
+ WebGPU (GPU)
+ WASM (CPU)
+ File System Access (file)
+ Service Worker (background)
+ Push API (notification)
+ Periodic Sync
→ "Web 가 Win32 / macOS API 와 비슷" 가 modern.
Production 사용
- StackBlitz / WebContainer — Node in browser
- Figma — file, hardware (palette device)
- Photopea — Photoshop in browser
- VS Code Web — File system + ext
- Adafruit — Arduino in browser (WebSerial + WebUSB)
🤔 의사결정 기준
| 작업 | 추천 |
|---|---|
| Low-latency game/stream | WebTransport |
| Game controller / MIDI | WebHID |
| Firmware flash | WebUSB |
| Arduino REPL | WebSerial |
| IoT 통신 | Web Bluetooth |
| NFC tag | Web NFC (Android) |
| Cross-browser 필요 | WebSocket / Bluetooth fallback X |
| GPU compute | WebGPU |
❌ 안티패턴
- 모든 browser 가정: Chrome 만 흔함.
- User gesture 없이: error.
- HTTPS 안: blocked.
- HID report parse 무기준: binary 잘못.
- Disconnect handling 없음: hang.
- Persistent permission 무시: 매번 picker.
- WebTransport server 없이: fail.
🤖 LLM 활용 힌트
- WebTransport = HTTP/3 stream + datagram (WebSocket 의 모던).
- WebHID / WebUSB / WebSerial = Chrome 만.
- User gesture + HTTPS 의무.
- Native vs Web — 작은 use case.