이 글은 김영한님의 모든 개발자를 위한 HTTP 웹 기본 지식 강의를 요약한 것이며 강의 자료 및 출처는 가장 아래에서 확인할 수 있습니다.
*HTTP(HyperText Transfer Protocol)
HTTP는 문서 간의 링크를 통해서 연결할 수 있는(=hypertext 문서를 통해서 연결할 수 있는) html을 전송하는 프로토콜로 시작되었으며, 지금은 HTML 텍스트 뿐만아니라 이미지,음성,영상,파일,JSON,XML 등등 거의 모든 데이터에 HTTP를 사용한다.
실무에서 일을 하면 TCP만 직접 이용하여 연결하는 경우는 거의 없으며 거의 모든 경우에 HTTP를 사용한다.
거의 모든 기능이 HTTP/1.1에 포함 되어있어 가장 많이 사용되며, 2와 3은 성능 개선에 초점이 맞춰져 있다.
HTTP/1.1과 HTTP/2는 TCP기반이지만 HTTP/3는 UDP를 기반으로 사용한다.
실제로 구글에 어떤 검색어를 입력하고 관리자 모드를 보면 Protocol에 http버전을 확인할 수 있다.
* HTTP는 클라이언트 서버 구조이다.
요청과 응답으로 간단해 보이지만 사실은 이렇게 독립적으로 나눠져있는게 중요한 부분이다.
예를들어 클라이언트는 UI/UX를 그리는 부분에만 집중하면 되고, 서버는 비즈니스 로직에 집중할 수있다.
*HTTP는 무상태 프로토콜을 지원한다. (Stateless)
무상태 프로토콜이 무엇인지 알아보기 위해 Stateful과 Stateless 차이점을 살펴보자.
중간에 점원이 바뀐다면?
점원 B는 어떤 노트북인지 모르고 점원 C는 어떤 제품을 몇개 구매할지 모른다.
따라서 무상태는 아래와 같이 표현할 수 있다.
(참고로 노트북은 매장에 하나밖에 없다고 가정하자)
무상태는 고객이 필요한 데이터를 그때그때 다 넘겨주기 때문에 중간에 점원이 변경되어도 자연스럽게 흘러가는 것을 볼수있다.
따라서 정리해보자면 Stateful(상태유지)은 중간에 다른 점원으로 변경되면 안되고,
Stateless(무상태)는 중간에 다른 점원으로 변경되어도 된다. 예를들어 고객이 막 증가하여도 점원을 대거 투입할수있다.즉, 갑자기 클라이언트 요청이 증가하여도 서버를 대거 투입(증설)할수있다.
따라서 Stateless는 모든 필요한 요청을 다 보내기때문에 서버1이 고장나도 상태를 보관하지 않기때문에 아무 서버나 호출해도 상관이 없다. 역으로 상태유지는 서버1이 응답한 내용을 기억하고 있어야하고, 서버1이 고장나게되면 문제가 생기게된다.
따라서 무상태는 스케일 아웃 즉, 수평 확장에 매우 유리하다.
필요한 요청이 모두 클라이언트에 포함되어 있기때문에 어떤 서버를 추가해도 문제가 되지 않는다.
실무에선 모든 것을 무상태로 설계할수는 없기 때문에, 쿠키와 서버 세션등을 이용하여 상태를 유지한다.
또한 상태 유지는 최소한만 사용한다.
* HTTP는 비연결성이다.
만약 연결을 유지하는 모델이라면 서버는 클라이언트1,2의 요청후 3의 요청을 응답할때도 1,2를 여전히 유지하기 때문에서버에 과부하를 줄일수있다.
HTTP는 연결을 유지하지 않기 때문에 매우 빠른속도로 응답하며 서버 자원을 효율적으로 사용할 수 있다.
그러나 웹 브라우저를 연결할때 TCP/IP를 계속 새로 연결해야하고, HTML뿐만 아니라 자바스크립트 , CSS, 추가 이미지등수많은 자원이 함께 다운로드 된다.
예를들어 아래와 같이 실제로 구글에 검색을 하게되면 아래와 같이 수많은 자원이 다운로드 되는것을 확인할 수 있다.
위 자원을 하나하나 받을때 마다 연결하고 끊고 연결하고 끊으면 너무 비효율적이기 때문에
HTTP는 지속 연결(Persistent Connections)을 사용하여 이를 해결한다.
같은 시간에 맞춰서 대용량 트래픽이 발생하는 경우는 어떻게 될까?
이것은 비연결성이 필요가없다. 왜냐하면 모두 정말 같은 시간에 몰려오기 때문이다.
그러나 이런 경우에도 최대한 스테이트리스하게 설계하는것을 잊지 말아야 한다.
보통 실무에서 이벤트를 설계할땐 첫페이지는 로그인이 필요없는(=연결상태가 아닌) 정적 페이지 즉,상태가 없는 순수한html페이지를 두고,그후 사람들이 그 안에서 페이지를 구경하게 한 다음 이벤트 참여 버튼을 누르게 하도록 설계하면 사람들이 페이지를 둘러 보다가 누르게 되기 때문에 자연스럽게 트래픽이 줄어들게 하는식으로 설계한다고 한다.
* HTTP 메서드
HTTP메서드는 GET,POST,PUT,PATCH,DELETE등등이 있다.
API의 URI를 고민할때 회원 목록/조회/등록/수정/삭제가 있다고 가정하면,
리소스와 행위를 분리하여 URI는 리소스만 식별하도록 설계하는것이 중요하다.
예를들어 리소스는 회원이고 행위는 조회,등록,삭제,변경이다.
즉,위와같이 설계할 수 있다.
1. GET
최근에는 get메서드에 body를 담아서 보낼수 있지만 실무에서는 사용하지 않는다고 한다.
이유는 중간에 지원하지 않는 서버가 많다고 한다.
2.POST
POST메서드는 스펙상 "대상 리소스가 고유 한 의미 체계에 따라 요청에 포함 된 표현을 처리하도록 요청"한다고 명시되어있다. 정리하자면 아래와 같은 곳에서 사용된다.
2번의 예시와 같이, 리소스로만 URI를 설계할 수 없는경우 직접 동사를 넣기도한다. 이때, 이 동사를 컨트롤URI라고 부른다. URI를 설계할땐 기본적으로 리소스로 최대한 URI를 설계하되 어쩔 수 없는 부분들은 컨트롤URI를 사용하도록 한다.
3번과 같이 BODY에 JSON데이터를 보내고싶을때, GET 메서드는 지원하지 않는 서버가 있기때문에 POST를 사용한다.이런 경우와같이 애매할때도 POST를 쓴다.
3.PUT
PUT의 중요한점은 리소스를 완전히 대체한다는 것이다.
예를들어 서버에 /members/100 라는 리소스의 내용이 { "age":20 , "username":"hun" } 일때, 클라이언트에서{ "age":"50" }으로 요청한다면 username은 사라지고 age가 50으로 대체된다.
4.PATCH
PATCH는 리소스를 부분만 변경한다.
/members/100 라는 리소스의 내용이 { "age":20 , "username":"hun" } 일때, 클라이언트에서 { "age":"50" }으로 요청한다면username은 그대로 남아있고 age만 50으로 변경된다.
정리하자면 PUT과 PATCH의 차이는 대체와 부분 변경이며 간혹 PATCH 지원이 안되는 서버가 있는데 이럴땐 무적의POST를 쓰면 된다고 한다.
5.DELETE
* HTTP메서드의 속성
HTTP 메서드의 속성은 안전,멱등,캐시가능 3가지가 있다.
1. 안전
GET메서드의 경우는 단순 조회만 하기때문에 안전하다고 볼 수있다. 역으로 위에서 언급한 나머지 메서드들은 안전하지않다. Q와 같이 질문이 들어온다면 안전이라는 속성은 해당 리소스만 고려하기 때문에 복잡하게 생각할 필요가 없다.
2. 멱등
멱등은 여러번 호출해도 결과가 같은것을 의미한다.
멱등은 자동 복구 메커니즘으로 활용할수있다. 예를들어 DELETE로 서버를 호출했는데 서버에서 응답이 없다고 가정할때, 클라이언트는 다시 자동으로 DELETE를 재시도한다. 이것이 가능한 이유는 멱등하기 때문에 똑같은 요청을해도 상관이 없다. 실제 개발에서 이런 매커니즘이 많이 사용된다고 한다.
멱등이 아닌 예를 들면 결제를 두번하면 중복 결제가 되기 때문에 문제가 발생하는 예시가 있다.
멱등의 개념은 외부 요인으로 중간에 리소스가 변경되는것 까진 고려하지 않는다.
위와 같은 부분은 역등하지 않다고 판단하는것이 맞으며, 멱등개념과 별개로 서버에서 변경된 부분을 판별해야 한다.
3. 캐시가능
캐시를 하려면 똑같은 리소스와 키가 맞아야하기 때문에 실무에서는 거의 GET만 캐시로 사용한다고 한다.
* 참고하면 좋은 URI 설계 개념
컬렉션 타입의 경우 서버가 리소스의 URI를 생성하고, 스토어 타입의 경우 클라이언트에서 리소스의 URI를 모두 알고 요청하는 것이다. 대부분의 경우 컬렉션을 사용하며 현업에선 리소스+HTTP메서드로는 해결되는 경우가 잘 없기 때문에 컨트롤러 및 컨트롤러 URI를 사용하여 해결한다.
결론적으로 컬렉션과 문서를 가지고 최대한 해결을 하고 (= 리소스 + GET,POST,PUT.DELETE로 해결하고) 해결이 되지
않는 경우는 컨트롤 URI를 사용하여 해결한다.
* HTTP 상태코드
100번대는 보통 사용하지 않기 때문에 아래에서 설명하지 않는다.
만약 모르는 오류코드가 나와 어떤 코드인지 모를때는 그냥 상위 상태코드로 해석해서 처리하면 된다.
예를들어 미래에 299번 오류코드가 나왔다하더라도 위에서 2xx즉 요청이 정상적으로 처리되었다고 해석하면 된다.
1.2xx
201은 요청이 성공해서 새로운 리소스가 생성됨을 의미한다.
202는 요청이 접수되었으나 처리가 완료되지 않았음을 의미한다. 배치 처리 같은 곳에서 사용한다.
204는 서버가 요청을 성공적으로 수행했지만, 응답 페이로드 본문에 보낼 데이터가 없을때 사용한다.
예를들어 웹 문서 편집기에 save 버튼이 있을때, save 버튼의 결과로 아무 내용이 없어도 되고 같은 화면을 유지해야 하는경우에 사용할 수 있다.
현업에선 거의 200만 사용하는 경우가 많고 201까지 사용하는 경우가 많다. 따라서 개발팀마다 다르다고 한다.
2.3xx
3xx는 요청을 완료하기 위해 웹 브라우저의 추가 조치가 필요함을 의미한다. 유저 에이전트는 웹 브라우저를 의미하며 300대 시리즈는 301~308을 대부분 사용한다. 이제 리다이렉트를 먼저 이해할 필요가 있다.
* 리다이렉션의 흐름
/event로 요청이오면 서버에선 3xx메시지와 함께 HTTP response헤더에 Location을 실어주고, 웹 브라우저에선 자동으로redirect된다.
예를 들어 옛날에 사용하던 유저가 /event url를 기억하여 해당 페이지로 접근하였지만 현재 서버에선 해당 url을 사용하지않고 /new-event와 같이 새로운 url을 사용중이라면 서버에서 자동으로 위와같이 redirect 시켜줄수 있다.
* 리다이렉션의 종류
리다이렉션은 위와같이 3가지 종류로 나뉘며 바로 위에서 언급한 경우는 영구 리다이렉션에 해당한다.
1.영구 리다이렉션
영구 리다이렉션엔 301,308이 있다.
301은 리다이렉트시 GET으로 변경되고, 308은 POST를 유지한다. 다음 예시를 보자
첫 POST요청시 Body에 메시지를 담아서 보냈지만 redirect 되면서 메시지가 제거되었다.
따라서 이런경우 301를 쓰고 메시지가 유지되는 경우 308을 사용한다.
그러나 현업에선 대부분 위처럼 /event에서 /new-event로 url이 변경되면 내부적으로 전달해야되는 데이터 자체가 변경되기 때문에 사진처럼 GET으로 주는게 맞다고 한다. 또한 301,308은 많이 사용하지 않는다고 한다.
2. 일시적 리다이렉션
307은 요청 메서드와 본문을 유지하고, 303은 GET으로 변경되어 명확하게 구분되지만 실무에선 302를 대부분 사용한다.(과거잔재)
* PRG
먼저, 이해를 돕기 위해 아래 예시를 보자
위는 PRG 사용전 예시이다.
먼저 POST로 item과 count를 body에 담아 주문 요청을 보내고 주문완료가 되어 다시 클라이언트에 요청을했다.
그런데 url이 동일하다면 클라이언트 결과 화면에서 또 주문 요청을하게 되고 중복 주문이 되는일이 발생할 수 있다.
따라서 클라이언트 측에서는 아래와 같이 처리할 수 있다.
대부분 결과 화면을 GET으로 다시 조회시키는 것이다.
이제 PRG를 사용한 예시를 보자.
먼저 POST로 주문요청을 보낸후, 응답으론 3xx을 이용하여 redirect시키게 한다. 그후 GET을 사용하여 재요청하고 다시응답하게되면 사용자는 결과 화면에서 새로고침을 해도 결과 화면만 보이게 된다.
* 그래서 302 , 307, 303중에 뭘 써야하나?
처음 302 스펙의 의도는 HTTP메서드를 유지하는 것이였지만 웹 브라우저 대부분이 GET으로 바꾸어 버리기 때문에 명확한 307,303이 등장하였다. 따라서 이를 쓰는것을 권장하지만 이미 많은 애플리케이션이 302를 기본값으로 사용하기에 자동 리다이렉션시 GET 으로 변경되는 경우 302를 사용해도 큰 문제는 없다.
* 기타 리다이렉션
304는 굉장히 많이 사용되며, 캐시로 리다이렉트 함을 의미한다.304는 로컬 캐시를 사용해야 하기때문에 응답에 Body를 포함하면 안된다.
3.4xx
4xx오류는 원인이 클라이언트에 있고 5xx오류는 원인이 서버에 있다
예를 들어 서버 요청시 그 시점에 db시스템에 문제가 생겨 5xx문제가 생긴후 나중에 db시스템이 복구되어 5xx문제가 해결될 수 있는 반면 4xx오류는 클라이언트에 있기에 문제가 해결될 수 없는 차이점이 있다.
401은 간단하게 인증되지 않음을 의미한다.
403은 보통 권한이 없을경우의 오류이다.
404는 요청 리소스가 서버에 없을경우의 오류이다.
4.5xx
위에서 언급한것과 같이 5xx오류는 4xx와 달리 재시도하면 성공할 수도 있다.
중요한점은 5xx은 서버 문제만 다뤄야한다.
예를 들어 20세 이상에게만 제공하는 서비스에 15세가 들어왔을 경우 비즈니스 로직상 예외 케이스인것이지 정상적으로 코드가 작동하는 것이므로 5xx로 처리하면 안된다.
*HTTP 헤더
HTTP헤더는 HTTP 전송에 필요한 모든 부가정보를 포함한다.
과거에는 General,Request,Response,Entity헤더로 나눠져 있었으며, 최근으로 오면서
엔티티->표현으로 대체되고 표현은 표현 메타데이터 + 표현 데이터로 구성된다.
표현 데이터는 메시지 본문을 통해 전달된다. 표현 데이터 내부에 메시지 본문이 있다고 보면 되는데 메시지 본문은 다른말로 페이로드(payload)라고도 한다.
표현은 전달할 실제 데이터를 의미하며 표현 헤더는 표현 데이터를 해석할 수 있는 정보를 제공한다.
표현 헤더에 Content-Type은 표현 데이터의 형식을 의미하며 Content-Length는 표현 데이터의 길이를 의미한다.
*협상(콘텐츠 네고시에이션)
협상은 요청시에만 사용되며 앞에 Accept가 붙는다.
Accept-Language 적용사례를 보자.
한국어 브라우저를 사용하는 클라이언트에서 다중 언어를 지원하는 서버에 Accept-Language를 ko로 보내면
답변은 ko로 올것이다. 그런데 다중 언어를 지원하는 서버에서 ko가 선언되어 있지 않다면 ?
위와 같이 헤더에 선언된 Quality Values에 의해 언어가 결정된다.
만약 서버에 한국어를 제외한 언어가 있다고 가정하고 위처럼 한국어를 요청했는데 서버에 한국어가 없다면 위에선
미국어를 내려줄것이다.
또한 Quality Values는 위처럼 계층형 구조로 명시되어 있을시 더 구체적인 것이 우선시된다.
* 전송 방식
전송 방식은 단순 전송,압축 전송,분할 전송,범위 전송 4가지가 있다.
단순 전송은 단순히 헤더에 Content-Length를 이용하는 방법이며 압축 전송은 Content-Encoding 타입을 지정하여 전송한다. 분할 전송은 Transfer-Encoding 을 이용하며 전송 방식은 아래와 같다.
만약 클라이언트에서 헤더에 Transfer-Encoding을 설정하여 서버에 전송하였다면 서버는 위와 같이 각각 끊어서 보내게 된다.
범위 전송은 클라이언트측에서 Range를 설정하여 보내주면 서버에선 Content-Range를 통해 클라이언트가 요청한 범위를 보내주게 된다.
* Header의 각종 일반 정보
From
요청에서 사용한다. 일반적으로 잘 사용되지 않으며 검색 엔진 같은 곳에서 사용된다.
Referer
요청에서 사용한다. 현재 요청된 페이지의 이전 웹 페이지 주소이며 유입 경로 분석이 가능하다.
User-Agent
요청에서 사용한다. 클라이언트의 애플리케이션 정보이다. 웹 브라우저 정보등등이 있으며 예시는 아래와 같다.
Server
응답에서 사용한다. 요청을 처리하는 ORIGIN 서버의 소프트웨어 정보를 나타낸다.
Date
응답에서 사용한다. 메시지가 발생한 날짜와 시간을 나타낸다.
*Header의 각종 특별한 정보
Host
요청한 호스트 정보(도메인)을 의미하며 하나의 IP 주소에 여러 도메인이 적용되어 있을 때 요청에서 사용된다.
Location
페이지 리다이렉션을 의미하며 웹 브라우저는 3xx 응답 결과에 이 헤더가 있으면 자동 이동한다.
201응답의 Location값은 요청에 의해 생성된 리소스 URI 이다.
Allow
405(Method Not Allowed)응답에 포함해야 하며 허용 가능한 HTTP 메서드를 의미한다.
Retry-After
유저 에이전트가 다음 요청을 하기까지 기다려야 하는 시간을 의미한다.
Date
응답에서 사용한다. 메시지가 발생한 날짜와 시간을 나타낸다.
* 자료 출처
https://www.inflearn.com/course/http-%EC%9B%B9-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC/dashboard
'HTTP' 카테고리의 다른 글
HTTP 웹 기본 지식 정리 3) 쿠키와 캐시 (0) | 2023.10.19 |
---|---|
HTTP 웹 기본 지식 정리 1) 인터넷 네트워크 및 웹 브라우저 요청 흐름 (0) | 2023.10.10 |