아키텍처

PWA를 안정적이고, 설치 가능하며, 사용할 수 있게 하는 기술을 최대한 활용하도록 애플리케이션을 설계하려면 먼저 애플리케이션과 그 제약 조건을 이해하고 PWA에 적합한 아키텍처를 선택해야 합니다.

SPA와 MPA 비교

오늘날 웹 개발에는 단일 페이지 앱(SPA)과 다중 페이지 앱(MPA)이라는 두 가지 주요 아키텍처 패턴이 있습니다.

단일 페이지 앱은 앱에서 검색하거나 앱에 제공된 데이터를 기반으로 클라이언트 측 JavaScript가 페이지의 HTML 렌더링 대부분 또는 전체를 제어하도록 하여 정의됩니다. 앱은 브라우저의 내장 탐색을 재정의하여 라우팅 및 뷰 처리 기능으로 대체합니다.

다중 페이지 앱에는 일반적으로 사전 렌더링된 HTML이 브라우저로 직접 전송되고, 브라우저가 HTML 로드를 완료한 후 클라이언트 측 자바스크립트로 개선되는 경우가 많으며 브라우저의 내장 탐색 메커니즘을 사용하여 후속 보기를 표시합니다.

두 아키텍처 모두 PWA를 만드는 데 사용할 수 있습니다.

각각 장단점이 있으므로 사용 사례와 상황에 맞는 적절한 구성을 선택하면 사용자에게 빠르고 안정적인 환경을 제공할 수 있습니다.

단일 페이지 앱

장점
  • 대부분 원자적 인페이지 업데이트
  • 시작 시 클라이언트 측 종속 항목이 로드됩니다.
  • 후속 로드는 캐시 사용량 때문에 빠릅니다.
단점
  • 초기 로드 비용이 높습니다.
  • 성능은 기기 하드웨어 및 네트워크 연결에 따라 달라집니다.
  • 추가적인 앱 복잡성이 필요합니다.

다음과 같은 경우 단일 페이지 앱이 아키텍처에 적합합니다.

  • 사용자 상호작용은 주로 실시간 데이터 대시보드나 동영상 편집 앱 등 동일한 페이지에 표시되는 상호 연결된 데이터의 원자적 업데이트에 중점을 둡니다.
  • 애플리케이션에 클라이언트 측 전용 초기화 종속 항목이 있습니다(예: 시작 비용이 지나치게 높은 서드 파티 인증 제공업체).
  • 뷰를 로드하는 데 필요한 데이터는 특정 클라이언트 측 전용 컨텍스트(예: 연결된 하드웨어의 컨트롤 표시)에 의존합니다.
  • 앱이 작고 단순하여 크기와 복잡성이 위에 나열된 단점에 영향을 미치지 않습니다.

다음과 같은 경우 SPA는 좋은 아키텍처 선택이 아닐 수 있습니다.

  • 초기 로드 성능이 중요합니다. SPA는 일반적으로 로드할 항목과 표시 방법을 결정하기 위해 더 많은 JavaScript를 로드해야 합니다. 이 자바스크립트의 파싱 및 실행 시간은 콘텐츠 검색과 결합되어 렌더링된 HTML을 전송하는 것보다 느립니다.
  • 앱이 대부분 저전력에서 평균을 실행하는 기기에서 실행됩니다. SPA는 렌더링에 JavaScript에 의존하기 때문에 사용자 환경은 MPA에서보다 특정 기기의 성능에 훨씬 더 크게 의존합니다.

SPA는 브라우저의 내장 탐색을 해당 라우팅으로 대체해야 하므로 SPA는 현재 뷰를 효율적으로 업데이트하고 탐색 변경을 관리하고 다른 방법으로는 브라우저에서 처리할 이전 뷰를 정리하는 것과 관련하여 최소한의 복잡성을 요구하므로, 전반적으로 유지 관리하기가 어렵고 사용자의 기기에 더 많은 부담을 줍니다.

다중 페이지 앱

장점
  • 대부분 전체 페이지 업데이트
  • 초기 렌더링 속도는 매우 중요합니다.
  • 클라이언트 측 스크립팅을 개선할 수 있습니다.
단점
  • 보조 보기를 사용하려면 다른 서버 호출이 필요합니다.
  • 맥락은 보기 간에 적용되지 않습니다.
  • 서버 또는 사전 렌더링이 필요합니다.

다중 페이지 앱은 다음과 같은 경우에 적합한 아키텍처입니다.

  • 사용자 상호작용은 주로 뉴스나 전자상거래 앱 등 선택적인 컨텍스트 기반 데이터가 포함된 단일 데이터 조회에 중점을 둡니다.
  • 자바스크립트 기반의 대안을 로드, 파싱 및 실행한 후에는 이미 렌더링된 HTML을 브라우저로 전송하는 것이 데이터 요청에서 조합하는 것보다 빠르므로 초기 렌더링 속도가 중요합니다.
  • 클라이언트 측 상호작용 또는 컨텍스트는 초기 로드 후에 개선사항으로 포함될 수 있습니다. 예를 들어 렌더링된 페이지에 프로필을 레이어링하거나 클라이언트 측 컨텍스트에 종속된 보조 구성요소를 추가할 수 있습니다.

