[Next] Next 14 app router에서 PWA가 될까?
들어가며
무료한 주말.. 최근에 react conf(2024)와 js conf(2024)가 올라와서 이것저것 보면서 시간을 보내다 갑자기 PWA 기능에 대한 POC를 진행해 봤다.
PWA
progressive web app인가 줄임말인데. 이것에 대한 설명은 다른 곳에서도 많으니 간략하게 살펴보겠다.
pwa란 웹 기술을 사용하여 네이티브 앱과 유사한 UX/UI를 제공하는 웹 애플리케이션 기술을 의미한다. 기존에 웹브라우저에서 제한적이었던 푸시 알람, 앱 설치, 오프라인 사용등을 지원한다.
번외로 pwa는 구글 진형에서는 나름 밀고 있는데, ios 쪽에선 반대한다고 한다.
구현
우선 내가 검증하고 싶은 포인트는 총 3개였다.
- PWA에서도 스토리지들이 잘 동작할까?
- PWA에서도 worker, wasm 등이 제대로 동작할까?
- next.js 14 app router에도 제대로 동작할까?
결론부터 말하자면 제대로 되는듯하다.(확답을 하지 못하는 것은 고민하고 구현까지 1시간 정도밖에 안 걸렸기 때문이다.)
아직 기능적으로 여러 테스트가 필요하지만 주요 기능으로 테스트해 봤더니 제대로 동작하는 것까지 확인했다. 추가로 PWA환경에서 테스트를 어떻게 돌려야 할지도 가늠이 안되니 이건 추후에 PWA도입한다면 테스트코드도 작성해 보면 좋을듯하다(물론 PWA커녕, 아직 브라우저 환경에서도 제대로 된 테스트가 없다. 지금 도입 중이긴 하니 언젠간 되겠지)
설치
우선 next.js에서 pwa에 관한 라이브러리를 찾으니 next-pwa가 나온다. 다른 문서를 보면 제대로 안된다고 했는데 지금은 또 돼서 이것으로 구현했다.
yarn add next-pwa
라이브러리 설치해 주면 준비는 끝이다.
manifest 파일 추가
app router 기준으로 src/app 하위에 두면 된다. 그리고 이 파일을 만들면 되는데 인터넷에 제너레이터사이트들이 많다.
나는 그중에 https://progressier.com/pwa-manifest-generator 이 사이트를 이용했다. 파일을 만들고 나서 src/app 위치에 두면 된다.
파일명은 manifest.webmanifest로 했는데, 유튜브 형님들 파일명이 이렇게 생겨서 나도 이렇게 했다. 어디 문서에는 manifest.json으로 하라고 되어있다. 실제로 형식도 json파일 형식이기도 하다.
수정된 파일은 아래처럼 생겼다.
src/app/manifest.webmanifest
{
"theme_color": "#8936FF",
"background_color": "#2EC6FE",
"icons": [
{
"purpose": "maskable",
"sizes": "512x512",
"src": "/images/gaudio/icon512_maskable.png",
"type": "image/png"
},
{
"purpose": "any",
"sizes": "512x512",
"src": "/images/gaudio/icon512_rounded.png",
"type": "image/png"
}
],
"orientation": "any",
"display": "standalone",
"dir": "auto",
"lang": "ko-KR",
"name": "Gaudio Studio",
"short_name": "GS",
"start_url": "/?feature=pwa"
}
icons랑 start_url이 신경 쓰자. 이게 이상하면 pwa가 동작하지 않는다.
next.config.js 수정
그다음으로는 이 파일을 수정하는 것이다.
다만 현재 poc 한 프로젝트는 sentry와 next-intl를 사용하고 있어서 export 하는 부분이 다르다. 하지만 그렇게 중요한 문제는 아니다.
// ...중략
const withPWA = require("next-pwa")({
dest: "public",
});
module.exports = withPWA(
withSentryConfig(withNextIntl(nextConfig), sentryWebpackPluginOptions)
);
여기서 끝이면 좋겠지만 현재 middleware도 사용하고 있기에 이 파일도 함께 수정해 주자.
// ...중략
export const config = {
/**
* 아래 경로 제외하고 middleware 적용
* ------
* api: 경로에 api가 포함된 경우
* _next/static: 경로에 _next/static이 포함된 경우
* _next/image: 경로에 _next/image가 포함된 경우
* robot: 경로에 robot이 포함된 경우
* sitemap: 경로에 sitemap이 포함된 경우
* images: 경로에 images가 포함된 경우
* fonts: 경로에 fonts가 포함된 경우
* assets: 경로에 assets가 포함된 경우
* favicon.ico: 경로에 favicon.ico가 포함된 경우
* sw.js: 경로에 sw.js가 포함된 경우
* manifest.webmanifest: 경로에 manifest.webmanifest가 포함된 경우
* ------
*/
matcher: [
"/((?!api|_next/static|_next/image|robot|sitemap|images|fonts|assets|favicon.ico|sw.js|manifest.webmanifest).*)",
],
};
manifest.webmanifest를 예외처리로 추가해야 한다. 아니면 middleware가 가져가서 이상한 값을 뱉는다.
metadata 수정
이제 브라우저가 웹페이지에 들어왔을 때 manifest 파일이 있음을 알려줘야 한다. 이는 metadata로 하기 때문에 next.js의 generateMetadata 함수를 활용하자.
기존에 SEO를 만드는 코드가 있어서 여기에 한 줄을 추가했다.
export async function generateMetadata({
params: { locale },
}: RootLayoutProps): Promise<Metadata> {
try {
const localedSeo = await getLocaledSeo(locale, "home");
return localedSeo;
} catch (e) {
return {
manifest: "/manifest.webmanifest",
applicationName: "Gaudio Studio",
appleWebApp: {
capable: true,
title: "Gaudio Studio",
statusBarStyle: "default",
},
};
}
}
기본적으로 seo에도 i18n이 적용된 터라 코드가 이상한데, 그냥 return 하는 값에 manifest 관련 값을 추가해 준다고 생각하자.
확인
그리고 yarn dev를 통해서 확인해 보면
스크립트에서 PWA 관련된 내용이 추가된 것을 확인할 수 있다.
그리고 url 창을 보면 pwa 다운로드 창이 보이는 것을 확인할 수 있다.
그리고 열기(원래는 설치? 같은 내용이었는데 나는 이미 설치를 해서 그런가 이렇게 뜸)를 하면 완성이다.
그리고 내가 설정한 아이콘에 따라 맥북의 Dock에도 추가되었음을 확인할 있다.
그 외
lighthouse > PWA 사라짐
이전 문서나 블로그를 보면 PWA는 크롬 개발자 도구 > lighthouse > progressive web app를 눌러서 확인하라고 되어있다.
근데 이마저도 최근에 동작은 안 한다. 구글 형님들이 뺐다고 한다.
근데 아직 UI상으로는 남아있어서 저거 누르고 해 봤자 흰 화면만 나온다.
개발자 도구로 디버깅
대신에 개발자도구 > Application > Manifest 쪽을 살펴보면 내용은 잘 나온다. 여기까지 따라왔으면 아래처럼 나오면 된다.
만약 내용을 추가하고 싶으면 이미 PWA로 유명한 사이트 꺼 확인해서 만들면 된다. 챗형 기준으로 5개 뽑아봤다.
물론 나는 트위터랑 유튜브 꺼 매니페이스 파일만 확인했다.
마무리
이것으로 next 프로젝트에서 pwa를 도입하는 방법에 대해서 살펴보았다. 생각보다 간단했고 오히려 글 읽고 내용정리하는데 시간을 더 썼다.
과연 POC를 통과하여 정식 기능으로 추가될지 모르겠지만 오늘 또 이렇게 PWA 만들어봤다.