본 콘텐츠의 이미지 및 내용은 AI로 생성되었습니다.
본 콘텐츠의 이미지 및 내용을 무단으로 복제, 배포, 수정하여 사용할 경우 저작권법에 의해 법적 제재를 받을 수 있습니다.
이미지 로딩 중...
AI Generated
2025. 11. 4. · 20 Views
PWA 베스트 프랙티스 완벽 가이드
프로그레시브 웹 앱(PWA)의 핵심 기능과 최적화 기법을 다룹니다. Service Worker, 캐싱 전략, 오프라인 지원, 설치 프롬프트 등 고급 개발자를 위한 실전 베스트 프랙티스를 제공합니다.
들어가며
이 글에서는 PWA 베스트 프랙티스 완벽 가이드에 대해 상세히 알아보겠습니다. 총 12가지 주요 개념을 다루며, 각각의 개념에 대한 설명과 실제 코드 예제를 함께 제공합니다.
목차
- Service_Worker_등록
- 캐시_우선_전략
- 네트워크_우선_전략
- 앱_설치_프롬프트
- 백그라운드_동기화
- 푸시_알림_구독
- 캐시_버전_관리
- IndexedDB_오프라인_저장
- 연결_상태_감지
- Workbox_캐싱_전략
- 매니페스트_최적화
- 성능_모니터링
1. Service Worker 등록
개요
PWA의 핵심인 Service Worker를 등록하고 생명주기를 관리하는 방법입니다. 브라우저 지원 여부를 확인한 후 안전하게 등록합니다.
코드 예제
if ('serviceWorker' in navigator) {
window.addEventListener('load', async () => {
try {
const reg = await navigator.serviceWorker.register('/sw.js');
console.log('SW registered:', reg.scope);
} catch (err) {
console.error('SW registration failed:', err);
}
});
}
설명
load 이벤트 후 Service Worker를 등록하여 초기 페이지 로딩 성능에 영향을 주지 않습니다. async/await로 에러 처리를 명확하게 합니다.
2. 캐시 우선 전략
개요
네트워크보다 캐시를 우선 조회하여 빠른 응답 속도를 제공합니다. 오프라인 환경에서도 앱이 작동하도록 보장합니다.
코드 예제
self.addEventListener('fetch', (event) => {
event.respondWith(
caches.match(event.request).then((cached) => {
return cached || fetch(event.request).then((response) => {
return caches.open('v1').then((cache) => {
cache.put(event.request, response.clone());
return response;
});
});
})
);
});
설명
캐시에서 먼저 찾고 없으면 네트워크 요청 후 캐시에 저장합니다. 오프라인 우선(Offline-First) 전략의 핵심 패턴입니다.
3. 네트워크 우선 전략
개요
최신 데이터가 중요한 API 요청에 사용하는 전략입니다. 네트워크 실패 시에만 캐시를 사용하여 데이터 신선도를 유지합니다.
코드 예제
self.addEventListener('fetch', (event) => {
if (event.request.url.includes('/api/')) {
event.respondWith(
fetch(event.request).catch(() => {
return caches.match(event.request);
})
);
}
});
설명
API 요청은 네트워크를 우선 시도하고, 실패 시 캐시된 응답을 반환합니다. 동적 데이터의 신선도와 오프라인 가용성의 균형을 맞춥니다.
4. 앱 설치 프롬프트
개요
사용자에게 PWA 설치를 유도하는 커스텀 UI를 제공합니다. beforeinstallprompt 이벤트를 활용하여 적절한 시점에 프롬프트를 표시합니다.
코드 예제
let deferredPrompt;
window.addEventListener('beforeinstallprompt', (e) => {
e.preventDefault();
deferredPrompt = e;
document.getElementById('installBtn').style.display = 'block';
});
document.getElementById('installBtn').addEventListener('click', async () => {
deferredPrompt.prompt();
const { outcome } = await deferredPrompt.userChoice;
deferredPrompt = null;
});
설명
브라우저 기본 프롬프트를 막고 커스텀 버튼으로 사용자 경험을 개선합니다. 설치 결과를 추적하여 분석에 활용할 수 있습니다.
5. 백그라운드 동기화
개요
오프라인에서 발생한 작업을 온라인 복귀 시 자동으로 처리합니다. 폼 제출, 데이터 전송 등에 활용됩니다.
코드 예제
// 등록
navigator.serviceWorker.ready.then((reg) => {
return reg.sync.register('sync-posts');
});
// Service Worker에서 처리
self.addEventListener('sync', (event) => {
if (event.tag === 'sync-posts') {
event.waitUntil(sendPendingPosts());
}
});
설명
네트워크가 복구되면 자동으로 동기화 이벤트가 발생합니다. 사용자가 앱을 닫아도 백그라운드에서 작업이 완료됩니다.
6. 푸시 알림 구독
개요
사용자의 푸시 알림 권한을 요청하고 구독 정보를 서버에 저장합니다. 재참여(Re-engagement)를 위한 필수 기능입니다.
코드 예제
async function subscribePush() {
const reg = await navigator.serviceWorker.ready;
const sub = await reg.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: urlBase64ToUint8Array(publicKey)
});
await fetch('/api/subscribe', {
method: 'POST',
body: JSON.stringify(sub),
headers: { 'Content-Type': 'application/json' }
});
}
설명
VAPID 키를 사용해 안전하게 구독하고 서버에 등록합니다. userVisibleOnly 옵션으로 사용자에게 항상 알림을 표시합니다.
7. 캐시 버전 관리
개요
앱 업데이트 시 오래된 캐시를 정리하여 저장 공간을 효율적으로 관리합니다. 버전별 캐시 전략으로 충돌을 방지합니다.
코드 예제
const CACHE_VERSION = 'v2';
const CACHE_NAMES = ['v2-static', 'v2-dynamic'];
self.addEventListener('activate', (event) => {
event.waitUntil(
caches.keys().then((keys) => {
return Promise.all(
keys.filter(k => !CACHE_NAMES.includes(k))
.map(k => caches.delete(k))
);
})
);
});
설명
activate 이벤트에서 이전 버전의 캐시를 삭제합니다. 새 Service Worker가 활성화되면 자동으로 정리되어 항상 최신 리소스를 사용합니다.
8. IndexedDB 오프라인 저장
개요
대용량 구조화 데이터를 오프라인에서 저장하고 조회합니다. 캐시 API보다 복잡한 데이터 관리에 적합합니다.
코드 예제
const db = await idb.openDB('myDB', 1, {
upgrade(db) {
db.createObjectStore('posts', { keyPath: 'id' });
}
});
await db.add('posts', { id: 1, title: 'Hello', content: 'World' });
const post = await db.get('posts', 1);
await db.delete('posts', 1);
설명
idb 라이브러리로 Promise 기반 인터페이스를 사용합니다. Object Store에 JSON 데이터를 저장하여 복잡한 쿼리와 트랜잭션이 가능합니다.
9. 연결 상태 감지
개요
네트워크 연결 상태를 실시간으로 모니터링하여 UI를 업데이트합니다. 오프라인 모드 전환을 사용자에게 명확히 알립니다.
코드 예제
window.addEventListener('online', () => {
document.body.classList.remove('offline');
showNotification('연결됨');
});
window.addEventListener('offline', () => {
document.body.classList.add('offline');
showNotification('오프라인 모드');
});
const isOnline = navigator.onLine;
설명
online/offline 이벤트로 연결 상태 변화를 감지합니다. navigator.onLine으로 현재 상태를 확인하여 초기 UI를 설정할 수 있습니다.
10. Workbox 캐싱 전략
개요
Google의 Workbox 라이브러리로 복잡한 캐싱 로직을 간단히 구현합니다. 다양한 전략을 선언적으로 설정할 수 있습니다.
코드 예제
import { registerRoute } from 'workbox-routing';
import { CacheFirst, NetworkFirst } from 'workbox-strategies';
registerRoute(
({request}) => request.destination === 'image',
new CacheFirst({ cacheName: 'images' })
);
registerRoute(
({url}) => url.pathname.startsWith('/api/'),
new NetworkFirst({ cacheName: 'api' })
);
설명
이미지는 Cache First, API는 Network First 전략을 자동 적용합니다. 라우팅 기반으로 리소스 타입별 최적 전략을 설정합니다.
11. 매니페스트 최적화
개요
manifest.json으로 앱 메타데이터와 설치 동작을 정의합니다. 다양한 화면 크기와 플랫폼을 지원하는 아이콘을 설정합니다.
코드 예제
{
"name": "My PWA",
"short_name": "PWA",
"start_url": "/",
"display": "standalone",
"background_color": "#ffffff",
"theme_color": "#2196F3",
"icons": [
{ "src": "/icon-192.png", "sizes": "192x192", "type": "image/png" },
{ "src": "/icon-512.png", "sizes": "512x512", "type": "image/png" }
]
}
설명
display를 standalone으로 설정하여 네이티브 앱처럼 실행됩니다. theme_color는 주소창 색상을 변경하여 브랜딩을 강화합니다.
12. 성능 모니터링
개요
Performance API로 PWA의 핵심 성능 지표를 측정합니다. LCP, FID, CLS 등 Web Vitals를 추적하여 사용자 경험을 개선합니다.
코드 예제
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
if (entry.entryType === 'largest-contentful-paint') {
console.log('LCP:', entry.startTime);
analytics.send('lcp', entry.startTime);
}
}
});
observer.observe({ entryTypes: ['largest-contentful-paint'] });
설명
PerformanceObserver로 실시간 성능 메트릭을 수집합니다. 분석 도구로 전송하여 실제 사용자 환경에서의 성능을 모니터링합니다.
마치며
이번 글에서는 PWA 베스트 프랙티스 완벽 가이드에 대해 알아보았습니다. 총 12가지 개념을 다루었으며, 각각의 사용법과 예제를 살펴보았습니다.
관련 태그
#JavaScript #ServiceWorker #PWA #Caching #OfflineFirst
이 카드뉴스가 포함된 코스
댓글 (0)
함께 보면 좋은 카드 뉴스
서비스 메시 완벽 가이드
마이크로서비스 간 통신을 안전하고 효율적으로 관리하는 서비스 메시의 핵심 개념부터 실전 도입까지, 초급 개발자를 위한 완벽한 입문서입니다. Istio와 Linkerd 비교, 사이드카 패턴, 실무 적용 노하우를 담았습니다.
EFK 스택 로깅 완벽 가이드
마이크로서비스 환경에서 로그를 효과적으로 수집하고 분석하는 EFK 스택(Elasticsearch, Fluentd, Kibana)의 핵심 개념과 실전 활용법을 초급 개발자도 쉽게 이해할 수 있도록 정리한 가이드입니다.
Grafana 대시보드 완벽 가이드
실시간 모니터링의 핵심, Grafana 대시보드를 처음부터 끝까지 배워봅니다. Prometheus 연동부터 알람 설정까지, 초급 개발자도 쉽게 따라할 수 있는 실전 가이드입니다.
분산 추적 완벽 가이드
마이크로서비스 환경에서 요청의 전체 흐름을 추적하는 분산 추적 시스템의 핵심 개념을 배웁니다. Trace, Span, Trace ID 전파, 샘플링 전략까지 실무에 필요한 모든 것을 다룹니다.
CloudFront CDN 완벽 가이드
AWS CloudFront를 활용한 콘텐츠 배포 최적화 방법을 실무 관점에서 다룹니다. 배포 생성부터 캐시 설정, HTTPS 적용까지 단계별로 알아봅니다.