Nextjs에 PWA(Progressive Web Application) 기술 적용하기

LIMHALIM·2024년 3월 13일
2

해커톤 시작 D-2! 내가 이번에 함께하게 된 팀의 프로젝트가 웹/앱으로 개발이 진행 될 예정이라, PWA라는 개념과 적용 과정에 대해 설명하고자 한다.


PWA는 Progressive Web Application의 줄임말로, HTML, CSS, 자바스크립트와 같은 웹 기술들을 사용해 만드는 앱을 말한다. PWA는 네이티브 앱보다 빨리 개발할 수 있으며 푸시 알림이나 오프라인 지원과 같은 네이티브 앱의 특징들을 모두 제공한다고 한다.

쉽게 말해, 우리가 기존에 앱 스토어에서 설치하는 것 뿐만 아니라, 웹 기술만으로 앱과 같은 기능을 갖춘 웹 앱이다.

장점

  1. PWA는 안드로이드, iOS 각 네이티브 앱을 개발하는 데 필요한 기술이 하나도 요구되지 않는다. 그저 웹 개발에 필요한 기술들 만으로 다양한 플랫폼에서 동작하고 설치 가능한 앱을 빠르게 만들 수 있다. 즉 한 번의 개발로 안드로이드, iOS 모두 호환이 가능하다. 이는 앱 생산성을 극대화하고 개발 비용을 줄이는 효과를 가져온다고 한다.

  2. 네이티브 앱처럼 푸쉬 알림이 가능하면서도 SEO(검색 엔진 최적화)가 가능하는 것입니다. 기존의 웹은 푸쉬 알림 같은 기능은 꿈꾸기도 힘들었을 만큼 푸쉬 알림은 네이티브 앱의 일종의 특권이었는데, 이제 PWA도 푸쉬 알림이 가능해지면서 웹에서도 이를 통한 사용자의 재참여 유도가 가능해졌다고 한다. 그러면서도 PWA는 본질적으로 웹이기 때문에 검색엔진을 통한 검색을 통해 새 사용자를 유입할 수 있다.

  3. PWA는 Service Worker 덕분에 앱 동작에 필요한 asset 들과 일부 API call들에 대한 캐싱이 가능하다. 이 덕분에 PWA는 사용자의 장치가 오프라인이거나 불안정한 저속도 환경에 있더라도 캐싱 된 리소스로 안정적인 앱 사용을 지원한다.

특징

1. 메인 엔트리 포인트
PWA(프로그레시브 웹 앱)은 일반적으로 index.html 파일을 메인 엔트리 포인트로 사용한다.
이 파일은 앱의 기본적인 구조와 레이아웃을 정의하며, 필요한 리소스 및 스크립트 파일을 로드한다.

2. 서비스 워커(Service Worker)

  • 서비스 워커는 프로그레시브 웹 앱의 핵심 요소로, 브라우저와 웹 앱 사이에 위치하여 웹 앱의 동작을 제어하는 백그라운드에서 실행되는 JavaScript 파일이다.
  • 서비스 워커는 네트워크 요청을 가로채고 관리하여 오프라인 작동이 가능하도록 하고, 캐싱 및 푸시 알림과 같은 기능을 제공하여 웹 앱의 성능을 향상시킨다고 한다.
  • 서비스 워커는 일반적으로 웹 앱의 루트 디렉토리에 service-worker.js와 같은 이름으로 작성되며, 등록 및 설치 과정을 거친 후에 브라우저에서 실행된다.
  • 서비스 워커는 웹 앱의 컨텍스트에서 분리되어 독립적으로 동작하므로, 브라우저 종속성과는 독립적으로 개발될 수 있다. 브라우저의 백그라운드에서 독립된 스레드를 실행하기 때문에 사용자가 해당 메인 앱을 켜놓고 있지 않아도 백그라운드에서 실행할 수 있다.

3. Manifest 파일
매니페스트 파일은 웹 앱의 메타데이터를 포함하는 JSON 파일이다. 이 파일에는 앱의 이름, 아이콘, 시작 URL 등의 정보가 포함되어 있다. 이 파일은 웹 앱을 설치하고 홈 화면에 아이콘을 추가하는 데 사용된다고 한다.


적용 방법

1. pwa 설치

npm i next-pwa

2. next config 설정
next.config.js

const withPWA = require('next-pwa');
const isProduction = process.env.NODE_ENV === 'production';

const config = {
  reactStrictMode: true,
  swcMinify: true,
  compiler: {
    styledComponents: true,
  },
  webpack(config) {
    config.module.rules.push({
      test: /\.svg$/,
      use: ['@svgr/webpack'],
    });

    return config;
  },
};

const nextConfig = withPWA({
  dest: 'public',
  // disable: !isProduction,
  runtimeCaching: [],
})(config);

module.exports = nextConfig;

3. manifest 파일과 아이콘 추가
public/manifest.json

{
  "theme_color": "#ededed",
  "background_color": "#ededed",
  "display": "standalone",
  "scope": "/",
  "start_url": "/",
  "name": "걱정보관함",
  "short_name": "걱정보관함",
  "icons": [
    {
      "src": "/assets/icons/app/16x16.png",
      "sizes": "16x16",
      "type": "image/png"
    },
    {
      "src": "/assets/icons/app/24x24.png",
      "sizes": "24x24",
      "type": "image/png"
    },
    {
      "src": "/assets/icons/app/32x32.png",
      "sizes": "32x32",
      "type": "image/png"
    },
    {
      "src": "/assets/icons/app/48x48.png",
      "sizes": "48x48",
      "type": "image/png"
    },
    {
      "src": "/assets/icons/app/64x64.png",
      "sizes": "64x64",
      "type": "image/png"
    },
    {
      "src": "/assets/icons/app/128x128.png",
      "sizes": "128x128",
      "type": "image/png"
    },
    {
      "src": "/assets/icons/app/256x256.png",
      "sizes": "256x256",
      "type": "image/png"
    },
    {
      "src": "/assets/icons/app/512x512.png",
      "sizes": "512x512",
      "type": "image/png"
    },
    {
      "src": "/assets/icons/app/1024x1024.png",
      "sizes": "1024x1024",
      "type": "image/png"
    }
  ]
}

⚠️ 여기서 주의할점! src의 경로는 public절대 경로이다.
아이콘은 public/assets/icons/app에 저장했다.

4. _document.tsx 파일에 manifest.json 파일 추가

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

export default function Document() {
  return (
    <Html lang="en">
      <Head>
        <link rel="manifest" href="/manifest.json" /> // 추가
      </Head>
      <body>
        <Main />
        <NextScript />
      </body>
    </Html>
  );
}
  1. 빌드 후 개발자 도구의 Lighthouse 탭에서 아래와 같이 pwa 임을 확인할 수 있다! 🎉
profile
모든 익숙함에 물음표 더하기

0개의 댓글