HTTP 프로토콜

공부의 기록·2021년 10월 30일
0

Dev Computer Science

목록 보기
3/18
post-thumbnail

Introduce

본 문서는 2022년 1월 25일 에 작성되었습니다.
구 버전은 2021년 10월 30일 에 작성되었는데,
시간이 지남에 따라서 HTTP 에 대해서 더욱 깊게 공부하고 싶은 마음이 들어서 재작성 하게 되었습니다.
현재 완성되지 않은 문서입니다.


✅ 시작에 앞서...

이 문서는 Real World HTTP 을 기준으로 작성하게 되었습니다.

또한 HTTP 아래의 TCP와 IP 계층 혹은 DNS, 와이파이 등의 계층도 거의 설명하지 않습니다.
Real World HTTP

요즘은 서버와 클라이언트가 통신하는 프로그램을 쉽게 만들어주는 도구도 많습니다. ... 이런 도구에 관해서도 다루지 않습니다.
Real World HTTP

curl

curl 은 두 가지로 이루어져 있습니다.

  1. libcurl | HTTP, HTTPS 와 파일 전송용 통신 프로토콜인 FTP, SCP 와 메일 전송 프로토콜인 IMAP, SMTP, POP3 와 사용자나 그룹관리에 사용되는 데이터 엑세스 프로토콜인 LDAP 등 다양한 통신 방식에 대응하는 라이브러리
  2. curl | liburl 를 이용해 다양한 통신을 하기 위한 커맨드라인

본 도서에서는 curl 를 사용하고 있으며,
비슷한 HTTP 통신 커멘드라인 도구로 wget 을 소개하기도 하였습니다.

curl 을 사용하기 위해서
Windows 에서는 Chocolatey 라고 하는 패키지 매니저가 필요했습니다.
관련 설치법에 대한 내용 및 주의사항은 Chocolaety and Powerhsell 을 참고해주세요.

choco install curl

위 명령어로 curl 을 설치할 수 있으며, 설치 완료 시 경로 를 알려주는데, 꼭 이 경로를 환경변수 에 추가해줍시다. 그래야 커맨드라인에서 curl 명령어를 실행할 수 있습니다.

만약 관리자 모드의 PowerShell 이 위의 커맨드를 거부한다면, 에일리어스를 제거해줍시다.

Remove-Item alias:curl

자세한 내용은 아래 포스트를 참고했습니다.

https://butteryoon.github.io/tools/2021/10/01/WindowsPowershellAlias.html

GOlang

GOlang, 통칭 GO 는 구글에서 개발한 언어입니다.
매우 강력한 퍼포먼스와 높은 가독성을 가지고 있는 것으로 알고 있습니다.

본 도서에서는 이러한 GO 를 사용하여 HTTP 를 학습하고 있습니다.

각 언어군 별로 http 모듈은 다음과 같습니다.

  1. Python, httplib
  2. PHP, fopen()
  3. Node.js, http module, request library
  4. Java, Java.net.HttpURLConnection Class
  5. C#, System.Net.Http.HttpClient Class
  6. Swift, NSURLSession Class
  7. Ruby, net/http library

개발환경

본 도서에서는 IntelliJ IDEA 를 추천했지만,
저는 VSC 를 사용하기로 하였습니다.


✅ HTTP History

HTTP, Hyper Text Transfer Protocol

HTTP 0.9

Git Repository / first go server
현재는 HTTP 0.9 를 지원하지 않으므로 1.0 으로 구현되었습니다.
아래의 HTTP 1.0 에 두 버전의 차이점이 기술되어 있습니다.

curl 실행 예
$ curl --http1.0 http://localhost:18888/greeting
<html><body>hello</html></body>

