HTTP가 어떻게 통신하고 동작하는지 간결하게 설명한다.

  • 리소스(Resource)란?
  • 웹 트랜잭션의 동작
  • HTTP 통신을 위해 사용되는 메시지 형식
  • HTTP 기저의 TCP 네트워크 전송

웹 클라이언트와 서버

HTTP 통신은 클라이언트와 서버로 구성된다.

HTTP 클라이언트와 서버

요소 설명
클라이언트 웹 브라우저, 모바일 앱, PC 프로그램, CLI 등
서버 Apache, Nginx, Tomcat, DB, API 서버 등

HTTP: 인터넷의 멀티미디어 배달부

멀티미디어(Multimedia)는 JPEG 이미지, 동영상, HTML 페이지와 같은 다양한 매체를 말함

수 많은 멀티미디어가 HTTP를 통해 빠르고, 간편하고, 정확하게 웹 브라우저로 전송된다.

  • 기저에 신뢰성 있는 데이터 전송 프로토콜 사용함
  • 덕분에 인터넷 결함에 대해 걱정 없이 애플리케이션 고유의 기능을 개발하는데 집중

웹 트래픽 전송하기

멀티미디어는 웹 콘텐츠로 웹 서버에 존재한다. 웹 서버는 HTTP 라는 방법으로 의사소통하기 때문에 HTTP 서버라고 불린다.

  1. 웹 서버는 데이터를 저장하고 있다.
  2. 클라이언트는 웹 서버로부터 데이터를 요청한다.
  3. 요청하는 방법은 HTTP를 사용한다.

단순한 연결


리소스란?

웹 콘텐츠의 원천은 리소스(Resource)이다.

가장 단순한 리소스는 웹 서버 파일 시스템의 정적 파일이다. 텍스트 파일, HTML, JPEG 이미지, 동영상, 엑셀 파일 등 모든 종류의 파일이 될 수 있다.

리소스는 반드시 정적 파일이어야 할 필요가 없다. 요청에 따라 콘텐츠를 생성하는 프로그램이 될 수 있다. 사용자가 누구인지, 어떤 정보를 요청했는지에 따라 매번 다른 콘텐츠를 생성한다.

이를테면

  • HTML 코드로 이루어져 있는 파일
  • JPEG, PNG 등의 이미지 파일
  • 동영상 또는 동영상 스트림
  • 실시간 웹 캠, 주식 거래, IoT 기기 등의 JSON 정보

웹 리소스

미디어 타입

HTTP는 리소스를 다루기 위해 데이터 타입을 알려주는 라벨을 붙인다. 이를 MIME(Multipurpose Internet Mail Extensions, 다목적 인터넷 메일 확장)이라고 한다.

MIME은 원래 전자메일 시스템에서 메시지가 오갈 때 겪는 문제점을 해결하기 위해 설계 되었다. HTTP에서도 멀티미디어 콘텐츠를 기술하고 라벨을 붙이기 위해 채택 되었다.

모든 HTTP 메시지지에 MIME 타입을 붙인다.

  • 웹 서버는 리소스에 대한 데이터 타입을 MIME으로 정의한다.
  • 웹 브라우저는 MIME을 통해 다룰 수 있는 리소스인지 확인한다.
  • 이미지 파일을 보여주거나 HTML 파일을 분석하고 페이지로 렌더링한다.

MIME 타입

MIME은 /으로 구분된 주 타입(primary object type)과 부 타입(specific subtype)으로 이루어져 있다.

예를 들면,

MIME 설명
text/html HTML로 작성된 텍스트 문서
text/plain ASCII 일반 텍스트 문서
image/jpeg JPEG 포맷의 이미지 파일

URI

웹 서버는 URI를 이용하여 리소스 찾는다.

URI(Uniform Resource Identifier)라고 불리는 통합 지원 식별자는 우편물 주소와 같은 것으로, 리소스를 고유하게 식별한다.

예를 들어, “선주의 기술 블로그”에 “AWS EC2에서 App Runner 전환하여 비용 절감하기” 글을 가져오려면 이런식이다.

https://boy672820.github.io/aws/2023/10/15/aws-app-runner.html
컴포넌트 설명
https://boy672820.github.io “선주의 기술 블로그” 서버가 있는 곳
/aws/2023/10/15/aws-app-runner.html “AWS EC2에서…” 글이 위치하는 곳

URI

URI는 2가지의 식별자가 있다.

  • URL(Uniform Resource Locator)
  • URN(Uniform Resource Name)

    URL

