🤖

본 콘텐츠의 이미지 및 내용은 AI로 생성되었습니다.

⚠️

본 콘텐츠의 이미지 및 내용을 무단으로 복제, 배포, 수정하여 사용할 경우 저작권법에 의해 법적 제재를 받을 수 있습니다.

이미지 로딩 중...

PWA 기초부터 심화까지 완벽 가이드 - 슬라이드 1/13
A

AI Generated

2025. 11. 2. · 22 Views

PWA 기초부터 심화까지 완벽 가이드

Progressive Web App의 핵심 개념부터 고급 기능까지 실전 예제로 배웁니다. Service Worker, Cache API, Web App Manifest 등 PWA의 모든 것을 다룹니다.


카테고리:JavaScript
언어:JavaScript
메인 태그:#PWA
서브 태그:
#ServiceWorker#CacheAPI#WebManifest#OfflineFirst

들어가며

이 글에서는 PWA 기초부터 심화까지 완벽 가이드에 대해 상세히 알아보겠습니다. 총 12가지 주요 개념을 다루며, 각각의 개념에 대한 설명과 실제 코드 예제를 함께 제공합니다.

목차

  1. Service_Worker_등록
  2. Service_Worker_Install_이벤트
  3. Service_Worker_Fetch_가로채기
  4. Web_App_Manifest
  5. Cache_Then_Network_전략
  6. Background_Sync
  7. Push_Notification
  8. IndexedDB_저장
  9. Workbox_라이브러리
  10. App_Install_Prompt
  11. Network_First_전략
  12. Service_Worker_업데이트

1. Service Worker 등록

개요

PWA의 핵심인 Service Worker를 등록하고 생명주기를 관리합니다. 오프라인 기능의 시작점입니다.

코드 예제

if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('/sw.js')
    .then(reg => console.log('SW registered:', reg))
    .catch(err => console.error('SW error:', err));
}

설명

브라우저가 Service Worker를 지원하는지 확인 후 등록합니다. 등록 성공 시 백그라운드에서 동작합니다.


2. Service Worker Install 이벤트

개요

Service Worker 설치 시 정적 자원을 미리 캐싱하여 오프라인 대비를 합니다.

코드 예제

const CACHE_NAME = 'v1';
const urlsToCache = ['/', '/styles.css', '/script.js'];

self.addEventListener('install', event => {
  event.waitUntil(
    caches.open(CACHE_NAME)
      .then(cache => cache.addAll(urlsToCache))
  );
});

설명

install 이벤트에서 필요한 파일들을 캐시에 저장합니다. 앱이 오프라인에서도 작동할 수 있게 준비합니다.


3. Service Worker Fetch 가로채기

개요

네트워크 요청을 가로채서 캐시 우선 전략을 구현합니다. 오프라인 경험의 핵심입니다.

코드 예제

self.addEventListener('fetch', event => {
  event.respondWith(
    caches.match(event.request)
      .then(response => response || fetch(event.request))
      .catch(() => caches.match('/offline.html'))
  );
});

설명

요청을 캐시에서 먼저 찾고, 없으면 네트워크로 요청합니다. 실패 시 오프라인 페이지를 보여줍니다.


4. Web App Manifest

개요

앱처럼 보이도록 메타데이터를 정의합니다. 홈 화면 추가와 전체 화면 실행이 가능합니다.

코드 예제

{
  "name": "My PWA App",
  "short_name": "PWA",
  "start_url": "/",
  "display": "standalone",
  "background_color": "#ffffff",
  "theme_color": "#2196F3",
  "icons": [{"src": "/icon.png", "sizes": "192x192"}]
}

설명

manifest.json 파일로 앱 이름, 아이콘, 테마 색상 등을 설정합니다. 네이티브 앱과 유사한 경험을 제공합니다.


5. Cache Then Network 전략

개요

캐시된 데이터를 즉시 보여주고 백그라운드에서 업데이트하는 고급 패턴입니다.

코드 예제

async function getCacheThenNetwork(url) {
  const cache = await caches.open('dynamic-v1');
  const cachedResponse = await cache.match(url);

  const networkPromise = fetch(url).then(res => {
    cache.put(url, res.clone());
    return res;
  });

  return cachedResponse || networkPromise;
}

설명

캐시를 먼저 반환하여 빠른 로딩을 제공하고, 동시에 최신 데이터를 가져와 캐시를 업데이트합니다.


6. Background Sync

개요

오프라인 상태에서 발생한 작업을 온라인 복귀 시 자동으로 동기화합니다.

코드 예제

// 등록
navigator.serviceWorker.ready.then(reg => {
  return reg.sync.register('post-data');
});

// Service Worker에서
self.addEventListener('sync', event => {
  if (event.tag === 'post-data') {
    event.waitUntil(sendPendingData());
  }
});

