PWA : 프로그레시브 웹앱

2023. 6. 28. 15:04카테고리 없음

네이티브 앱이란..

스마트폰 운영체제에서만 작동하는 앱을 말한다. 따라서 운영체제 환경에 맞는 별도의 프로그래밍 언어와 SDK라는 개발 도구를 이용해야 제작할 수 있다.

ex) 안드로이드 : 안드로이드 스튜디오, 아이폰 : Xcode

  • 네이티브앱은 일반적으로 개발 난도가 높다. 하지만 카메라, 스피커, GPS, 가속기 처럼 기기에 탑재된 모든 기능을 사용할 수 있다는 것이 장점
  • 네이티브 앱은 전 서계를 시장으로 삼는다. 하지만 업데이트가 필요하면 다시 다운 받아야 한다.

모바일 웹앱 이란…

브라우저로 통신해 운영체제의 한계를 뛰어넘어서 사용자 경험을 똑같이 제공하는 방법.

  • 웹 표준 언어로 만들므로 제작 비용도 저렴하고 개발기간도 짧다. 현재 자신이 사용하는 익숙한 개발언어인 HTML5, CSS3, JS를 그대로 사용해 스마트폰에서 작동하는 앱을 만들 수 있음.
  • URL 링크만 있으면 언제든 앱을 배포할 수 있다. 웹이기 때문에 검색에도 노출이 된다.
  • 웹앱은 웹 파일만 바꿔주면 업데이트가 된다.

하이브리드 앱, 네이티브와 웹앱의 강점을 합쳐보자.

하이브리드앱은 웹 표준 기술을 그대로 사용해서 웹앱을 먼저 만든다. 그 다음 별도의 프레임워크를 활용해 네이티브 앱으로 변환해서 배포한다.

  • 기본기능은 웹 표준으로 구현하고 패키징만 모바일 운영체제로 다르게 적용한다.
  • 앱 개발은 모바일 웹앱, 배포는 네이티브 앱처럼 함한다.

프로그레시브 웹앱!

프로그레시브 웹앱은 모바일 웹앱 처럼 쉽개 개발하고, 네이티브 앱과 똑같은 사용자 경험을 제공하는 것이 궁극적인 목표이다.

웹 처럼 브라우저로 접속하지만, 네이티브 앱처럼 홈화면에 바로가기 아이콘 생성, 알림도 보낼 수 있고, 심지어는 오프라인 상태에서도 동작한다.

프로그레시브 웹앱은 오프라인에서 실행되는 캐시, 보안성이 높은 HTTPS, SPA 와 같은 최신 웹 기술 덕분에 전통적인 모바일 웹앱과 달리 웹의 장점은 그대로 유지하면서 네이티브앱의 강점으로 무장되어 있다.

프로그레시브 웹앱의 조건

사실 프로그레시브 웹앱은 새로 생겨난 기술은 아니다. 여러 최신 웹 표준기술을 집약한 하나의 프로그래밍 철학이라고 볼 수 있다. 프로그레시브 웹앱이 탄생할 수 있었던 대표기술을 알아보자

서비스 워커

웹 브라우저 안에 있지만 웹 페이지와는 분리되어 항상 실행되는 백그라운드 프로그램

  • 브라우저와 서버사이에서 상탯값의 변경을 감지하고, 푸시 알림으로 사용자에게 메시지와 댓글알림을 보냅니다.
  • 오프라인 상태에서도 작동합니다. → 인터넷 연결 여부가 중요하지 않다.

웹앱 메니페스트

앱 소개 정보와 기본 설정을 담은 JSON 파일을 말한다. PWA는 무조건 메니페스트 파일을 포함해야 한다. 그래야 브라우저는 PWA를 인식할 수 있다.

HTTPS

HTTPS는 HTTP 프로토콜에 암호화와 인증을 거쳐 보안을 강화한 웹 통신 규약이다.

  • 서버와 브라우저 사이에 주고받는 데이터가 암호화 되므로 도중에 데이터를 가로채도 어떤 내용인지 알 수 없다. 따라서 전자상거래 등의 결제 시스템을 구축할 때 특히 유용하다.
  • 서비스 워커를 이용하여 PWA를 배포할 때는 반드시 HTTPS 프로토콜을 사용해야 한다. 왜냐하면 HTTPS 프로토콜은 라이트하우스에서 인증을 받기 위한 의무사항인 데다가 홈화면 추가는 HTTPS에서만 지원하기 때문이다.

푸시알림

