2017년 7월 27일 목요일

[HTTP 프로토콜 강좌]#13 HTTP 요청 헤더 III - If-Match, If-Modified-Since, If-None-Match


오늘은 HTTP 요청헤더 중 다음 3가지에 대해 이야기 해보려한다.


  1. If-Match
  2. If-Modified-Since
  3. If-None-Match




원래 한번에 헤더 5개씩 정리를 하려 했는데, 이번주 외근과 출장이 좀 있다보니.. 이게 쉽지 않다. 그렇다고 5개가 다 정리될때까지 대기하려니.. 포스팅간의 시간적인 간격이 길어지기도 해서.. 이건 좀 아닌거 같기도 하고.. 

시간이 허락하는 만큼 정리해서 자주 올리는 방향으로 진행해 보려한다.




1. If-Match

If-Match 헤더를 이해하기 위해서는 "ETag 헤더"를 먼저 이해하는게 좋다.
ETag 헤더는 요청헤더가 아닌 응답 헤더인데, 그래서 여기에서는 E-tag 헤더가 이런것이다 라는 언급만 하고, 상세한 것은 요청헤더가 마무리되면 후에 다시 다루기로 한다.

먼저 ETag 헤더..
ETag 헤더는 웹서버가 제공하는 컨텐츠들에 각각 부여되는 일종의 식별자 같은 정보이다.
사람에게 지문 또는 주민 등록 번호와 같이 개개인을 구별할 수 있는 정보가 있는것과 같이 ETag도.. 그런것이다.

웹서버는 클라이언트에게 컨텐츠를 제공할때 ETag 정보를 같이 전달한다. 클라이언트와 프록시서버들은 이 정보를 다음 요청(subsequence Request)에 활용할 수 있다.
예컨데, 캐시기능에서 활용하면 좋은데.. 웹서버는 사용자가 요청한 컨텐츠가 이전에 제공했던 컨텐츠인지 새롭게 제공해야 할 컨텐츠인지 구별할 수 있다.

"twice.jpg" 라는 요즘 핫한 트와이스 걸그룹의 이쁜 이미지 파일 하나가 있다고 가정하자.
여름이어서 쭉~ 아래와 같은 수영복 복장의 이미지를 서비스 컨텐츠고 제공해왔었는데



겨울이 되어서 다음과 같은 이미지로 변경을 했다. 


파일은 변경되었으나, 파일네임은 twice.jpg 로 같은 경우 웹서버는 이를 구분해야 할텐데.. 이때 ETag 정보를 활용할 수 있는 것이다. 

ETag 를 어느 정도 이해했다면.. 이제 본격적으로 If-Match 헤더를 알아볼 차례이다. 

If-Match 는 요청 헤더의 한 종류이고 헤더 값(Value)으로 서버에서 제공해준 ETag 정보를 표기한다.
예를 들어 어떤 웹개발자가 위와 같이 트와이스 이미지를 변경하려 할때, 서버에게 ...

"웹서버야~~ 전에 니가 내게 주었던 여름옷의 트와이스 이미지를 겨울옷으로 변경하고 싶은데.. 해주면 알될까? 
지금 너가 서비스 하는 트와이스 이미지가 여름옷의 이미지지? 그렇다면 겨울옷으로 변경해줘.. 여름옷의 트와이스 이미지가 아니라면 내게 아니라고 알려주고~~~"

이런것이다. 

이걸 다음과 같이 동작 흐름으로 표현해 본다. 



두 사용자가 있다. 클라이언트 A 그리고 클라이언트 B

  1. 클라이언트 A가 특정 컨텐츠(여름복장의 트와이스)를 요청했다.
  2. 서버는 트와이스 이미지를 클라이언트 A에게 ETag 정보와 함께 정상적으로 건네준다.
  3. 클라이언트 B가 같은 이미지를 요청했다. 
  4. 서버는 클라이언트 A에게 제공했던 같은 이미지를 B에게도 ETag 정보와 함께 전달한다. 
이때 A와 B가 전달받은 이미지는 같은 것이므로, ETag 정보가 다르지 않다. (둘다 AABB임)

이런 상태에서 클라이언트 A가 겨울복장의 트와이스 이미지로 변경한 경우....




  1. 클라이언트 A가 PUT 요청방식(Method)를 이용하여 겨울복장의 트와이스 이미지로 변경한다.
    이때, 변경된 이미지에 대한 Etag 이미지를 전달 받는다.
    서버에서는 당연히 컨텐츠 이미지가 변경되었으므로 더이상 AABB 의 Etag 정보를 가진 컨텐츠는 존재하지 않는다. 
  2. 클라이언트 B가 A가 작업을 한지 모르고 마찬가지로 PUT 방식을 이용하여 이미지를 변경하려 한다. 
  3. 웹서버는 클라이언트 B가 전달해 준 ETag 정보 ( 이전 여름복장의 이미지 ) 와 다르기 때문에 실패라는 메시지를 B에게 전달한다. 