통합 자원 지시자(uniform resource locator)는 리소스를 식별하는 가장 흔한 형태이다. URL은 리소스에 대한 구체적인 위치를 서술한다.

https://boy672820.github.io/aws/2023/10/15/aws-app-runner.html

✅ 첫번째 https://는 스키마(Schema)라고 불리우며, 리소스에 사용되는 프로토콜을 서술한다. ✅ 두번째 boy672820.github.io는 서버의 인터넷 주소를 제공한다. ✅ 마지막 /aws/.../aws-app-runner.html 웹 서버의 리소스를 가리킨다.

URL은 리소스가 정확히 어디 있고 어떻게 접근할 수 있는지 분명히 알려준다.

대부분 URI는 URL이다.

URN

통합 자원 이름(uniform resource name)은 리소스 위치에 영향을 받지 않는 유일무이한 이름 역할을 한다. URN은 실험 중인 상태로, 사용하기 위해서는 인프라가 필요하다.

통상적 관례에 따라 URI와 URL을 같은 의미로 언급한다.


트랜잭션

클라이언트와 웹 서버가 리소스를 주고 받기 위해 HTTP를 어떻게 사용하는지에 대해 알아보자

트랜잭션은 요청 명령응답 결과로 구성되어 있다.

HTTP 트랜잭션

이 상호작용은 HTTP 메시지라고 불리는 정형화된 데이터 덩어리를 이용한다.

메서드

모든 요청 메시지는 한 개의 HTTP 메서드를 갖는다. 메서드는 서버에게 어떻게 동작해야 되는지 말해준다.

예를 들어

  • 웹 페이지 가져오기
  • 프로그램 실행하기
  • 파일 삭제하기
  • 그 밖에 기능들 ETC…

다음은 HTTP 메서드의 종류이다.

메서드 설명
GET 서버의 리소스를 가져옴
PUT 리소스를 서버에 저장함
DELETE 지정한 리소스를 서버에서 삭제함
POST 리소스를 서버에게 보냄
PATCH 지정한 리소스의 특정 부분들을 업데이트함
HEAD 헤더 데이터만 보냄
OPTIONS 웹 서버의 상태를 점검

상태 코드

모든 HTTP 응답 메시지는 상태 코드가 존재한다. 상태 코드는 요청이 성공 or 실패 했는지, 추가 조치가 필요한지 알려주는 세 자리 숫자다.

아래는 흔히 쓰이는 상태 코드표

상태 코드 설명
200 문서가 올바르게 반환됨
302 지정한 콘텐츠가 일시적으로 이동됨, 명시된 장소로 찾아가셈
404 리소스를 찾을 수 없음

HTTP는 상태 코드와 “사유 구절(reason phrase)”도 함께 보낸다. 이 구문은 단지 설명만을 위해 사용된다.

200 OK
200 Document attached
200 Success
201 Created
204 No Content
400 Bad Request
404 Not Found
500 Internal Server Error
...

웹 페이지는 여러 객체로 이루어질 수 있다

예를 들어, 시각적으로 풍부한 웹 페이지를 가져올 때 대량의 HTTP 트랜잭션이 이루어진다.

  • 뼈대를 구성하기 위해 HTML 코드가 필요하다.
  • 디자인을 적용하기 위해 CSS 코드가 필요하다.
  • 시각적으로 풍부한 애니메이션 등을 위해 JavaScript 코드가 필요하다.
  • JPEG, PNG 등의 이미지가 필요하다.

이와 같이 웹 페이지는 하나의 리소스가 아닌 “리소스의 모음“이다.

리소스 모음


메시지

HTTP 요청과 응답 메시지의 구조에 대해 간략하게 알아보자.

HTTP 메시지는 단순한 줄 단위 문자열이다. 이진 데이터가 아니기 때문에 사람이 읽고 쓰기 쉽다.

✅ 클라이언트 ▶︎ 서버 방향을 요청 메시지라고 한다. ✅ 클라이언트 ◀︎ 서버 방향을 응답 메시지라고 한다.

