캐시와 조건부 요청 정리

2023. 6. 19. 19:24네트워크

클라이언트가 요청을 보내면 서버가 응답을 보내주면 해당 정보를 통해 클라이언트가 랜더링하는 방식으로 동작한다.

하지만 정보가 동일한 경우에도 이러한 과정을 매번 해준다면 비효율적일 것이다.

이러한 문제점을 해결하기 위해 등장한 개념이 캐시다.

캐시란? 서버 지연을 줄이기 위해 웹 페이지, 이미지 등의 웹 문서들을 임시로 저장하는 기술이다.

 

캐시가 없을 경우 어떻게 동작할까?

클라이언트가 서버에게 star.jpg를 달라고 get메소드를 사용하여 요청하고 있다.

 

서버가 star.jpg를 클라이언트에게 응답을 보내주고 클라이언트는 해당 정보를 랜더링하여 star.jpg를 보여준다.

 

동일한 요청을 두번째에 요청을 해도 위와 같은 동일한 과정을 반복해야 한다. 상당히 비효율적이라는 것을 알 수 있다.

 

따라서 캐시가 없을 경우에

1. 데이터가 변경되지 않아도 계속 네트워크를 통해서 데이터를 다운로드 받아야 한다.

2. 인터넷 네트워크는 매우 느리고 비싸다.

3. 브라우저 로딩 속도가 느리다.

4. 느린 사용자 경험

 

캐시를 사용하는 경우

 

클라이언트가 get메소드 방식으로 star.jpg를 요청한다. 서버가 클라이언트에게 응답을 할 때 아까와는 다르게 캐시 유효 시간을 http 헤더에 추가한다.

클라이언트는 해당 정보를 받아 랜더링하여 사용자에게 보여주고 브라우저 캐시는 응답 결과를 캐시에 저장을 한다. 

 

캐시 유효 시간이 지나지 않은 경우

캐시 유효시간이 지나지 않은 경우 클라이언트는 브라우저 캐시에 요청을 보낸다.

 

브라우저 캐시에서 캐시를 조회하여 브라우저에게 정보를 준다.

 

캐시를 적용함으로써

캐시 사용 가능 시간동안 네트워크를 사용하지 않아도 된다.

비싼 네트워크 사용량을 줄일 수 있다.

브라우저 로딩 속도가 빨라진다.

사용자가 빠르다고 생각한다.

 

 

캐시 유효시간이 지난 경우

클라이언트가 브라우저 캐시에 요청을 보냈지만 캐시 유효 시간이 지나서 데이터를 가져올 수 없다.

 

그 다음부터는 캐시 유효시간이 지나지 않았을 경우와 동일한 과정이 진행된다. 즉 캐시 유효시간이 지나면 데이터가 필요하면 서버에 요청을 보내고 응답을 받아오는 과정이 필요하다.

 

캐시 사용시에 캐시 유효시간이 초과하면

서버를 통해 데이터를 다시 조회하고 캐시를 갱신해야 한다.

이러한 과정에서 다시 네트워크 다운로드가 발생한다.

 

캐시 유효 시간이 초과한 후에는 2가지 경우의 수가 있을 것이다.

1. 서버에서 기존 데이터를 변경

2. 서버에서 기존 데이터를 변경하지 않음

 

만약 서버에서 기존데이터를 변경하지 않았을 경우에는 캐시를 재사용하는 방법도 있다. 단, 클라이언트의 데이터와 서버의 데이터가 같다는 사실을 확인해야 하는 방법이 필요하다.

이를 위해 검증 헤더를 사용한다.

 

클라이언트에서 요청을 보내면 서버에서 응답을 보낼때 http 헤더에 데이터가 마지막에 수정된 시간을 같이 보내준다.

 

클라이언트는 데이터를 받아 렌더링하고 브라우저 캐시는 응답 결과를 캐시에 저장한다.

 

클라이언트에서 브라우저 캐시에 요청을 보내지만 캐시 유효시간이 초과하여 데이터를 받을 수 없다.

 

클라이언트는 요청을 보낼 때 수 데이터 최종 수정시간을 담아 서버에 보낸다.

 

클라이언트에서 보내온 데이터 최종 수정일과 브라우저 캐시에 저장되어 있는 데이터 최종 수정일을 비교한다.

비교 후 일치하면 데이터가 수정되지 않았다는 것을 알 수 있다.

 

서버는 클라이언트에게 응답을 보내주는데 304 상태의 http 헤더만 보낸다.(http body는 보내지 않는다.)

 

브라우저 캐시도 응답 결과는 재사용하고 헤더 데이터만 갱신한다.

브라우저 캐시에서 조회를 해온다.

 

정리하자면

캐시 유효시간이 초과해도 서버의 데이터가 갱신되지 않는 경우에 304 + 헤더 메타 정보만 응답을 한다.

클라이언트는 서버가 보낸 응답 헤더 정보로 캐시의 메타 정보를 갱신하고 캐시에 저장되어 있는 데이터를 재활용한다.

