Next.js PWA 설정법

Rachel·2025년 1월 5일
1

projects

목록 보기
2/2

PWA 설정법

오늘은 Next.js Page Router 환경에서 PWA 설정하는 방법을 설명하겠습니다.

1. next-pwa 패키지 설치

PWA 설정을 위해 다음 패키지를 설치합니다.

npm i next-pwa

2. next.config.mjs 파일 설정

import withPWA from "next-pwa";

/** @type {import('next').NextConfig} */
const nextConfig = {
  reactStrictMode: true, // Re-enable reactStrictMode if needed
};

export default withPWA({
  dest: "public",
  skipWaiting: true, // PWA-specific options here
})(nextConfig);

위와 같이 withPWA 설정을 넣어줍니다.

전체 코드

import withPWA from 'next-pwa';

/** @type {import('next').NextConfig} */
const nextConfig = {
	reactStrictMode: true, // Re-enable reactStrictMode if needed
	i18n: {
		locales: ['en', 'ko'],
		defaultLocale: 'ko',
		localeDetection: false,
	},
	images: {
		remotePatterns: [
			{
				protocol: 'https',
				hostname: '*.googleusercontent.com',
				port: '',
				pathname: '**',
			},
			{
				protocol: 'https',
				hostname: 'firebasestorage.googleapis.com',
				port: '',
				pathname: '**',
			},
		],
	},
};

export default withPWA({
	dest: 'public',
	skipWaiting: true, // PWA-specific options here
})(nextConfig);

제가 설정한 next.config.mjs 코드 전체입니다.
저는 i18n 다국화 설정과 이미지 설정이 포함되어 있습니다.

3. manifest 설정

PWA 설정을 위해서는 앱의 구성 정보를 담고 있는 manifest.json 파일이 필요합니다.

manifest.json을 쉽게 생성하기 위해서는 manifest-generator 검색해서 편한 사이트 이용하면 됩니다.

저는 progressier 사이트를 이용했습니다.
name, short_name, icons, display, background_color, theme_color, start_url, scope를 설정해주고 json을 다운받아 줍니다.

✏️ 설정 옵션
"display": "standalone" 설정 (추천)

  • "standalone"은 PWA가 설치 후 실행될 때 브라우저 크롬(주소 표시줄, 뒤로 가기 버튼 등)을 숨기고 독립 실행형 앱처럼 표시되도록 설정합니다. 웹 브라우저 창처럼 보이지 않고 네이티브 앱처럼 보이는 환경을 제공합니다.

"orientation": "any" (default)

  • "any"는 PWA가 실행될 때 화면의 방향을 제한하지 않고, 사용자가 장치의 화면을 회전하면 해당 방향(세로 또는 가로)에 맞게 앱이 실행됩니다.
  • 이 옵션을 사용하면 사용자 경험이 유연해질 수 있지만, 앱이 특정 방향에서만 제대로 동작하도록 설계되었다면, 명시적인 방향 제한(예: "portrait" 또는 "landscape")을 사용하는 것이 좋습니다.

🎨 icons 만드는 법

manifest를 만들기 위해서는 앱을 대표하는 아이콘이 필요합니다.
icons에 넣을 이미지를 피그마 등을 이용해서 512 x 512 사이즈로 준비합니다.
(권장 사이즈(192x192, 512x512 등) 중 최소 하나는 제공하는 것이 좋습니다.)

그냥 네모로 만든 앱 아이콘을 저장하면 다른 응용 프로그램들과 다르게 보이는 문제가 있어서 Maskable Icon을 만들어 적용시켜줬습니다.

public 폴더 하위에 생성된 앱 아이콘 이미지 모두 넣어주고 이미지 경로에 유의합니다.
저는 깔끔하게 public 하위에 icons 폴더로 묶어서 넣었습니다.

[참고]

maskable 적용 전 - Mac 환경에서 다른 응용 프로그램처럼 rounded 설정 적용이 안되어 어색하다.

maskable 적용 후 - 다른 응용 프로그램처럼 자연스러운 모습

전체 코드

{
  "theme_color": "#f472b6",
  "background_color": "#fce7f3",
  "icons": [
    {
      "purpose": "maskable",
      "sizes": "512x512",
      "src": "/icons/icon512_maskable.png",
      "type": "image/png"
    },
    {
      "purpose": "any",
      "sizes": "512x512",
      "src": "/icons/icon512_rounded.png",
      "type": "image/png"
    }
  ],
  "orientation": "any",
  "display": "standalone",
  "dir": "auto",
  "lang": "ko",
  "name": "Our Story Ing",
  "short_name": "Ing",
  "start_url": "/",
  "scope": "/"
}

