회사에서 개발한 Web App 하나가 있는데, 이 녀석을 모바일 버전으로도 구현해달라는 요구를 전달 받았다.
반응형 웹으로 만들면 될 것 같다고 생각하고 딱 그정도만 해놨는데 그러고나니 매번 브라우저로 들어가서 url을 치고 들어가는게 힘들다는 이야기가 있어서
결국 PWA 를 적용하기로 결정했다..
1. 굳이 PWA를 적용하게 된 이유
RN(React Native)로 뭐 모바일 앱도 하나 만들면 되지 않나요? 라고 할 수 있는데, 물론 내가 React로 SPA를 개발하는 사람이긴 하다만
RN을 사용해서 개발해본적은 없기도 하고, 시도하자니 너무 처음부터 또 App을 빌딩을 해야해서 솔직히 귀찮았던게 크다.
또 몇 년 전쯤 마침 Apple이 PWA의 지원을 확대하겠다고 WWDC에서 발표했던걸 알고 있었기 때문에, 음 그럼 PWA로 구현해볼까? 하는 생각을 했다.
그러면 어차피 반응형으로 개발한 앱이니 모바일 디바이스에서는 자연스레 모바일 화면으로 나올테니까 말이다.
2. PWA 란?
PWA는 Progressive Web App의 약어이다. 원래 모바일 네이티브 앱을 개발하는 이유 중에 가장 크고 대부분을 차지하는 것이 알림 기능을 웹은 적용할 수 없다는 것이었는데,
모바일 디바이스를 통해서 프로그램에 접근하는 사용자의 수가 훠얼씬 더 많기 때문에 웹앱만을 개발하는 경우엔 사용자 유치가 쉽지 않았다.
하지만 PWA가 그 벽을 허물면서, 상당히 개발의 생산성이 올라갔다고 볼 수 있다. 대표적인 PWA로 개발된 앱들이 스타벅스, 트위터 가 있음.
기본적으로 PWA를 구현할 때 필요한 것은 두가지다. Service-Worker 라는 JS 파일을 구현해야하고, Manifest 파일이 존재해야함.
이 두가지만 존재한다면 브라우저가 자연스럽게 PWA 구나 하고 설치버튼을 따란 하고 띄워줌.
Service-Worker의 역할은 백그라운드에서 캐싱도 하고, 구현만 한다면 알림을 띄우는 등 다양한 백그라운드 기능들을 구현하는 용도다. 즉 이 파일이 전달되어 실행되면서 네이티브 앱과 같은 역할을 하는 것임.
Manifest 파일 같은 경우엔 CRA로 앱을 생성하면 자동으로 생긴다고 알고 있는데, Next도 그렇다고 알고 있음.
이건 그냥 메타데이터 묶음이다. 이 앱에 대한 대략적인 정보를 담고 있는 파일이라고 보면 된다. 여기에 앱 아이콘이라던지 PWA 가 설치되는데 필요한 정보들이 조금씩 담겨 있음.
이 두가지만 구현하면 그냥 PWA가 되는거다.
3. 구현 방법
사실 내가 만든 건 알림 같은건 굳이 필요하지 않은 앱이기 때문에, 설치만 가능하게끔 상당히 심플하게 만들기만 하면 됐었다. 그래서 커스터마이즈를 할 필요도 없었고,
그냥 모바일 환경에서 "홈화면에 추가" 와 비슷한 기능을 구현하되, 매번 배포를 할 때마다 새로운 정적자원을 패치해오도록 하는게 중요한 부분이었음.
또, Vite 라는 번들러를 통해 앱을 빌드하고 있었기 때문에, 마침 Vite PWA라는 플러그인의 존재를 알게 되어서 그냥 그걸로 설정만 해주는 방식으로 가져갔다.
길게 설명을 하긴 했는데 요약하면 그냥 날먹하기로 했다는 거임.
// package.json
"devDependencies": {
"@types/node": "20.12.13",
"@types/react": "18.3.3",
"@types/react-dom": "18.3.0",
"@types/rollup-plugin-auto-external": "2.0.5",
"@typescript-eslint/eslint-plugin": "6.21.0",
"@typescript-eslint/parser": "6.21.0",
"@vitejs/plugin-react": "4.3.0",
"autoprefixer": "10.4.19",
"eslint": "8.57.0",
"eslint-plugin-react-hooks": "4.6.2",
"eslint-plugin-react-refresh": "0.4.7",
"postcss": "8.4.38",
"postcss-import": "16.1.0",
"postcss-nesting": "12.1.5",
"tailwindcss": "3.4.3",
"typescript": "5.4.5",
"vite": "5.2.12",
"vite-plugin-pwa": "0.20.0"
}
위와 같이 dependencies에 vite-plugin-pwa를 추가해준다.
// vite.config.js | ts
export default defineConfig({
plugin: [VitePWA({
registerType: 'autoUpdate',
devOptions:{enabled: true}, // vite dev 로 돌려도 PWA 까지 볼 수 있게끔 주는 옵션
includeAssets: [
'favicon.ico',
'/assets/icons/icon-60.png',
'/assets/icons/icon-192-maskable.png',
"/assets/icons/icon-512-maskable.png"
],
manifest: {
name: 'App Name',
short_name: 'App Name',
start_url: "/",
display: "standalone",
theme_color: '#ffffff',
icons:['아이콘정보들이 들어가는 자리']
}
})
]
})
그리고 이런 식으로 PWA로 만들겠다고 Vite.config.js/ts에다가 설정만 해주면 끝나는거임.
이렇게만 해주면 이 녀석이 앱이 빌드 될 때 PWA에 필요한 Service-Worker 랑 manifest 파일을 자동으로 만들어준다고 보면 됨.
4. 생겼던 이슈
- Service Worker가 자꾸 요청을 못보내게 함.
사실 이 PWA로 구현한 앱이 도메인을 여러개 만들지 않고 한개의 도메인 안에서 SubPath를 사용해 4개의 앱을 배포해야하는 케이스였는데,
이런 케이스에서 진짜 불편한 내용이 바로 Service-Worker의 존재였다. Service-Worker는 기본적으로 로드해온 정적자원들을 캐싱해두고
이 녀석이 네트워크 요청을 가로채서 캐싱해둔 애들을 갖다 주거나 뭐 이런 일을 하는데, 이런 것 때문에 SubPath 내에 배포되어있는 자원을 요청하려고
url을 치면 자꾸 이 Service-Worker가 지가 캐싱해둔걸 갖다주는거였음.
때문에 한가지 앱을 제외하고 나머지 앱은 구경도 못해보는 상황이 생겼었다.
그래서 캐싱을 안하도록 커스텀을 할까 하다가, 시간이 촉박해서 Service Worker 파일은 만들되, Resource를 fetch 해오는 로직을 구현하지 않는 selfDestroying이라는
옵션을 찾아서 걍 진짜 설치만 가능하도록 껍데기만 PWA로 구현했다.
5. 마무리
PWA 구현이 필요해서 하긴 했다만.. 솔직히 제대로 사용해본건 아니라고 보긴한다. 그래서 좀 아쉬움. 알림도 구현해보고 좀 그래야하는데 말이다. 다음에 포트폴리오 같은 용도로 개발하게 된다면 적용해봐야지..
'Dev > MobileApp' 카테고리의 다른 글
[APP] 앱 개발을 시작하기 전에 (0) | 2023.06.09 |
---|---|
[React Native] React Native cli 로 시작하기 (0) | 2023.06.08 |
[Flutter] Template 실행시켜보기 (0) | 2023.06.08 |
[React Native] EnvSet (0) | 2023.06.08 |
[Flutter] EnvSet (0) | 2023.06.07 |