Web API
웹 API
브라우저가 제공하는 JavaScript 인터페이스. DOM, Fetch, Canvas, Web Storage API 등 웹 애플리케이션 개발에 필수적인 기능 제공.
웹 API
브라우저가 제공하는 JavaScript 인터페이스. DOM, Fetch, Canvas, Web Storage API 등 웹 애플리케이션 개발에 필수적인 기능 제공.
Web API(웹 API)는 웹 브라우저가 JavaScript에 제공하는 내장 인터페이스입니다. HTML 문서 조작, 네트워크 요청, 그래픽 렌더링, 로컬 저장소 접근 등 웹 애플리케이션 개발에 필요한 다양한 기능을 제공합니다. ECMAScript(JavaScript 언어 명세)와 별개로, W3C와 WHATWG가 표준화를 담당합니다.
대표적인 Web API로는 DOM API(문서 객체 모델 조작), Fetch API(HTTP 요청), Canvas API(2D/WebGL 그래픽), Web Storage API(localStorage/sessionStorage), Geolocation API(위치 정보), Web Audio API(오디오 처리), Intersection Observer API(요소 가시성 감지) 등이 있습니다. 2025년 기준 100개 이상의 Web API가 표준화되어 있습니다.
Web API와 REST API의 구분이 중요합니다. Web API는 브라우저가 제공하는 클라이언트 측 인터페이스이고, REST API는 HTTP 프로토콜 기반의 서버-클라이언트 통신 규약입니다. 면접에서 "Web API"를 물으면 보통 브라우저 API를 의미하지만, 문맥에 따라 "웹 서비스 API(REST/GraphQL)"를 의미할 수도 있으니 확인이 필요합니다.
실무 활용: localStorage로 사용자 설정 저장, Fetch API로 백엔드와 통신, Intersection Observer로 무한 스크롤/레이지 로딩 구현, Notification API로 푸시 알림, Clipboard API로 복사/붙여넣기 등이 일상적으로 사용됩니다. React/Vue 등 프레임워크도 내부적으로 Web API를 활용합니다.
// Fetch API - HTTP 요청을 위한 모던 인터페이스
// XMLHttpRequest를 대체, Promise 기반
// 1. GET 요청 (데이터 조회)
async function fetchUsers() {
try {
const response = await fetch('https://api.example.com/users', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer your-token'
}
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const users = await response.json();
console.log(users);
return users;
} catch (error) {
console.error('Fetch 실패:', error);
}
}
// 2. POST 요청 (데이터 생성)
async function createUser(userData) {
const response = await fetch('https://api.example.com/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(userData)
});
return response.json();
}
// 3. AbortController로 요청 취소 (타임아웃 구현)
async function fetchWithTimeout(url, timeout = 5000) {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), timeout);
try {
const response = await fetch(url, {
signal: controller.signal
});
clearTimeout(timeoutId);
return response.json();
} catch (error) {
if (error.name === 'AbortError') {
console.log('요청 시간 초과');
}
throw error;
}
}
// Web Storage API - 브라우저에 데이터 저장
// localStorage: 영구 저장 (브라우저 종료해도 유지)
// sessionStorage: 세션 동안만 유지
// 1. 기본 사용법
localStorage.setItem('username', 'kaitrust');
const username = localStorage.getItem('username'); // 'kaitrust'
localStorage.removeItem('username');
localStorage.clear(); // 전체 삭제
// 2. 객체 저장 (JSON 변환 필수)
const userSettings = {
theme: 'dark',
language: 'ko',
notifications: true
};
// 저장
localStorage.setItem('settings', JSON.stringify(userSettings));
// 불러오기
const savedSettings = JSON.parse(localStorage.getItem('settings'));
console.log(savedSettings.theme); // 'dark'
// 3. 실무 패턴: 유틸리티 함수
const storage = {
set(key, value, expiresInDays = null) {
const item = {
value,
timestamp: Date.now(),
expires: expiresInDays
? Date.now() + (expiresInDays * 24 * 60 * 60 * 1000)
: null
};
localStorage.setItem(key, JSON.stringify(item));
},
get(key) {
const itemStr = localStorage.getItem(key);
if (!itemStr) return null;
const item = JSON.parse(itemStr);
// 만료 확인
if (item.expires && Date.now() > item.expires) {
localStorage.removeItem(key);
return null;
}
return item.value;
}
};
// 사용 예: 7일 후 만료되는 토큰 저장
storage.set('authToken', 'abc123', 7);
const token = storage.get('authToken');
// Intersection Observer API - 요소 가시성 감지
// 무한 스크롤, 레이지 로딩, 애니메이션 트리거에 활용
// 1. 무한 스크롤 구현
const infiniteScrollObserver = new IntersectionObserver(
(entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
// 마지막 요소가 보이면 다음 데이터 로드
loadMoreData();
}
});
},
{
root: null, // viewport 기준
rootMargin: '100px', // 100px 전에 미리 로드
threshold: 0 // 조금이라도 보이면 트리거
}
);
// 마지막 아이템 관찰
const sentinel = document.querySelector('#load-more-trigger');
infiniteScrollObserver.observe(sentinel);
// 2. 이미지 레이지 로딩
const lazyImageObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src; // data-src -> src
img.classList.add('loaded');
lazyImageObserver.unobserve(img); // 로드 후 관찰 중지
}
});
});
// 모든 lazy 이미지에 적용
document.querySelectorAll('img[data-src]').forEach(img => {
lazyImageObserver.observe(img);
});
// 3. 스크롤 애니메이션 (요소가 보일 때 페이드인)
const fadeInObserver = new IntersectionObserver(
(entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add('visible');
}
});
},
{ threshold: 0.1 } // 10% 보이면 트리거
);
document.querySelectorAll('.fade-in-element').forEach(el => {
fadeInObserver.observe(el);
});
"무한 스크롤은 scroll 이벤트 대신 Intersection Observer API로 구현하는 게 좋겠습니다. 스크롤 이벤트는 성능 이슈가 있고, Intersection Observer는 브라우저가 최적화해서 처리하니까요. 이미지 레이지 로딩도 같이 적용하면 초기 로딩 시간 50% 이상 줄일 수 있어요."
"Web API와 REST API는 다른 개념입니다. Web API는 브라우저가 제공하는 JavaScript 인터페이스로, DOM API나 Fetch API 같은 것들이고요. REST API는 HTTP 기반의 서버 통신 규약입니다. 실무에서는 Fetch API(Web API)를 사용해서 REST API 서버와 통신하는 식으로, 둘 다 함께 사용합니다."
"localStorage에 민감한 정보 저장하면 XSS 공격에 취약해요. 토큰은 httpOnly 쿠키에 저장하고, localStorage는 테마 설정이나 장바구니처럼 노출되어도 괜찮은 데이터만 넣는 게 좋습니다. 그리고 JSON.parse 할 때 try-catch로 감싸주세요."
모든 Web API가 모든 브라우저에서 지원되지 않습니다. Can I Use(caniuse.com)에서 확인하고, 필요시 폴리필(polyfill) 적용. 특히 Safari/iOS는 지원이 늦는 경우가 많습니다.
Geolocation, Notification, Clipboard API 등은 사용자 클릭/터치 이벤트 내에서만 권한 요청 가능. 페이지 로드 시 자동으로 요청하면 차단됩니다. 먼저 UI로 안내 후 버튼 클릭 시 요청하세요.
core-js 전체를 import하면 번들 크기가 급증합니다. @babel/preset-env의 useBuiltIns: 'usage' 옵션으로 필요한 폴리필만 포함하세요. 또는 최신 브라우저만 지원하면 폴리필 없이 진행.
feature detection 패턴 사용: if ('IntersectionObserver' in window) { ... }. 지원하지 않는 브라우저에서는 대체 구현(fallback) 제공. MDN 문서에서 브라우저 호환성 표를 꼭 확인하세요.