icon
16장 : 고급 주제

PWA 설정

현대의 웹 애플리케이션은 단순히 정보를 보여주는 것을 넘어, 사용자에게 네이티브 앱과 같은 경험을 제공하는 방향으로 진화하고 있습니다. 프로그레시브 웹 앱(Progressive Web App, PWA) 은 이러한 목표를 달성하기 위한 웹 기술의 집합체로, 웹사이트의 접근성과 기능을 향상시켜 앱 스토어 설치 없이도 모바일 앱처럼 작동하게 합니다. Next.js는 PWA를 구현하는 데 필요한 다양한 기능을 지원하며, 특정 라이브러리와 설정을 통해 쉽게 PWA로 변환할 수 있습니다.

이 절에서는 PWA의 핵심 개념과 이점, Next.js 프로젝트에서 PWA를 설정하는 방법, 특히 next-pwa 라이브러리 사용법, 그리고 오프라인 지원, 푸시 알림 등 PWA의 주요 기능을 구현하는 전략에 대해 상세히 알아보겠습니다.


PWA란 무엇이며 왜 중요한가요?

PWA는 웹 기술(HTML, CSS, JavaScript)을 사용하여 구축되지만, 웹의 장점(접근성, SEO)과 네이티브 앱의 장점(오프라인 지원, 푸시 알림, 홈 화면 설치)을 결합한 애플리케이션입니다. PWA는 점진적 향상(Progressive Enhancement) 원칙을 따르므로, 최신 PWA 기능을 지원하는 브라우저에서는 앱과 같은 경험을 제공하고, 그렇지 않은 브라우저에서는 일반 웹사이트처럼 작동합니다.

PWA의 핵심 기능 및 이점

  • 신뢰성 (Reliable): 서비스 워커(Service Worker) 를 사용하여 네트워크 연결이 불안정하거나 오프라인 상태에서도 빠르게 로드되고 작동합니다. 캐싱 전략을 통해 반복 방문 시 거의 즉시 로드됩니다.
  • 빠른 로딩 (Fast): 서비스 워커와 캐싱 전략으로 빠른 로딩 속도를 보장하여 사용자 이탈률을 줄입니다.
  • 높은 참여도 (Engaging)
    • 홈 화면 설치(Add to Home Screen): 사용자가 웹사이트를 스마트폰의 홈 화면에 추가하여 앱처럼 실행할 수 있습니다.
    • 푸시 알림(Push Notifications): 사용자에게 실시간 알림을 보내 재방문을 유도하고 참여도를 높입니다.
    • 풀스크린 모드: 브라우저 UI 없이 전체 화면으로 실행되어 몰입감을 제공합니다.
  • 접근성 및 발견 용이성: URL을 통해 접근 가능하고 검색 엔진에 노출됩니다. 앱 스토어 설치 과정 없이 바로 사용할 수 있습니다.
  • 플랫폼 독립적: 모든 브라우저와 장치에서 작동하며, 앱 스토어의 심사 과정을 거치지 않아도 됩니다.
  • 적은 데이터 사용량: 효율적인 캐싱으로 데이터 사용량을 줄입니다.

Next.js PWA 설정 (next-pwa 라이브러리)

Next.js 프로젝트를 PWA로 만드는 가장 쉽고 널리 사용되는 방법은 next-pwa 라이브러리를 활용하는 것입니다. 이 라이브러리는 서비스 워커를 등록하고 웹 앱 매니페스트 파일을 자동으로 생성하는 등 PWA에 필요한 복잡한 설정을 간소화합니다.

필요한 패키지 설치

먼저 next-pwa 패키지를 설치합니다.

npm install next-pwa
# 또는
yarn add next-pwa

next.config.js 설정

프로젝트 루트에 있는 next.config.js 파일에 next-pwa 설정을 추가합니다.

next.config.js
// next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
  // 여기에 Next.js 기본 설정을 추가합니다.
  reactStrictMode: true,
  swcMinify: true,
  // output: 'standalone', // Docker 등 독립 실행 가능한 빌드 시 사용

  // PWA 설정
  // 'next-pwa' 패키지를 임포트하여 withPWA 래퍼를 사용합니다.
  // 이 래퍼가 Next.js 빌드 시 PWA 관련 파일을 자동으로 생성하고 서비스 워커를 설정합니다.
  // (Next.js 13 이상에서 withPWA 임포트 방식 변경)
};