server log 예
GET /greeting HTTP/1.0
Host: localhost:18888
Connection: close
Accept: */*
User-Agent: curl/0.0.0

위에서 0.0.0 은 사용자의 버전입니다.

0.9 의 기본기능은 위가 전부입니다.
curl 커멘드는 호스트명과 경로가 함께 있는 URI, Uniform Resource Identifier 을 사용하지만, 서버에서는 경로인 /greeting 만 받아들입니다.

또한 <isindex> 태그를 이용하면 문서내 검색 기능을 지원했습니다.

localhost:1888/post?category+basic

현재는 이 태그가 사라지고 다음과 같이 대체 되었습니다.
HTML <from> 나 WHATWG 의 querystring 에서 문서 안의 데이터 검색 등의 기능을 지원해주고 있습니다. query 스트링은 예를 들면 다음과 같은 것입니다.

localhost:18888/post?category=basic

HTTP 0.9 + curl

본 도서에 나온 예제 코드가 작동하지 않아서 아래의 방식으로 코드를 작성하였습니다.

// Request, cmd
curl
http://localhost:18888/greeting?search+hello
// Response
StatusCode        : 200
StatusDescription : OK
Content           : <html><body>Hello</body></html>

RawContent        : HTTP/1.1 200 OK
                    Content-Length: 32
                    Content-Type: text/html; charset=utf-8
                    Date: Tue, 25 Jan 2022 13:28:00 GMT

                    <html><body>Hello</body></html>

Forms             : {}
Headers           : {[Content-Length, 32], [Content-Type, text/html; charset=utf-8], [Date, Tue, 25 Jan 2022 13:28:00 GMT]}
Images            : {}
InputFields       : {}
Links             : {}
ParsedHtml        : mshtml.HTMLDocumentClass
RawContentLength  : 32

신기해서 네이버에도 Request 를 보내봤습니다.

// Request, cmd
curl
http://naver.com/
// Response
StatusCode        : 200
StatusDescription : OK
Content           :
                    <!doctype html>                          <html lang="ko" data-dark="false"> <head> <meta charset="utf-8"> <title>NAVER</title> <meta http-eq
                    uiv="X-UA-Compatible" content="IE=edge"> <meta name="viewpo...
RawContent        : HTTP/1.1 200 OK
                    Transfer-Encoding: chunked
                    Connection: keep-alive
                    Pragma: no-cache
                    X-Frame-Options: DENY
                    X-XSS-Protection: 1; mode=block
                    Strict-Transport-Security: max-age=63072000; includeSubdo...
Forms             : {sform}
Headers           : {[Transfer-Encoding, chunked], [Connection, keep-alive], [Pragma, no-cache], [X-Frame-Options, DENY]...}
Images            : {@{innerHTML=; innerText=; outerHTML=<img width="250" height="49" style="padding-left: 70px;" alt="" src="https://static-whale.pstatic.net/m
                    ain/img_hwp_v2@2x.png">; outerText=; tagName=IMG; width=250; height=49; style=padding-left: 70px;; alt=; src=https://static-whale.pstatic.ne
                    t/main/img_hwp_v2@2x.png}, @{innerHTML=; innerText=; outerHTML=<img height="20" class="news_logo" alt="지지통신" src="https://s.pstatic.net/
                    static/newsstand/2020/logo/light/0604/376.png">; outerText=; tagName=IMG; height=20; class=news_logo; alt=지지통신; src=https://s.pstatic.ne
                    t/static/newsstand/2020/logo/light/0604/376.png}, @{innerHTML=; innerText=; outerHTML=<img height="20" class="news_logo" alt="서울경제" src=
                    "https://s.pstatic.net/static/newsstand/2020/logo/light/0604/011.png">; outerText=; tagName=IMG; height=20; class=news_logo; alt=서울경제; s
                    rc=https://s.pstatic.net/static/newsstand/2020/logo/light/0604/011.png}, @{innerHTML=; innerText=; outerHTML=<img height="20" class="news_lo
                    go" alt="MBC" src="https://s.pstatic.net/static/newsstand/2020/logo/light/0604/214.png">; outerText=; tagName=IMG; height=20; class=news_log
                    o; alt=MBC; src=https://s.pstatic.net/static/newsstand/2020/logo/light/0604/214.png}...}
InputFields       : {@{innerHTML=; innerText=; outerHTML=<input name="sm" id="sm" type="hidden" value="top_hty">; outerText=; tagName=INPUT; name=sm; id=sm; typ
                    e=hidden; value=top_hty}, @{innerHTML=; innerText=; outerHTML=<input name="fbm" id="fbm" type="hidden" value="0">; outerText=; tagName=INPUT
                    ; name=fbm; id=fbm; type=hidden; value=0}, @{innerHTML=; innerText=; outerHTML=<input name="acr" disabled="disabled" id="acr" type="hidden"
                    value="">; outerText=; tagName=INPUT; name=acr; disabled=disabled; id=acr; type=hidden; value=}, @{innerHTML=; innerText=; outerHTML=<input
                    name="acq" disabled="disabled" id="acq" type="hidden" value="">; outerText=; tagName=INPUT; name=acq; disabled=disabled; id=acq; type=hidden
                    ; value=}...}
Links             : {@{innerHTML=<span>뉴스스탠드 바로가기</span>; innerText=뉴스스탠드 바로가기; outerHTML=<a href="#newsstand"><span>뉴스스탠드 바로가기</span
                    ></a>; outerText=뉴스스탠드 바로가기; tagName=A; href=#newsstand}, @{innerHTML=<span>주제별캐스트 바로가기</span>; innerText=주제별캐스트 바
                    로가기; outerHTML=<a href="#themecast"><span>주제별캐스트 바로가기</span></a>; outerText=주제별캐스트 바로가기; tagName=A; href=#themecast},
                     @{innerHTML=<span>타임스퀘어 바로가기</span>; innerText=타임스퀘어 바로가기; outerHTML=<a href="#timesquare"><span>타임스퀘어 바로가기</spa
                    n></a>; outerText=타임스퀘어 바로가기; tagName=A; href=#timesquare}, @{innerHTML=<span>쇼핑캐스트 바로가기</span>; innerText=쇼핑캐스트 바로
                    가기; outerHTML=<a href="#shopcast"><span>쇼핑캐스트 바로가기</span></a>; outerText=쇼핑캐스트 바로가기; tagName=A; href=#shopcast}...}
ParsedHtml        : mshtml.HTMLDocumentClass
RawContentLength  : 208581

HTTP 1.0

HTTP 0.9 와 HTTP 1.0 의 차이점은 다음과 같습니다.

  1. 요청 시의 메서드 (GET, POST 등) 가 추가되었다.
  2. 요청 시의 HTTP 버전이 추가되었다.
  3. 헤더가 추가되었다.
    3.1. Host
    3.2. User-Agent
    3.3. Acept

# 헤더 전송

Request

// cmd
curl --http1.0 -H "X-Test: Hello" http://localhost:18888/greeting

Response

// html
<html><body>Hello</body></html>

# 헤더 수신

curl 커맨드에 자세한 로그를 보여주는 -v 옵션을 지정하면 수신한 헤더 등을 자세하게 표현해줍니다.

Request

// cmd
curl --http1.0 -H "X-Test: Hello" http://localhost:18888/greeting -v
*   Trying IP번호:18888...
* Connected to localhost (IP번호) port 18888 (#0)
> GET /greeting HTTP/1.0
> Host: localhost:18888
> User-Agent: curl/7.79.1
> Accept: */*
> X-Test: Hello
>
* Mark bundle as not supporting multiuse
* HTTP 1.0, assume close after body
< HTTP/1.0 200 OK
< Date: Tue, 25 Jan 2022 13:45:35 GMT
< Content-Length: 32
< Content-Type: text/html; charset=utf-8
<
<html><body>Hello</body></html>
* Closing connection 0

