이 Codelab에서는 Express 제공 프레임워크를 실행하는 Node.js 기반 웹 서버에서 반환된 HTTP 캐싱 헤더를 변경하는 방법을 보여줍니다. 또한 Chrome DevTools의 네트워크 패널을 사용하여 예상되는 캐싱 동작이 실제로 적용되는지 확인하는 방법도 보여줍니다.
샘플 프로젝트 익히기
다음은 샘플 프로젝트에서 사용할 키 파일입니다.
server.js
에는 웹 앱의 콘텐츠를 제공하는 Node.js 코드가 포함됩니다. Express를 사용하여 HTTP 요청과 응답을 처리합니다. 특히express.static()
는 공개 디렉터리의 모든 로컬 파일을 제공하는 데 사용되므로serve-static
문서가 유용합니다.public/index.html
는 웹 앱의 HTML입니다. 대부분의 HTML 파일과 마찬가지로 URL에 버전 관리 정보가 포함되어 있지 않습니다.public/app.15261a07.js
및public/style.391484cf.css
는 웹 앱의 JavaScript 및 CSS 애셋입니다. 이러한 파일의 URL에는 콘텐츠에 해당하는 해시가 각각 포함되어 있습니다.index.html
는 로드할 특정 버전의 URL을 추적합니다.
HTML의 캐싱 헤더 구성
버전 관리 정보가 포함되지 않은 URL 요청에 응답할 때는 응답 메시지에 Cache-Control: no-cache
를 추가해야 합니다. 이와 함께 Last-Modified
또는 ETag
중 하나의 추가 응답 헤더를 설정하는 것이 좋습니다. index.html
가 이 카테고리에 속합니다. 이 과정을 두 단계로 나눌 수 있습니다.
먼저 Last-Modified
및 ETag
헤더는 etag
및 lastModified
구성 옵션으로 제어됩니다. 이 두 옵션은 모두 모든 HTTP 응답에 대해 기본적으로 true
로 설정되므로 현재 설정에서는 이 동작을 사용 설정할 필요가 없습니다. 하지만 구성에서 명시적으로 지정할 수 있습니다.
두 번째로, HTML 문서 (이 경우 index.html
)에 대해서만 Cache-Control: no-cache
헤더를 추가할 수 있어야 합니다. 이 헤더를 조건부로 설정하는 가장 쉬운 방법은 맞춤 setHeaders function
를 작성하고 그 내에서 수신 요청이 HTML 문서인지 확인하는 것입니다.
- 리믹스하여 수정을 클릭하여 프로젝트를 수정할 수 있도록 합니다.
server.js
의 정적 게재 구성은 다음과 같이 시작됩니다.
app.use(express.static('public'));
- 위에 설명된 대로 변경하면 다음과 같이 표시됩니다.
app.use(express.static('public', {
etag: true, // Just being explicit about the default.
lastModified: true, // Just being explicit about the default.
setHeaders: (res, path) => {
if (path.endsWith('.html')) {
// All of the project's HTML files end in .html
res.setHeader('Cache-Control', 'no-cache');
}
},
}));
버전이 지정된 URL의 캐싱 헤더 구성
'디지털 지문' 또는 버전 관리 정보가 포함되어 있고 콘텐츠가 변경되지 않는 URL 요청에 응답할 때는 응답에 Cache-Control: max-age=31536000
를 추가합니다. app.15261a07.js
및 style.391484cf.css
가 이 카테고리에 속합니다.
마지막 단계에서 사용한 setHeaders function
를 기반으로 로직을 추가하여 특정 요청이 버전 관리 URL인지 확인하고, 버전 관리 URL인 경우 Cache-Control:
max-age=31536000
헤더를 추가할 수 있습니다.
이를 실행하는 가장 강력한 방법은 정규 표현식을 사용하여 요청된 저작물이 해시가 속하는 것으로 알고 있는 특정 패턴과 일치하는지 확인하는 것입니다. 이 샘플 프로젝트의 경우 항상 0~9의 숫자와 소문자 a~f (즉, 16진수 문자)의 문자 8개로 구성됩니다. 해시는 항상 양쪽에서 .
문자로 구분됩니다.
이러한 일반 규칙과 일치하는 정규 표현식은 new RegExp('\\.[0-9a-f]{8}\\.')
로 표현할 수 있습니다.
setHeaders
함수를 다음과 같이 수정합니다.
app.use(express.static('public', {
etag: true, // Just being explicit about the default.
lastModified: true, // Just being explicit about the default.
setHeaders: (res, path) => {
const hashRegExp = new RegExp('\\.[0-9a-f]{8}\\.');
if (path.endsWith('.html')) {
// All of the project's HTML files end in .html
res.setHeader('Cache-Control', 'no-cache');
} else if (hashRegExp.test(path)) {
// If the RegExp matched, then we have a versioned URL.
res.setHeader('Cache-Control', 'max-age=31536000');
}
},
}));
DevTools를 사용하여 새 동작 확인
정적 파일 서버를 수정한 후 DevTools 네트워크 패널을 열고 실시간 앱을 미리 보고 올바른 헤더가 설정되었는지 확인할 수 있습니다.
사이트를 미리 보려면 앱 보기를 누른 다음 전체 화면
을 누릅니다.
열 헤더를 마우스 오른쪽 버튼으로 클릭하여 가장 관련성 높은 정보를 포함하도록 네트워크 패널에 표시되는 열을 맞춤설정합니다.
여기서 주목해야 할 열은 Name
, Status
, Cache-Control
, ETag
, Last-Modified
입니다.
- DevTools가 네트워크 패널로 열려 있는 상태에서 페이지를 새로고침합니다.
페이지가 로드되면 네트워크 패널에 다음과 같은 항목이 표시됩니다.
첫 번째 행은 이동한 HTML 문서에 관한 것입니다. Cache-Control: no-cache
를 사용하여 올바르게 제공됩니다. 이 요청의 HTTP 응답 상태는 304
입니다. 즉, 브라우저는 캐시된 HTML을 즉시 사용하지 않아야 함을 알고 있었지만 대신 Last-Modified
및 ETag
정보를 사용하여 웹 서버에 HTTP 요청을 보내 캐시에 이미 있는 HTML이 업데이트되었는지 확인했습니다. HTTP 304 응답은 업데이트된 HTML이 없음을 나타냅니다.
다음 두 행은 버전이 지정된 JavaScript 및 CSS 애셋용입니다. Cache-Control: max-age=31536000
로 제공되는 것을 확인할 수 있으며 각 항목의 HTTP 상태는 200
입니다.
사용된 구성으로 인해 Node.js 서버에 실제 요청이 전송되지 않으며 항목을 클릭하면 응답이 '(디스크 캐시에서)' 전송되었다는 등의 추가 세부정보가 표시됩니다.
ETag 및 Last-Modified 열의 실제 값은 중요하지 않습니다. 중요한 것은 설정되고 있는지 확인하는 것입니다.
요약
이 Codelab의 단계를 완료하면 HTTP 캐시를 최적으로 사용하기 위해 Express를 사용하여 Node.js 기반 웹 서버에서 HTTP 응답 헤더를 구성하는 방법을 익혔습니다. Chrome의 DevTools에 있는 네트워크 패널을 통해 예상되는 캐싱 동작이 사용되고 있는지 확인하는 단계도 있습니다.