사용자의 재방문을 유도하고 서비스 이용시간을 늘리는 기능이다.

  • PWA에서는 푸시 알림에 동의만 했다면 웹사이트에 한 번 방문하고 떠난 사용자에게도 알림을 보낼 수 있다.

홈 화면에 추가

다음 4가지 조건을 만족하면 운영체제에 진짜 앱처럼 인식하는 바로가기를 추가할 수 있다.

  1. HTTPS 접속
  2. 매니페스트 등록
  3. 서비스 워커 설치
  4. PWA 설치 여부

웹 API

PWA 웹 API를 이용해서 네이티브 앱처럼 위치 정보를 받거나 스마트폰의 카메라도 작동할 수 있습니다.

PWA가 제공하는 사용자 경험 9가지

  1. 오프라인 온라인에서도 걱정없는 신뢰성
  2. 네이티브 앱보다 간단히 설치할 수 있는 편리성
  3. 훨씬 강력한 보안성
  4. 단골 손님을 늘리는 구독자 고객 관리
  5. 모든 곳에서 실행되는 멀티 플랫폼 지원
  6. 검색에 잘 노출되고 잘 퍼지는 확장성
  7. 항상 새것 같은 최신성
  8. 네이티브 앱도 부럽지 않은 사용성
  9. 네이티브 앱보다 빠른 배포, 실행, 반응 속도

PWA를 순수 자바스크립트로 만들어 보기

사전작업 : 이미지 파일을 만들어야 한다.

PWA는 멀티플렛폼에 대비해 다양한 아이콘 파일이 필요하다.

  • 홈 화면 아이콘
  • 웹브라우저 파비콘
  • 프로그램 자체에서 사용하는 이미지

1. 매니 페스트 작성하기

전체 매니페스트 파일

{
  "name": "Stake House PWA by yeongi",
  "short_name": "Stake House",
  "description": "스테이크 냠냠",
  "scope": ".",
  "start_url": "./",
  "display": "fullscreen",
  "orientation": "portrait",
  "theme_color": "#ffffff",
  "background_color": "#ffffff",
  "icons": [
    {
      "src": "images/android-chrome-512x512.png",
      "sizes": "512x512",
      "type": "image/png"
    }
  ]
}
    "name": "Stake House PWA by yeongi",
  "short_name": "Stake House",
  "description": "스테이크 냠냠",
  • 다양한 곳에 표시되는 제목과 앱소개 정보
    • name : 바로가기 아이콘 설치를 권장하는 팝업 배너, 스플래시 스크린에 표시되는 제목
    • short_name : 바탕화면 바로가기 아이콘 아래 표시되는 제목
    • decription : 애플리케이션의 자기소개 문장 ( 웹 크롤러에 의해 수집됨 )
"scope": ".",
"start_url": "./",
  • 매니 페스트에 정의된 내용이 적용 될 수 있는 파일들의 범위를 지정
"display": "fullscreen",
  • PWA를 실행하면 나타나는 화면의 형태를 설정함
"orientation": "portrait",
  • 화면의 방향을 설정
    • portrait : 세로
    • landscape : 가로
"theme_color": "#ffffff",
"background_color": "#ffffff",
  • theme_color : 상태 표시줄의 색상
  • background_color : 스플래시 스크린의 배경색
"icons": [
    {
      "src": "images/android-chrome-512x512.png",
      "sizes": "512x512",
      "type": "image/png"
    }
  ]
  • 아이콘 설정

2. 메인 화면 작성하기

<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="UTF-8" />
    <!-- PWA 메니페스트 파일 연결, 상태 표시줄 흰색으로 변경 -->
    <link rel="manifest" href="manifest.json" />
    <meta name="theme-color" content="#FFFFFF" />

    <!-- 모바일 기기 뷰포트, 브라우저 주소 표시줄의 파비콘 설정 -->
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link
      rel="shortcut icon"
      type="image/png"
      sizes="32x32"
      href="/images/favicon.ico"
    />
    <link
      rel="apple-touch-icon"
      sizes="180x180"
      href="/images/apple-touch-icon.png"
    />
    <link
      rel="icon"
      type="image/png"
      sizes="32x32"
      href="/images/favicon-32x32.png"
    />
    <link
      rel="icon"
      type="image/png"
      sizes="16x16"
      href="/images/favicon-16x16.png"
    />

    <title>Document</title>
  </head>
  <body></body>
</html>
  • 언어를 작성하지 않으면 ‘다른 언어로 번역하시겠습니까?’를 계속 물어봄 ux 가 감소함
  • 모바일 브라우저로 pc용 사이트에 접속하면 가끔 화면이 작게 보이는 경우가 있음 → 뷰포트 설정으로 해결
  • 파비콘은 브라우저의 탭이나 즐겨찾기 옆에 있는 귀여운 아이콘을 말함.
