인터넷에서 소통이란 IP에서 IP로 정보를 보내는 것이다.
정보는 여러 포장을 거쳐서 패킷(packet)으로 보내진다.
TCP는 전송 제어 프로토콜인데, 3 way handshake라는 방식을 쓴다.
특정 서비스를 제공하는 사이트에서 그 서비스 하나만 제공하는 경우는 별로 없다.
유저가 한 사이트에서 여러 서비스를 이용하려면 IP 접근만으로는 한계가 있다.
그래서 PORT가 있다.
유명한 포트 번호로는 443(HTTPS)가 있다. 보안 기능을 함께 제공한다.
IP가 도시라면 port는 항구다.
도시에서 교역을 하려면 1번 항구로 가야하고, 배를 수리하려면 2번 항구로 가야하는 식이다.
IP는 111.111.111.111 이런 식으로 구성되어있는데, 저렇게 주소를 입력해서 사이트를 접속하는 사람은 나는 아직 못 봤다.
DNS(Domain Name System)를 이용하면 도메인을 IP 주소로 변환해서 들어가게 해준다.
Uniform: 구분한다.
Resource: 자원을,
Identifier: 식별자로.
URI는 보통 아래와 같은 형식을 가진다.
(port라던지, 생략되는 부분도 있다.)
schema://host/path?query=...
coffee png라고 검색하면 구글은 저렇게 긴 URI로 검색한다.
이름에 Resource가 들어가는 만큼, URI는 리소스를 기준으로 만들면 좋다.
/create/user... [X]
/user [O]
그렇지만 모든 URI를 리소스로만 만들 순 없다. 위의 구글 예시도 그렇다.
/search같은 건 컨트롤 URI다. 동사로 만드는 편.
똑같은 URI에서 회원 가입도 하고, 회원 조회도 하고..그런 건 어떻게 하지?
바로 HTTP 메소드(GET,POST 등)를 쓰면 된다.
안전성(safe) : 해당 메소드를 호출해도 리소스는 변하지 않는다.
멱등성(Idempotent) : 해당 메소드를 몇 번 호출해도 결과는 동일하다.
캐시 가능(Cacheable) : 해당 메소드는 호출했을 때 캐싱 가능하다.
POST처럼 서버가 URI를 만들고 관리하는 디렉토리는 Collection,
PUT처럼 클라이언트가 URI를 알고 관리하면 디렉토리는 Store라 부른다.
정상 처리된 상태
리다이렉트 관련
삭제된 글 링크를 클릭했더니 저렇게 리다이렉트 됐다.
클라이언트에서 잘못 요청함
따라서 요청을 재시도해도 성공할 가능성이 없다.
서버에서 뭔가 잘못함.
요청을 재시도하면 성공할 가능성이 있다.
서버 에러는 정말로 서버 문제일 때에만 띄우자.
먼 옛날에는 RFC2616라는 HTTP 표준이 있었다고 한다.
Entity Header, Entity Body 구조였다는데...지금은 달라졌다.
지금은 entity 대신 representation이라고 쓴다.
(REST API에서 RE가 representational이다.)
본문을 payload라고도 표현한다.
헤더는 중요하다. 일종의 육하원칙이 담기는 곳이다.
처음에 IP, TCP 패킷 헤더에서도 IP, PORT 등의 정보가 들어간다는 얘기를 했다.
원칙 | HTTP 요청, 응답에 대한 설명 |
---|---|
who(누가) | 클라이언트 or 서버 |
when(언제) | 접속이 가능하면, 조건이 성립하면. |
where(어디서) | 앱, 웹 브라우저 등에서. |
what(무엇을) | 데이터 작업, 처리, 생성, 서비스 이용 등 |
how(어떻게) | 헤더 조건에 맞게 포장해서. |
why(왜) | 서비스를 이용하고 싶어서(나), 요청이 들어와서(서버) |
헤더에 들어가는 옵션들
그 외에도 여러 가지 중요한 것들이 많이 담겨온다.
아래에 소개하는 것들도 전부 헤더에 들어가는 것들이다.
척 봐도 유저의 유입 경로를 분석할 때 최고다.
어느 브라우저에서 문제가 발생한다던지 조사할 수 있다.
origin 서버란?
HTTP로 요청과 응답을 주고받을 때엔 중간에 여러 서버들을 거치게 된다.
origin은 최종적으로 응답을 주는 진짜 서버를 일컫는다.
“웬 네고? 네고왕? 당근에서 악명 높은 네고?”
거기서 말하는 네고 맞다. 협상이다.
우리는 HTTP 요청을 보낼 때 네고를 시도할 수 있다.
그림과 같이 HTTP 헤더에 Accept: 불라불라를 덧붙여서 요청을 보내면 서버는 그 요청에 '최대한' 맞춰서 응답한다.(무조건은 아니다.)
영어와 일본어만 제공하는 사이트에서 Accept-Language: ko로 보내면 서버는 지 맘대로 보낸다.
만약 서버가 일본어를 기본 옵션으로 설정했으면 일본어를 구경하게 된다.
내가 기본적으로 일본어보단 영어로 보고 싶다면? 아래와 같이 우선 순위를 옵션으로 넣으면 된다.
한국어를 최우선으로 요청하고, 없으면 영어, 일본어를 달라고 요청하는 것.
HTTP는 기본적으로 무상태(Stateless) 프로토콜이다.
-> 요청을 보내고, 응답을 받았으면 역할은 끝난다. 기억할 필요도 없다.
하지만 우리는 접속할 때 로그인 상태를 기억해두는 게 일반적이다.
그래서 쿠키를 사용한다. 서버는 응답 시에 헤더에 set-cookie를 준다.
우리(브라우저)는 그 쿠키를 쿠키 저장소에 보관했다가 사용한다.
쿠키의 옵션들
Domain : 도메인을 지정해주면 서브(하위) 도메인에서도 쿠키를 사용할 수 있다. 지정 안 하면 정확히 그 도메인에서만 쿠키 사용 가능.
Path : 경로를 지정해두면 그 경로의 하위 경로들까지 쿠키들이 접근 가능하다.
expires : xxxx년 xx월 xx일 xx시 xx분 xx초까지 유효하게 두겠다.
Max-Age : 쿠키 발급일 기준으로 xx초 동안 유효하게 두겠다.
secure : 적용하면 https에서만 쿠키 전송, 미적용시 http에도 쿠키 전송.
HttpOnly : XSS 공격 방지. js에서 쿠키 접근이 불가능.
SameSite : XSRF 공격 방지. 요청 도메인과 쿠키에 설정된 도메인이 같을 때에만 쿠키 전송.
쿠키 덕분에 로그인 여부를 기억할 수 있게 됐다. 하지만 이걸로는 부족하다.
3MB 이미지를 요청하고, 2초 뒤에 또 그 이미지를 요청한다고 해보자.
캐시가 없으면 똑같은 이미지인데도 3MB짜리 요청을 또 해서 네트워크를 낭비한다.
캐시를 설정하면?
처음에만 다운로드 제대로 받고, 브라우저는 캐시 저장소에 캐시를 저장한다.
캐시가 유효할 동안에는 재방문 시 내 캐시에서 결과를 가져오기 때문에 로딩이 빠르다.
캐시의 장점
캐시의 단점
위키에서도 찾아볼 수 있는 내용.
오래된 캐시가 문제라면 보통은 캐시를 비워주면 해결된다.
오늘의 집 cache-control 예시.
쿠키와 마찬가지로 max-age를 사용하고 있다.
유효기간을 31534702초나 준다. 대략 1년이다.
근데 정확히 1년은 아니고 364일 23시간 38분 22초라고 계산된다.
왜 저렇게 설정했는지는 모르겠다.
캐시 유효기간이 끝나면 어떻게 처리할까?
누군가는 캐시 유효기간을 비교적 짧게 둘 수도 있다. 예컨대 100초 동안만 유효하도록 설정했다고 치면, 2분 뒤에 또 요청하면 큰 용량을 처음부터 다운로드 받아야한다.
두 가지 방법을 사용한다.
캐시를 저장할 때 최종 수정일 정보를 같이 넣고, 요청을 보낼 때 서버에서 비교한다.
클라이언트에 있는 캐시, 서버에 있는 캐시의 최종 수정일이 동일하면, 동일한 캐시라고 판단한다.
서버는 304 status를 보내면서 "클라이언트야. 네 캐시를 재사용해봐."라고 말한다.
이 때, 서버는 payload를 보낼 필요가 없어서 body가 비어있다.
그러면 브라우저는 캐시 저장소에서 유효기간이 끝난 애를 부활시킨다.
요청에선 if-modified-since: 를 사용한다.
한계 : 수정일만 비교하기 때문에, 내용물 변화가 없는 가벼운 수정에도 재다운로드를 시킨다.
캐시 데이터에는 우리가 임의로 태그를 붙일 수 있다.
etag만 비교해보고 다르면 재다운로드, 같으면 유지하는 식이다.
요청할 땐 if-none-match를 사용한다.
그림과 같이 확실하게 명시해줘야 한다.
명시를 안 하면 브라우저가 멋대로 판단해서 캐시하는 경우도 생긴다.
no-cache와 must-revalidate는 둘 다 웹 캐시(프록시 서버)에서 검증한다는 공통점이 있다.
예를 들어 프록시 서버와 origin 서버와의 연결에 일시적으로 문제가 생겼다고 가정해보자.
그럴 때 no-cache는 옛날 결과를 돌려주는 경우도 있다고 한다.(2월 25일 계좌 잔액 요청을 했는데, 1월 11일에 조회한 계좌 잔액을 보여준다던지.)
must-revalidate는 서버 에러(504)를 내보낸다.
우리가 아는 유명한 서비스들이 다 한국산은 아니다.
외국의 서비스들을 우리가 빠르게 이용할 수 있는 이유는 한국에 프록시 서버를 둬서 캐시를 저장해두기 때문이다. 그런데 위에서 말했듯이, 캐시는 최초로 조회할 땐 풀 다운로드를 받는다.
따라서 서비스를 최초로 이용하는 유저는 시간이 좀 걸린다.
두 번째 이용자부터는 웹 캐시에 저장된 것들을 조회하기 때문에 시간이 단축된다.
HTTP 위키피디아 문서
MDN representation 헤더
MDN HTTP 헤더
MDN HTTP 헤더에 들어가는 것들
MDN 컨텐츠 네고
웹 캐시에 관한 이야기
XSS 공격과 HttpOnly
XSRF 공격과 SameSite
10분 테코톡 - cache
캐시