HTTP

taehyung·2023년 8월 10일

Internet

목록 보기
6/6
post-thumbnail

HTTP ( Hyper Text Transfer Protocol )

과거 - HTML 문서를 통신하는 규약
현재 - HTML을 포함한 그 외 모든 데이터를 전송할 때 사용됨 ( Imgae,음성,영상,파일,Json,XML(api) ) 거의 모든 형태의 데이터를 전송할 수 있습니다.

HTTP의 역사

  • 1991년 HTTP/0.9 : GET 메서드만 지원, HTTP 헤더 X
  • 1996년 HTTP/1.0 : 메서드, 헤더 추가
  • 1997년 HTTP/1.1 : 가장 많이 사용 / 대부분의 스펙이 개발 완료 되었고, 2,3버전은 성능개선 정도입니다.
    RFC2068 (1997) - RFC2616(1999) - RFC7230~7235(2014)
  • 2015년 HTTP/2 : 성능 개선
  • HTTP/3 : 현재 개발중

TCP기반 프로토콜 : HTTP/1.1, HTTP/2
UDP기반 프로토콜 : HTTP/3

현재 유명 포털사이트들은 HTTP 1.1, 2, 3 를 모두 혼용해서 사용합니다.


HTTP의 통신 구조

요청과 응답의 분리, 그 중요성

복잡한 비즈니스 로직, 데이터 처리는 모두 서버쪽에서 처리하고 클라이언트는 오직 렌더링에만 신경쓰게 만들면 렌더링과 비즈니스 로직의 처리를 독립적으로 하기 때문에 효율도 좋아지고, 고도화도 독립적으로 진행하면 되서 편하다.


HTTP의 중요한 특징 1(상태성, 무상태성)

무상태 프로토콜 지향 (Stateless)

  • 서버가 클라이언트의 상태를 보존하지 않음
  • 장점 : 서버 확장성 높음 ( 스케일 아웃 )
  • 단점 : 클라이언트가 추가 데이터를 전송해야함

상태유지 프로토콜 지양 ( Stateful )

  • 서버가 클라이언트의 상태를 보존합니다.
  • 장점 : 서버가 상태를 유지해주기 때문에 클라이언트를 식별할 수 있고, 통신이 유지된다면 빠른 데이터 처리가 가능할것이라고 생각됩니다.(주관적)
  • 단점 : 서버의 확장이 어렵고, 통신상태가 불량할 때 사용할 수 없습니다.

Stateful과 Stateless의 차이

1. 서버가 클라이언트의 상태 "노트북"을 유지
2. 서버가 클라이언트의 상태 "2대"를 유지
3. "노트북" "2개" 상태를 가지고 결제 완료
위 예제는 클라이언트가 요청했을 때 모종의 이유로 서버가 변경되는 상황입니다.상태통신(Stateful)은 클라이언트의 상태를 서버가 유지,보존 하고있기에 클라이언트와 서버가 1:1로 대응 및 유지 되어야만합니다.클라이언트는 서버가 복구될때까지 기다리고 처음부터 다시 시작해야한다.
무상태통신(Stateless)은 서버가 클라라이언트의 상태를 유지하지 않는다 하였습니다.
무상태 통신은 클라이언트가 서버에게 요청할 때 필요한 상태정보를 클라이언트 측에서 제공합니다.
위 예제는 클라이언트가 요청했을 때 모종의 이유로 서버가 변경되는 상황입니다.무상태통신(Stateless)는 클라이언트의 상태를 클라이언트가 요청시 제공하기 때문에 서버가 변경되어도 에러가 생기지 않으며 서버의 확장이 매우 용이하다.서버 확장이 매우 용이하다.
  • 상태유지 : 중간에 다른 서버로 바뀌면 안된다. ( 변경시 바뀔 서버에게 정보 전달 해야함 )

  • 무상태 : 중간에 다른 서버로 바뀌어도 된다. ( 클라이언트가 서버에게 필요한 정보를 모두 제공하기 때문에 )

    • 갑자기 트래픽 ( 접속량 )이 크게 증가해도 서버를 증설하여 해결할 수 있다.
    • 갑자기 클라이언트 ( 처리할 데이터 )의 요청이 증가해도 서버를 증설하여 해결할 수 있다.
    • 무상태는 응답 서버를 쉽게 변경할 수 있다. -> 이론적 무한한 서버 증설 가능

무상태 설계의 한계