다음과 같은 경우 MPA는 좋은 아키텍처 선택이 아닐 수 있습니다.

  • JavaScript 또는 CSS를 다시 다운로드하고, 다시 파싱하고, 재실행하는 것은 엄청난 비용이 듭니다. 이 문제는 서비스 워커가 있는 PWA에서 완화됩니다.
  • 사용자 위치와 같은 클라이언트 측 컨텍스트는 뷰 간에 원활하게 이전되지 않으며 해당 컨텍스트를 다시 얻는 데 많은 비용이 들 수 있습니다. 이를 캡처하여 가져오거나 뷰 간에 다시 요청해야 합니다.

개별 뷰는 서버에 의해 동적으로 렌더링되거나 액세스하기 전에 사전 렌더링되어야 하므로 호스팅이 제한되거나 데이터 복잡성이 추가될 수 있습니다.

어느 것을 선택해야 할까요?

이러한 장단점이 있지만 두 아키텍처 모두 PWA를 만드는 데 유효합니다. 필요에 따라 앱의 다양한 부분에 조합할 수도 있습니다. 예를 들어 스토어 등록정보는 MPA 아키텍처를 따르고 결제 흐름은 SPA 아키텍처를 따릅니다.

어떤 선택이든, 다음 단계는 서비스 워커를 가장 잘 사용하여 최상의 경험을 제공하는 방법을 이해하는 것입니다.

서비스 워커의 기능

이 서비스 워커는 캐시된 응답과 네트워크 응답의 기본 라우팅과 전달 외에 더 많은 권한이 있습니다. 복잡한 알고리즘을 만들어 사용자 환경과 실적을 개선할 수 있습니다.

서비스 워커 포함 (SWI)

서비스 워커를 사이트 아키텍처의 필수 요소로 사용하는 새로운 패턴은 서비스 워커 포함 (SWI)입니다. SWI는 캐싱 요구사항에 따라 개별 애셋(일반적으로 HTML 페이지)을 조각으로 나눈 다음 서비스 워커에서 다시 함께 연결하여 일관성, 성능, 안정성을 개선하고 캐시 크기를 줄입니다. 전체 헤더, 콘텐츠 영역, 사이드바, 바닥글이 있는 웹사이트

이 이미지는 샘플 웹페이지입니다. 이 페이지는 페이지를 다음과 같이 세분화하는 다섯 개의 섹션으로 구성되어 있습니다.

  • 전체 레이아웃
  • 전역 헤더 (상단의 어두운 막대)
  • 콘텐츠 영역 (왼쪽 가운데 선 및 이미지)
  • 사이드바 (오른쪽 가운데에 약간 어두운 색이 도는 높은 막대)
  • 바닥글 (어두운 하단 표시줄)

전체 레이아웃

전체 레이아웃은 자주 변경되지 않으며 종속 항목이 없습니다. 프리캐싱에 적합합니다.

전역 헤더와 바닥글은 상단 메뉴 및 사이트 바닥글과 같은 항목을 포함하며 특정 문제를 제시합니다. 즉, 페이지 전체가 캐시되는 경우 해당 페이지가 캐시된 시점에 따라 페이지가 로드되는 동안 이러한 요소가 변경될 수 있습니다.

콘텐츠를 콘텐츠와 독립적으로 구분하고 캐시하면 사용자가 캐시되는 시점과 관계없이 항상 동일한 버전을 사용할 수 있습니다. 또한 자주 업데이트되지 않으므로 사전 캐싱에 적합합니다. 하지만 사이트의 CSS와 자바스크립트에 종속 항목이 있습니다.

CSS 및 JavaScript

사이트의 CSS 및 JavaScript는 사전 캐시된 자산의 경우와 같이 서비스 워커를 업데이트하지 않고도 증분 업데이트를 허용하는 전략을 재검증하는 동안 오래된 상태로 캐시하는 것이 좋습니다. 그러나 서비스 워커가 새로운 전역 헤더나 바닥글로 업데이트될 때마다 최소 버전으로 유지해야 합니다. 따라서 서비스 워커가 설치되면 캐시도 최신 버전의 자산으로 업데이트해야 합니다.

콘텐츠 영역

다음은 콘텐츠 영역입니다. 업데이트 빈도에 따라, 네트워크 우선 또는 비활성 기간 재검증이 적합한 전략입니다. 이미지는 이전에 설명한 것처럼 캐시 우선 전략을 사용하여 캐시되어야 합니다.

마지막으로 메뉴 콘텐츠에 태그 및 관련 항목과 같은 보조 콘텐츠가 포함되어 있다고 가정하면 네트워크에서 가져올 만큼은 중요하지 않습니다. 재검증 전략이 작동하는 동안 비활성 상태가 됩니다.