위와 같이 도식으로 살펴보니 이해가 좀 쉬웠는지 모르겠다. 

중요한건 웹서버가 가지고 있는 컨텐츠 별로 ETag 정보를 부여하여 관리하게 되는데, 컨텐츠의 변경시 동시작업의 경우 컨텐츠 무결성이 훼손될수 있으므로, 이를 방지하기 위해 If-Match 라는 헤더를 사용한다는 것을 기억했으면 한다. 

추가적으로, If-Match 헤더의 값으로 "*(asterisk)" 를 사용할 수 있는데, 이건 컨텐츠의 내용은 잘 모르겠고, 파일이 존재하기만 한다면, 클라이언트가 요청한 것을 처리해 달라라는 뜻이다. 

위 두번째 도식에서 클라이언트 B가 If-Match 의 값으로 AABB 가 아닌 "*" 를 사용했다면, A가 이미 변경했음에도 불구하고 B가 요청한 동작이 처리된다. 




2. If-Modified-Since

If-Modified-Since 헤더를 이해하기 위해서는 Last-Modified 헤더의 의미를 먼저 알아야 한다. Last-Modified 는 ETag 와 같이 응답헤더이다. 

Last-Modified 헤더는 단어 의미와 같이 컨텐츠가 마지막으로 변경된 시점 정보를 값으로 가진다. 그러니까 웹서버의 컨텐츠가 가장 마지막으로 수정된 시점을 표현하는 것이다. 이정도로만 이해하고 자세한 내용은 마찬가지로 응답헤더를 다룰 때 다시 설명하기로 한다. 

이제 If-Modified-Since 헤더를 알아 보도록 하자.

If-Modified-Since 헤더는 캐시(Cache)관련 헤더이다. 
웹브라우져(클라이언트)나 캐시서버는 웹서버의 응답컨텐츠들을 디스크나 램에 저장하게 되는데, 이 녀석들은 캐싱된 이미지등의 컨텐츠들을 유효한지 여부를 늘 고민해야 한다. 
(웹서버에서 컨텐츠가 변경되었는데, 그것을 반영하지 못하면 안되니까.....)

If-Modified-Since 는 웹브라우져나 캐시서버가 웹서버에게 바로 이런 확인 절차를 거치는 용도로 사용되는 것이다. 

> 웹브라우져 / 캐시서버 : 내가 가지고 있는 여름복장의 트와이스 이미지 직접 줘두 되지?
> 웹서버 : 응.. 나도 똑같은 이미지 가지고 있으니까 그거 보내줘

이런 형태의 동작인것이다. 아래 동작 흐름도를 살펴보자. 

먼저, 첫번째 최초 요청이다. 



  1. 클라이언트가 특정 컨텐츠를 요청한다.
  2. 프록시 서버는 클라이언트의 요청을 받아 대신 실제 서버로 전달한다.
  3. 실제 서버는 컨텐츠를 제공하는데 이때, 컨텐츠의 최종 수정시간을 Last-Modified 헤더에 포함하여 전달한다. 
  4. 프록시 서버는 실제 서버의 응답컨텐츠를 자신의 디스크나 램에 저장한후 그대로 클라이언트에게 전달한다.

두번째 동일한 컨텐츠를 다시 요청하는 경우..


  1. 클라이언트가 같은 컨텐츠를 요청한다.
  2. 프록시 서버는 클라이언트 요청을 받아 서버에 전달할때, 캐시되어 있는 컨텐츠임을 알고 If-Modified-Since 헤더에 Last-Modified 의 값(시간정보)을 표기하여 전달한다.
  3. 실제 서버는 동일한 컨텐츠임을 확인하고 변경된 바가 없으니 직접 제공하라는 메시지를 전달한다 (304 Not Modified)
  4. 프록시 서버는 자신의 디스크 또는 램에 저장되어 있는 컨텐츠를 클라이언트에게 전달한다. 

이와 같이 If-Modified-Since 헤더는 캐시동작에 있어서 유효한 컨텐츠를 클라이언트에게 제공할 수 있게 해 주는 중요한 정보이다.

그렇다면 이러한 중요한 If-Modified-Since 헤더의 정보에 오류가 있는 경우는 어떻게 될까? 가령, If-Modified-Since 의 표시 형식이 잘못되었다던지.. 서버의 현재시간보다 더 늦은경우라던지.. 
이경우 웹서버는 If-Modified-Since 헤더의 정보를 무시하고, 컨텐츠 전체를 서비스하게 된다. 

* 참고: 캐시동작의 장점 중 하나는 네트워크 대역폭(Bandwidth) 절감이라는 것인데.. 
이와 같은 경우 프록시 서버에 캐시되어 있는 컨텐츠가 큰 용량인 경우 프록시 서버와 실제 서버간의 네트워크 대역폭을 절약할 수 있다.




3. If-None-Match

If-None-Match 헤더는 If-Match 헤더와 사용 목적이 비슷하다. 단지 클라이언트가 확인하고 싶은 정보가 None 이 들어가 있으므로 If-Match 헤더와는 의미적으로 반대이긴 하다.