-------------------------------                -------------------------------
GET /test/hi-there.txt HTTP/1.0 <--- 시작줄 ---> HTTP/1.0 200 OK
-------------------------------                -------------------------------
Accept: text/*                                 Content-type: text/plain
Accept-Language: en,fr           <--- 헤더 ---> Content-length: 19

-------------------------------                -------------------------------
                                      본문 ---> Hi I'm a message!
                                               -------------------------------
시작줄

메시지의 첫 줄은 시작줄이다.

  • 요청(▶︎)이라면 무엇을 해야 하는가
  • 응답(◀︎)이라면 무슨 일이 일어났는가
    헤더

    시작줄 다음에는 헤더 필드가 이어진다. 각 헤더 필드는 쌍점(:)으로 구분되는 Key-Value 구조이다. 헤더 필드를 추가하려면 그저 한 줄을 더하기만 하면 된다.

Accept: text/*         <--- 헤더는 쌍점(:)으로 구분한다.
Accept-Language: en,fr <--- 필드를 추가하려면 한 줄을 더하기만 하면 된다.
...

메시지 예시

HTTP 메시지의 간단한 예로 다음 주소를 URI를 웹 서버에게 요청해보자.

HTTP 메시지 예제

MIME 타입은 “Content-type” 헤더에 적혀있다.

TCP 커넥션

HTTP는 TCP/IP 통신을 이용한다. HTTP가 어떻게 TCP 통신을 이용하는지 알아보자.

TCP/IP

HTTP는 네트워크 통신의 세부적인 사항에 대해 신경 쓰지 않는다. 대신 대중적이고 신뢰성 있는 TCP(Transmission Control Protocol) 프로토콜을 사용한다.

전세계 네트워크는 TCP/IP를 기초하고 있다. 네트워크 초기에 TCP/IP 통신을 주로 사용해왔고, 지금도 대부분 그러하다.

TCP는 다음을 제공한다.

  • 오류 없는 데이터 전송
  • 순서에 맞게 전달
  • 조각나지 않는 데이터 스트림

네트워크 개념상, HTTP 프로토콜은 TCP 위의 계층이다. HTTP는 메시지를 전송하기 위해 TCP를 사용한다.

![iso minimal 380](https://boy672820.github.io/assets/images/2023-11-03-open-http/iso-minimal.png)

IP와 포트 번호

인터넷 프로토콜(Internet Protocol) 또는 IP 주소와 포트(Port) 번호를 이용해 클라이언트와 서버 간에 TCP/IP 커넥션을 맺어야 한다.

다른 누군가와 통화하는 것과 비슷하다. “전화를 걸고 상대방이 전화를 받는다” = “IP와 포트 번호를 통해 서버와 커넥션을 맺는다”

웹 서버의 IP와 포트번호는 URL을 이용하여 알아낸다.

# 다음 두 주소는 같다.

https://boy672820.github.io/aws/2023/10/15/aws-app-runner.html
https://207.200.83.29:80/aws/2023/10/15/aws-app-runner.html

위 주소를 웹 브라우저에 입력하면 다음과 같은 일이 일어난다.

  1. 웹 브라우저는 URL의 호스트 명을 추출한다. ☞ boy672820.github.io
  2. DNS 서버에서 해당 호스트(도메인)의 IP를 찾는다 ☞ 207.200.83.29
  3. 스키마는 HTTP 프로토콜이다. 웹 서버에 접속하기 위해 포트 번호 80으로 접속한다. ☞ 207.200.83.29:80
  4. 웹 서버에게 HTTP 요청을 보낸다.
  5. 웹서버는 메시지에 명시된 요청 경로로 리소스를 찾는다.
  6. 응답 메시지를 받는다.

HTTP 서버는 기본적으로 80 포트 번호를 사용한다.

netcat을 이용한 실전 예제

HTTP는 이진 형식이 아닌 일반 문자열을 사용하기 때문에, 웹 서버와 대화하는 것도 간단하다.

$ nc boy672820.github.io 80

GET /aws/2023/10/15/aws-app-runner.html HTTP/1.1
Host: www.boy672820.github.io

HTTP/1.1 404 Not Found
Connection: keep-alive
Content-Length: 9115
Server: GitHub.com
Content-Type: text/html; charset=utf-8
permissions-policy: interest-cohort=()
ETag: "65020b3f-239b"
Content-Security-Policy: default-src 'none'; style-src 'unsafe-inline'; img-src data:; connect-src 'self'
X-GitHub-Request-Id: 9308:3B2F2E:B8DD8:FB344:654498E7
Accept-Ranges: bytes
Date: Fri, 03 Nov 2023 06:53:27 GMT
Via: 1.1 varnish
Age: 0
X-Served-By: cache-icn1450093-ICN
X-Cache: MISS
X-Cache-Hits: 0
X-Timer: S1698994408.540958,VS0,VE180
Vary: Accept-Encoding
X-Fastly-Request-ID: 9a733d7de8ebb3b1c080caa1b4bcf23672ee3608

<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-type" content="text/html; charset=utf-8">
    <meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src 'unsafe-inline'; img-src data:; connect-src 'self'">
    <title>Site not found &middot; GitHub Pages</title>

...
</html>