HTTP, Socket 통신의 차이
일반적으로 휴대폰, 컴퓨터 등에서 필요로 하는 데이터들은 Server에서 받아온다. 네트워크를 통해 서버로부터 데이터를 가져오기 위한 통신으로는 크게 HTTP 통신과 Socket 통신 2가지가 있다. 오늘은 이 2가지 통신에 대해 알아보자.
HTTP(HyperText Transfer Protocol)
하이퍼 텍스트를 주고 받기 위한 규칙(통신 규약)을 말한다. 하이퍼 텍스트란 연결 고리를 통해 다른 문서로 접근할 수 있는 텍스트를 말한다. HTML의 <a태그>를 떠올리면 이해하기 쉽다. HTTP라는 통신 규칙을 만든 것은 좋은데, 정작 하이퍼 텍스트를 보기좋게 표현할 방법이 없었다. 누구든 동일한 방법으로 하이퍼 텍스트를 표현할 방법이 필요했다.
이에 팀 버너스리는 인터넷 기반의 하이퍼 텍스트 작성을 위한 방법들을 만들었는데, 그것이 바로 현재의 HTML이다.
HTTP를 위키피디아 정의로 보면,
웹 서비스에서 클라이언트와 서버 간에 정보를 요청(request)하고 응답(response)받기 위한 프로토콜을 말한다. 초기에는 서버로부터 페이지를 요청하는 GET이라는 이름의 하나의 메소드만 있었다. 서버로부터의 응답은 무조건 HTML 문서였다. 그러나 프로토콜 확장의 필요성으로 HTTP/1.0에서는 메소드와 헤더가 추가되고, 현재는 HTTP/1.1을 가장 많이 사용한다.
HTTP/2에서는 성능이 개선되고, HTTP/3은 TCP 대신 UDP를 사용하여 성능을 개선 중이다.
📡 HTTP의 특징 4가지
1) 클라이언트 - 서버 구조
클라이언트의 요청이 있을 때만 서버에서 요청에 따른 응답을 반환한다.
클라이언트에서 서버에 요청을 하는 단방향 통신으로, 서버가 먼저 요청을 할 수 없고 무조건 요청을 받아야 한다.
단방향 통신의 단점은? A(클라이언트)와 B(서버)가 채팅을 하는데, B가 A한테 먼저 톡을 보낼 순 없다. |
2) 무상태 프로토콜(Stateless) 지향
서버가 클라이언트의 연결/상태 정보를 보존하지 않는다. 즉, 클라이언트가 이전 요청과 같은 데이터를 원한다고 하더라도 다시 서버에 동일한 요청을 해야 한다. 클라이언트가 이전에 자신이 요청한 정보를 저장해놓고 해당 정보를 다시 보내주므로, 클라이언트의 요청에 어떤 서버가 응답해도 상관이 없어서 서버 확장성이 높은 장점이 있는 반면, 클라이언트가 많은 양의 추가 데이터를 전송해야 하는 단점이 있다. 하지만 로그인 같은 상태 정보는 서버에 유지시켜야 하는데 이 경우 브라우저 쿠키나 세션 등을 이용해 상태를 유지해야 한다.
무상태에서 로그인을 해야 한다면? 네이버 접속 -> 메일함 -> 로그인 -> 쪽지함 -> 다시 로그인 |
3) 비연결성
클라이언트가 서버에 요청을 하고 응답을 받으면 바로 TCP/IP 연결을 끊어 연결을 유지하지 않는 것이다. 이를 통해 서버의 자원을 효율적으로 관리하고, 수많은 클라이언트의 요청에도 대응할 수 있게 한다. HTTP는 연결을 유지하지 않는 모델을 기본으로 한다. 수 천명이 서비스를 사용해도 실제 서버에서 0.000001초까지 동일한 시간에 동시에 요청을 하지는 않는다.
3-1) 비연결성의 한계 & 해결
한계: 새로 연결될 때마다 TCP/IP 연결을 새로 맺어야 하므로 3-way handshake에 따른 시간이 추가된다.
(HTML을 받기 위해 연결하고 종료 -> 자바스크립트 파일을 받기 위해 연결하고 종료)
해결: HTTP 지속연결(Persisten Connections)을 통해 이를 해결. 처음 연결이 되고 나서, 여러 파일의 요청/응답이 다 끝난 뒤 연결을 종료한다.
4) HTTP 메세지를 통해 통신
HTTP메세지는 HTTP 요청메세지와 HTTP 응답메세지로 구분된다.
HTTP메세지에 모든 것을 전송할 수 있다. HTML, TEXT, 음성, 영상, 파일, JSON, XML 등등
기본 구조 start-line 시작 라인 header 헤더 empty line 공백 라인(CRLF, 필수) message body |
💡 HTTP start-line: HTTP 요청 메세지
request-line: GET /search?q=hello&hl=ko HTTP/1.1
method SP(공백) request-target SP HTTP-version CRLF(엔터)
1) method: 서버가 수행해야 할 동작 지정 (GET:리소스 조회, POST:요청 내역 처리, PUT, DELETE.. )
2) request-target: 요청 대상, 절대경로 '/'로 시작하는 경로, /absolute-path[?query]
3) HTTP-version
💡 HTTP start-line: HTTP 응답 메세지
status-line: HTTP-version SP status-code SP reason-phrase CRLF
1) HTTP-version
2) HTTP 상태코드: 요청의 성공, 실패를 나타냄
- 200: 성공
- 400: 클라이언트 오류
- 500: 서버 내부 오류
3) reason-phrase: 사람이 이해할 수 있는 짧은 상태 코드 설명 글
구글에서 헤더를 확인해보면, 아래처럼 General로 요청 Method와 상태코드를 함께 나타내기도 한다.
💡 HTTP Header
- HTTP 헤더 내 일반(General) 헤더
요청 및 응답 메세지 모두에서 공통적으로 사용 가능한 일반 목적의 헤더 항목이다.
전송되는 HTTP의 바디(본문 컨텐츠)와는 상관 없고, 요청/응답이 생성된 날짜 및 시간 등과 같은 HTTP통신에 대한 일반적인 정보가 포함된다.
Date : 요청과 응답시에 자동으로 현재 날짜와 시간이 만들어진다.
Connection : 클라이언트와 서버의 연결 방식 설정
HTTP/1.0은 Connection: keep-alive가 기본 디폴드 값이 아니었고, 표준도 아니었다.
HTTP/1.1에서는 keep-alive를 더이상 사용하지 않고, 기본적으로 Persistent 연결을 지원한다. 만약 응답 이후에 TCP 연결을 끊어야 하는 경우에만 Connection: close로 헤더를 선언한다.
Pragma : 캐시제어 (no-cache), HTTP/1.0에서 쓰던 것으로 HTTP/1.1에서는 Cache-Control이 쓰인다.
Cache-Control : 캐시를 허용할지 말지를 제어하기 위해 사용한다.
+ no-store : 캐시를 저장하지 않겠다.
+ no-cache : 모든 캐시를 쓰기 전에 서버에 해당 캐시를 사용해도 되는지 확인하겠다.
+ must-revalidate : 만료된 캐시만 서버에 확인하겠다.
+ public : 공유 캐시에 저장해도 된다.
+ private : '브라우저' 같은 특정 사용자 환경에만 저장하겠다.
+ max-age : 캐시의 유효시간을 명시하겠다.
Transfer-Encoding : body 내용 자체 압축 방식 지정
'chunked'면 본문의 내용이 동적으로 생성되어 길이를 모르기 때문에 나눠서 보낸다는 의미다.
본문에 데이터 길이가 나와서 야금야금 브라우저가 해석해서 화면에 뿌려줄 때 이 기능을 사용한다.
Upgrade : 프로토콜 변경시 사용 ex) HTTP/2.0
Via : 중계(프록시)서버의 이름, 버전, 호스트명
Expires : 자원의 만료 일자
Allow : 사용이 가능한 HTTP 메소드 방식 ex) GET, HEAD, POST
Last-Modified : 최근에 수정된 날짜
ETag : 캐시 업데이트 정보를 위한 임의의 식별 숫자
- HTTP 헤더 내 엔터티/개체(Entity) 헤더
엔터티 헤더 또한 요청 및 응답 메세지에서 모두 사용 가능하며, 주로 HTTP 바디에 내용이 존재할 때 이 내용에 대한 세부 정보를 나타내는데 사용한다. 보통 응답 메세지에 Content 헤더들이 포함되어 있다.
ex. 내용 길이, 컨텐츠 언어, 인코딩, 만료 날짜 및 기타 중요한 정보와 같은 정보.
Content-Encoding : 본문의 리소스 압축 방식
Content-type : 본문의 미디어 타입(MIME)과 문자열 인코딩을 지정하기 위해 사용
Content-Length : 본문의 길이, 메세지 크기에 따라 자동으로 생성
Content-language : 사용자가 선호하는 언어에 따라 사용자를 구분할 수 있게 한다. 예를 들어 한국인한테 독일어를 가르치는 사이트일 경우, 페이지 언어는 일본어더라도 Content_language는 ko_KR일 수 있다.
- 요청 헤더
요청 헤더는 요청한 URL, 메소드, 요청 생성에 사용된 브라우저 및 기타 정보와 같은 요청에 대한 정보가 포함된다.
Host : 요청하려는 서버 호스트 이름과 포트번호
User-agent : 현재 사용자가 어떤 클라이언트(운영체제와 브라우저를 포함한)를 이용해 요청을 보냈는지 확인
ex) Mozilla/4.0, Windows NT5.1
이 정보를 통해서 서버는 클라이언트 프로그램(브라우저)에 맞는 최적의 데이터를 보내줄 수 있다.
Accept : 요청을 보낼 때 서버에게 어떤 터입으로 응답을 보내줬으면 좋겠다고 명시. 브라우저가 알아서 생성.
ex) */* - 모든 타입 처리 가능, application/json - json데이터 처리 가능.
Referer : 바로 직전에 머물렀던 웹 링크 주소.
이 헤더를 이용하면 어떤 페이지에서 지금 페이지로 왔느지를 알 수 있어서 애널리틱스를 하는데 많이 사용된다.
Accept-charset : 클라이언트가 지원가능한 문자열 인코딩 방식
Accept-language : 클라이언트가 지원가능한 언어 나열
Accept-encoding : 클라이언트가 해석가능한 압축 방식 지정 ex) gzip, deflate
압축이 되어있다면 content-length와 content-encoding으로 압축을 해제한다.
Authorization : 사용자가 서버에 인가된 사용자임을 증명할 때 사용
Content-location : 해당 개체의 실제 위치
Content-disposition : 응답 메세지를 브라우저가 어떻게 처리할지 알려줌. ex) inline, attachment; filename='jeong-pro.xlsx'
Content-Security-Policy : 다른 외부 파일을 불러오는 경우 차단할 리소스와 불러올 리소스 명시
ex) default-src https -> https로만 파일을 가져옴
ex) default-src 'self' -> 자기 도메인에서만 가져옴
ex) default-src 'none' -> 외부파일은 가져올 수 없음
If-Modified-Since : 여기에 쓰여진 시간 이후로 변경된 리소스 취득. 페이지가 수정되었으면 최신 페이지로 교체하기 위해 사용된다.
Origin : 서버로 Post 요청을 보낼 때 요청이 어느 주소에서 시작되었는지 나타내는 값
이 값으로 요청을 보낸 주소와 받는 주소가 다르면 CORS 에러가 난다.
Cookie : 쿠기 값 key-value로 표현된다. ex) attr1=value1; attr2=value2
- 응답 헤더
Location : 301, 302 상태코드일 때만 볼 수 있는 헤더로 서버의 응답이 다른 곳에 있다고 알려주면서 해당 위치(URI)를 지정한다.
Server : 웹서버의 종류를 나타낸다. ex) nginx
Age : max-age 시간내에서 얼마나 흘렀는지 초 단위로 알려주는 값
Referrer-policy : 서버(참조 페이지)의 정책을 알려주는 값 ex) origin, no-referrer, unsafe-url
WWW-Authenticate : 사용자 인증이 필요한 자원을 요구할 시, 서버가 제공하는 인증 방식
Proxy-Authenticate : 요청한 서버가 프록시 서버인 경우 유저 인증을 위한 값
💡 HTTP 메세지 바디
실제 전송할 데이터를 담는 부분으로 html, 이미지, 영상, JSON 등 byte로 표현할 수 있는 모든 데이터 전송 가능
Socket 통신이 왜 필요할까?
HTTP는 단방향 통신이기 때문에 서버가 클라이언트한테 먼저 메세지를 보낼 수가 없다.
실기간 채팅 기능을 구현하려면 서버도 클라이언트에게 요청을 보낼 수 있는 양방향 통신인 Socket이 필요하다.
📡 Socket 통신
소켓(Socket)이란 네트워크상에서 동작하는 프로그램 간 통신의 종착점(Endpoint), 접속의 끝부분이라 한다.
종착점인 Endpoint는 IP주소와 Port번호의 조합으로 이루어진 최종 목적지(PC, 핸드폰 등의 접속 연결부)를 나타낸다.
클라이언트(프로그램 1)와 서버(프로그램 2) 양쪽에서 서로에게 데이터 전달을 하는 방식의 양방향 통신으로, 소켓에서 서버는 요청을 기다릴 필요가 없다. 모든 연결은 2개의 앤드포인트로 유일하게 식별될 수 있다.
위키피디아 정의로는 막 와닿지 않으므로.. 예시를 들어본다.
소켓은 사전적으로 '전구 따위를 끼워 넣어 접속하게 하는 기구, 연결부'를 일컫는데 콘센트 구멍을 떠올리면 쉽다.
즉, 네트워크 상에서의 소켓은 멀리 떨어진 프로그램끼리 연결될 수 있게 만들어진 연결부인 것이다.
예를 들어, 휴대폰(프로그램 A)을 충전하기 위해 휴대폰 연결부 소켓과 보조배터리(프로그램 B)에 충전선을 꽂는 연결부 소켓이 있어야 한다. 또한 전기 충전이 제대로 작동되려면 220v라는 표준 규격에 맞게 만들어져야 하는 것처럼, 소켓 통신도 TCP, UDP 규약에 맞는 소켓을 미리 만들어 소켓에 꽂아 쓴다는 개념으로 프로그램 간에 데이터를 교환할 수 있다.
보통 스트리밍이나 실시간 채팅 등 실시간으로 데이터를 주고 받아야 하는 경우 Connection을 자주 맺고 끊는 HTTP 통신보다 소켓 통신이 적합하다. 하지만, 소켓 통신은 계속해서 Connection을 들고 있기 때문에 HTTP 통신에 비해 많은 리소스가 소모된다.
참조: 위키피디아, 모두의 네트워크 책, 모든 개발자를 위한 HTTP 웹 기본 지식(인프런, 김영한 님)