웹 애플리케이션 설계시 최대한 무상태설계를하며 필요한경우에만 최소한으로 상태설계를한다.


HTTP는 무상태입니다.

다만, 무상태라는 특징을 가지는 HTTP에서 상태 유지를 위해 쿠키, 세션, 토큰과 같은 방법을 사용합니다.

로그인은 상태유지 일까요 무상태일까요

로그인을 "유지"하려면 로그인 "상태"를 서버에서 관리해야 합니다.

따라서, 로그인은 stateless가 될 수 없습니다.

다만, 토큰을 이용하는 환경에서는 stateless로 로그인을 구현할 수 있습니다.

HTTP가 무상태 특성을 갖는 이유

HTTP의 구조인 클라이언트 서버 구조가 하나의 요청과 응답안에서만 데이터를 유지하는 Request, Response 구조이기 때문입니다.

동일한 사이트(서비스)이지만 많은 사용자에게 서비스를 쾌적하게 제공하기 위해 동일한 기능을 수행하는 서버를 여러 대 사용할 수 있습니다. 각 서버는 서로 다른 IP를 가집니다.

사용자는 중계서버 IP만 알고 있으면 됩니다. 중계서버가 뒷단에 있는 서버1, 2, 3에게 요청을 위임하고 처리되는 응답을 받아서 사용자에게 전달할 것이기 때문입니다.

학습을 위한 추천 키워드
로드밸런싱, 프록시, 부하분산


HTTP의 중요한 특징 2( 비 연결성, connectionlees )

HTTP의 연결 모델

각 클라이언트가 서버와 연결을 유지하고 있으면 서버의 자원이 낭비되기 때문에 비효율적입니다.HTTP 통신은 각 클라이언트와 요청 응답 과정이 끝나면 연결을 종료합니다.

비연결성의 한계와 극복

페이지를 전환하게 되면 그에 따른 HTML,CSS,JS 등 렌더링에 필요한 데이터들을 전환할 때마다 요청( 통신 )해야한다.과거에는 렌더링에 필요한 데이터를 발견할때마다 계속 연결을 했어야 했습니다.현재는 렌더링에 필요한 데이터를 한번에 다 받고 연결을 종료합니다.

HTTP메시지

* start-line : request-line / status-line
시작 라인은 아래와 같이 나누어져있다. 요청/응답 시 표시되는 내용이 다르다.
* request-line : HTTP 요청메시지의 규격
* status-line : HTTP 응답메시지의 상태

*header-field : host / content-type, content-length
*host : HTTP 요청메시지의 규격
*content-type, content-length : HTTP 응답메시지의 규격

message body :
실제 전송할 데이터, HTML,이미지,영상,JSON등 byte로 표현할 수 있는 모든 데이터 전송 가능
* start-line : method SP(공백) request-target SP HTTP-version CRLF(엔터)
* 시작라인 : 메소드 + /경로 + 쿼리스트링 + HTTP버전 (일반적으로 경로는 절대경로 사용 /로시작)

*header-field : host ( 요청할 호스트의 도메인 )
* start-line : HTTP-version SP + status-code SP + reason-pharse CRLF
* 시작라인 : HTTP버전 + 상태코드 + 이유문구 ( 성공인지 실패인지 )
  상태코드 종류 = 200: 성공 / 400: 클라이언트 요청오류 / 500: 서버내부 오류

*header-field :
HTTP 전송에 필요한 모든 부가정보 ex) 메시지바디의 내용, 메시지바디의 크기,압축,요청 클라이언트 정보 등
content-type : 파일 종류;인코딩방식
content-length : 응답해 줄 내용의 길이

HTTP API를 만들어보자

  • 요구사항 - 회원 정보 관리 API를 만들어라.

    • 회원 목록 조회
    • 회원 조회
    • 회원 등록
    • 회원 수정
    • 회원 삭제

    1.URI 설계

    이것은 좋은 URI 설계일까?
    URI는 리소스를 기준으로 설계해야한다. 명사와 동사를 구분하는게 바람직 합니다..
    회원 관련 동작에서는 "회원" 이라는 명사가 리소스리이기 때문에 "회원" 리소스를 URI에 매핑위와 같이 설계하는게 바람직하지만, 그렇다면 행위에 대해서는 어떻게 분리해서 적용할 수 있을까?,

    URI 설계도 개발에 있어서 변수와 함수를 생각하면 이해가 수월 할 것 같습니다. 위와 같이 설계하면 동사(행위)에 대해 구분하기가 어렵습니다.

    이것을 해결해 주는것이 HTTP 메서드 입니다.