결과적으로 네트워크 다운로드가 발생하지만 용량이 적은 헤더 정보만 다운로드 하기 때문에 매우 실용적이다.

 

 

하지만 데이터 수정일로만 비교하면 이러한 문제점이 발생할 수 있다. 예를 들어 데이터가 A였는데 B로 변경했다가 다시 A로 변경하는 경우가 있다. 데이터는 동일하지만 클라이언트와 서버의 데이터 최종 수정일은 다르다.

이 문제를 해결하기 위해 조건부 요청 헤더에 etag를 사용한다.

 

etag란 entity tag로 캐시용 데이터에 임의의 고유한 버전 이름을 달아두는 것을 말한다.

 

클라이언트에서 요청을 보내면 서버에서 http 응답 메시지를 만드는데 http 헤더에 etag를 생성한다.

 

클라이언트는 데이터를 받아 렌더링하고 브라우저 캐시는 응답 결과를 캐시에 저장한다.

 

클라이언트가 브라우저 캐시에 캐시를 요청하고 있지만 캐시 시간이 초과된 상태이다.

 

클라이언트가 조건부 요청에 etag를 담아 서버에게 요청을 보낸다.

 

클라이언트에 있는 etag와 브라우저 캐시에 있는 etag를 비교한다. 일치하면 데이터가 수정되지 않았다는 뜻이다.

 

etag가 일치하므로 304 상태코드를 담아 클라이언트에게 응답을 준다. 이 때 데이터는 변하지 않았으므로 http 헤더만 보낸다.

 

브라우저 캐시에도 헤더 데이터만 갱신하고 응답 결과는 재사용하도록 한다. 즉 http 헤더만 갱신해준다.

 

클라이언트는 브라우저 캐시에서 조회를 해서 데이터를 받아서 랜더링한다.

 

만약 etag 값이 일치하지 않는다면 데이터가 수정된 것이기 때문에 서버에서 클라이언트로  http body를 포함하여 응답을 준다. 이 떄 상태코드는 200이다.

 

즉 etag를 비교해서 같으면 유지, 다르면 다시 받는다는 뜻이다.

캐시 제어 로직은 서버에서 완전히 관리하기 때문에 클라이언트는 캐시 매커니즘을 모른다.

 

캐시 제어 헤더

1. cache-control : 캐시 제어

- max-age : 캐시 유효 시간, 초단위

- no-cache : 데이터는 캐시해도 되지만, origin 서버에 검증하고 사용

- no-store : 데이터에 민감한 정보가 있으므로 저장하면 안됨 (메모리에서 사용하고 최대한 빨리 삭제)

 

2. pragma : 캐시 제어 (하위 호환)

3. expires : 캐시 유효 기간(하위 호환)

- 캐시 만료일을 정확한 날짜로 지정

- cache-control: max-age와 함께 사용하면 무시됨

 

프록시 캐시

예를 들어 한국에서 미국이랑 통신을 한다면 거리가 멀기 때문에 어느정도 시간이 걸릴것이다.

프록시 캐시를 사용한다면 이 문제를 해결할 수 있다.

 

한국에서 미국유튜브 영상 중 조회수가 낮은 영상을 본다면 시간이 오래걸리고 조회수가 높은 영상을 볼 때는 금방 볼 수 있다는 것을 경험해 본 적이 있을것이다. 조회수가 높다는 것은 그만큼 많은 사람이 봤다는 것이고 프록시 캐시에 캐시가 남아있을 수 있다는 것이다.

 

cache-control

- public : 응답이 public 캐시에 저장되어도 됨

- private : 응답이 해당 사용자만을 위한 것(기본값)

- s-maxage : 프록시 캐시에만 적용되는 max-age

- age : origin 서버에서 응답 후 프록시 캐시 내에 머문 시간 (초)

 

캐시 무효화

cache-control

- no-cache : 데이터는 캐시해도 되지만, origin서버에 검증하고 사용해야 됨

- no-store : 데이터에 민감한 정보가 있으므로 저장하면 안됨

- must-validate : 캐시 만료 후 최초 조회시 origin서버에 검증해야된다. origin 서버 접근 실패시 반드시 오류 발생(504 gateway timeout)

 

클라이언트에서 프록시 캐시로 요청을 보낸 후 프록시 캐시에서 원 서버로 요청을 보내면 원 서버에서 검증 후 응답을 준다. 브라우저 캐시의 캐시 데이터를 사용해 클라이언트에서 사용한다.

 

원 서버에 접근 불가하면 200상태코드를 보낸다.

 

must-revalidate인 경우에는 원 서버와 접근이 불가하면 오류가 발생한다.

'네트워크' 카테고리의 다른 글

postman을 통한 http 메시지 다루기  (0) 2023.06.19
http 기본  (0) 2023.06.12
uri와 웹 브라우저 흐름 정리  (0) 2023.06.11
인터넷 네트워크 정리- ip, tcp, udp, port, dns  (0) 2023.06.11