해커톤 시작 D-2! 내가 이번에 함께하게 된 팀의 프로젝트가 웹/앱으로 개발이 진행 될 예정이라,
PWA
라는 개념과 적용 과정에 대해 설명하고자 한다.
PWA
는 Progressive Web Application의 줄임말로, HTML, CSS, 자바스크립트와 같은 웹 기술들을 사용해 만드는 앱을 말한다. PWA는 네이티브 앱보다 빨리 개발할 수 있으며 푸시 알림이나 오프라인 지원과 같은 네이티브 앱의 특징들을 모두 제공한다고 한다.
쉽게 말해, 우리가 기존에 앱 스토어에서 설치하는 것 뿐만 아니라, 웹 기술만으로 앱과 같은 기능을 갖춘 웹 앱이다.
PWA는 안드로이드, iOS 각 네이티브 앱을 개발하는 데 필요한 기술이 하나도 요구되지 않는다. 그저 웹 개발에 필요한 기술들 만으로 다양한 플랫폼에서 동작하고 설치 가능한 앱을 빠르게 만들 수 있다. 즉 한 번의 개발로 안드로이드, iOS 모두 호환이 가능하다. 이는 앱 생산성을 극대화하고 개발 비용을 줄이는 효과를 가져온다고 한다.
네이티브 앱처럼 푸쉬 알림이 가능하면서도 SEO(검색 엔진 최적화)가 가능하는 것입니다. 기존의 웹은 푸쉬 알림 같은 기능은 꿈꾸기도 힘들었을 만큼 푸쉬 알림은 네이티브 앱의 일종의 특권이었는데, 이제 PWA도 푸쉬 알림이 가능해지면서 웹에서도 이를 통한 사용자의 재참여 유도가 가능해졌다고 한다. 그러면서도 PWA는 본질적으로 웹이기 때문에 검색엔진을 통한 검색을 통해 새 사용자를 유입할 수 있다.
PWA는 Service Worker 덕분에 앱 동작에 필요한 asset 들과 일부 API call들에 대한 캐싱이 가능하다. 이 덕분에 PWA는 사용자의 장치가 오프라인이거나 불안정한 저속도 환경에 있더라도 캐싱 된 리소스로 안정적인 앱 사용을 지원한다.
1. 메인 엔트리 포인트
PWA(프로그레시브 웹 앱)은 일반적으로 index.html
파일을 메인 엔트리 포인트로 사용한다.
이 파일은 앱의 기본적인 구조와 레이아웃을 정의하며, 필요한 리소스 및 스크립트 파일을 로드한다.
2. 서비스 워커(Service Worker)
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>
);
}