PWA 홈 설치의 모든 것 (A2HS)
PWA의 캐싱과 푸쉬 기능은 익히 알려져 있지만, 홈 설치에 대해선 제대로 되어있는 문서가 거의 없다. 기능은 기존 바로가기의 전체화면 버전이라 간단해보이지만 구현해보면 빙산의 일각인 걸 절실히 깨닫게 된다.
A2HS
Add To Home Screen, 홈 설치, 웹 앱 설치
사전지식
아래 사전지식이 없으면 이 문서가 읽기 힘들 수 있다.
- es6
- 서비스워커
- 캐싱 전략
조건
홈 설치가 되려면 다음과 같은 조건이 필요하다. 크롬 측 설명인데 다른점이 많아서 하나씩 까보자.
- HTTPS
- 서비스워커 설치
- start_url 이 오프라인 사용가능
- 최소 192px 아이콘 지원
- manifest.json 에 name 과 short_name 값 등록
HTTPS
HTTPS 를 통해 서비스가 제공되어야한다고 나오는데, 도메인 뿐아니라 페이지의 모든 리소스가 HTTPS 프로톨콜로 전송되어야한다.
서비스워커 설치
PWA 를 시작하는데 필수 요소니 자세한 설명은 생략
start_url 오프라인 사용가능
어느 캐싱전략을 사용해도 상관없으나 오프라인 모드로 연결이 되어야한다. 국내 서비스일 경우 크게 느리지 않으므로 Network First Strategy 로 캐싱하는 걸 추천한다. 국외 서비스일 경우 로드되는 리소스까지 캐싱전략을 세워야될 수 있다.
여기서 start_url 에 querystring 을 추가해 사용하는 경우가 대부분일텐데 캐싱되는 URL 은 querystring 이 없다는 걸 감안해야한다.
예를 들어보자.
{
// 보통 fetch request 로 접근되는 경로는 다음과 같다.
"start_url": "/",
// 검색 파라미터가 달려있다면 이런 모양일 것이다.
"start_url": "/?NaPm=",
// 하지만 manifest.json 에 들어있는 경로는 다음과 같을 것이다.
"start_url": "/?pwa=1&utm_source=pwa"
}
유저가 접근시 ['NaPm', 'pwa', 'utm_source']
등의 파라미터를 제거해야 경로가 캐시처리되며 오프라인 접근이 될 것이다.
아이콘 지원
크롬에선 최소 192px 의 아이콘을 지원하라고 나와있지만 스플래시 스크린에서 사용되는 아이콘은 512px 이 우선이다. 게다가 엣지 등의 다른 브라우저는 512px 도 있어야한다.
큰 사이즈의 이미지가 있을 경우 설치시에 네이티브 코드에서 이미지를 리사이징해서 아이콘을 만드므로 512px 하나만 있어도 되지만 홈 설치 시간이 느려지는 원인이 되므로 최소 192px, 512px 두 개는 지원해주자.
여력이 된다면 더 많은 사이즈의 이미지를 지원해줘도 된다. 이미지 업로드 하는 페이지의 리사이징 비용과 이미지별 트래픽 비용도 추가되겠지만 항상 유저의 속도가 중요한 것 아닌가?
이미지가 많을 경우 아래 쪽에 언급할 compatible 기능에서 문제가 생길 수 있다.
앱 이름
name 속성은 스플래시 스크린에 사용되며, short_name 은 바로가기 앱 명에 사용된다. name 속성에 빈 값이 들어갈 경우 (빈 값엔 space 및 'ㄱ' 한자 1키도 포함된다.) short_name 으로 대체된다. 두 속성이 모두 빈 값일 경우 홈 설치가 비활성화 된다.
이 기능은 스펙에 명시되어 있어서 변경 불가능하다.
크롬에선 스플래시 스크린 하단에 앱 이름이 노출되며 기타 브라우저에선 중앙에 노출된다. 최근에 하단으로 변경된 것으로 보인다.
고려 대상
필수 조건에는 없지만 고려해야할 대상들은 아래와 같다.
- background_color
- theme_color
- display
- related_applications
background_color
이 속성은 스플래시 스크린의 배경색을 담당하는데, 배경색은 스플래시 스크린 상의 앱 이름 (name 속성)의 색상에 영향을 미친다.
앱 이름은 배경색이 거므스름한지의 여부에 따라 흰색 또는 검정색으로 노출된다. 이 공식은 contrast ratio 란 스펙으로 정의되어 있으며, 안드로이드 내부에 구현되어있는 소스는 다음과 같다.
private static final float CONTRAST_LIGHT_ITEM_THRESHOLD = 3f;
/**
* Calculates the contrast between the given color and white, using the algorithm provided by
* the WCAG v2 in http://www.w3.org/TR/WCAG20/#contrast-ratiodef.
*/
private static float getContrastForColor(int color) {
float bgR = Color.red(color) / 255f;
float bgG = Color.green(color) / 255f;
float bgB = Color.blue(color) / 255f;
bgR = (bgR < 0.03928f) ? bgR / 12.92f : (float) Math.pow((bgR + 0.055f) / 1.055f, 2.4f);
bgG = (bgG < 0.03928f) ? bgG / 12.92f : (float) Math.pow((bgG + 0.055f) / 1.055f, 2.4f);
bgB = (bgB < 0.03928f) ? bgB / 12.92f : (float) Math.pow((bgB + 0.055f) / 1.055f, 2.4f);
float bgL = 0.2126f * bgR + 0.7152f * bgG + 0.0722f * bgB;
return Math.abs((1.05f) / (bgL + 0.05f));
}
/**
* Check whether lighter or darker foreground elements (i.e. text, drawables etc.)
* should be used depending on the given background color.
* @param backgroundColor The background color value which is being queried.
* @return Whether light colored elements should be used.
*/
public static boolean shouldUseLightForegroundOnBackground(int backgroundColor) {
return getContrastForColor(backgroundColor) >= CONTRAST_LIGHT_ITEM_THRESHOLD;
}
theme_color
이 속성은 주소창의 색상 또는 standalone 모드 시의 상단 상태바의 색상으로 노출된다.
하지만 IOS Safari 에서는 ['black', 'black-translucent']
두 가지 색상으로만 선택이 가능하다.
이 것도 위의 Contrast 알고리즘을 활용해 거므스름한 여부에 따라 설정하면 된다.
display
크롬 문서엔 standalone, fullscreen, minimal-ui 모두 A2HS 의 기능을 활용할 수 있다고 설명되어 있으나, 실제로는 앞의 두 속성만 가능하다. 삼성브라우저는 minimal-ui 속성을 지원하지 않는다.
related_applications
앱을 가지고 있을 경우 앱 다운로드를 유도할 수 있는데, manifest 에 아래 속성만 넣으면 된다. id 는 apk 업로드할 때 그 것과 같다.
{
"prefer_related_applications": true,
"related_applications": [
{
"platform": "play",
"id": "com.google.samples.apps.iosched"
}
]
}
Install Banner
App Install Prompt 또는 각각 브라우저마다 불리는 용어가 다른 이 기능은 PWA 접속시 홈 화면에 추가하라는 유도 배너를 말한다. 이 기능은 브라우저별로 이벤트 및 노출 유무가 천차만별이다.
스펙
배너 | 설치아이콘 | 배너재노출일 | 브라우저아이콘 | |
---|---|---|---|---|
Chrome | 노출 | - | ~3 months | - |
Firefox | - | 노출 | - | 표시 |
Samsung | 노출 | 노출 | ~2 weeks | 표시 |
Edge | 노출 | - | ? | 표시 |
UC | ? | - | ? | ? |
Opera | 노출 | - | ? | 표시 |
Whale | ? | - | - | - |
크롬 빼고는 지원되는 브라우저에서 홈 설치시에 브라우저 아이콘이 모두 노출된다. 이러면 웹 푸쉬를 받을 시에 원래 브라우저에 뱃지가 생긴다고 보면 된다.
배너를 닫을 시에 재노출 기간이 비상식적으로 길다.
배너는 prompt()
메소드로 강제 노출이 불가능하며, 버튼을 클릭하는 액션이 있어야만 한다.
재노출일을 초기화할 시에는 브라우저의 데이터를 모두 삭제해야한다.
(서비스워커 삭제로 불가능, 계정 또는 브라우저에 저장되는 값으로 추정됨)
UC 브라우저는 문서도 있고 설치가 되었던 것 같은데 최근 설치가 되지 않는다. Whale 는 크로미움 기반이라 설치가 되었던 것 같은데 최근 설치가 되지 않는다.
IOS Safari
모바일계의 IE인 사파리는 Web App Manifest 기능을 아직 개발 중에 있다. 그리고 매우 불친절한 개발자 문서1 와 불친절한 개발자 문서2만 가지고 있다.
사파리 버그
사파리에서만 나타나는 크리티컬한 버그가 몇 가지 있다.