ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 9. HTTP 헤더 (2)
    HTTP 2022. 8. 1. 22:10

    캐시가 없는 경우, 동일한 데이터를 요청할 때마다 매번 네트워크를 통한 데이터를 다운로드 받아야 한다.

    이럴 경우, 브라우저 로딩 속도가 매우 느려지고, 사용자 입장에서는 속도가 답답할 수 있다.

    캐시

    HTTP/1.1 200 OK
    Content-Type: image/jpeg
    cache-control: max-age=60
    Content-Length: 34012
    lkj123kljoiasudlkjaweioluywlnfdo912u34ljko98udjkla
    slkjdfl;qkawj9;o4ruawsldkal;skdjfa;ow9ejkl3123123

    사용자가 특정 데이터를 요청하였을 때, 서버에서 해당 데이터에 대한 캐시의 유효한 시간을 설정해준다.

    이후, 동일한 요청을 하였을 때, 웹 브라우저에 존재하는 브라우저 캐시를 확인하여 불필요한 다운로드를 없애준다.

    만약, 서버에서 설정한 캐시의 유효 시간이 초과되었을 경우, 동일한 데이터를 다시 다운로드 받아야 한다.

    즉, 캐시 유효 시간이 초과되면, 동일한 데이터를 요청하더라도 서버를 통해 데이터를 조회하고 캐시를 갱신해야한다. 

    캐시 유효 시간이 초과되었을 때, (1).서버의 데이터 변경된 경우, (2).서버의 데이터 유지된 경우가 존재한다.

    (2)의 경우 즉, 서버의 데이터가 기존과 동일한 경우 불필요한 데이터를 다운받을 필요가 없게 된다.

    "검증 헤더"를 사용하면, 기존의 데이터가 변경되지 않았다는 사실을 검증하여 캐시를 사용할 수 있게 된다.

    ● 검증 헤더와 조건부 요청

    HTTP/1.1 200 OK
    Content-Type: image/jpeg
    cache-control: max-age=60
    Last-Modified: 2020년 11월 10일 10:00:00 (데이터 수정 시간)
    Content-Length: 34012
    lkj123kljoiasudlkjaweioluywlnfdo912u34ljko98udjklasl
    kjdfl;qkawj9;o4ruawsldkal;skdjfa;ow9ejkl3123123

    위와 같이 Response Message가 도착하면, 브라우저 캐시에 데이터, 캐시 유효시간, 데이터 최종 수정시간을 저장한다.

    이때, 캐시 유효 시간이 초과된 경우, 웹 브라우저에서 서버에 요청을 보낼 때 아래와 같은 검증 헤더를 추가한다.

    ※ UTC 표기법을 사용하는 것이 원칙이나, 이해를 위해 한글로 표기하였음

    GET /star.jpg
    if-modified-since: 2020년 11월 10일 10:00:00

    위와 같이, 캐시에 존재하는 데이터의 최종 수정일을 헤더에 추가하여 전송한다.

    서버에 존재하는 데이터의 변경이 발생하지 않은 경우, 아래와 같은 Response Message가 전송된다.

    HTTP/1.1 304 Not Modified
    Content-Type: image/jpeg
    cache-control: max-age=60
    Last-Modified: 2020년 11월 10일 10:00:00
    Content-Length: 34012

    304 (Not Modified) 상태 코드는 데이터의 변경이 없으므로, 기존의 데이터를 사용하라는 뜻이다.

    따라서, Message Body 부분이 존재하지 않는다.

    클라이언트에서는 해당 Response Message를 참고하여, 브라우저 캐시의 유효 시간 등(메타 정보)을 다시 설정한다.

    기존 데이터를 전송하는데 발생하는 네트워크 부하보다 적은 데이터를 전송 받기 때문에, 네트워크 부하가 해결된다.

    위와 같이, "if-modified-since" - "Last-Modified"를(if-modified도 존재) 통해 검증하는 방법은 여러 단점이 존재한다.

    먼저, 1초 미만의 캐시 유효시간을 조정할 수 없다.

    또한, 날짜 기반의 로직을 사용하기 때문에, 수정 날짜는 바뀌었지만 실제 데이터가 기존과 동일한 경우가 발생할 수 있다.

    또한, 서버에서 주석과 같은 데이터에 크게 영향 없는 변경이 발생하여, 캐시를 유지하고 싶은 경우 해결할 수 없다.

    이를 해결하는 방법이 "if-none-match" - "ETag"를 사용하는 것이다. (if-match도 존재)

     

    캐시용 데이터에는 해시 함수를 사용한 임의의 고유 버전 이름(Entity Tag)을 달아둔다.

    데이터가 변경 되면, 해시 함수를 통해 다른 값이 Tag로 적용되고, 이전과 동일한 데이터 일 경우 동일한 해시 값이 나오므로, 위와 같이 수정 날짜는 변경되었지만 실제 데이터의 변경이 없는 경우를 검증할 수 있게 된다. 

    HTTP/1.1 200 OK
    Content-Type: image/jpeg
    cache-control: max-age=60
    ETag: "aaaaaaaaaa"
    Content-Length: 34012
    lkj123kljoiasudlkjaweioluywlnfdo912u34ljko98udjklasl
    kjdfl;qkawj9;o4ruawsldkal;skdjfa;ow9ejkl3123123

    해당 데이터의 캐시 유효 시간과 ETag를 저장해두었다가, 유효시간이 만료 되었을 경우 ETag를 서버에 보냄으로써 데이터의 변경이 발생했는지 알 수 있다. 

    Request Message Response Message
    GET /star.jpg
    If-None-Match: "aaaaaaaaaa"
    HTTP/1.1 304 Not Modified
    Content-Type: image/jpeg
    cache-control: max-age=60
    ETag: "aaaaaaaaaa"
    Content-Length: 34012

    위와 같이, 304 (Not Modified) 상태 코드가 온 경우, 브라우저 캐시의 메타 데이터를 변경하여 재사용할 수 있다.

     "if-none-match" - "ETag"를 사용하게 되면, 캐시 제어 로직 권한이 오직 서버에게 있게 된다.

    ex) 애플리케이션 배포 주기에 맞게 ETag 갱신 등

    ● 캐시 제어 헤더

    ● Cache-Control (캐시 제어)

    1. Cache-Control: max-age

    캐시 유효 시간을 가리키며, 초단위로 나타낸다.

    2. Cache-Control: no-cache

    데이터를 캐시해도 되지만, 항상 Origin 서버에 검증하고 사용해야 한다.

    3. Cache-Control: no-store

    데이터에 개인 정보와 같은 민감한 정보가 존재하므로, 캐시에 저장하면 안된다.

    즉, 메모리에서 사용하고 최대한 빨리 삭제하라는 뜻이다.

     

    ● Pragma (캐시 제어 하위 호환)

    1. Pragma: no-cache

    Cache-Control의 HTTP 1.0 하위 호환이다.

     

    ● Expires (캐시 만료일 지정 하위 호환)

    1. expires: Mon, 01 Jan 1990 00:00:00 GMT

    기존에는 캐시 유효 시간을 입력했지만, expires를 사용하면 캐시 만료일을 정확한 날짜로 지정할 수 있다.

    HTTP 1.0 부터 지원하며, expires보다는 Cache-Control: max-age를 권장하고 있다.

    만약, Cache-Control: max-age와 함께 사용하면 Expires는 무시된다.

     

    ● 프록시 캐시

    한국에서 외국에 있는 Origin 서버에 데이터를 요청하면, 비교적 많은 시간이 걸릴 것이다.

    그렇다면, 이러한 네트워크 접근 시간을 줄일 수 있는 방법이 뭐가 있을까 ?

    바로, 한국에 프록시 캐시 서버를 두는 것이다.

    프록시 캐시 서버를 통해, 외국에 존재하는 Origin 서버에 데이터를 요청하지 않고 해당 프록시 캐시서버에서 데이터를 요청하면 비교적 짧은 시간이 소모될 것이다.

    이 때, 프록시 캐시 서버에 저장되는 캐시를 public 캐시라고 하며, 웹 브라우저에 저장되는 캐시를 private 캐시라고 한다.

    ● Cache-Control: public - 응답이 public 캐시에 저장되어도 됨
     Cache-Control: private - 응답이 특정 사용자만을 위한 것이므로, private 캐시에 저장되어야 한다. (Defualt 값)
     Cache-Control: s-maxage - 프록시 캐시에만 적용되는 max-age를 나타낸다.
     Age: 60 - 응답 메세지의 HTTP 헤더에 포함되며, Origin 서버에서 응답 후 프록시 캐시 내에 머문 시간(초)를 의미한다.

    ● 캐시 무효화

    "Cache-Control: no-store" 등을 사용하여도, 웹 브라우저에 따라 임의로 캐시로 사용하는 경우가 발생한다.

    이러한 확실한 캐시 무효화를 하기 위해서는 다음과 같은 캐시 지시어를 넣어주어야 한다.

    Cache-Control: no-cache, no-store, must-revalidate

    ※ Pragma: no-cache (HTTP 1.0 하위 호환)

    ● Cache-Control: must-revalidate

    캐시가 만료된 후, 최초 조회시 Origin 서버에 검증해야하며, Origin 서버 접근 실패시 반드시 오류가 발생해야 한다.

    *504 (Gateway Timeout)

    no-cache와는 다르게, 캐시 유효 시간에는 별다른 검증 없이 캐시를 사용하여도 된다.

    no-cache+ETag를 통해, 서버에 데이터를 요청하였을 때, 만약 프록시 캐시 서버와 Origin 서버의 연결이 끊겼다고 해보자.

    이럴 경우, 서버의 설정에 따라 프록시 서버에 존재하는 데이터를 전달해줄 수도 있다.

    하지만, 단순한 데이터가 아닌 중요한 정보가(통장 잔고 등) 포함된 경우, must-revalidate를 사용하여 오류를 발생시켜야만 한다 !

    'HTTP' 카테고리의 다른 글

    8. HTTP 헤더 (1)  (0) 2022.08.01
    7. HTTP 상태코드  (0) 2022.07.28
    6. HTTP 메서드 활용 (2)  (0) 2022.07.28
    5. HTTP 메서드 활용 (1)  (0) 2022.07.28
    4. HTTP 메서드  (0) 2022.07.28

    댓글

Designed by Tistory.