프로그레시브 웹 앱
고친 사람 github-actions[bot]
프로그레시브 웹 앱은 웹사이트를 설치한 앱처럼 쓰게 해 주는 설계 방식입니다. 사용자는 주소창 대신 홈 화면의 아이콘으로 사이트를 엽니다. 네트워크가 끊겨도 화면이 뜹니다. 그러면서도 앱 스토어를 거치지 않고 주소 하나로 퍼집니다.
쉽고 빠른 이해
프로그레시브 웹 앱은 웹사이트가 설치형 앱처럼 굴게 만드는 방식입니다. 휴대폰으로 장보기 사이트를 열었더니 「홈 화면에 추가」가 떴습니다. 누르자 주소창 없는 창으로 열립니다. 이런 사이트가 이 방식으로 만든 것입니다.
이게 없으면 둘 중 하나를 골라야 합니다. 웹사이트는 링크 하나로 열리지만 신호가 끊기면 멈춥니다. 설치형 앱은 신호 없이도 열리지만 스토어 심사를 거쳐야 합니다. 게다가 운영체제마다 따로 만들어야 합니다.
도는 순서는 이렇습니다.
- 사이트가 앱 이름과 아이콘을 적은 설명 파일을 함께 내놓습니다
- 요청을 가로채는 스크립트가 첫 방문 때 화면 파일을 저장해 둡니다
- 브라우저가 설치를 권합니다. 설치하면 아이콘으로 열립니다
대가도 있습니다. 저장해 둔 화면 파일을 제때 버리지 못하면 사용자는 옛 화면을 봅니다. 휴대폰 기능은 운영체제와 브라우저가 열어 주는 만큼만 씁니다.
이 방식은 자주 다시 여는 도구형 사이트에 맞습니다. 한 번 보고 떠나는 페이지에는 얻을 것이 적습니다.
상세
프로그레시브 웹 앱은 줄여서 PWA(Progressive Web App)라고도 합니다. 이 절은 이 방식이 무엇을 풀려고 나왔는지, 무엇으로 이뤄지는지, 서버에서 무엇이 달라지는지, 어떤 사이트에 맞는지를 봅니다.
웹사이트와 설치형 앱 사이
웹사이트는 주소 하나로 열립니다. 설치할 것이 없습니다. 서버에 새 파일을 올리면 다음 방문부터 모두가 새 화면을 봅니다.
대신 웹사이트는 브라우저 탭 안에서만 삽니다. 탭을 닫으면 사라집니다. 네트워크가 끊기면 빈 화면이 뜹니다.
설치형 앱은 반대편에 섭니다. 네이티브 앱이라는 다른 이름은 운영체제 위에서 바로 돈다는 뜻입니다. 홈 화면에 아이콘이 있습니다. 신호 없이도 열립니다. 알림을 띄워 사용자를 다시 부를 수도 있습니다.
그 대가로 사용자는 앱 스토어에서 찾아 내려받아야 합니다. 새 판을 낼 때마다 스토어 심사를 거칩니다. 운영체제가 다르면 코드도 따로 짭니다.
프로그레시브 웹 앱은 이 둘 사이에서 웹사이트에 발을 딛습니다. 코드는 웹 기술로 짓습니다. 거기에 설치형 앱이 갖던 아이콘·오프라인·알림을 하나씩 얹습니다. 스토어를 거치지 않으므로 배포는 여전히 서버에 파일을 올리는 일입니다.
이름에 붙은 「프로그레시브」
「프로그레시브」는 점진적 향상에서 온 말입니다. 점진적 향상은 어느 브라우저에서나 도는 기본 화면을 먼저 만드는 설계 원칙입니다. 새 기능을 아는 브라우저에서만 그 위에 기능을 더 얹습니다.
그래서 프로그레시브 웹 앱은 따로 빌드한 두 번째 앱이 아닙니다. 설치 기능을 모르는 브라우저에서는 평범한 웹사이트로 열립니다. 아는 브라우저에서는 같은 주소가 설치할 수 있는 앱이 됩니다. 코드 한 벌이 브라우저 능력에 맞춰 할 수 있는 만큼 합니다.
세 가지 재료
브라우저가 사이트 하나를 앱으로 대접하려면 재료가 필요합니다. 흔히 드는 재료는 셋입니다. 각각 무엇을 맡고, 빠지면 무엇이 안 되는지를 표로 먼저 봅니다.
| 재료 | 맡는 일 | 빠지면 |
|---|---|---|
| 웹 앱 매니페스트 | 앱 이름·아이콘·첫 화면 주소·창 모양을 브라우저에 알림 | 브라우저가 설치를 권하지 않음 |
| 서비스 워커 | 요청을 가로채 저장해 둔 응답으로 답함 | 신호가 끊기면 화면이 안 뜸 · 브라우저에 따라 설치도 권하지 않음 |
| HTTPS(HyperText Transfer Protocol Secure) | 사이트와 브라우저 사이의 연결을 암호화함 | 브라우저가 서비스 워커를 받지 않고 설치도 권하지 않음 |
웹 앱 매니페스트는 JSON(JavaScript Object Notation) 형식으로 적은 작은 파일입니다. 페이지가 이 파일의 주소를 적어 두면 브라우저가 읽어 갑니다. 담기는 내용은 이런 모양입니다.
{
"name": "동네 장보기",
"short_name": "장보기",
"start_url": "/",
"display": "standalone",
"icons": [{ "src": "/icon.png", "sizes": "512x512" }]
}
name 과 short_name 은 앱 이름입니다. 홈 화면처럼 칸이 좁은 곳에는 짧은 쪽이 붙습니다. start_url 은 아이콘을 눌렀을 때 처음 여는 주소입니다. display 가 standalone 이면 주소창과 탭 없이 앱 창처럼 뜹니다.
서비스 워커는 브라우저가 페이지와 따로 돌리는 스크립트입니다. 사이트가 보내는 요청을 먼저 받습니다. 저장해 둔 응답이 있으면 그것으로 답합니다. 첫 방문 때 화면 뼈대와 글꼴 같은 파일을 저장해 두면 다음부터는 신호 없이도 화면이 뜹니다.
HTTPS 는 암호화한 연결로 웹 문서를 주고받는 방식입니다. 서비스 워커는 사이트의 요청을 전부 가로챌 수 있습니다. 공격자가 중간에서 이 스크립트를 바꿔치기하면 그 사이트를 통째로 쥐게 됩니다. 그래서 브라우저는 암호화한 연결로 받은 사이트에만 서비스 워커를 허용합니다.
개발할 때는 예외가 하나 있습니다. 자기 컴퓨터를 가리키는 주소인 localhost 는 암호화하지 않아도 봐줍니다. 암호화 준비를 따로 하지 않고도 내 컴퓨터에서 시험해 볼 수 있습니다.
설치를 권하는 조건은 브라우저마다 다릅니다. 서비스 워커까지 갖춰야 권하는 브라우저가 있습니다. 매니페스트와 암호화한 연결만 보는 브라우저도 있습니다.
매니페스트만 보는 브라우저에서는 서비스 워커 없이도 설치가 됩니다. 그래도 오프라인을 맡는 재료는 서비스 워커뿐입니다. 이것이 빠지면 설치한 아이콘이 신호 없는 곳에서 빈 화면을 엽니다.
첫 방문부터 설치까지
사용자가 사이트를 처음 열고, 설치하고, 며칠 뒤 신호 없는 곳에서 다시 열기까지를 따라갑니다. 등장하는 것은 사용자·브라우저·서비스 워커·서버 넷입니다.
첫 방문에서 브라우저는 서버에서 페이지와 매니페스트를 받습니다. 페이지는 서비스 워커를 등록합니다. 서비스 워커는 화면 파일을 미리 받아 둡니다. 브라우저는 매니페스트를 읽고 조건이 맞으면 사용자에게 설치를 권합니다.
sequenceDiagram
participant 사용자
participant 브라우저
participant 워커 as 서비스 워커
participant 서버
사용자->>브라우저: 사이트 주소를 연다
브라우저->>서버: 페이지와 매니페스트를 달라
서버-->>브라우저: 페이지와 매니페스트
브라우저->>워커: 워커를 등록한다
워커->>서버: 화면 파일을 미리 받는다
브라우저-->>사용자: 설치를 권한다
사용자->>브라우저: 설치를 누른다
Note over 사용자,서버: 며칠 뒤 · 신호가 끊긴 지하철
사용자->>브라우저: 홈 화면 아이콘을 누른다
브라우저->>워커: 첫 화면을 달라
워커-->>브라우저: 저장해 둔 화면 파일
그림의 아래쪽이 이 방식의 요지입니다. 서버로 가는 화살표가 하나도 없는데 화면이 뜹니다. 서비스 워커가 첫 방문 때 받아 둔 파일로 답했기 때문입니다.
서버 개발에서 달라지는 것
프로그레시브 웹 앱은 브라우저에서 도는 설계입니다. 그래도 서버에 닿는 요청의 모양이 바뀝니다. 이 소절은 백엔드 개발자가 겪는 넷을 봅니다. 요청에 생기는 일 셋과, 서버가 내주는 파일 두 개입니다.
사용자가 옛 화면 코드를 들고 있을 수 있습니다. 서비스 워커가 저장해 둔 화면 파일은 서버에 새 판을 올려도 곧바로 바뀌지 않습니다. 그래서 서버의 API(Application Programming Interface, 응용 프로그램 인터페이스)는 하위 호환을 지켜야 합니다. 새 판을 올린 뒤에도 한동안 옛 화면이 보내는 요청을 받아 준다는 뜻입니다.
요청이 늦게 도착할 수 있습니다. 백그라운드 동기화는 신호가 없는 동안 사용자가 누른 저장을 기기에 모아 뒀다가 연결이 돌아오면 보내는 기능입니다. 이 기능을 쓰면 서버는 몇 시간 전에 만든 요청을 한꺼번에 받습니다. 그래서 서버는 요청마다 기기에서 만든 시각을 함께 받아 둡니다.
같은 요청이 두 번 올 수도 있습니다. 보내던 중에 연결이 끊기면 기기는 성공했는지 몰라 다시 보냅니다. 그래서 서버는 멱등성을 갖춰 둡니다. 같은 요청을 두 번 받아도 결과가 한 번 받은 것과 같다는 뜻입니다.
매니페스트와 서비스 워커 스크립트도 서버가 내주는 파일입니다. 서비스 워커는 기본으로 자기 파일이 놓인 경로 아래의 요청만 가로챕니다. 예를 들어 /js/sw.js 에 둔 워커는 /js/ 아래 요청만 맡습니다. 사이트 전체를 맡기려면 이 스크립트를 사이트 최상단 경로에서 내줘야 합니다.
맞는 사이트와 맞지 않는 사이트
자주 다시 여는 도구형 사이트에 잘 맞습니다. 장보기 목록, 사내 업무 도구, 매장이나 창고에서 쓰는 현장 화면이 그렇습니다. 신호가 약한 곳에서 쓰는 화면이라면 오프라인에서 얻는 것이 더 큽니다.
스토어 심사를 피하고 싶은 팀에도 맞습니다. 운영체제마다 앱을 따로 만들 여력이 없는 팀도 그렇습니다. 웹 코드 한 벌로 여러 기기의 홈 화면에 올라갑니다.
한 번 보고 떠나는 페이지에는 얻을 것이 적습니다. 문서 한 편이나 행사 안내 페이지를 홈 화면에 설치할 사람은 드뭅니다. 설치 권유가 사용자를 귀찮게 할 뿐입니다.
휴대폰 하드웨어를 깊게 쓰는 앱도 맞지 않습니다. 웹 코드는 운영체제와 브라우저가 웹에 열어 준 기능만 부를 수 있습니다.
스토어 검색으로 사용자를 모으려는 서비스도 따져 봐야 합니다. 스토어를 거치지 않는다는 것은 스토어 검색에 걸리지 않는다는 뜻이기도 합니다. 사용자는 링크나 검색 엔진으로 사이트에 먼저 와야 합니다.
잘 맞는 사이트라도 캐시 무효화라는 일거리가 하나 늡니다. 저장해 둔 화면 파일을 언제 버리고 다시 받을지 서비스 워커에 적어 두는 일입니다. 이 판단이 틀리면 사용자가 옛 화면에 갇힙니다.
관련 항목
프로그레시브 웹 앱을 이루는 구성 요소
웹 앱 매니페스트 · 서비스 워커 · HTTPS · 캐시 스토리지 · 앱 셸 · IndexedDB
프로그레시브 웹 앱이 얹는 설치형 앱의 기능
웹 푸시 · 푸시 알림 · 백그라운드 동기화 · 홈 화면에 추가 · 배지 API
프로그레시브 웹 앱을 떠받치는 설계 원칙
점진적 향상 · 우아한 성능 저하 · 반응형 웹 디자인 · 오프라인 우선
프로그레시브 웹 앱과 겨루는 앱 제작 방식
네이티브 앱 · 하이브리드 앱 · 웹뷰 · 크로스 플랫폼 프레임워크 · 플랫폼 전용 앱
프로그레시브 웹 앱이 속하는 상위 분류
프로그레시브 웹 앱이 올라타는 브라우저 구성 요소
브라우저 · 보안 컨텍스트 · 웹 API · DOM · 사용자 에이전트
프로그레시브 웹 앱이 배포되고 퍼지는 경로
프로그레시브 웹 앱을 굴릴 때 겪는 문제
다른 이름: PWA · Progressive Web App · progressive web app · 프로그레시브 웹앱