이제 해당 manifest.json 파일 적용을 위해,
src/pages/_document.tsx 파일 Head에 manifest link를 추가해줍니다.

<link rel="manifest" href="/manifest.json" />

전체 코드

import { Html, Head, Main, NextScript } from "next/document";

const Document = () => {
  return (
    <Html lang="en">
      <Head>
        <link rel="manifest" href="/manifest.json" />
        <meta name="theme-color" content="#f472b6" />
        <meta
          name="description"
          content="커플들이 자신들의 여정을 공유할 수 있는 특별한 공간"
        />
      </Head>
      <body>
        <Main />
        <NextScript />
      </body>
    </Html>
  );
};

export default Document;

4. 테스트 (빌드 & 실행)

먼저 빌드 후 재실행해줍니다.

여기서 오류 메시지가 뜬다면 설정이 제대로 완료되지 않은 것으로 오류 메시지를 따라 고쳐줍니다.

자, 이제 설정을 모두 완료했으므로 PWA 앱을 설치해볼까요?

앱이 설치 안된 상태에서 해당 사이트를 접속하면 상단 주소창에 설치 아이콘이 뜨고 누르면 앱을 설치할 수 있습니다. localhost, 배포 환경에서 모두 확인 가능합니다.

설치를 완료하면 다른 응용 프로그램이 있는 곳에
잘 설치된 모습을 확인할 수 있고, 상단 주소창 아이콘이 연결 프로그램 아이콘으로 바뀌고 해당 아이콘을 눌러 다운로드한 프로그램을 열 수 있습니다.

배포후 모바일 환경에서도 똑같이 잘 설치되는 모습을 확인할 수 있습니다.

PWA 앱을 모바일에서 설치하려면 해당 웹사이트에 접속해 '하단 공유 아이콘 클릭-> 홈 화면에 추가'를 누르면 됩니다.


🔍 개념 공부

PWA 앱 실행시 작동하는 Service Worker에 대해 알아보았습니다.
참고

Service Worker란?

Service Worker는 브라우저와 네트워크 사이의 가상 프록시입니다. 이는 프론트엔드 개발자들이 수년간 어려움을 겪었던 문제들을 결국 해결하였습니다(특히 웹 사이트의 자원을 적절히 캐싱하는 방법과, 사용자의 기기가 오프라인일 때 이를 사용할 수 있도록 하는 것 등).

이는 페이지의 메인 JavaScript 코드와 독립된 스레드에서 실행되며, DOM 구조에 대한 어떠한 접근도 갖지 않습니다. 이는 전통적인 웹 프로그래밍과 다른 접근법을 소개합니다. API는 비차단형(non-blocking)이며 여러 컨텍스트 사이에 커뮤니케이션을 주고 받을 수 있습니다. 여러분은 Service Worker에 어떤 작업을 전달할 수 있으며, Promise 기반 접근법을 사용해 결과가 준비될때마다 전달받을 수 있습니다.

Service Worker는 "단지" 오프라인 기능을 제공하는 것 이상으로 알림 처리, 독립된 스레드에서의 복잡한 계산 등 많은 것들을 할 수 있습니다. Service worker는 네트워크 요청을 제어하고 수정하며, 캐시로부터 반환된 커스텀 응답을 제공하거나 응답을 완전히 가공할 수도 있으므로 매우 강력합니다.

보안
Service Worker는 매우 강력하기 때문에 안전한 컨텍스트(HTTPS를 의미)에서만 실행됩니다.
코드를 상용으로 푸시하기전에 먼저 테스트하길 원하신다면, localhost에서 테스트하거나 GitHub Pages를 설정하면 됩니다. 둘 다 HTTPS를 지원합니다.


위 글을 통해 Service Worker는 브라우저와 네트워크 사이의 가상의 프록시로, 메인 JS 코드와 독립된 스레드에서 실행되어 오프라인에서 작동할 수 있음을 알 수 있습니다.

이를 이용해 해당 PWA 앱 프로젝트에서 채팅 알림을 브라우저 알림으로 구현했습니다.
기회가 된다면 브라우저 알림에 관해서도 포스팅하겠습니다.

OKKY 웹사이트에서 처음으로 PWA 앱 설치를 어떻게 하는지 알았었습니다.
웹앱을 구현하고 제일 간단하게 설치할 수 있는 방법이라고 생각합니다.
구현하는 프로젝트에 적합하다면 한 번 시도해보시길!


💗 현재 진행중인 커플 웹앱 ing 구경가기
https://our-story-ing.vercel.app/

profile
기존 블로그: https://hi-rachel.tistory.com

0개의 댓글