If-Match 헤더와 If-None-Match 헤더의 값은 서버가 반환해 준 ETag 정보이다.
ETag 헤더의 간략한 정보는 If-Match 헤더에서 다룬적이 있으니, 오늘 강좌의 제일 첫번째 If-Match 부분을 참고 하는게 좋겠다.

If-Match 와 If-None-Match 는 서버가 제공하는 컨텐츠의 변경 여부를 확인하기 위해서 사용되는 헤더이다.

  • If-Match : 컨텐츠가 변경되지 않고 같다면...
  • If-None-Match : 컨텐츠가 변경되었다면...
하지만 사용목적이 If-None-Match가 좀 넓다고 해야 할까? 암튼 그렇다. 
그럼 두가지 요청헤더의 차이점을 통해 If-None-Match 헤더를 이해해 보도록 하자. 

If-Match

웹서버가 If-Match 헤더에 값을 확인했을때 컨텐츠가 변경되지 않고 그대로 있다면 클라이언트가 요청한 동작을 서버는 수행한다. 가령 If-Match 의 값이 일치하는 경우에는 GET 요청방식에 대해서는 컨텐츠를 반환하여 주고, PUT 요청방식에 대해서는 컨텐츠를 변경하도록 허용한다. 
반면 If-Match 의 값이 다른경우에는 서버에서 412 상태코드를 반환하며 클라이언트가 요청한 동작을 수행하지 않는다. 
그러니까 정보가 맞으면 뭔가를 하고, 다르면 아예 하지 않는다. 

GET과 PUT 요청방식에 대해 If-Match의 경우를 동작흐름으로 살펴보면 다음과 같다. 
먼저 GET..


클라이언트가 웹서버에게 twice.jpg 라는 이미지 컨텐츠를 최초 요청하면, 서버는 이미지를 ETag 정보와 함께 제공한다. 

이후 같은 이미지를 다시 요청하는 경우를 보자. 


웹서버가 전달해준 동일한 ETag 정보를 가지고 같은 이미지 컨텐츠를 요청하면 서버는 If-Match의 정보와 같기 때문에 정상적으로 이미지를 전달한다. 

반면, 동일한 이미지 컨텐츠지만 ETag 정보가 다른경우는.. 


그렇다. 412 상태코드를 반환한다. 조건이 맞지 않으므로 클라이언트에게 요청한 이미지를 제공하지 않는다. 

그다음 PUT 방식..
클라이언트가 최초 요청으로 특정컨텐츠의 ETag 정보를 얻은 후 (ETag : AABB)


PUT으로 내용을 바꾸려 하는 경우.. GET과 결과는 같다. 


ETag가 같은 경우 클라이언트 요청대로 twice.jpg 파일을 교체 하게 되지만, ETag가 다른 경우에는 412 상태코드 메시지를 전달한다. 


If-None-Match

If-None-Match 는 If-Match와 비슷하지만 GET 방식에 있어서는 좀 다르다. 
If-None-Match 는 GET 에서는 If-Modified-Since 헤더처럼 사용된다. If-None-Match 헤더를 이용해서 컨텐츠의 변경여부를 묻고 그렇지 않다고 한다면(ETag 정보가 다른지 않은 경우 그러니까 동일한 경우) 412 상태코드를 반환하는게 아니라 "304 Not Modified" 메시지를 전달한다. 

다음 동작흐름을 통해 이해를 해보자.

먼저 GET으로 최초 이미지 컨텐츠를 요청한 후 ETag 정보를 받는다. 


이후 클라이언트가 If-None-Match 헤더에 동일한 ETag 를 전달하는 경우와 그렇지 않은 경우는 다음과 같다. 


웹서버는 If-None-Match 헤더의 값이 같은 경우와 다른 경우 모두 정상응답에 해당되는 200, 304 상태코드를 반환했다. 

GET에서는 If-None-Match의 값이 ETag와 같을 경우 캐싱되어 있는 이미지를 사용할 수 있도록 304 상태코드를 반환한다. If-Modified-Since 와 같은 목적으로 사용되어 지는것을 확인했다. 
굳이 차이가 있다면.. If-Modified-Since 헤더는 시간정보를 담기 때문에 웹서버나 클라이언트의 환경적인 측면에서 정보의 정확성이 보장되지 않을수도 있지만.. If-None-Match 헤더는 ETag 정보를 활용하기 때문에 컨텐츠의 변경 유무를 아주 정확하게 반영할 수 있는 장점이 있긴 하다. 

PUT은 If-Match 헤더와 결과는 같다. 다만 차이가 있다면.. 
If-Match는 덮어쓰기 위한 동작에 사용된다. 새로운 파일 생성을 금지하는 컨셉이 있고
If-None-Match는 신규로 생성하기 위한 동작에 사용된다. 파일 덮어쓰기를 금지하는 컨셉인 점이다. 


이번 내용은 여기까지.. .

끝!





댓글 없음:

댓글 쓰기