서비스 워커가 부분 응답이 요청될 때 무엇을 해야 하는지 알고 있는지 확인합니다.
일부 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.request
에 Range:
헤더가 포함된 경우 해당 헤더가 자동으로 삭제되었습니다. 원격 서버에서 수신한 요청에는 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.request
가 fetch()
에 전달될 때 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님이 제공해 주셨습니다.