HTTP 메서드

주요 메서드

  • GET : 리소스 조회

  • POST : 요청 데이터 처리, 주로 등록에 사용 ( 서버에 데이터를 보내는 용도 )

  • PUT : 리소스를 대체, 해당 리소스가 없으면 생성 ( 서버에 데이터를 보내는 용도 서버에 데이터가 없으면 새로 생성하고 있으면 덮어씌움 )

  • PATCH : 리소스 부분 변경

  • DELETE : 리소스 삭제

    최근에는 리소스라는 표현이 레프레젠테이션이라는 용어로 바뀌었다고 합니다.

GET

리소스 조회, 서버에 전달하고 싶은 데이터는 query string을 통해서 전달합니다.
메시지 바디를 통해 데이터를 전달할 수 있지만, 지원하지 않는 서버들이 많아서 사용을 권장하지 않습니다.


POST

서버로 요청을 보낼 때 메시지 바디를 통해서 데이터를 전달하고 서버에서 요청데이터를 처리하는 방식
주로 전달된 데이터로 신규 리소스 등록, 프로스 처리에 사용합니다.

필자는 전에 그누보드를 이용한 개발회사에서 근무한적이 있었습니다. 글을 작성하다보니 서버에서 DB 데이터를 처리했던게 기억이 납니다 ㅎㅎ..

  • 요청 데이터 처리

  • 메시지 바디를 통해 서버로 데이터 전달

  • 서버는 요청 데이터를 처리

    • 메시지 바디를 통해 들어온 데이터를 처리하는 모든 기능을 수행합니다.
  • 주로 전달된 데이터로 신규 리소스 등록, 프로세스 처리에 사용

    주문 -> 결제완료 -> 배달시작 -> 배달완료 / 결제완료, 배달시작 같은 큼지막한 프로세스의 변화는 POST로 작업합니다.
    그에따른 URI 설계도 달라질 수 있습니다.. ( 동사( 컨트롤URI )가 들어갈 수 있다는 말 )
    GET 메서드는 메시지 바디를 허용하지 않는 서버가 많습니다. 이럴 때도 POST를사용합니다.
    GET 메서드는 캐싱을 해주기 때문에 "조회"에 이용할 때 유리합니다.( POST는 모든걸 할 수 있지만 각 메서드마다 장점이 있기에 사용에 유의합시다. )

    PUT ( 이전 데이터 모두 삭제후 보낸 데이터로 대체 )

  • 리소스를 대체

    • 리소스가 있으면 대체 ( 완전히 덮어쓰기 )
    • 리소스가 없으면 생성
  • 클라이언트가 리소스 위치를 알고있어야한다. URI 지정

기존에있던 데이터를 완전히 제거 후 새로작성 됩니다. 주의하세요.

PUT 단점을 해결하기 위한 PATCH ( 이전 데이터 그대로 남겨두고 보낸 부분만 업데이트 )


DELETE


HTTP 메서드의 속성

