HTTP 캐시를 공부하다 보면 가장 자주 헷갈리는 표현이 no-cache와 no-store입니다. 이름만 보면 둘 다 “캐시하지 말라”는 뜻처럼 보이지만, 실제 동작은 꽤 다릅니다.
핵심부터 말하면 no-store는 응답을 저장하지 말라는 뜻이고, no-cache는 저장은 하되 사용하기 전에 서버에 다시 확인하라는 뜻입니다. 그리고 이 확인 과정에서 리소스가 바뀌지 않았다면 서버는 304 Not Modified를 응답해 본문 전송을 생략할 수 있습니다.
HTTP 캐시는 “저장”보다 “언제 재사용할지”가 중요하다
HTTP 캐시는 한 번 받은 응답을 다음 요청에서 다시 사용할 수 있게 해주는 계층입니다. 하지만 중요한 건 단순히 저장 여부가 아닙니다. 더 중요한 질문은 이것입니다.
저장된 응답을 지금 그대로 써도 되는가?
Cache-Control은 이 판단 기준을 정하는 헤더입니다. 브라우저 캐시뿐 아니라 CDN, 프록시 같은 중간 캐시에도 영향을 줄 수 있기 때문에 실무에서는 성능과 보안을 함께 고려해야 합니다.
no-store: 저장 자체를 금지한다
Cache-Control: no-store는 응답 본문과 관련 메타데이터를 저장하지 말라는 강한 지시입니다.
const headers = {
"Cache-Control": "no-store",
};
이 설정은 개인정보, 토큰, 계정 정보, 결제 결과처럼 브라우저나 중간 캐시에 남으면 안 되는 응답에 적합합니다.
예를 들어 사용자별 민감 정보가 포함된 API 응답이라면 “나중에 다시 확인해서 쓰자”가 아니라 “애초에 저장하지 말자”가 맞습니다. 이럴 때는 no-cache보다 no-store가 더 정확한 선택입니다.
no-cache: 저장은 하되 사용 전 재검증한다
Cache-Control: no-cache는 이름 때문에 오해하기 쉽습니다. 저장하지 말라는 뜻이 아니라, 저장된 응답을 사용하기 전에 반드시 서버에 재검증하라는 뜻입니다.
const headers = {
"Cache-Control": "no-cache",
ETag: '"v3-asset-9f2c"',
};
브라우저는 응답을 저장할 수 있습니다. 다만 다음 요청에서 바로 사용하지 않고 서버에 이렇게 물어봅니다.
const requestHeaders = {
"If-None-Match": '"v3-asset-9f2c"',
};
서버는 클라이언트가 보낸 ETag와 현재 리소스의 상태를 비교합니다. 같으면 리소스가 바뀌지 않았다는 뜻이므로 새 본문을 다시 보내지 않고 304 Not Modified를 응답합니다.
304 Not Modified는 “캐시 없음”이 아니다
304 Not Modified는 “새 본문이 없다”는 뜻입니다. 캐시가 없다는 뜻이 아닙니다.
서버가 304를 보내면 브라우저는 이전에 저장해 둔 응답 본문을 그대로 사용합니다. 덕분에 네트워크 요청은 발생하지만, 본문을 다시 다운로드하지 않아도 됩니다.
정리하면 흐름은 다음과 같습니다.
- 첫 요청에서 서버가
200 OK와 본문,ETag를 보낸다. - 브라우저가 응답을 저장한다.
- 다음 요청에서 브라우저가
If-None-Match로 이전ETag를 보낸다. - 서버가 변경 여부를 확인한다.
- 변경이 없으면
304 Not Modified를 보낸다. - 브라우저는 저장된 본문을 재사용한다.
no-cache와 no-store는 언제 써야 할까?
실무에서는 “항상 최신이어야 한다”와 “절대 저장되면 안 된다”를 구분해야 합니다.
변경 여부만 확인하면 되는 정적 파일이나 준정적 응답이라면 no-cache + ETag 조합을 검토할 수 있습니다. 네트워크 왕복은 발생하지만, 변경이 없을 때 본문 전송을 줄일 수 있습니다.
반대로 보안이나 개인정보가 중요한 응답이라면 no-store를 사용해야 합니다. 저장 자체를 막아야 하기 때문입니다.
- 사용자 토큰, 계정 정보, 결제 결과:
no-store - 변경 가능성이 있지만 본문 재사용이 가능한 리소스:
no-cache + ETag - 버전 해시가 붙은 정적 파일: 긴 캐시 수명과
immutable검토
개발자 도구에서 확인해보기
브라우저 개발자 도구의 Network 탭을 열고 같은 리소스를 여러 번 새로고침해 보면 200과 304가 언제 나오는지 확인할 수 있습니다.
응답 헤더에서는 Cache-Control, ETag, Last-Modified를 보고, 요청 헤더에서는 If-None-Match, If-Modified-Since가 붙는지 보면 됩니다.
특히 304가 나왔다면 응답 본문이 새로 내려온 것이 아니라, 브라우저가 기존에 저장한 본문을 재사용했다는 점을 기억하면 됩니다.
마무리
no-cache와 no-store의 차이는 이름보다 동작으로 이해해야 합니다.
no-store는 저장하지 않는 설정이고, no-cache는 저장하되 사용 전에 재검증하는 설정입니다. 그리고 재검증 결과 리소스가 바뀌지 않았다면 서버는 304 Not Modified로 본문 전송을 생략합니다.
캐시 정책을 정할 때는 “빠르게 보여야 하는가”와 “남으면 안 되는가”를 분리해서 판단하는 것이 좋습니다. 이 차이를 알고 있으면 HTTP 캐시를 성능 문제와 보안 문제 사이에서 더 정확하게 다룰 수 있습니다.