✅ HTTP 의 기본요소

HTTP 는 다음과 같은 요소들로 이루어져 있습니다.

  1. 메서드, Method
  2. 상태 코드, Status Code
  3. 헤더, Context-Type
  4. 경로, URL
  5. 바디, Body

Method

HTTP 1.0 ~

Method 는 데이터를 넘겨줄 때,
어떠한 프로세스를 진행할 것인지에 대한 명시적 정보입니다.

  • GET | 서버와 헤더에 콘텐츠 요청
  • HEAD | 서버에 헤더만 요청
  • POST | 새로운 데이터 서버에 전달

HTML 문서에서는 GET과 POST 만 지원됩니다.
간혹 브라우저마다 다음과 같은 메서드가 지원되기 도합니다. (필수아님)

  • PUT | 이미 존재하는 URL 의 문서를 갱신한다
  • DELETE | 문서 간의 링크를 삭제한다.

XMLHttpRequest

자바스크립트는 XMLHttpRequest 를 이용해서
이러한 메서드로 서버에 요청을 보낼 수 있게 되었습니다.


Status Code

Status Code 는 상태코드라고 불립니다.
흔히들 서버에서 404 Not Found 라는 메세지를 본 적이 있을 것입니다. 이는 클라이언트의 요청에 오류가 있음을 의미합니다.

