이것저것 다양한 기술들을 사용해볼 겸 인터렉티브한 웹 포트폴리오를 만들고 있다! 어느정도 구현된 포트폴리오를 PWA로 만들어봤는데, 그 과정을 기록해보려고 한다.

PWA (Progressive Web Apps)

구글 PWA 학습 가이드를 차근차근 읽어보면서 PWA가 어떤 기술인지, 왜 적용하면 좋은지를 이해할 수 있었다. 웹의 접근성과 네이티브 앱의 안정성, 성능을 동시에 가져갈 수 있기 때문에 사용자에게 훨씬 좋은 웹앱 경험을 제공할 수 있다. PWA의 이점을 극대화하려면 서비스워커와 다양한 캐싱 전략 등을 적용해보는 것이 좋을 것 같다.

사실 지극히 개인적인 포트폴리오 사이트를 PWA로 만드는 것이 과하다는 생각이 들긴 하지만, 시도해보기 딱 적당한 사이즈의 프로젝트라 도전해봤다. 🤓

2023.11.02 - UPDATE

서비스 워커가 등록되지 않아 next-pwa 레포 이슈를 확인해봤더니 pages를 기준으로 동작하는 라이브러리이기에 app router와 호환성 문제가 있는 것 같았고, 라이브러리의 유지보수는 이뤄지지 않고 있었다.

해결 방법으로는 next config를 직접 수정하거나 다른 사람이 포크 후 유지보수하고 있는 라이브러리 @ducanh2912/next-pwa 를 사용하는 방법이 있다.

현재는 프로젝트에서 해당 패키지를 제거하고, 직접 서비스 워커를 등록했다.

1. next-pwa 패키지 설치

Next.js 환경에서 PWA 플러그인들을 편리하게 사용하기 위해 next-pwa 패키지를 설치한다. yarn berry zero install 환경에서 설치를 진행했다. (Next.js 프로젝트는 이미 세팅되어 있는 상태이다.)

yarn add next-pwa

2. next config 설정

next-pwa에서 설명하고 있는 것 처럼 프로젝트에서는 Next.js 9 버전 이상을 사용하고 있기 때문에 next.config.js 파일을 다음과 같이 수정해주었다.

const withPWA = require('next-pwa')({
  dest: 'public',
});

/** @type {import('next').NextConfig} */
const nextConfig = {
  // next.js config
};

module.exports = withPWA(nextConfig);

그리고 빌드를 해보면

yarn build

/public 내부에 workbox-*.jssw.js 파일이 자동으로 생성되는 것을 확인할 수 있다.

3. manifest 파일과 아이콘 추가

웹 앱 매니페스트는 웹 콘텐츠를 운영체제에서 앱으로 표시하는 방법을 브라우저에 알려주는 파일입니다. 매니페스트에는 앱 이름, 아이콘, 테마 색상과 같은 기본 정보, 원하는 방향 및 앱 바로가기와 같은 고급 환경설정, 스크린샷과 같은 카탈로그 메타데이터가 포함될 수 있습니다.

출처: https://web.dev/learn/pwa/web-app-manifest?hl=ko

생성하기

앱 아이콘으로 사용할 512 x 512 사이즈의 png 이미지를 준비한 후, 아래 Generator를 활용해서 manifest 파일과 사이즈별 아이콘들을 만들었다.

저장하기

app router를 사용하고 있는데, Next.js 공식문서에서 manifest 파일은 app 디렉토리 최상단에 위치시키라고 설명하고 있다.

아이콘은 /public/icons/pwa-icons 디렉토리 내부에 저장했다. 원하는 경로에 아이콘들을 저장하고, manifest 파일 icons의 경로만 잘 지정해주면 될 것 같다. public 폴더가 절대경로의 시작임을 주의해서!

{
  "name": "Fryfolio",
  "short_name": "Fryfolio",
  "description": "김규란 - Frontend Developer",
  "theme_color": "#ffc211",
  "background_color": "#ffffff",
  "display": "standalone",
  "scope": "./",
  "start_url": "./",
  "icons": [
    {
      "src": "/icons/pwa-icons/icon-72x72.png",
      "sizes": "72x72",
      "type": "image/png",
      "purpose": "maskable any"
    },
    ...
  ]
}

4. metadata 제공

이제 manifest와 같은 메타 데이터가 제공될 수 있도록 관련 태그를 작성해야한다.

그런데 Next.js의 metadata 관련 문서를 읽어보니, app 디렉토리에 특정 컨벤션의 파일이 존재하면 자동으로 <head /> 내부에 관련 태그들을 삽입한다는 것을 알 수 있었다. 그래서 manifest 관련 태그를 따로 작성하지 않아도 manifest 파일의 정보가 잘 제공된 것을 확인할 수 있다. (편..편하다!😲)

chrome application 탭에서 manifest 정보 확인

아이콘

favicon은 이미 적용되어 있고, iOS 아이콘을 적용하기 위해 app 디렉토리 최상단에 appple-icon.png 파일을 하나 더 두었다. (참고)

스플래쉬 스크린

넷플릭스 촤라락.. 하는 것처럼 멋진 스플래쉬 화면을 만들고 싶었지만.. PWA로 동작하는게 빨리 보고싶어서 아이콘으로 iOS Splash Screen Generator를 활용해서 후다닥 만들었다.

위 사이트에서는 디바이스 크기별 태그들을 바로 복사해서 사용할 수 있게 제공해준다.

<link
  href="splashscreens/iphone5_splash.png"
  media="(device-width: 320px) and (device-height: 568px) and (-webkit-device-pixel-ratio: 2)"
  rel="apple-touch-startup-image"
/>
...

하지만 Next.js app router를 사용할 때는 app/layout.tsx 파일 내부에 metatdata를 통해 객체 형태로 제공해야한다. lighthouse로 PWA 관련 리포트를 확인해가면서 적용했는데, theme-color 메타태그가 없다는 메세지가 보여서 함께 설정해줬다.

export const metadata: Metadata = {
  title: 'Fryfolio',
  description: 'developer kyurankim portfolio',
  themeColor: '#ffc211',
  icons: {
    other: [
      {
        url: '/icons/splashscreens/iphone5_splash.png',
        media:
          '(device-width: 320px) and (device-height: 568px) and (-webkit-device-pixel-ratio: 2)',
        rel: 'apple-touch-startup-image',
      },
      ...
    ],
  },
};

Next.js 14부터는 metadata 객체의 themeColor 필드가 사용되지 않고, viewport 객체를 통해 사용해야한다고 한다. (참고)

5. 빌드 & 서버 실행

이제 구색은 어느정도 갖춰진 것 같다. 다시 프로젝트를 빌드를 하고, dev server를 실행시켜보면

yarn build && yarn dev

앱을 설치할 수 있는 아이콘이 url 표시줄에 보인다! 🥺

chrome-pwa-result

모바일에서도 잘 동작한다! 😆
아이콘과 스플래쉬 화면 수정이 필요해보이지만.. 꽤 귀엽다.. 🫢

iphone-pwa-result

마무리

PWA를 만들었으니, 그 목적에 부합하게 다양한 모바일 디바이스에 대응이 가능하도록 리팩터링을 해야될 것 같다. 그리고 앱뷰로 디자인된 프로젝트를 하나 진행하고 있는데, 여유가 된다면 PWA로 만들어보면서 서비스워커, 캐싱 등도 적절히 사용해봐야겠다!

참고하면 좋을 글