CS 상식/네트워크

웹 캐시(HTTP 캐시, 브라우저 캐시)를 이용해 성능 개선하기

SparkIT 2024. 11. 1. 15:33

여러분은 '캐시'에 대해 정확히 이해하고 계시나요? 저는 개인적으로 캐시에 대해 대충 느낌만 이해하고 있고 정확히 어떻게 동작하는지에 대한 내용을 잘 모르고 있었습니다. 캐시는 대충 자주 사용되는 데이터를 미리 저장해 빠르게 응답하기 위한 것 아니야? 이 정도로만 이해하고 있었습니다. 하지만 캐시에는 종류도 많고 각 캐시마다 역할도 달랐습니다. 오늘은 그 중 웹 브라우저에서 사용되는 웹 캐시(혹은 HTTP 캐시, 브라우저 캐시라고도 부름)에 대해 알아보겠습니다.

 


간단한 API 만들어 테스트하기

저는 NestJS를 이용해 간단한 api를 만들고 이를 테스트해 보았습니다.

먼저 localhost/test/1 요청을 처음으로 보냅니다.

첫번째 요청

이후에 같은 url에 요청을 또 한 번 보냅니다.

두번째 요청

이때 이상하게 200 상태코드를 반환하는게 아니라, 304 상태코드를 반환하는데요. 이 상태코드는 해당 리소스는 수정되지 않았으니 캐시된 데이터를 그대로 이용하라는 뜻입니다.

❓그런데 여기서 궁금한 점이 생깁니다. 리소스가 수정되지 않았음을 어떻게 알았을까요? 이는 Etag, if-none-math 등의 HTTP 헤더를 통해 확인됩니다. 더 정확한 원리에 대해 알아보겠습니다.

참고자료 : 

 

웹 서비스 캐시 똑똑하게 다루기

웹 성능을 위해 꼭 필요한 캐시, 제대로 설정하기 쉽지 않습니다. 토스 프론트엔드 챕터에서 올바르게 캐시를 설정하기 위한 노하우를 공유합니다.

toss.tech

 

 

 


웹 캐시(Web Cache)

Etag, if-none-match 활용한 캐시

위 그림을 통해 알 수 있는 것은 바로 웹 캐시의 목적이 응답 시 네트워크 트래픽을 줄이는 것이라는 거죠. 저는 웹 캐시에 대해 정확히 몰랐을 때는  캐시는 서버에서의 데이터베이스 I/O를 줄이는 것이 목표라고 생각했었습니다. 하지만 그게 아니었던것이죠... 웹 캐시는 사진이나 영상 등을 네트워크로 받는 것은 부담되는 행위이기 때문에 이를 최대한 줄이기 위한 용도였던 것입니다. 데이터베이스 I/O는 줄일 수 없습니다.

일단 위 그림에 대해 설명해보면 다음과 같습니다. 서버는 데이터베이스 조회 요청이 들어오면 데이터베이스를 조회하고, 조회된 값을 이용해 Etag를 생성합니다. 그리고 웹 브라우저 요청 헤더에 포함된 if-none-match 값과 이를 비교하면 데이터베이스 조회값이 같은지를 알 수 있습니다. 그래서 이 값이 같으면 웹 브라우저에 남아있는 값을 그대로 써도 된다라는 명령을 보내는 것입니다. 이것이 바로 304 코드이고 이 때는 응답에 아무런 값을 포함하지 않고 보내 네트워크 트래픽을 절약하죠.

 

 


웹 캐시 관련 헤더

웹 캐시에서는 Etag, if-none-match 이외의 HTTP 헤더들도 캐시 과정에 관여합니다. 웹 캐시와 관련된 대표적인 헤더들을 간단하게 정리해보았습니다.

  • Etag
    위치 : 응답 헤더
    설명 : 리소스의 공유 해시값. 이를 통해 리소스가 수정되었는지 확인할 수 있습니다. 서버는 클라이언트에게 Etag값을 응답 헤더에 넣어서 보내고, 클라이언트는 서버에 다시 요청을 보낼 때 이 값을 if-none-match에 넣어서 보냄.

  • If-None-Match
    위치 : 요청 헤더
    설명 : 클라이언트가 서버에 요청을 할 때 Etag가 있다면 이 값을 if-none-match에 넣어서 보냅니다. 서버는 이 값을 서버에서 생성한 Etag값과 비교하여 304를 반환한지 결정합니다.

  • Last-Modified
    위치 : 응답 헤더
    설명 : 우선 이 값은 If-None-Match 이용할 시 무시됩니다. 해당 값이 없다고 가정하면 서버가 리소스가 마지막으로 수정되었다고 생각하는 날짜와 시간을 의미합니다. 서버는 클라이언트에게 last-modified값을 응답 헤더에 넣어서 보내고, 클라이언트는 서버에 다시 요청을 보낼 때 이 값을 last-modified에 넣어서 보냄.

  • If-Modified-Since
    위치 : 요청 헤더
    설명 : 클라이언트가 서버에 요청을 할 때 If-Modified-Since가 있다면 이 값을 if-none-match에 넣어서 보냅니다. 서버는 이 값을 서버에서 생성한 Etag값과 비교하여 304를 반환한지 결정합니다.

  • Cache-Control
    위치 : 요청 헤더, 응답 헤더
    설명 : 클라이언트가 서버에 요청을 할 때 Etag가 있다면 이 값을 if-none-match에 넣어서 보냅니다. 서버는 이 값을 서버에서 생성한 Etag값과 비교하여 304를 반환한지 결정합니다.