각 번호는 다음과 같습니다.

  • 100 | 처리가 계속됨을 의미
  • 200 | 성공, 200 OK 가 가장 많이 쓰이며, 정상종료를 의미한다.
  • 300 | 서버->클라이언트 명령, 리다이랙트 및 캐시 이용 등
  • 400 | 클라이언트가 보낸 요청에 오류가 있다.
  • 500 | 서버 내부에서 오류가 발생했다.

3XX Redirect

300번대 상태 코드의 일부는 서버가 브라우저에 대해 Redirect(속칭 새로고침)을 지시 하는 코드입니다.

300 이외의 경우,
Location 헤더를 사용해 리디렉트할 곳을 서버에서 클라이언트로 전달합니다.
이 단어는 생각보다 낯익었는데 React 의 state 기능 에서 들어본 기억이 있습니다.

# 3xx Status

상태 코드부제설명
300Multiple Chocies선택사항이 복수인 경우
301Moved Permanently도메인 전송, 웹사이트 이전, HTTPS
302Found일시적 관리(서버 점검 중), 모바일 기반 전송
303See Others로그인 후 페이지 전환
307Temporary Redirect301 과 동일 RFC 7231 에서 추가
308Moved Permanently302 와 동일 RFC 7538 에서 추가

언어 별로 리디렉트 설정 제한 이 있습니다.
따로 확인할 수 있으며 또한 변경할 수 있습니다.
다만, 구글에서는 이 값을 5회(권고는 3회)로 안내하고 있습니다.

리디렉션의 정의 및 목적은 이 포스트 를 참고해주세요.


Context-Type

HTTP 1.0~

Context-Type 은 서버에서 돌아온 파일의 형식을 나타내는 문자열, MIME 타입 으로 불리는 문자열이 값으로 있습니다.

MIME 타입 / MDN 을 확인해보세요.

⚡ Content Sniffing

Content Sniffing 이란,
브라우저 가 인터넷 옵션에 따라 MIME 타입이 아닌 내용을 보고 파일 형식을 추측해 실행하려는 성격을 의미합니다.

이러한 부분은 보안의 구멍이 될 수 있습니다.
본 도서에서는 다음과 같은 헤더를 전송해 브라우저가 추측하지 않도록 지시하는 것을 권장하고 있습니다.

html
X-Content-Type-Options: nosniff
https://webhack.dynu.net/?idx=20161120.001

다만, 이 방법은 브라우저 의존적이며 모든 브라우저에서 실행되는 것은 아니다 라는 단점이 있다.


URL

일반적으로 URL 은 다음과 같이 생겼습니다.

http://www.sitename.com/index.html

스키마://호스트명/경로

본 도서에서는 모든 요소가 들어간 예제 가 있었습니다.

스키마://사용자:패스워드명@호스트명:포트/경로#프래그먼트?쿼리

더 깊게 작성된 포스트는 다음의 포스트들, URL 분석하기 1URL 분석하기 2 를 참고해주세요.


Body

HTTP 1.0~

Request 에 데이터를 포함할 수 있습니다.
이러한 데이터는 <form> 이나 XMLHttpRequest 를 이용합니다.
자세한 내용은 다루지 않습니다.

body + curl