안전 ( safe )

  • 호출해도 리소스를 변경하지 않는다.

  • Q: 무한대로 호출해서 에러가 생겨도 안전하지 않은가?

  • A: 안전은 리소스의 변경 가능성이 있는지만 고려합니다.


    멱등 ( Idempotent )

    하나의 클라이언트가 같은 요청을 반복한다는 가정하에 생각해야 합니다.

  • 호출 한 결과가 횟수에 상관없이 같을때 멱등성을 가진다고 합니다.

  • 멱등 메서드

    • GET : 같은 리소스를 백번, 천번 조회해도 결과는 같다. 그러므로 멱등
    • PUT : 같은 리소스를 백번, 천번 덮어써도 결과는 같다. 그러므로 멱등
    • DELETE : 같은 리소스를 백번, 천번 삭제해도 결과는 같다. 그러므로 멱등
    • POST : 같은 리소스를 백번, 천번 실행하면 결과는 달라진다. 그러므로 멱등하지 아니함
  • 멱등한가 안한가는 외부의 요인을 고려하지 않는다. ( 같은 클라이언트가 같은 요청을 했을 때만을 고려합니다. )

    • user1 : GET -> username:A, age:20
    • user2 : PUT -> username:B, age:50 - user1 이 반복 조회중 user2가 리소스 변경
    • user1 : GET -> username:B, age:50 - user2 의 영향으로 변경된 데이터 조회

    캐시 가능 ( cachable )

  • 응답 결과 리소스를 캐시해서 사용할 수 있는가? ( 브라우저 내부에 저장할 수 있는가? )

  • GET,HEAD, POST, PATCH

  • 실제로는 GET, HEAD 정도만 캐시로 사용합니다.

  • POST, PATCH 는 본문 내용까지 캐시 키로 고려해야 하는데, 구현이 어렵고 실제 잘 사용하지 않습니다.


    HTTP 메서드 활용

    클라이언트에서 서버로 데이터 전송

  • 쿼리스트링을 통한 데이터 전송 ( GET 메서드 )

  • 메시지 바디를 통한 데이터 전송

    • POST,PUT,PATCH
    • 회원 가입, 상품 주문, 리소스 등록, 리소스 변경

    클라이언트에서 서버로 데이터 전송하는 4가지 상황

  • 정적 데이터 조회

    • 이미지, 정적 텍스트 문서
  • 동적 데이터 조회

    • 주로 검색, 게시판 목록에서 정렬, 검색어 필터
  • HTML Form을 통한 데이터 전송

    • 회원가입, 상품주문, 데이터 변경
  • HTTP API를 통한 데이터 전송

    • 회원가입, 상품주문, 데이터변경
    • 서버 to 서버, 앱 클라이언트, 웹클라이언트 (Ajax)

    데이터 조회

    이미지, 정적 텍스트 문서
    조회는 GET 메서드
    정적 데이터는 일반적으로 쿼리 파라미터 없이 리소스 경로로 단순하게 조회
    검색, 게시판 목록에서 검색어 필터 할 때
    조회 조건을 줄여주는필터 등 GET메서드는 쿼리스트링을 사용해 서버에 데이더 전달

    HTML Form 데이터 전송

    HTML Form 태그 내부에 여러가지 데이터를 입력받고 Submit 버튼을 클릭하면 브라우저가 HTTP 요청메시지를 생성합니다.GET 메서드로 변경해서 보낼 수 있으나 URL에 노출되기 때문에 단순 조회시에만 사용해야 합니다.

    HTTP API 데이터 전송


HTTP 상태 코드

200


300

리다이렉션의 이해
웹 브라우저는 3xx 번대 응답 결과에 Location 헤더가 있으면, Location 위치로 자동 이동( 리다이렉트 )

상황 : 구형 이벤트 페이지에서 신형 이벤트 페이지가 개발되었고,
이전 사용자들은 구형 이벤트 페이지를 북마크 하거나, 과거 주소로 접속하게 됩니다.

위와 같은 상황에 301 응답결과와 함께 Location 헤더에 신형이벤트 페이지 URL를 주면 브라우저는 자동으로 신형 페이지로 리다이렉션 합니다.

마치 개인 전화번호가 변경되었을때 과거의 번호로 연락하면 변경된 전화번호로 자동으로 넘어가는것과 같은 맥락입니다.

영구 리다이렉션 응답코드 301과 308
일반적으로 이벤트 페이지가 변경되어서 리다이렉션이 필요하다면 신형 이벤트 페이지에서 필요한 데이터가 변경되어서 자주 사용되진 않습니다.
또한, 위의 의유로 사용해도 301을 많이 사용하는 편입니다.

영구 리다이렉션 응답코드 301은 리다이렉션 과정중 요청이 일어날 때
HTTP 메서드가 POST 메서드로 되어있다면 GET 메서드로 자동 변경되고, 메시지 바디의 내용을 모두 제거해버립니다.
영구 리다이렉션 응답코드 308은 리다이렉션 과정을 마쳐도 메서드가 자동 변환되지 않고 메시지 바디의 내용도 유지됩니다.

일시적 리다이렉션 응답코드 302, 303, 307
실무에서 가장 많이 사용합니다.

302,303,307 모두 기능은 같으나 디테일이 다릅니다.

302 Found 는 요청메서드가 GET으로 변할수도있고 안변할 수도있습니다.
303 See Other 는 요청메서드가 GET으로 100% 변경됩니다.
307 Temporary 는 요청메서드, 메시지바디 모두 유지됩니다.

실무에서 302를 가장 많이 사용하고, 대부분의 프레임워크들의 디폴드가 302입니다.

