Angular Service Worker 심화: 캐싱 전략과 푸시 알림 구현

Adam Kim·2026년 2월 1일

angular

목록 보기
97/102

이번 글에서는 Angular 앱의 PWA 기능을 한 단계 더 발전시키기 위한 동적 캐싱 전략(Dynamic Caching Strategies)푸시 알림(Push Notifications) 구현 방법에 대해 알아보겠습니다.

동적 캐싱 전략 (Dynamic Caching Strategies)

정적 캐싱과 달리 동적 캐싱은 데이터의 중요도와 업데이트 빈도에 따라 전략을 다르게 가져가야 합니다. async/await 패턴을 사용하여 Service Worker 스크립트 내에서 구현할 수 있는 대표적인 3가지 패턴입니다.

1. Cache First Strategy

이미지나 폰트처럼 자주 변경되지 않는 리소스에 적합합니다. 캐시를 먼저 확인하고, 없을 경우에만 네트워크 요청을 보냅니다.

// sw.js (Service Worker)
const CACHE_NAME = 'asset-cache-v1';

self.addEventListener('fetch', (event: FetchEvent) => {
  event.respondWith(
    (async () => {
      // 1. 캐시에서 요청 확인
      const cachedResponse = await caches.match(event.request);
      if (cachedResponse) {
        return cachedResponse;
      }

      // 2. 캐시에 없다면 네트워크 요청
      return fetch(event.request);
    })()
  );
});

2. Network First Strategy

실시간 데이터나 계정 정보처럼 항상 최신 상태가 중요한 경우 사용합니다. 네트워크 요청을 우선 시도하고, 오프라인 상태이거나 실패했을 때만 캐시를 사용합니다.

// sw.js
self.addEventListener('fetch', (event: FetchEvent) => {
  event.respondWith(
    (async () => {
      try {
        // 1. 네트워크 요청 우선 시도
        const networkResponse = await fetch(event.request);
        return networkResponse;
      } catch (error) {
        // 2. 네트워크 실패 시(Offline) 캐시로 폴백(Fallback)
        console.warn('Network request failed, serving from cache.', error);
        return caches.match(event.request);
      }
    })()
  );
});

3. Stale-While-Revalidate Strategy

성능과 최신 데이터 사이의 균형을 맞추는 전략입니다. 캐시된 데이터를 즉시 보여주어 반응 속도를 높이면서, 백그라운드에서 네트워크 요청을 통해 캐시를 최신화합니다. 뉴스 피드 등에 유용합니다.

// sw.js
const DYNAMIC_CACHE = 'dynamic-data-v1';

self.addEventListener('fetch', (event: FetchEvent) => {
  event.respondWith(
    (async () => {
      const cachedResponse = await caches.match(event.request);

      // 1. 백그라운드에서 네트워크 요청 및 캐시 업데이트 진행
      const networkFetch = fetch(event.request).then(async (res) => {
        const cache = await caches.open(DYNAMIC_CACHE);
        cache.put(event.request, res.clone()); // 캐시 갱신
        return res;
      });

      // 2. 캐시 데이터가 있으면 즉시 반환(Fast), 없으면 네트워크 응답 대기
      return cachedResponse || networkFetch;
    })()
  );
});

푸시 알림 핸들링 (Handling Push Notifications)

Service Worker를 사용하면 브라우저 탭이 닫혀 있어도 사용자에게 알림을 보낼 수 있습니다. Angular에서는 복잡한 window API 대신 @angular/service-worker 패키지의 SwPush 서비스를 사용하여 간결하게 구현할 수 있습니다.

Step 1: 푸시 구독 (Subscribing in Angular)

SwPushrequestSubscription 메소드를 사용하면 권한 요청과 구독 생성을 한 번에 처리할 수 있습니다.

// notification.component.ts
import { Component, inject } from '@angular/core';
import { SwPush } from '@angular/service-worker';
import { HttpClient } from '@angular/common/http';

@Component({
  selector: 'app-notification',
  standalone: true,
  template: `
    <button (click)="subscribeToNotifications()" [disabled]="!isEnabled">
      알림 켜기
    </button>
  `
})
export class NotificationComponent {
  private swPush = inject(SwPush);
  private http = inject(HttpClient);

  // VAPID 키 생성 후 백엔드 및 여기에 설정 필요
  readonly VAPID_PUBLIC_KEY = 'YOUR_VAPID_PUBLIC_KEY'; 
  
  get isEnabled() {
    return this.swPush.isEnabled;
  }

  subscribeToNotifications() {
    this.swPush.requestSubscription({
      serverPublicKey: this.VAPID_PUBLIC_KEY
    })
    .then(sub => {
      // 생성된 구독 객체(subscription)를 백엔드 서버로 전송하여 저장
      this.http.post('/api/notifications/subscribe', sub).subscribe({
        next: () => console.log('알림 구독 성공!'),
        error: err => console.error('구독 실패', err)
      });
    })
    .catch(err => console.error('알림 구독 중 오류 발생', err));
  }
}

Step 2: 알림 수신 및 표시 (Service Worker)

마지막으로 Service Worker에서 push 이벤트를 감지하여 실제 알림 UI를 띄워줍니다.

// sw.js
self.addEventListener('push', (event: PushEvent) => {
  if (!event.data) return;

  const payload = event.data.json();
  const title = payload.title || '새로운 알림';
  const options = {
    body: payload.body,
    icon: '/assets/icons/icon-192x192.png',
    badge: '/assets/icons/badge-72x72.png',
    data: payload.url // 클릭 시 이동할 URL 등을 저장
  };

  event.waitUntil(
    self.registration.showNotification(title, options)
  );
});

Conclusion

Stale-While-Revalidate와 같은 동적 캐싱 전략을 적절히 활용하면 Angular 앱의 체감 성능을 극대화할 수 있습니다. 또한 Angular의 SwPush 서비스를 활용하면 복잡한 푸시 구독 프로세스를 매우 직관적인 코드로 처리할 수 있습니다.

이러한 Service Worker의 심화 패턴들을 적용하여 단순한 웹사이트를 넘어선 강력한 PWA를 구축해 보시기 바랍니다.

Reference

Service Workers in Angular: Advanced Techniques (Part 2)

profile
Angular2+ Developer

0개의 댓글