curl 옵션용도
-d, --data, --data-ascii텍스트 데이터(변환완료)
--data-urlencode텍스트 데이터(변환은 curl 커멘드로 실시)
--data-binary바이너리 데이터
-T 파일명 혹은 -d @파일명보내고 싶은 데이터를 파일에서 읽어온다.
// cmd
curl -d "{\"hello\": \"world\"}" -H "Content-Type: application/json" http://localhost:18888

✅ HTTP 1.0 Sementics

이 챕터에서는 브라우저가 기본적으로 지원해주고 있는 기능에 대해서 다루고자 합니다.

다음과 같은 내용이 있습니다.

  1. form
  2. Content Negotiation
  3. Cookie
  4. Auth, Session
  5. Proxy
  6. Cache
  7. Referer
  8. 검색 엔진용 콘텐츠 접근 제어 / Robot, Sitemap

✅ HTTP 1.1 Syntax

참고 제목 | 고속화와 안정성을 위한 확장

  1. 통신 고속화
  2. TLS
  3. ...

✅ HTTP 1.1 Sementics

참고 제목 | 확장되는 HTTP 용도

✅ HTTP 2.0 Syntax

참고 제목 | 프로토콜 재정의

✅ HTTP 2.0 Sementics

참고 제목 | 반응형 디자인


Introduce(구버전)

HTTP:Hyper Text Transfer Protocol은 초본문전송규약은 W3:WWW 상에서 정보를 주고받을 수 있는 Protocol이다. 주로 HTML 문서를 주고받는데 쓰인다.
주로 TCP:Transmission Control Protocol 를 사용하고 HTTP/3 부터는 UDP:User Datagram Protocol 를 사용한다.

HTTP는 Client서버 사이에 이루어지는 request/response 프로토콜이다.

history

explanation

응답 메세지는 다음으로 구성된다.

  • 상태표시 행
  • 응답 헤더필트
  • 기타 메세지
  • 빈 줄

비연결지향 : Connectionless

HTTP 는 기본적으로 request 를 보내고 response 를 하는 순간만 서버와 클라이언트가 연결되는 특성을 가지고 있다.

상태없음 : Stateless

HTTP 는 resquest 와 response 가 되지 않을 때에는 연결이 끊겨 있고 그 순간에 클라이언트의 상태 정보를 유지하지 않는 특성이 있다.

이런 상태 정보의 부재는 여러 문제를 야기할 수 있다.
대표적으로는 특정 기능에 결제 등급 인증이 필요한 경우가 있다.
이 경우, 매 refresh 마다 인증을 다시 해야하는 것이다.
이런 문제를 해결하기 위한 것으로는 쿠키와 세션 velog 등이 있다.

응답코드

클라이언트가 서버에 접속하여 어떠한 요청을 하면, 서버는 세 자리 수로 된 응답코드와 함께 응답한다. 클라이언트의 브라우저는 이 응답코드에 따라 적절한 조치를 취하게 된다. 이를 테면, 404 에러가 뜰 경우 브라우저의 히스토리 기록에 남지 않는 등과 같은 경우이다.

예제

  • Clinet Session
GET /restapi/v1.0 HTTP/1.1
Accept: application/json
Authorization: Bearer UExBMDFUMDRQV1MwMnzpdvtYYNWMSJ7CL8h0zM6q6a9ntw
  • Server Response
HTTP/1.1 200 OK
Date: Mon, 23 May 2005 22:38:34 GMT
Content-Type: text/html; charset=UTF-8
Content-Encoding: UTF-8
Content-Length: 138
Last-Modified: Wed, 08 Jan 2003 23:11:55 GMT
Server: Apache/1.3.3.7 (Unix) (Red-Hat/Linux)
ETag: "3f80f-1b6-3e1cb03b"
Accept-Ranges: bytes
Connection: close
<html>
  	<head>
      		<title>An Example Page</title>
  	</head>
  	<body>
		<main>Hello World, this is a very simple HTML document.</main>
	</body>
</html>

참고자료

정아마추어 블로그
HTTP 나무위키

profile
블로그 이전 : https://inblog.ai/unchaptered

0개의 댓글