Cache API를 사용하여 애플리케이션 데이터를 오프라인에서 사용할 수 있도록 하는 방법을 알아봅니다.
Cache API는 네트워크 요청 및 해당 응답을 저장하고 검색하기 위한 시스템입니다. 이러한 요청과 응답은 애플리케이션을 실행하는 과정에서 생성된 일반 요청과 응답일 수도 있고 나중에 사용할 데이터를 저장하기 위한 목적으로만 생성될 수도 있습니다.
Cache API는 서비스 워커가 네트워크 요청을 캐시하여 네트워크 속도나 가용성에 관계없이 빠른 응답을 제공할 수 있도록 하기 위해 만들어졌습니다. 그러나 이 API는 일반적인 저장소 메커니즘으로도 사용할 수 있습니다.
어느 지역에서 제공되나요?
Cache API는 모든 최신 브라우저에서 사용할 수 있습니다. 전역 caches
속성을 통해 노출되므로 간단한 기능 감지로 API가 있는지 테스트할 수 있습니다.
const cacheAvailable = 'caches' in self;
Cache API는 창, iframe, 워커 또는 서비스 워커에서 액세스할 수 있습니다.
저장할 수 있는 항목
캐시에는 각각 HTTP 요청과 응답을 나타내는 Request
및 Response
객체 쌍만 저장됩니다. 그러나 요청과 응답에는 HTTP를 통해 전송할 수 있는 모든 종류의 데이터가 포함될 수 있습니다.
얼마나 저장할 수 있나요?
간단히 말해 매우 많습니다. 최소 수백 메가바이트에서 수백 기가바이트 이상일 수 있습니다. 브라우저 구현은 다양하지만 사용 가능한 저장용량은 일반적으로 기기에서 사용 가능한 저장용량을 기준으로 합니다.
캐시 만들기 및 열기
캐시를 열려면 caches.open(name)
메서드를 사용하여 캐시 이름을 단일 매개변수로 전달합니다. 이름이 지정된 캐시가 없으면 새로 생성됩니다. 이 메서드는 Cache
객체로 확인되는 Promise
를 반환합니다.
const cache = await caches.open('my-cache');
// do something with cache...
캐시에 추가
항목을 캐시에 추가하는 방법에는 add
, addAll
, put
세 가지가 있습니다.
세 메서드 모두 Promise
를 반환합니다.
cache.add
먼저 cache.add()
가 있습니다. Request
또는 URL(string
) 매개변수 하나를 사용합니다. 네트워크에 요청을 보내고 응답을 캐시에 저장합니다. 가져오기에 실패하거나 응답의 상태 코드가 200 범위에 있지 않으면 아무것도 저장되지 않고 Promise
가 거부됩니다. CORS 모드가 아닌 교차 출처 요청은 0
의 status
를 반환하므로 저장할 수 없습니다. 이러한 요청은 put
에만 저장할 수 있습니다.
// Retreive data.json from the server and store the response.
cache.add(new Request('/data.json'));
// Retreive data.json from the server and store the response.
cache.add('/data.json');
cache.addAll
다음은 cache.addAll()
입니다. add()
와 비슷하게 작동하지만 Request
객체 또는 URL (string
)의 배열을 사용합니다. 이는 개별 요청마다 cache.add
를 호출하는 것과 유사하게 작동하지만, 단일 요청이 캐시되지 않으면 Promise
가 거부된다는 점을 제외하고는 동일합니다.
const urls = ['/weather/today.json', '/weather/tomorrow.json'];
cache.addAll(urls);
이러한 경우 새 항목이 일치하는 기존 항목을 덮어씁니다. 여기서는 검색 섹션에 설명된 것과 동일한 일치 규칙을 사용합니다.
cache.put
마지막으로 cache.put()
가 있습니다. 이 함수를 사용하면 네트워크의 응답을 저장하거나 자체 Response
를 만들고 저장할 수 있습니다. 두 개의 매개변수가 필요합니다. 첫 번째는 Request
객체 또는 URL(string
)일 수 있습니다. 두 번째는 네트워크에서 가져오거나 코드에서 생성한 Response
여야 합니다.
// Retrieve data.json from the server and store the response.
cache.put('/data.json');
// Create a new entry for test.json and store the newly created response.
cache.put('/test.json', new Response('{"foo": "bar"}'));
// Retrieve data.json from the 3rd party site and store the response.
cache.put('https://example.com/data.json');
put()
메서드는 add()
또는 addAll()
보다 관대한 메서드이며, CORS가 아닌 응답이나 응답의 상태 코드가 200 범위에 있지 않은 다른 응답을 저장할 수 있습니다. 동일한 요청의 이전 응답을 덮어씁니다.
요청 객체 만들기
저장되는 항목의 URL을 사용하여 Request
객체를 만듭니다.
const request = new Request('/my-data-store/item-id');
Response 객체 작업
Response
객체 생성자는 Blob
, ArrayBuffer
, FormData
객체, 문자열을 비롯한 다양한 유형의 데이터를 허용합니다.
const imageBlob = new Blob([data], {type: 'image/jpeg'});
const imageResponse = new Response(imageBlob);
const stringResponse = new Response('Hello world');
적절한 헤더를 설정하여 Response
의 MIME 유형을 설정할 수 있습니다.
const options = {
headers: {
'Content-Type': 'application/json'
}
}
const jsonResponse = new Response('{}', options);
Response
를 검색했고 본문에 액세스하려면 사용할 수 있는 여러 도우미 메서드가 있습니다. 각 메서드는 다른 유형의 값으로 확인되는 Promise
를 반환합니다.
메서드 | 설명 |
---|---|
arrayBuffer |
바이트로 직렬화된 본문이 포함된 ArrayBuffer 를 반환합니다.
|
blob |
Blob 를 반환합니다. Response 가 Blob 로 만들어진 경우 이 새로운 Blob 도 동일한 유형을 가집니다. 그렇지 않으면 Response 의 Content-Type 가 사용됩니다.
|
text |
본문의 바이트를 UTF-8로 인코딩된 문자열로 해석합니다. |
json |
본문의 바이트를 UTF-8 인코딩된 문자열로 해석한 후 JSON으로 파싱하려고 시도합니다. 결과 객체를 반환하거나 문자열을 JSON으로 파싱할 수 없는 경우 TypeError 을 발생시킵니다.
|
formData |
본문의 바이트를 multipart/form-data 또는 application/x-www-form-urlencoded 로 인코딩된 HTML 형식으로 해석합니다. FormData 객체를 반환하거나 데이터를 파싱할 수 없으면 TypeError 을 발생시킵니다.
|
body |
본문 데이터의 ReadableStream을 반환합니다. |
예:
const response = new Response('Hello world');
const buffer = await response.arrayBuffer();
console.log(new Uint8Array(buffer));
// Uint8Array(11) [72, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100]
캐시에서 검색
캐시에서 항목을 찾으려면 match
메서드를 사용하면 됩니다.
const response = await cache.match(request);
console.log(request, response);
request
이 문자열이면 브라우저에서 new Request(request)
를 호출하여 Request
로 변환합니다. 이 함수는 일치하는 항목이 있는 경우 Response
로 확인되는 Promise
을 반환하고, 그렇지 않은 경우에는 undefined
을 반환합니다.
두 개의 Requests
가 일치하는지 확인하기 위해 브라우저는 URL 외에도 다른 정보를 사용합니다. 두 요청의 쿼리 문자열, Vary
헤더 또는 HTTP 메서드(GET
, POST
, PUT
등)가 서로 다른 경우 서로 다른 요청으로 간주됩니다.
옵션 객체를 두 번째 매개변수로 전달하여 이러한 항목의 일부 또는 전부를 무시할 수 있습니다.
const options = {
ignoreSearch: true,
ignoreMethod: true,
ignoreVary: true
};
const response = await cache.match(request, options);
// do something with the response
캐시된 요청이 두 개 이상 일치하는 경우 먼저 생성된 요청이 반환됩니다. 일치하는 응답을 모두 검색하려면 cache.matchAll()
를 사용하면 됩니다.
const options = {
ignoreSearch: true,
ignoreMethod: true,
ignoreVary: true
};
const responses = await cache.matchAll(request, options);
console.log(`There are ${responses.length} matching responses.`);
바로가기로 각 캐시의 cache.match()
를 호출하는 대신 caches.match()
를 사용하여 모든 캐시를 한 번에 검색할 수 있습니다.
검색 중
Cache API는 Response
객체와 일치하는 항목을 제외하고 요청이나 응답을 검색하는 방법을 제공하지 않습니다. 하지만 필터링을 사용하거나 색인을 만들어 자체 검색을 구현할 수 있습니다.
필터링
자체 검색을 구현하는 한 가지 방법은 모든 항목을 반복하고 원하는 항목으로 필터링하는 것입니다. .png
로 끝나는 URL이 있는 모든 항목을 찾으려 한다고 가정해 보겠습니다.
async function findImages() {
// Get a list of all of the caches for this origin
const cacheNames = await caches.keys();
const result = [];
for (const name of cacheNames) {
// Open the cache
const cache = await caches.open(name);
// Get a list of entries. Each item is a Request object
for (const request of await cache.keys()) {
// If the request URL matches, add the response to the result
if (request.url.endsWith('.png')) {
result.push(await cache.match(request));
}
}
}
return result;
}
이렇게 하면 Request
및 Response
객체의 속성을 사용하여 항목을 필터링할 수 있습니다. 대규모 데이터 세트를 검색하는 경우 속도가 느려집니다.
색인 만들기
자체 검색을 구현하는 다른 방법은 검색할 수 있는 항목의 별도 색인을 유지하고 색인을 IndexedDB에 저장하는 것입니다. 이는 IndexedDB가 설계된 작업 유형이므로 항목 수가 많을 때 훨씬 더 우수한 성능을 발휘합니다.
검색 가능한 속성과 함께 Request
의 URL을 저장하면 검색 후 올바른 캐시 항목을 쉽게 검색할 수 있습니다.
항목 삭제
캐시에서 항목을 삭제하려면 다음 단계를 따르세요.
cache.delete(request);
여기서 요청은 Request
또는 URL 문자열일 수 있습니다. 이 메서드는 cache.match
와 동일한 옵션 객체도 사용합니다. 따라서 동일한 URL에 대해 여러 개의 Request
/Response
쌍을 삭제할 수 있습니다.
cache.delete('/example/file.txt', {ignoreVary: true, ignoreSearch: true});
캐시 삭제
캐시를 삭제하려면 caches.delete(name)
를 호출합니다. 이 함수는 캐시가 존재하고 삭제된 경우 true
로 확인되는 Promise
를 반환하고 그렇지 않은 경우에는 false
를 반환합니다.
감사합니다.
이 도움말의 원본 버전을 작성하고 WebFundamentals에 처음 게시한 맷 스케일스님께 감사드립니다.