설명

네트워크가 끊겨도 작업을 등록하고, 연결 복구 시 자동으로 서버에 전송합니다. 신뢰성 있는 데이터 전송을 보장합니다.


7. Push Notification

개요

사용자 동의 후 서버에서 푸시 알림을 보낼 수 있습니다. 사용자 재참여를 유도합니다.

코드 예제

// 권한 요청 및 구독
const permission = await Notification.requestPermission();
if (permission === 'granted') {
  const subscription = await registration.pushManager.subscribe({
    userVisibleOnly: true,
    applicationServerKey: vapidPublicKey
  });
  await sendToServer(subscription);
}

설명

사용자에게 알림 권한을 요청하고 푸시 구독을 생성합니다. 서버로 구독 정보를 전송하여 푸시 발송을 준비합니다.


8. IndexedDB 저장

개요

구조화된 대용량 데이터를 클라이언트에 저장합니다. 복잡한 오프라인 앱에 필수적입니다.

코드 예제

const request = indexedDB.open('MyDB', 1);
request.onsuccess = e => {
  const db = e.target.result;
  const tx = db.transaction('store', 'readwrite');
  tx.objectStore('store').add({id: 1, data: 'value'});
};
request.onupgradeneeded = e => {
  e.target.result.createObjectStore('store', {keyPath: 'id'});
};

설명

IndexedDB를 열고 객체 저장소를 만들어 데이터를 저장합니다. LocalStorage보다 훨씬 큰 용량과 성능을 제공합니다.


9. Workbox 라이브러리

개요

Google의 Workbox로 Service Worker를 쉽게 구현합니다. 복잡한 캐싱 전략을 간단히 설정할 수 있습니다.

코드 예제

importScripts('https://storage.googleapis.com/workbox-cdn/releases/6.5.4/workbox-sw.js');

workbox.routing.registerRoute(
  ({request}) => request.destination === 'image',
  new workbox.strategies.CacheFirst()
);

workbox.precaching.precacheAndRoute(self.__WB_MANIFEST);

설명

Workbox를 import하고 이미지는 캐시 우선, 사전 캐싱 매니페스트를 자동으로 처리합니다. 보일러플레이트 코드를 대폭 줄여줍니다.


10. App Install Prompt

개요

사용자에게 앱 설치를 유도하는 커스텀 프롬프트를 구현합니다. 설치율을 높일 수 있습니다.

코드 예제

let deferredPrompt;
window.addEventListener('beforeinstallprompt', e => {
  e.preventDefault();
  deferredPrompt = e;
});

installBtn.addEventListener('click', async () => {
  deferredPrompt.prompt();
  const {outcome} = await deferredPrompt.userChoice;
  console.log(`User ${outcome}`);
});

설명

브라우저의 기본 설치 프롬프트를 가로채서 원하는 타이밍에 표시합니다. 사용자 경험을 개선하고 전환율을 향상시킵니다.


11. Network First 전략

개요

최신 데이터를 우선하되 네트워크 실패 시 캐시를 사용합니다. API 요청에 적합합니다.

코드 예제

self.addEventListener('fetch', event => {
  event.respondWith(
    fetch(event.request)
      .then(res => {
        const clone = res.clone();
        caches.open('api-v1').then(cache => cache.put(event.request, clone));
        return res;
      })
      .catch(() => caches.match(event.request))
  );
});

설명

네트워크 요청을 먼저 시도하고 성공하면 캐시를 업데이트합니다. 실패 시에만 캐시된 데이터를 반환하여 최신성을 유지합니다.


12. Service Worker 업데이트

개요

새로운 Service Worker 버전을 감지하고 업데이트를 적용합니다. 사용자에게 새로고침을 유도할 수 있습니다.

코드 예제

navigator.serviceWorker.register('/sw.js').then(reg => {
  reg.addEventListener('updatefound', () => {
    const newWorker = reg.installing;
    newWorker.addEventListener('statechange', () => {
      if (newWorker.state === 'installed' && navigator.serviceWorker.controller) {
        showUpdateNotification();
      }
    });
  });
});

설명

Service Worker 업데이트를 감지하고 새 버전이 설치되면 사용자에게 알립니다. skipWaiting()과 함께 사용하여 즉시 활성화할 수 있습니다.


마치며

이번 글에서는 PWA 기초부터 심화까지 완벽 가이드에 대해 알아보았습니다. 총 12가지 개념을 다루었으며, 각각의 사용법과 예제를 살펴보았습니다.

관련 태그

#PWA #ServiceWorker #CacheAPI #WebManifest #OfflineFirst

#PWA#ServiceWorker#CacheAPI#WebManifest#OfflineFirst#JavaScript

댓글 (0)

댓글을 작성하려면 로그인이 필요합니다.