사용자 관점에서 앱을 열었을 때 로딩 스피너를 기다리지 않고 이미 최신 데이터가 렌더링되어 있는 경험은 매우 매력적입니다. Periodic Background Sync API를 활용하면 사용자가 브라우저 탭을 열지 않더라도, OS와 브라우저가 최적의 타이밍을 계산해 데이터를 백그라운드에서 주기적으로 가져옵니다.
periodicsync 이벤트 수신Periodic Background Sync API는 사용자가 웹 애플리케이션을 켜두지 않거나 탭을 모두 닫은 상태에서도 브라우저 서비스 워커(Service Worker)를 통해 주기적으로 네트워크 데이터를 가져와 오프라인 캐시(Cache Storage)를 최신화할 수 있게 해주는 차세대 PWA(Progressive Web Apps) API입니다.
뉴스 사이트의 최신 헤드라인, 주식 시세, 날씨 정보, 팟캐스트 에피소드 목록처럼 주기적 갱신이 필요하지만 사용자가 매번 로딩 대기 시간을 겪을 필요가 없는 콘텐츠에 최적화되어 있습니다.
기존 웹 애플리케이션은 사용자가 웹 페이지에 접속한 이후에야 REST API나 GraphQL 요청을 보냅니다. 그러나 Periodic Background Sync API를 적용하면 사용자가 출근길에 뉴스 앱을 클릭하는 순간, 이미 새벽에 백그라운드 동기화가 완료된 최신 기사가 즉각적으로 화면에 렌더링됩니다.
많은 개발자들이 기존의 Background Sync API와 Periodic Background Sync API를 혼동합니다. 두 API는 백그라운드 동작이라는 점은 같지만 동기화 주도권과 목적이 완전히 다릅니다.
| 구분 | Background Sync (1회성) | Periodic Background Sync (주기적) |
|---|---|---|
| 주요 목적 | 오프라인 상태에서 실패한 요청(폼 제출 등)의 재시도 | 사용자가 앱을 열기 전 데이터 미리 가져오기(Prefetch) |
| 실행 횟수 | 네트워크가 연결되는 시점에 단 1회 실행 후 종료 | 브라우저 판단에 따라 주기적으로 반복 실행 |
| 호출 주체 | 사용자의 특정 액션 (예: 작성 완료 버튼 클릭) | OS 및 브라우저 스케줄러 (사용자 행동 예측) |
| 설치 요구 | PWA 설치 없이도 서비스 워커 지원 시 가능 | PWA (A2HS) 설치 및 high engagement score 필수 |
| 이벤트명 | sync |
periodicsync |
1회성 Background Sync는 **“네트워크가 돌아오면 메시지를 전송해 줘”**라는 개념이라면, Periodic Background Sync는 **“12시간마다 최신 날씨를 미리 캐싱해 줘”**라는 개념입니다.
Periodic Background Sync는 사용자 기기의 배터리와 데이터(cellular data)를 소모합니다. 따라서 악의적인 웹사이트가 배경에서 무한대로 네트워크 요청을 보내 시스템 자원을 고갈시키는 것을 막기 위해 매우 엄격한 제약 사항이 존재합니다.
💡 Site Engagement Score란? Chrome 브라우저가 사용자 행동(클릭, 스크롤, 체류 시간, 방문 횟수)을 종합하여 산출하는 0~100점 사이의 점수입니다. 주소창에
chrome://site-engagement를 입력하면 현재 내 브라우저의 사이트별 인지도 점수를 확인할 수 있습니다.
Periodic Sync를 사용하려면 웹 앱이 Service Worker를 등록한 PWA 형태여야 합니다. 기본적인 웹 앱 구조를 설정합니다.
<!-- index.html -->
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<link rel="manifest" href="/manifest.json">
<title>Periodic Sync News Reader</title>
</head>
<body>
<h1>📰 오늘의 백그라운드 뉴스</h1>
<div id="news-container">로딩 중...</div>
<script src="app.js"></script>
</body>
</html>// manifest.json
{
"name": "Periodic News PWA",
"short_name": "NewsPWA",
"start_url": "/",
"display": "standalone",
"background_color": "#ffffff",
"icons": [
{
"src": "/icon-192.png",
"sizes": "192x192",
"type": "image/png"
}
]
}메인 메인 스레드(app.js)에서 periodicSync 객체가 존재하는지 확인하고 권한 상태에 따라 백그라운드 동기화를 등록합니다.
// app.js
async function registerPeriodicNewsSync() {
// 1. Service Worker 지원 여부 및 periodicSync API 지원 확인
if (!('serviceWorker' in navigator)) {
console.log('Service Worker를 지원하지 않는 브라우저입니다.');
return;
}
const registration = await navigator.serviceWorker.ready;
if (!('periodicSync' in registration)) {
console.log('이 브라우저는 Periodic Background Sync API를 지원하지 않습니다.');
return;
}
try {
// 2. periodic-background-sync 권한 확인
const status = await navigator.permissions.query({
name: 'periodic-background-sync',
});
if (status.state === 'granted') {
// 3. Periodic Sync 등록 (최소 간격 12시간 설정)
await registration.periodicSync.register('update-news-feed', {
minInterval: 12 * 60 * 60 * 1000, // 12시간 (ms 단위)
});
console.log('✅ Periodic Background Sync 등록 성공 (태그: update-news-feed)');
} else {
console.warn('⚠️ Periodic Background Sync 권한이 거부되었습니다.');
}
} catch (error) {
console.error('❌ Periodic Sync 등록 실패:', error);
}
}
// 서비스 워커 등록 후 Periodic Sync 실행
navigator.serviceWorker.register('/sw.js')
.then(() => registerPeriodicNewsSync());periodicsync 이벤트 수신이제 백그라운드에서 브라우저가 지정된 시점에 periodicsync 이벤트를 서비스 워커(sw.js)로 트리거합니다.
// sw.js
const CACHE_NAME = 'news-cache-v1';
const NEWS_API_URL = 'https://api.example.com/latest-news';
self.addEventListener('install', (event) => {
self.skipWaiting();
});
self.addEventListener('activate', (event) => {
event.waitUntil(clients.claim());
});
// periodicSync 이벤트 수신
self.addEventListener('periodicsync', (event) => {
if (event.tag === 'update-news-feed') {
console.log('[SW] ⏱️ Periodic Sync 실행: 최신 뉴스 가져오는 중...');
event.waitUntil(fetchAndCacheLatestNews());
}
});
// 백그라운드에서 최신 데이터를 가져와 Cache Storage에 저장하는 함수
async function fetchAndCacheLatestNews() {
try {
const response = await fetch(NEWS_API_URL);
if (!response.ok) throw new Error('네트워크 응답 오류');
const cache = await caches.open(CACHE_NAME);
// 응답 객체를 클론하여 캐시에 저장
await cache.put(NEWS_API_URL, response.clone());
console.log('[SW] ✅ 백그라운드 뉴스 캐싱 완료');
} catch (error) {
console.error('[SW] ❌ 백그라운드 동기화 실패:', error);
}
}
// 메인 앱에서 fetch 요청 시 캐시 우선 전략(Cache First) 응답
self.addEventListener('fetch', (event) => {
if (event.request.url.includes('/latest-news')) {
event.respondWith(
caches.match(event.request).then((cachedResponse) => {
// 캐시된 데이터가 있으면 캐시 반환, 없으면 네트워크 요청
return cachedResponse || fetch(event.request);
})
);
}
});| 비판 요소 | 기존 REST Polling | Push Notification 기반 갱신 | Periodic Background Sync |
|---|---|---|---|
| 탭 닫힘 시 작동 | ❌ 불가 | ⭕ 가능 (푸시 수신 시 백그라운드 갱신) | ⭕ 가능 (브라우저 자체 스케줄링) |
| 서버 인프라 비용 | 없음 | ❌ 높음 (FCM / WebPush 서버 관리 필요) | ⭕ 없음 (클라이언트 단독 등록) |
| 배터리/데이터 효율 | ❌ 최악 (지속적 접속 유지) | ⚠️ 보통 (푸시 수신 시 순간 소모) | ⭕ 최상 (OS가 디바이스 상태 감지 후 통합 수행) |
| 실시간성 | 높음 (앱 켜진 상태) | 아주 높음 (즉시 전송) | ⚠️ 주기적 (정확한 정시 실행 미보장) |
| 사용자 방해 요소 | 없음 | ⚠️ 알림 팝업으로 방해 가능성 존재 | ⭕ 완전히 보이지 않는 백그라운드 갱신 |
Periodic Background Sync는 기본 최소 간격이 수 시간 단위이며, Site Engagement 점수에 의존하기 때문에 실제 자연 실행을 기다리며 디버깅하는 것은 불가능에 가깝습니다. Chrome 개발자 도구(DevTools)에서는 이를 인위적으로 즉시 트리거하는 기능을 제공합니다.
F12를 눌러 개발자 도구를 엽니다.Tag 입력란에 코드에서 등록한 태그명(update-news-feed)을 입력합니다.[SW] ⏱️ Periodic Sync 실행 로그와 Cache Storage 갱신 여부를 확인합니다.# Console 출력 예시
[SW] ⏱️ Periodic Sync 실행: 최신 뉴스 가져오는 중...
[SW] ✅ 백그라운드 뉴스 캐싱 완료minInterval: 1000으로 설정하면 1초마다 실행될 것이라는 착각minInterval은 개발자가 요청하는 **“최소 간격 힌트”**일 뿐입니다. 브라우저는 minInterval 값과 Site Engagement Score, 배터리 충전 여부, Wi-Fi 연결 여부를 종합 판단하여 실제 실행 주기를 결정합니다. 개발자가 1초로 지정하더라도 브라우저 판단에 따라 실제로는 몇 시간마다 실행되거나 아예 실행되지 않을 수 있습니다.
대부분의 브라우저(Chrome 포함)는 보안 및 자원 보호를 이유로 **설치된 PWA(Standalone Mode)**에서만 Periodic Sync 권한을 granted로 처리합니다. 일반 웹 브라우징 탭에서 navigator.permissions.query({ name: 'periodic-background-sync' })를 호출하면 denied가 반환됩니다.
현재 Periodic Background Sync API는 **Chromium 기반 브라우저(Chrome, Edge, Opera 등)**에서만 주로 지원되며, Safari(WebKit) 및 Firefox(Gecko)는 지원하지 않습니다.
반드시 if ('periodicSync' in registration) 기능 감지(Feature Detection) 코드를 포함시켜 Progressive Enhancement 방식으로 구현해야 합니다.
Periodic Background Sync는 만능이 아닙니다. 아래와 같은 경우에는 이 API를 사용하면 안 됩니다.
✨ 한 줄 요약 Periodic Background Sync API를 활용하면 사용자가 PWA를 실행하는 순간, 로딩 스피너 없는 0초 오프라인 렌더링 경험을 완성할 수 있습니다.