// Next.js 13+ App Router에서 next-pwa 사용 시
const withPWA = require('@next/pwa')({
  dest: 'public', // 서비스 워커 및 매니페스트 파일이 생성될 디렉토리 (필수)
  register: true, // 서비스 워커 자동 등록
  skipWaiting: true, // 새 서비스 워커 활성화 시 기존 서비스 워커가 즉시 교체되도록 설정
  disable: process.env.NODE_ENV === 'development', // 개발 모드에서는 PWA 비활성화 (권장)
  // buildExcludes: [/middleware.js$/], // Next.js 미들웨어 파일을 서비스 워커 캐싱에서 제외
  // fallbacks: { // 오프라인 폴백 페이지 설정 (선택 사항)
  //   image: '/static/images/fallback.png',
  //   document: '/offline', // 오프라인일 때 보여줄 페이지
  // }
});

module.exports = withPWA(nextConfig);

설명

  • dest: 'public': 빌드된 서비스 워커(sw.js)와 워크박스 설정 파일(workbox-*.js)이 public 디렉토리에 생성되도록 지정합니다. 이 파일들은 웹 서버를 통해 접근 가능해야 합니다.
  • register: true: 서비스 워커가 자동으로 브라우저에 등록됩니다.
  • skipWaiting: true: 새로운 버전의 서비스 워커가 감지되면, 현재 활성화된 서비스 워커가 즉시 교체되어 사용자가 페이지를 새로고침할 필요 없이 최신 버전을 경험하게 합니다.
  • disable: process.env.NODE_ENV === 'development': 개발 모드에서는 PWA 기능을 비활성화하는 것이 좋습니다. 서비스 워커 캐싱이 개발 과정에서 예상치 못한 문제를 일으킬 수 있기 때문입니다. 프로덕션 빌드에서만 활성화됩니다.
  • buildExcludes: 특정 파일을 서비스 워커 캐싱에서 제외합니다. Next.js 미들웨어는 서비스 워커와 충돌할 수 있으므로 제외하는 것이 좋습니다.
  • fallbacks: 오프라인 상태일 때 보여줄 페이지나 이미지 등을 설정할 수 있습니다.

웹 앱 매니페스트 파일

PWA의 핵심 구성 요소 중 하나인 웹 앱 매니페스트(manifest.json) 파일은 애플리케이션의 이름, 아이콘, 시작 URL, 표시 모드 등을 정의합니다. next-pwa는 기본 매니페스트를 자동으로 생성하지만, 직접 커스텀하여 사용할 수도 있습니다. 프로젝트의 public 디렉토리에 manifest.json 파일을 생성합니다.

public/manifest.json
// public/manifest.json
{
  "name": "My Next.js PWA App",            // 앱의 전체 이름
  "short_name": "Next PWA",               // 홈 화면에 표시될 짧은 이름
  "description": "A Next.js PWA example.", // 앱 설명
  "start_url": "/",                       // 앱 시작 시 로드될 URL
  "display": "standalone",                // 앱 표시 모드 (standalone, fullscreen, minimal-ui, browser)
  "background_color": "#ffffff",          // 스플래시 화면 배경색
  "theme_color": "#000000",               // 브라우저 UI 테마 색상
  "icons": [                              // 다양한 크기의 앱 아이콘 정의
    {
      "src": "/icons/icon-192x192.png",
      "sizes": "192x192",
      "type": "image/png"
    },
    {
      "src": "/icons/icon-512x512.png",
      "sizes": "512x512",
      "type": "image/png"
    }
  ]
}

아이콘 준비: manifest.json에 정의된 경로에 따라 다양한 크기의 아이콘 파일을 public/icons 디렉토리에 준비해야 합니다.

매니페스트 파일 링크 및 테마 색상 설정

Next.js 앱의 layout.tsx 또는 _document.tsx (Page Router) 파일에서 매니페스트 파일을 링크하고 테마 색상을 설정합니다.

app/layout.tsx
// app/layout.tsx (App Router 예시)
import type { Metadata } from 'next';
import './globals.css'; // 전역 CSS 임포트

export const metadata: Metadata = {
  title: 'My Next.js PWA App',
  description: 'A Next.js PWA example.',
  manifest: '/manifest.json', // manifest.json 파일 링크
  themeColor: '#000000',     // 테마 색상 설정
  icons: {
    apple: '/icons/apple-icon-180x180.png', // iOS용 아이콘 (선택 사항)
  }
};

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body>{children}</body>
    </html>
  );
}

PWA 기능 구현 및 테스트

