브라우저는 이미 슈퍼컴퓨터다. 그냥 물어보기만 하면 된다.
Source: Dev.to
개발자들은 빌드 도구를 설정하고, 의존성을 감사하며, 번들 크기를 논의하는 데 시간을 보낸다—그 결과 브라우저 안에 이미 존재하고, 완전히 구축되어 있으며, 완전 무료이고 바로 사용할 수 있는 기능들을 배포하게 된다. npm install 필요 없음. CDN에서 가져올 필요 없음. 제3자 신뢰도 필요 없음.
아래는 그 중 10가지 기능이다. 각각은 프로덕션에 바로 사용할 수 있고, 널리 지원되며, 오늘날 여러분이 찾고 있는 라이브러리를 대체할 만큼 강력하다.
1. Fetch + Streams API
fetch는 HTTP 요청을 위한 표준입니다. Streams API와 결합하면 데이터가 도착하는 즉시 처리할 수 있습니다—바로 AI 토큰 스트리밍이 작동하는 방식입니다.
const res = await fetch('/api/data');
const reader = res.body.getReader();
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader.read();
if (done) break;
console.log(decoder.decode(value, { stream: true }));
}
2. Web Workers
JavaScript는 단일 스레드에서 실행됩니다. Web Workers는 두 번째 스레드를 제공하여 무거운 작업(파싱, 암호화, 데이터 처리)이 UI를 멈추게 하지 않고 백그라운드에서 실행될 수 있게 합니다.
// Worker code must live in its own scope — use a Blob URL to inline it
const code = `
self.onmessage = ({ data }) => {
const result = data.map(n => n * 2);
self.postMessage(result);
};
`;
const blob = new Blob([code], { type: 'application/javascript' });
const worker = new Worker(URL.createObjectURL(blob));
worker.postMessage([1, 2, 3, 4, 5]);
worker.onmessage = e => console.log('Done:', e.data); // [2, 4, 6, 8, 10]
3. IntersectionObserver
요소가 뷰포트에 들어가거나 나갈 때 콜백을 실행합니다. 지연 로딩 및 스크롤 애니메이션을 처리하는 올바른 방법—스크롤 이벤트 리스너가 필요 없습니다.
const observer = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add('visible');
observer.unobserve(entry.target);
}
});
}, { threshold: 0.2 });
document.querySelectorAll('.card').forEach(el => observer.observe(el));
4. IndexedDB
브라우저에서 완전한 비동기 데이터베이스입니다. 구조화된 데이터, 블롭, 파일을 저장하며, localStorage가 제공할 수 있는 범위를 훨씬 넘어섭니다.
const request = indexedDB.open('AppDB', 1);
request.onupgradeneeded = e => {
e.target.result.createObjectStore('notes', { autoIncrement: true });
};
request.onsuccess = e => {
const db = e.target.result;
const tx = db.transaction('notes', 'readwrite');
tx.objectStore('notes').add({ text: 'Hello', date: Date.now() });
};
5. WebSocket
브라우저와 서버 사이의 지속적인 양방향 연결. 양쪽 모두 언제든지 메시지를 보낼 수 있어 채팅, 실시간 대시보드, 멀티플레이어 게임에 최적입니다.
const ws = new WebSocket('wss://your-server.com/socket');
ws.onopen = () => ws.send(JSON.stringify({ type: 'hello' }));
ws.onmessage = e => console.log(JSON.parse(e.data));
ws.onclose = () => console.log('Disconnected');
6. 파일 시스템 액세스 API
사용자의 디스크에 실제 파일을 읽고 쓸 수 있습니다(허가 필요). 브라우저에서 완전히 실행되는 데스크톱급 편집기와 도구를 가능하게 합니다.
async function openAndSave() {
const [handle] = await window.showOpenFilePicker();
const file = await handle.getFile();
const text = await file.text();
const edited = text + '\n// edited';
const writable = await handle.createWritable();
await writable.write(edited);
await writable.close();
}
// Call the function, e.g. on a button click
// openAndSave();
7. Canvas & OffscreenCanvas
Canvas는 픽셀 단위의 그리기를 제공합니다. OffscreenCanvas는 렌더링을 Worker로 이동시켜 그래픽이 메인 스레드와 경쟁하지 않도록 합니다.
const ctx = document.getElementById('c').getContext('2d');
function draw(t) {
ctx.clearRect(0, 0, 400, 200);
ctx.fillStyle = '#c8f542';
ctx.beginPath();
ctx.arc(200 + Math.sin(t / 500) * 150, 100, 20, 0, Math.PI * 2);
ctx.fill();
requestAnimationFrame(draw);
}
requestAnimationFrame(draw);
8. MediaDevices & MediaRecorder
카메라, 마이크, 혹은 화면에 접근하여 들어오는 모든 것을 녹화합니다—서드파티 SDK가 필요 없습니다.
const audio = document.getElementById('playback');
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
const recorder = new MediaRecorder(stream);
const chunks = [];
recorder.ondataavailable = e => chunks.push(e.data);
recorder.onstop = () => {
const blob = new Blob(chunks, { type: 'audio/webm' });
audio.src = URL.createObjectURL(blob);
};
recorder.start();
setTimeout(() => recorder.stop(), 5000); // record for 5 seconds
9. requestAnimationFrame + Performance API
requestAnimationFrame은(는) 코드와 화면 재생 빈도를 동기화합니다. Performance API는 서브밀리초 정밀도로 경과 시간을 측정합니다. 이 둘을 함께 사용하면 부드럽고 정확한 애니메이션을 구현할 수 있습니다.
const canvas = document.getElementById('c');
const ctx = canvas.getContext('2d');
let x = 0;
let last = 0;
function loop(timestamp) {
const delta = timestamp - last;
last = timestamp;
ctx.clearRect(0, 0, canvas.width, canvas.height);
x = (x + 200 * (delta / 1000)) % canvas.width;
ctx.beginPath();
ctx.arc(x, canvas.height / 2, 16, 0, Math.PI * 2);
ctx.fillStyle = '#c8f542';
ctx.fill();
requestAnimationFrame(loop);
}
requestAnimationFrame(loop);
10. BroadcastChannel
같은 출처의 탭, 창, 워커가 즉시 통신할 수 있게 합니다. 인증 상태를 동기화하고, 캐시 업데이트를 공유하거나, 여러 열린 탭에서 UI를 조정할 수 있습니다—서버가 필요 없습니다.
const channel = new BroadcastChannel('app');
// Send from any tab
channel.postMessage({ type: 'logout' });
// Receive in every other tab
channel.onmessage = ({ data }) => {
if (data.type === 'logout') redirectToLogin();
};
요점
이러한 API는 npm이 필요하지 않으며, 번들에 추가하거나 서드파티 코드에 의존하지 않습니다. 이들은 모든 최신 브라우저에 내장되어 수년간 존재해 왔으므로, 더 빠르게 배포하고, 번들을 작게 유지하며, 앱을 완전히 제어할 수 있습니다.
라이브러리를 사용하기 전에, 플랫폼에 이미 필요한 것이 있는지 확인해 보는 것이 좋습니다. 대부분의 경우, 이미 존재합니다.
오늘 뭔가 유익한 것을 배웠나요?
— Muhammad Usman
개발자의 여정 – 지원해 주세요.