HTTP 헤더에 대해 자세히 알면 좋으니까! 시작했다.
리액트로 프론트 엔드를 공부하던 와중에 application/json 타입으로 통신을 할 때도 있었고,
multipart/form-data로 통신을 할 때도 있었다.
결론부터 말하자면 string 등의 타입만 보낼 때는 json이 편리하지만, 음악/사진/동영상 등은 form data가 편리하다고 생각한다.
JSON이란 JavaScript Object Notation의 줄임말로, 데이터를 전송하거나 저장할 때 많이 사용되는 경량의 데이터 교환 방식을 말한다.
다음은 장점과, application/json 형식으로 바이너리 데이터를 취급할 때의 단점을 정리했다.
이 타입은 MIME 데이터 스트림의 규칙을 준수한다.
(프론트) append
메소드로 key-value 값을 하나씩 추가해주고, 같은 key를 가진 값을 여러 개 넣을 수 있다.
단, set
으로 넣으면 덮어쓰인다.
숫자를 넣어도 문자열이 되고, 배열을 넣어도 콤마로 구분한 문자열이 된다. 또한 객체를 넣으면 무시가 된다.
위 특징을 잘 참고해서 사용해야 한다.
데이터를 보내는 각각의 방식에는 장단점이 있다.
검색을 하다 알게된 사실인데, form-data와 json으로 각각을 동시에 보내는 방법도 있다.
두 가지의 장점을 살리기 위해서 고안된 방법 같은데, form 안에 json을 넣어서 보냄으로써 구현된다.
캐시는 기본적으로 자주 사용되는 데이터를 임시로 복사해두는 임의의 장소를 의미하고, 캐싱은 캐시에 저장하는 행위를 말한다.
일반적으로 캐싱은 캐시에 저장된 데이터에 접근하는 시간에 비해 원본 데이터에 접근하는 시간이 오래 걸리는 경우 사용한다.
참고로 브라우저에서 캐시가 동작하려면 "Disable cache" 등의 브라우저 옵션이 꺼져 있어야 한다.
캐시는 크게 2개로 나눌 수 있다.
(이거는 내가 잘못 생각했던 부분인데, Cache-Control은 Shared Cache에 저장하는 행위에 대해서도 control할 수 있다)
캐시는 다음과 같이 동작한다.
이때, 재검증 시각에 대한 내용은 갱신된다.
예를 들어 15:00:00에 "max-age=15"를 가진 응답을 받았다고 하자.
이후 15:00:20에 재요청을 보내면 유효 기간이 지났다고 판단하고 재검증을 수행한다.
만약 서버로부터 304응답을 받았다면 15:00:35 전에 보내는 리소스 요청은 다시 Private Cache에서 읽어와 사용한다.
(자세한 재검증 관련 헤더는 아래에서 다루겠다)
더 많은 내용들이 있는데, 자주 사용하는 내용들 위주로 정리했다.
참고1
캐시를 사용하지 않기 위해서 다음과 같이 사용 가능하다.
Cache-Control: no-cache, no-store, must-revalidate
참고2
"max-age=0"(no-cache)의 경우, 일부 모바일 브라우저의 경우 웹 브라우저를 껐다 켜기 전까지 리소스가 만료되지 않도록 하는 경우가 있다.
아래에 부가적인 헤더 사용은 서버에서 결정한다.
하나만 쓸 수도 있고 여러 가지를 같이 혼용해서 쓸 수도 있다.
Age 헤더는 캐시 응답 때 나타나는데, max-age 시간 내에서 얼마나 흘렀는지 초 단위로 알려준다.
max-age=3600을 설정한 경우, 1분이 지나면
Age: 60
이 캐시 응답 헤더에 포함된다.
Cache-Control과 별개로 응답에 Expires라는 헤더를 줄 수도 있다.
Expires: Sun, 8 Oct 2023 07:28:00 GMT
응답 컨텐츠가 언제 만료되는지를 나타내며, Cache-Control의 max-age가 있는 경우 이 헤더는 무시된다.
Cache-Control 헤더가 캐시 제어를 더 세밀하게 설정할 수 있기 때문에, Expires를 혼용해서 사용하는 것은 일반적으로는 네트워크 리소스 낭비를 야기한다.
문서 유효 시간 체크하는 방법이다.
최초 요청 시 다음과 같은 응답을 내려준다.
Server는 리소스의 마지막 수정 날짜(Last-Modified)를 제공한다.
HTTP/1.1 200 OK
Content-Type: text/html
Cache-Control: max-age=3600
Last-Modified: Sat, 03 Sep 2022 00:00:00 GMT
캐시 기간이 초과된 이후 다음 요청 시 다음과 같은 내용을 보낸다.
이전 응답에서 Last-Modified 값을 If-Modified-Since의 값으로 넣는다.
GET /index.html HTTP/1.1
Host: example.com
Accept: text/html
If-Modified-Since: Sat, 03 Sep 2022 00:00:00 GMT
원본 리소스에 아무런 변경이 없다면 서버는 아래와 같은 응답을 보낸다.
Last-Modified 값에 대한 변경은 없다.
HTTP/1.1 304 Not Modified
Content-Type: text/html
Cache-Control: max-age=3600
Last-Modified: Sat, 03 Sep 2022 00:00:00 GMT
아래와 같은 경우 단순히 유효 시간을 체크하는 것으로 충분하지 않을 수 있다.
최초 요청 시 다음과 같은 응답을 내려준다.
Server는 특정 버전의 리소스를 구분하기 위한 식별자인 Etag를 제공한다.
HTTP/1.1 200 OK
Content-Type: text/html
Cache-Control: max-age=3600
ETag: "abcdefu"
캐시 기간이 초과된 이후 다음 요청 시 다음과 같은 내용을 보낸다.
이전 응답에서 Etag 값을 If-None-Match의 값으로 넣는다.
GET /index.html HTTP/1.1
Host: example.com
Accept: text/html
If-None-Match: "abcdefu"
원본 리소스에 아무런 변경이 없다면 서버는 아래와 같은 응답을 보낸다.
Etag 값에 대한 변경은 없다.
HTTP/1.1 304 Not Modified
Content-Type: text/html
Cache-Control: max-age=3600
Last-Modified: "abcdefu"
Last-Modified와 Etag를 같이 사용하는 경우 복잡성이 높아지며 일부 불필요한 오버헤드가 발생할 수 있다.
그러나 일부 상황에서는 두 가지 방법을 조합함으로써 캐시 효율성을 높일 수 있다.
Last-Modified는 리소스 변경 여부를 확인하는 간단한 방법을 제공하고, Etag는 보다 정확하게 캐시 유효성 검사를 수행할 수 있기 때문이다.
참고) Etag 생성 방법
등 다양함.
참고) weak ETag vs strong ETag
https://2ham-s.tistory.com/307
https://velog.io/@ryan-son/multipartform-data-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0-vs-applicationjson
https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching
https://hudi.blog/http-cache/
https://toss.tech/article/smart-web-service-cache
https://www.blog-dreamus.com/post/cache-control-%EC%9D%B4-%ED%95%84%EC%9A%94%ED%95%9C-%EC%9D%B4%EC%9C%A0
https://developer.mozilla.org/ko/docs/Web/HTTP/Headers/Cache-Control