Progressive Web Apps (PWA) 소개
HTTPS 위에 매니페스트와 서비스 워커를 구성해 설치·오프라인 캐시·푸시 알림을 지원하는 PWA 원리를 익힙니다.
우리는 지금까지 프론트엔드와 백엔드 핵심 기술을 익히고, 데이터베이스, 보안, 성능, 개발 도구까지 폭넓게 다뤘습니다.
이제 기본 웹 애플리케이션을 기획하고 배포할 수 있는 기반이 갖춰졌습니다.
다음 질문은 앞으로 무엇을 더 준비해야 하는가입니다.
웹 기술은 빠르게 바뀌고, 오늘의 선택이 내일의 기본이 되기도 합니다.
15장에서는 이런 변화 속에서 실제로 영향력이 큰 흐름을 살펴봅니다.
첫 주제는 PWA(Progressive Web App)입니다.
PWA는 웹 앱을 네이티브 앱에 가까운 경험으로 끌어올리는 접근입니다.
설치, 오프라인 지원, 푸시 알림처럼 웹의 한계를 확장하는 기술을 중심으로 구성됩니다.
FLOWCHART · B99 WEB FUNDAMENTALS
사용자 필요 기반 PWA 기능 결정
PWA는 secure context 위에서 manifest·service worker·cache and update policy를 조합해 설치·오프라인·push 등 선택적 기능을 제공한다. service worker는 register·install·waiting·activate·fetch와 update 수명을 가지며 기존 page가 새 worker 적용 시점을 좌우한다.
먼저 확인
실제 사용자 문제, secure context, 플랫폼 지원, 일반 웹 fallback, 운영 비용
설치
반복 진입을 줄여야 하고 manifest·icons·설치 UX를 유지할 수 있을 때
오프라인
네트워크 없이 핵심 여정을 지속해야 하며 cache expiry·storage를 운영할 때
push
시간 민감 알림에 사용자가 명시적으로 opt-in하고 쉽게 해지할 수 있을 때
background
지연 전송·동기화가 필요하고 quota·battery·플랫폼 제약을 감당할 때
채택 게이트
네 기능을 각각 평가하고 사용자 필요와 선행 조건을 통과한 최소 capability만 채택한다. 나머지는 일반 웹 경로를 유지한다.
PWA는 기능 묶음이 아니다. 사용자 문제를 해결하는 최소 capability만 채택하고 모든 권한 거부·미지원 상태에 웹 fallback을 둔다.
PWA (Progressive Web App)란?
PWA (Progressive Web App)는 웹 기술(HTML, CSS, JavaScript)을 사용하여 개발되었지만, 네이티브 애플리케이션(iOS, Android 앱)과 유사한 사용자 경험을 제공하는 웹 애플리케이션입니다.
PWA는 웹의 장점(설치 필요 없음, URL 기반 접근 용이성, 빠른 개발 및 배포)과 네이티브 앱의 장점(오프라인 지원, 푸시 알림, 홈 화면 아이콘, 시스템 자원 접근)을 결합하여 사용자에게 더욱 풍부하고 편리한 경험을 제공하는 것을 목표로 합니다.
왜 PWA가 중요한가?- 설치 장벽 낮춤: 사용자는 앱 스토어 방문, 다운로드, 설치 과정 없이 웹사이트 방문만으로 PWA를 사용하고, 필요하면 홈 화면에 추가할 수 있습니다. 이는 사용자 유입 장벽을 크게 낮춥니다.
- 접근성 향상: 낮은 네트워크 환경에서도 동작하며, 푸시 알림을 통해 사용자 재참여를 유도할 수 있습니다.
- 개발 및 유지보수 효율: 하나의 코드베이스로 모든 플랫폼(웹, 모바일)에 대응 가능하여 개발 비용과 시간을 절감합니다. 웹 표준 기술을 사용하므로 별도의 스킬셋을 익힐 필요가 적습니다.
- SEO 이점: 웹사이트이므로 검색 엔진에 노출되며, 빠른 로딩 속도와 좋은 사용자 경험은 SEO 랭킹에도 긍정적인 영향을 미칩니다.
PWA의 핵심 구성 요소
Progressive Web Apps (PWA) 소개에서는 실행 환경, 배포 구조, 사용자 경험 기준을 정리합니다.
PWA는 다음 세 가지 핵심 기술과 여러 권장 사항을 바탕으로 구현됩니다.
서비스 워커 (Service Worker)
-
PWA의 핵심 실행 계층: 서비스 워커는 웹 페이지와 독립적으로 백그라운드에서 실행되는 JavaScript 파일입니다. 네트워크 요청을 가로채고, 캐싱 전략을 프로그래밍 방식으로 제어하며, 푸시 알림을 수신하는 등의 역할을 수행합니다.
-
주요 기능
- 오프라인 지원 (Offline-first): 네트워크 연결이 없거나 불안정한 환경에서도 캐시된 콘텐츠를 제공하여 웹 앱이 동작하도록 합니다.
- 빠른 로딩: 네트워크 요청을 가로채 캐시된 리소스를 즉시 반환함으로써 페이지 로딩 속도를 비약적으로 향상시킵니다.
- 푸시 알림 (Push Notifications): 사용자가 웹 앱을 닫은 상태에서도 서버로부터 푸시 메시지를 받아 알림을 표시할 수 있게 합니다.
- 백그라운드 동기화: 네트워크가 다시 연결될 때까지 데이터를 저장하고 있다가 백그라운드에서 서버와 동기화할 수 있습니다.
-
동작 방식 (간략)
웹 페이지에서 서비스 워커를 등록(Register)합니다.
브라우저는 서비스 워커 파일을 다운로드하고 설치(Install)합니다.
이 단계에서 필요한 에셋들을 캐시에 저장할 수 있습니다.
서비스 워커가 활성화(Activate)되면 이후 모든 네트워크 요청을 가로채서(Fetch) 개발자가 정의한 캐싱 전략에 따라 응답을 제공합니다.
웹 앱 매니페스트 (Web App Manifest)
- PWA의 신분증: 웹 앱 매니페스트는 JSON 형식의 파일로, PWA의 메타데이터(이름, 아이콘, 시작 URL, 표시 방식 등)를 정의합니다.
-
주요 기능
- 홈 화면 아이콘: 사용자가 PWA를 홈 화면에 추가했을 때 표시될 아이콘을 정의합니다.
- 시작 화면 (Splash Screen): 앱을 실행할 때 표시되는 스플래시 화면을 정의합니다.
- 표시 모드 (Display Mode): PWA가 브라우저 UI 없이 독립적인 앱처럼 실행될지(standalone), 최소한의 UI를 가질지(minimal-ui), 아니면 일반 웹 페이지처럼 보일지(browser) 등을 설정합니다.
- 시작 URL: PWA를 실행했을 때 로드될 초기 URL을 지정합니다.
index.html에 연결:<link rel="manifest" href="/manifest.json">형태로 HTML 파일에 연결합니다.
HTTPS
- PWA의 필수 조건: PWA는 서비스 워커의 보안 및 무결성 문제 때문에 반드시 HTTPS 환경에서 호스팅되어야 합니다. 로컬 개발 환경(
localhost)에서는 예외적으로 HTTP가 허용됩니다. - 보안과 신뢰: HTTPS는 웹 페이지와 서버 간의 통신을 암호화하여 데이터 유출 및 변조를 방지하고, 사용자에게 신뢰성을 제공합니다.
PWA의 주요 특징 및 장점
PWA는 네이티브 앱의 장점을 웹으로 가져오면서도 웹 본연의 장점을 유지합니다.
| 특징 | PWA | 네이티브 앱 (iOS/Android) |
|---|---|---|
| 설치 | 앱 스토어 불필요, 홈 화면 추가 | 앱 스토어/플레이 스토어를 통해 설치 |
| 접근성 | URL로 직접 접근 가능, 즉시 사용 | 검색/설치 과정 필요 |
| 오프라인 | 서비스 워커로 지원 가능 | 기본적으로 지원 |
| 푸시 알림 | 지원 가능 | 지원 가능 |
| 업데이트 | 웹페이지처럼 자동으로 업데이트 (재방문 시) | 앱 스토어/플레이 스토어를 통해 수동 업데이트 또는 자동 |
| 개발 비용 | 단일 코드베이스, 웹 기술 사용으로 효율적 | 플랫폼별(iOS/Android) 개별 개발 필요 (높은 비용) |
| 배포 | 웹서버에 배포, 즉시 반영 | 앱 스토어 심사 필요 (시간 소요) |
| 시스템 접근 | 제한적 (카메라, 마이크, GPS 등 일부 가능) | 전반적인 시스템 자원(주소록, 캘린더 등) 접근 용이 |
| 용량 | 초기 다운로드 용량 적음 | 일반적으로 용량이 큼 |
| SEO | 검색 엔진 노출 용이 | 검색 엔진 노출 어려움 (앱 스토어 내 검색 위주) |
PWA 구현의 간단한 흐름 (예시)
manifest.json) 생성{
"name": "My Awesome PWA",
"short_name": "My PWA",
"start_url": ".",
"display": "standalone",
"background_color": "#ffffff",
"theme_color": "#000000",
"icons": [
{
"src": "/logo.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/logo.png",
"sizes": "512x512",
"type": "image/png"
}
]
}<head>
<link rel="manifest" href="/manifest.json">
<meta name="theme-color" content="#000000">
<link rel="apple-touch-icon" href="/logo.png">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
</head>sw.js) 생성 및 캐싱 전략 정의// sw.js (간단한 예시 - 캐시 우선 전략)
const CACHE_NAME = 'my-pwa-cache-v1';
const urlsToCache = [
'/',
'/index.html',
'/styles.css',
'/script.js',
'/logo.png',
// ... 기타 중요한 리소스
];
// 서비스 워커 설치 시점에 캐시할 리소스 정의
self.addEventListener('install', event => {
event.waitUntil(
caches.open(CACHE_NAME)
.then(cache => {
console.log('Opened cache');
return cache.addAll(urlsToCache);
})
);
});
// 네트워크 요청 가로채기 (캐시 우선 전략)
self.addEventListener('fetch', event => {
event.respondWith(
caches.match(event.request)
.then(response => {
// 캐시에 응답이 있으면 캐시된 응답 반환
if (response) {
return response;
}
// 캐시에 없으면 네트워크에서 가져옴
return fetch(event.request).then(
response => {
// 가져온 응답을 캐시에 저장 (나중에 사용할 수 있도록)
if (!response || response.status !== 200 || response.type !== 'basic') {
return response;
}
const responseToCache = response.clone();
caches.open(CACHE_NAME)
.then(cache => {
cache.put(event.request, responseToCache);
});
return response;
}
);
})
);
});
// 오래된 캐시 삭제
self.addEventListener('activate', event => {
const cacheWhitelist = [CACHE_NAME];
event.waitUntil(
caches.keys().then(cacheNames => {
return Promise.all(
cacheNames.map(cacheName => {
if (cacheWhitelist.indexOf(cacheName) === -1) {
return caches.delete(cacheName);
}
})
);
})
);
});if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('/sw.js')
.then(registration => {
console.log('Service Worker registered: ', registration);
})
.catch(error => {
console.error('Service Worker registration failed: ', error);
});
});
}HTTPS 환경에서 서비스 배포.
(또는 개발 시 localhost 사용)
참고: Vite, Next.js 같은 최신 프론트엔드 도구는 플러그인 기반으로 PWA를 구성합니다.
예를 들어 Vite는 vite-plugin-pwa를 추가해 서비스 워커/매니페스트를 명시적으로 관리하는 방식이 일반적입니다.
PWA는 구현 후에도 캐시 갱신, 설치 가능성, 오프라인 동작을 실제 기기에서 반복 점검해야 합니다.
STATE · B99 WEB FUNDAMENTALS
서비스 워커 설치·갱신 생명주기
PWA는 secure context 위에서 manifest·service worker·cache and update policy를 조합해 설치·오프라인·push 등 선택적 기능을 제공한다. service worker는 register·install·waiting·activate·fetch와 update 수명을 가지며 기존 page가 새 worker 적용 시점을 좌우한다.
- 1. 등록 또는 갱신 확인
브라우저가 secure context에서 서비스 워커 스크립트를 가져와 기존 버전과 비교합니다.
- 2. Installing
install이벤트에서 필요한 자원을 precache하며 실패하면 새 worker는 redundant가 됩니다. - 3. Installed · waiting
이미 active worker가 제어하는 탭이 있으면 새 worker는 기다리고 앱은 update 안내를 보여줄 수 있습니다.
- 4. Activating
기존 탭이 닫히거나 명시한 갱신 정책을 적용하면
activate에서 오래된 cache를 정리합니다. - 5. Activated
새 worker가 이후 client와 fetch를 제어하며 cache-first, network-first와 offline fallback 같은 전략을 수행합니다.
안전한 갱신
waiting worker가 있다는 이유만으로 열린 탭을 즉시 새 코드로 바꾸지 않습니다. 사용자 작업과 old/new asset 호환성을 확인해 적용 시점을 정합니다.
설치 실패의 fallback
새 worker 설치가 실패해도 이미 active인 worker와 현재 페이지는 계속 동작할 수 있어야 합니다.
PWA가 한 코드베이스로 모든 native 기능·플랫폼을 보장하거나 SEO를 자동 개선한다고 표현하지 않고 브라우저·OS별 설치와 push 지원 차이를 명시한다.
PWA 핵심 정리
핵심은 서비스 워커, 매니페스트, HTTPS를 기능 체크리스트가 아니라 배포 전략으로 함께 다루는 것입니다.
이번 장에서는 웹의 한계를 넘어 네이티브 앱과 같은 사용자 경험을 제공하는 PWA(Progressive Web App)에 대해 학습했습니다.
PWA의 개념과 서비스 워커(Service Worker), 웹 앱 매니페스트(Web App Manifest), HTTPS의 역할을 정리했습니다.
이 요소들이 오프라인 지원, 푸시 알림, 홈 화면 추가 기능과 어떻게 연결되는지도 함께 확인했습니다.
PWA는 오프라인 동작, 설치 가능성, 푸시 알림처럼 웹 앱의 사용성을 높이는 선택지입니다.
모든 웹 애플리케이션에 필요한 것은 아니므로, 서비스 특성과 사용자 환경에 맞춰 적용 여부를 판단해야 합니다.
PWA 흐름은 설치 가능성, 서비스 워커 요청 처리, 캐시 갱신을 배포 후 점검 루틴으로 연결해야 안정적으로 유지됩니다.