이제 이 모든 것을 살펴본 후에 단일 페이지 앱에 대해서만 이러한 종류의 섹션별 캐싱을 할 수 있다고 생각할 수 있습니다. 그러나 일부 고급 서비스 워커 기능을 통해 서비스 워커에 에지 측 포함 또는 서버 측 포함에서 영감을 받은 패턴을 채택하면 두 아키텍처에 상관없이 적용할 수 있습니다.

직접 해보기

다음 Codelab에서 서비스 워커에 포함된 기능을 사용해 볼 수 있습니다.

스트리밍 응답

이전 페이지는 SPA 환경에서 앱 셸 모델을 사용하여 생성할 수 있습니다. 이 경우 앱 셸이 캐시되고 서비스되고 콘텐츠가 클라이언트 측에서 로드됩니다. Streams API가 도입되고 폭넓게 제공되면서 앱 셸과 콘텐츠를 서비스 워커에서 결합하고 브라우저로 스트리밍할 수 있으므로 MPA 속도로 앱 셸의 캐싱 유연성을 확보할 수 있습니다.

이렇게 하는 이유는 다음과 같습니다.

  • 스트림은 비동기적으로 빌드될 수 있어, 다른 소스에서 스트림의 다른 부분을 가져올 수 있습니다.
  • 스트림 요청자는 전체 항목이 완료될 때까지 기다리는 대신 첫 번째 데이터 청크를 사용할 수 있게 되자마자 응답 작업을 시작할 수 있습니다.
  • 브라우저를 포함하여 스트리밍에 최적화된 파서는 스트림이 완료되기 전에 스트림의 콘텐츠를 점진적으로 표시하여 인지되는 응답 성능을 높일 수 있습니다.

이러한 세 가지 스트림 속성 덕분에 스트리밍을 중심으로 구축된 아키텍처가 그렇지 않은 아키텍처보다 일반적으로 더 빠르게 인지되는 성능을 보입니다.

Streams API는 복잡하고 낮은 수준이므로 사용하기 어려울 수 있습니다. 다행히 서비스 워커의 스트리밍 응답을 설정하는 데 도움이 되는 작업 상자 모듈이 있습니다.

도메인, 원본, PWA 범위

서비스 워커, 스토리지, 설치된 PWA의 창을 비롯한 웹 워커는 웹에서 가장 중요한 보안 메커니즘 중 하나인 동일 출처 정책의 적용을 받습니다. 동일한 출처 내에서 권한이 부여되고, 데이터가 공유될 수 있으며, 서비스 워커가 다른 클라이언트와 통신할 수 있습니다. 동일한 출처 외부에서는 권한이 자동으로 부여되지 않고 데이터가 격리되며 여러 출처 간에 액세스할 수 없습니다.

동일 출처 정책

프로토콜, 포트, 호스트가 동일한 경우 두 개의 URL은 정확한 출처를 갖는 것으로 정의됩니다.

예를 들어 https://squoosh.apphttps://squoosh.app/v2의 출처는 동일하지만 http://squoosh.app, https://squoosh.com, https://app.squoosh.app, https://squoosh.app:8080는 출처가 다릅니다. 자세한 내용과 예시는 동일 출처 정책 MDN 참조를 확인하세요.

하위 도메인을 변경하는 것이 호스트를 변경할 수 있는 유일한 방법은 아닙니다. 각 호스트는 최상위 도메인 (TLD), 2차 수준 도메인 (SLD), 0개 이상의 라벨 (하위 도메인이라고도 함)으로 구성되며, 각 호스트는 URL에서 점으로 구분되고 오른쪽에서 왼쪽으로 읽습니다. 항목을 변경하면 호스트가 달라집니다.

이미 창 관리 모듈에서 사용자가 설치된 PWA에서 다른 출처로 이동할 때 인앱 브라우저가 어떻게 표시되는지 확인했습니다.

이 인앱 브라우저는 웹사이트의 TLD와 SLD는 동일하지만 라벨이 다르더라도 다른 출처로 간주되기 때문에 표시됩니다.

웹 탐색 컨텍스트에서 출처의 주요 측면 중 하나는 저장소와 권한이 작동하는 방식입니다. 하나의 출처는 그 안의 모든 콘텐츠와 PWA 간에 다음과 같은 여러 기능을 공유합니다.

  • 스토리지 할당량 및 데이터 (IndexedDB, 쿠키, 웹 스토리지, 캐시 스토리지)
  • 서비스 워커 등록
  • 권한이 부여되거나 거부되었습니다 (예: 웹 푸시, 위치정보, 센서).
  • 웹 푸시 등록

한 출처에서 다른 출처로 이동하면 이전 액세스 권한이 모두 취소되므로 권한을 다시 부여해야 하며 PWA가 스토리지에 저장된 모든 데이터에 액세스할 수는 없습니다.

자료