일시적인 리다이렉션의 문제점
POST 요청으로 사용자가 물건을 주문후에 웹 브러우저를 새로고침한다면 ?
브라우저는 새로고침 하게되면 마지막 HTTP 요청을 다시하게 됩니다.
위와 같은 상황에서는 중복 주문이 될 수 있습니다. ( 웹브라우저가 마지막 요청을 새로고침 하기때문에 포스트 요청을 다시 한다. )

PRG : Post/Redirect/Get ( post요청 -> 302응답 -> redirect -> Get )

좌측 이미지에 일시적 리다이렉트의 문제점이 드러납니다.

주문완료 페이지에서 새로고침 했을 뿐인데 DB에 주문데이터가 중복으로 저장되는게 확인됩니다.

이러한 문제점을 해결하기위해 PRG(Post/Redirect/Get) 방법을 사용합니다.

위와 같은 문제는 클라이언트측, 그리고 서버측에서도 방지를 해준다면 사용자 경험, 서버는 자원을 아낄 수 있다고 생각합니다.
아래에 그 해결책이 있습니다.

ps. 뒤로가기 앞으로가기 버튼으로 막는것은 실무에서 사용하는 시스템과 상황에따라 다를 수 있습니다.

첫번째 주문 요청시 DB에 주문 데이터를 저장하고, 응답메시지를 200이 아닌 302 리다이렉션으로 줍니다. 물론 303도 가능합니다.

HTTP 메서드가 GET으로 변경되면서 새로고침을 하여도 주문데이터 조회만 가능할 뿐 (멱등성) POST 메서드가 요청되어서 중복주문되는 상황을 방지할 수 있습니다.
  • 정리

    • 302 Found -> HTTP요청 메서드가 GET으로 변할 수 있습니다. ( 불특정 변화 )
    • 303 See Other -> HTTP요청 메서드가 GET으로 확정적으로 변경됩니다.
    • 307 Temporary Redirect -> HTTP요청 메서드, 메시지바디가 처음 요청한것과 같이 유지됩니다.
  • 개발 역사

    • 첫 개발 당시 302의 스펙의 의도는 HTTP 메서드를 유지하는 것이었습니다. 그런데 의도와는 다르게 대부분 웹브라우저들이 GET으로 변경해버렸고 또 일부 브라우저는 다르게 작동하여 예측이 불가능 했습니다.
    • 그래서 개발된 스펙이 303(요청메시지 GET 변경), 307(요청메시지 유지) 입니다.
  • 현실

    • 303, 307 스펙을 권장하지만 현실적으로 수많은 애플리케이션 라이브러리들이 302를 기본값으로 사용하고있습니다.
    • 자동 리다이렉션시에 HTTP요청 메서드가 GET으로 변경되어도 상관없다면 302를 사용하여도 문제 없습니다.

    기타 리다이렉션

  • 300 Multiple Choices : 안씁니다.

  • 304 Not Modified ( 정말 많이 사용합니다. )

    • 캐시를 목적으로 사용
    • 클라이언트에게 리소스가 수정되지 않았음을 알려줍니다. 따라서 클라이언트(브라우저)는 로컬PC에 저장된 캐시데이터를 재사용합니다. ( 캐시데이터로 리다이렉트 )
    • 304 응답은 응답에 메시지 바디를 포함하면 안됩니다. ( 로컬 캐시를 사용해야하기 때문입니다. )
    • 조건부 GET, HEAD 요청시 사용합니다.

400, 500

4XX ( Client Error )

  • 클라이언트의 요청에 잘못된 문법등으로 서버가 요청을 수행할 수 없습니다.

  • 오류의 원인이 클라이언트에 있습니다.

  • 클라이언트가 이미 잘못된 요청, 데이터를 보내고있기 때문에 같은 요청을 재시도해도 실패합니다.


    클라이언트가 잘못된 요청을 했을 때 발생합니다. ( 서버가 요청을 처리할 수 없을 때 ) ex) 문자로 보내야하는데, 숫자를 보내거나 요청 자체가 잘못됐을 때

    5XX ( Server Error )

  • 서버 문제로 오류 발생

  • 오류의 원인이 서버에 있습니다.

  • 클라이언트가 알맞은 요청을 보내도 오류로 응답할 수 있고, 서버가 복구되거나 했을때 같은 요청을 재시도하면 성공할 수도 있습니다.

profile
Front End

1개의 댓글

comment-user-thumbnail
2023년 8월 18일

설명이 섹시하네요.

답글 달기