<title>Stake House by PWA</title>

    <style>
      html,
      body {
        height: 100%;
        background-color: #f3a530;
        color: #ffffff;
      }

      .container {
        height: 100%;
        display: flex;
        align-items: center;
        justify-content: center;
      }
    </style>

  <body>
    <div class="container">
      <h1>안녕하세요!</h1>
      <img src="/images/favicon-32x32.png" alt="" />
      <p>by yeongi</p>
    </div>

    <!-- 서비스 워커 등록 -->
    <script>
      if ("serviceWorker" in navigator) {
        navigator.serviceWorker.register("/service.js").then(function () {
          console.log("서비스 워커가 등록됨");
        });
      }
    </script>
  </body>

  • 실행 화면

3. 서비스 워커 작성하기

서비스워커는 브라우저와 분링되어 독립해서 실행될 수 있다. 서비스 워커는 캐시, 푸시 알림, 웹API와 연동 등 다양한 기능을 별도로 수행할 수 있지만, 여기서는 필요한 파일을 캐시하여 메모리에 저장하는 로직을 작성한다.

// 캐시 제목과 캐시할 파일 선언
const sCacheName = "hello-pwa";
const aFilesToCache = [
  "./",
  "./index.html",
  "./manifest.json",
  "./images/favicon-32x32.png",
];

// 서비스 워커 설치하고 캐시 파일 저장
self.addEventListener("install", (pEvent) => {
  console.log("서비스 워커 설치함!");
  pEvent.waitUntil(
    caches.open(sCacheName).then((pCache) => {
      console.log("파일을 캐시에 저장함!");
      return pCache.addAll(aFilesToCache);
    })
  );
});

//고유 번호를 할당받은 서비스워커 작동
self.addEventListener("activate", (pEvent) => {
  console.log("서비스 워커 동작 시작됨!");
});

// 데이터 요청을 받으면 네트워크 또는 캐시에서 찾아 반환
self.addEventListener("fetch", (pEvent) => {
  pEvent.respondWith(
    caches
      .match(pEvent.request)
      .then((response) => {
        if (!response) {
          console.log("네트워크에서 데이터 요청!", pEvent.request);
          return fetch(pEvent.request);
        }
        console.log("캐시에서 데이터 요청!", pEvent.request);
        return response;
      })
      .catch((err) => console.log(err))
  );
});

저장된 모습

 

실행 화면

서비스 워커의 생애주기

install → activate → fetch 순서로 이벤트를 발생시킨다.

install

// 서비스 워커 설치하고 캐시 파일 저장
self.addEventListener("install", (pEvent) => {
  console.log("서비스 워커 설치함!");
  pEvent.waitUntil(
    caches.open(sCacheName).then((pCache) => {
      console.log("파일을 캐시에 저장함!");
      return pCache.addAll(aFilesToCache);
    })
  );
});

PWA를 설치하는 단계.

  • 설치 진행 / 설치 완료 후 대기로 구분
  • 서비스 워커가 제대로 설치되면, 그제야 waitUntil( )를 통해서 캐시에 필요한 파일을 저장할 수 있음.

activate

//고유 번호를 할당받은 서비스워커 작동
self.addEventListener("activate", (pEvent) => {
  console.log("서비스 워커 동작 시작됨!");
});

서비스 워커의 두 번째 생애 주기이다.

고유한 ID를 발급받아 브라우저에 성공적으로 등록되면 동작함

엡을 업데이트 하면 서비스 워커도 새로운 내용으로 교체해야 한다. 이때 호출 되는것이 activate 이벤트 이다.

  • 활성중 / 활성 후 로 구분

fetch

// 데이터 요청을 받으면 네트워크 또는 캐시에서 찾아 반환
self.addEventListener("fetch", (pEvent) => {
  pEvent.respondWith(
    caches
      .match(pEvent.request)
      .then((response) => {
        if (!response) {
          console.log("네트워크에서 데이터 요청!", pEvent.request);
          return fetch(pEvent.request);
        }
        console.log("캐시에서 데이터 요청!", pEvent.request);
        return response;
      })
      .catch((err) => console.log(err))
  );
});

마지막 생애주기는 fetch 이벤트로 시작한다.

이 이벤트가 시작되는 대표적인 예는 새로고침을 누를 때이다.

서비스 워커가 있는 경우엔 캐시된 파일을 확인하고, 없으면 인터넷과 통신한다.

 

출처 : 프로그레시브 웹앱 만들기