서비스 워커에서 범위 요청 처리

부분 응답이 요청되었을 때 해야 할 일을 서비스 워커가 알고 있는지 확인하세요.

일부 HTTP 요청에는 전체 리소스의 일부만 반환되어야 함을 나타내는 Range: 헤더가 포함되어 있습니다. 이는 일반적으로 원격 파일 전체를 한 번에 요청하는 대신 더 작은 미디어 청크를 필요에 따라 로드할 수 있도록 오디오 또는 동영상 콘텐츠를 스트리밍하는 데 사용됩니다.

서비스 워커는 웹 앱과 네트워크 사이에 있는 JavaScript 코드로, 나가는 네트워크 요청을 가로채고 이에 대한 응답을 생성할 수 있습니다.

이전에는 범위 요청과 서비스 워커가 제대로 호환되지 않았습니다. 서비스 워커에서 나쁜 결과를 방지하기 위해 특별한 조치를 취해야 했습니다. 다행히 이러한 상황이 바뀌고 있습니다. 올바른 동작을 보이는 브라우저에서는 범위 요청이 서비스 워커를 통과할 때 '그냥 작동'합니다.

수신되는 모든 요청을 가져와 네트워크에 전달하는 다음 fetch 이벤트 리스너가 있는 서비스 워커를 생각해 보세요.

self.addEventListener('fetch', (event) => {
  // The Range: header will not pass through in
  // browsers that behave incorrectly.
  event.respondWith(fetch(event.request));
});

잘못된 동작이 있는 브라우저에서 event.requestRange: 헤더가 포함된 경우 해당 헤더가 자동으로 삭제되었습니다. 원격 서버에서 수신한 요청에 Range:가 전혀 포함되지 않습니다. 서버는 원래 요청에 Range: 헤더가 있는 경우에도 200 상태 코드와 함께 전체 응답 본문을 반환할 수 있으므로 기술적으로 반드시 '중단'되지는 않습니다. 하지만 이렇게 하면 브라우저 관점에서 꼭 필요한 것보다 더 많은 데이터가 전송됩니다.

이 동작을 알고 있는 개발자는 Range: 헤더의 존재를 명시적으로 확인하고 헤더가 있는 경우 event.respondWith()를 호출하지 않음으로써 이 문제를 해결할 수 있습니다. 이렇게 하면 서비스 워커가 응답 생성 사진에서 효과적으로 자신을 제거하고, 범위 요청을 보존하는 방법을 알고 있는 기본 브라우저 네트워킹 로직이 대신 사용됩니다.

self.addEventListener('fetch', (event) => {
  // Return without calling event.respondWith()
  // if this is a range request.
  if (event.request.headers.has('range')) {
    return;
  }

  event.respondWith(fetch(event.request));
});

하지만 대부분의 개발자들은 이 작업이 필요하다는 사실조차 몰랐습니다. 또한 이 기능이 필요한 이유도 명확하지 않았습니다. 궁극적으로 이 제한은 이 기능에 대한 지원을 추가한 기본 사양의 변경사항브라우저가 따라잡아야 하기 때문에 발생했습니다.

수정된 사항

올바르게 작동하는 브라우저는 event.requestfetch()에 전달될 때 Range: 헤더를 보존합니다. 즉, 초기 예시의 서비스 워커 코드를 사용하면 브라우저에서 설정한 경우 원격 서버에서 Range: 헤더를 볼 수 있습니다.

self.addEventListener('fetch', (event) => {
  // The Range: header will pass through in browsers
  // that behave correctly.
  event.respondWith(fetch(event.request));
});

이제 서버는 범위 요청을 올바르게 처리하고 206 상태 코드와 함께 부분 응답을 반환할 수 있습니다.

어떤 브라우저가 올바르게 동작하나요?

Safari 최신 버전에는 올바른 기능이 있습니다. 버전 87부터 Chrome과 Edge도 올바르게 작동합니다.

2020년 10월 현재 Firefox에서 이 동작을 아직 수정하지 않았으므로 서비스 워커의 코드를 프로덕션에 배포하는 동안 이를 고려해야 할 수 있습니다.

특정 브라우저에서 이 동작이 수정되었는지 확인하는 가장 좋은 방법은 웹 플랫폼 테스트 대시보드의 '네트워크 요청에 범위 헤더 포함' 행을 확인하는 것입니다.

캐시의 범위 요청은 어떨까요?

서비스 워커는 요청을 네트워크에 전달하는 것 외에도 훨씬 더 많은 작업을 할 수 있습니다. 일반적인 사용 사례는 오디오 및 동영상 파일과 같은 리소스를 로컬 캐시에 추가하는 것입니다. 그러면 서비스 워커가 네트워크를 완전히 우회하여 해당 캐시의 요청을 처리할 수 있습니다.

Firefox를 비롯한 모든 브라우저는 fetch 핸들러 내에서 요청을 검사하고, Range: 헤더의 존재를 확인한 다음, 캐시에서 가져온 206 응답으로 로컬에서 요청을 처리합니다. 하지만 Range: 헤더를 올바르게 파싱하고 전체 캐시된 응답의 적절한 세그먼트만 반환하는 서비스 워커 코드는 간단하지 않습니다.

다행히 도움을 원하는 개발자는 일반적인 서비스 워커 사용 사례를 간소화하는 라이브러리 모음인 Workbox를 사용할 수 있습니다. workbox-range-request module는 캐시에서 직접 부분 응답을 제공하는 데 필요한 모든 로직을 구현합니다. 이 사용 사례에 관한 전체 레시피는 Workbox 문서에서 확인할 수 있습니다.

이 게시물의 히어로 이미지는 Unsplash의 Natalie Rhea Riggs님이 제공해 주셨습니다.