오프라인 지원 (Caching Strategy)

next-pwa는 Workbox를 기반으로 서비스 워커를 생성하며, 기본적으로 정적 자산과 페이지를 캐싱하여 오프라인 지원을 제공합니다.

  • 정적 자산 캐싱: 이미지, CSS, JS 파일 등은 stale-while-revalidate 또는 cache-first 전략으로 캐싱되어 오프라인에서도 접근 가능하게 합니다.
  • 페이지 캐싱: 방문했던 페이지는 캐싱되어 오프라인일 때도 보여줄 수 있습니다. fallbacks 옵션을 통해 오프라인 시 보여줄 특정 페이지를 지정할 수 있습니다.

오프라인 테스트

  1. Next.js 앱을 프로덕션 빌드하고 실행합니다 (npm run build && npm run start).
  2. 브라우저에서 앱에 접속합니다.
  3. 개발자 도구(Chrome DevTools)를 열고 Application 탭으로 이동합니다.
  4. Service Workers 섹션에서 서비스 워커가 활성화되어 있는지 확인합니다.
  5. Network 탭으로 이동하여 네트워크 상태를 "Offline" 으로 변경합니다.
  6. 페이지를 새로고침하거나 다른 페이지로 이동하여 오프라인에서도 앱이 작동하는지 확인합니다.

푸시 알림 (Push Notifications)

푸시 알림은 PWA의 사용자 참여도를 높이는 강력한 기능입니다. 이를 구현하려면 다음 단계가 필요합니다.

  1. 서비스 워커에서 푸시 이벤트 수신: 서비스 워커 파일(sw.js)에서 push 이벤트를 리슨하고 알림을 표시하는 로직을 구현합니다. (이 부분은 next-pwa가 자동으로 처리하지 않으며, 직접 구현해야 합니다.)
  2. 푸시 API 사용: 클라이언트 측에서 PushManager API를 사용하여 사용자에게 알림 권한을 요청하고, 구독 정보를 백엔드로 전송하여 저장합니다.
  3. 백엔드에서 푸시 메시지 전송: 웹 푸시 라이브러리(예: web-push for Node.js)를 사용하여 저장된 구독 정보로 사용자에게 푸시 알림을 보냅니다. VAPID 키 설정이 필요합니다.

푸시 알림 구현은 백엔드 로직이 필요하므로, 이 가이드의 범위를 넘어섭니다. 하지만 PWA 설정의 중요한 부분으로 알아두는 것이 좋습니다.

홈 화면 설치 (Add to Home Screen)

사용자가 PWA를 홈 화면에 설치할 수 있도록 유도하는 기능입니다.

  • 설치 조건 충족
    • 웹 앱 매니페스트 파일이 유효해야 합니다.
    • 서비스 워커가 등록되어 있어야 합니다.
    • HTTPS로 서비스되어야 합니다.
    • 최소한 두 번 이상 웹사이트를 방문하고 충분한 사용 시간을 기록해야 합니다 (브라우저 휴리스틱).
  • 설치 프롬프트: 브라우저는 위의 조건이 충족되면 자동으로 "앱 설치" 또는 "홈 화면에 추가" 프롬프트를 사용자에게 표시할 수 있습니다. 개발자는 beforeinstallprompt 이벤트를 통해 이 프롬프트를 제어하고, 원하는 시점에 사용자에게 설치를 유도하는 버튼을 제공할 수 있습니다.

개발 환경에서 PWA 테스트

개발 모드(npm run dev)에서는 disable: process.env.NODE_ENV === 'development' 설정으로 next-pwa가 비활성화되므로, PWA 기능을 테스트하려면 항상 프로덕션 빌드(npm run build) 후 Next.js 서버를 시작(npm run start)해야 합니다.

프로덕션 빌드 및 실행

npm run build
npm run start

그 후 localhost:3000 (또는 설정된 포트)으로 접속하여 개발자 도구의 Application 탭에서 서비스 워커와 매니페스트를 확인하고, 네트워크를 오프라인으로 전환하여 캐싱 기능을 테스트할 수 있습니다.

PWA는 웹 애플리케이션에 네이티브 앱의 강력한 기능을 부여하여 사용자 경험을 혁신할 수 있는 중요한 기술입니다. Next.js와 next-pwa 라이브러리를 통해 비교적 쉽게 PWA를 구현할 수 있으며, 신뢰성, 속도, 그리고 사용자 참여도 측면에서 큰 이점을 얻을 수 있습니다.