Last updated
Last updated
WWW는 Internet을 통해 접근 가능한 공용 웹 페이지의 상호 연결 시스템이다.
다음과 같은 기술들로 이루어진다.
HTML
: 문서 기술 언어
HTTP
: 문서 전송 프로토콜
URL
: 문서의 주소를 지정하는 방법
단순히 TCP, IP만 가리키는 의미로보다는 전체 네트워크 계층을 가리키는 의미로 더 자주 사용됨.
애플리케이션 계층
어떤 프로토콜로 통신할지 결정
HTTP, FTP, DNS 등을 이용
트랜스포트 계층
어떤 포트로 통신할지 결정
TCP를 이용 (실시간성이 필요한 경우 UDP를 이용하기도)
통신하기 쉽도록 메시지를 패킷 단위로 분해 (조각낸다는 의미에서 Segmantation
이라고 부름)
이후 일련 번호를 부여 (순서 보장을 위함)
3 way handshaking
을 한다. (데이터를 확실하게 보내기 위함)
연결을 시도하려는 A가 SYN packet을 보낸다.
이를 받은 B가 SYN/ACK packet을 보낸다. (A가 이를 받을 시 A의 검증 완료)
이를 받은 A가 ACK packet을 보낸다. (B가 이를 받을 시 B의 검증 완료)
네트워크 계층
어떤 IP(HOST)로 통신할지 결정
IP를 이용
라우팅을 통해 목적지로 전달
라우터는 자기 역할만 수행한다.
즉, 누가 자기에게 보냈는지와 자기가 어디로 보내야 할지만 알고 있다.
링크 계층
물리적 계층
Uniform
: 통일된 서식의
Resource
: 식별 가능한 자료의
Identifier
: 식별자
URI 중에서도 리소스의 장소
를 나타내는 문자열 (그래서 Locator)
따라서 URL ⊂ URI 이다.
스키마: 어떤 프로토콜을 사용할 것인가?
자격정보: 아이디와 패스워드를 지정 (옵션)
서버 주소: DNS명, IP 주소
서버 포트: TCP에서 식별할 네트워크 포트 번호. (옵션)
생략 시 default number가 부여.
http는 80, https는 443
계층적 파일 경로: 서버 상에서의 파일 경로 (옵션)
쿼리 문자열: 해당 리소스에 임의의 parameter를 넘겨주기 위해 사용 (옵션)
프래그먼트 (식별자): 해당 리소스의 서브 리소스를 가리키기 위해 사용 (옵션)
HTTP 통신에서는 반드시 Client(리퀘스트를 송신) 와 Server(리퀘스트에 대한 리스폰스를 송신) 가 존재해야 한다.
Request Message는 다음과 같이 구성된다.
리퀘스트 라인(Request Line)
메소드, URI, 프로토콜 버전으로 이루어진다.
URI가 *이면 서버가 자기 자신에게 요청을 보낸다는 뜻
리퀘스트 헤더(Request Header)
key: value 형식으로 이루어진다.
key는 대문자와 하이픈(-)으로 구성
Response Message는 다음과 같이 구성된다.
스테이터스 라인(Status Line)
프로토콜 버전, 상태 코드, 상태 코드에 대한 설명으로 이루어진다.
리스폰스 헤더(Response Header)
리스폰스 바디 (Response Body)
⭐ 리스폰스 헤더와 공백(CRLF)으로 구분된다.
CRLF란?
CR(carriage return): 커서를 해당 줄의 맨 앞으로 이동
LF(line feed): 커서를 다음 줄로 이동
윈도우에서는 CRLF, 리눅스 계열에서는 CR이 필요없다고 판단하여 LF만 사용
이 때는 아직 쿠키가 없다.
Set-Cookie
헤더를 포함한다.
Set-Cookie 헤더는 쿠키명=쿠키값; 옵션명=값; ...으로 이루어진다.
세미콜론(;)으로는 같은 쿠키 내에서 쿠키값, 옵션값 등을 지정
컴마(,)로는 여러 쿠키를 구별
Cookie: 쿠키명=쿠키값
헤더를 포함한다.
HTTP 초기 연결은 TCP 연결 → 1회 통신 → TCP 연결 종료
로 이루어짐
HTTP 보급이 증가하며 통신도 증가하게 되고, 이 방식은 서버에 부하가 심해짐
HTTP 1.1에서는 한 번 연결 시 직접 연결을 끊을 때까지는 연결이 지속되는 지속 연결
을 도입
지속 연결과 함께 도입된 리퀘스트의 병렬 처리
속도는 개별 연결 < 지속 연결 < 파이프라인화
이다.
HTTP 통신의 기본 단위
엔티티의 운반을 위해 존재
request/response의 payload(부가물)
헤더와 바디로 구성
메시지와 동일한 형태이나 인코딩을 적용할 시 엔티티 바디가 변한다.
다량의 엑세스 처리 효율 증가
CPU 등의 리소스 소비량 증가
용량 절감을 위한 압축 "콘텐츠 코딩"
엔티티를 압축해서 송신
gzip, compress, deflate 등이 있다.
데이터를 분할해서 보내는 "청크 전송 코딩"
엔티티 바디를 청크(덩어리)로 분해
텍스트, 영상, 이미지 등 종류가 다른 데이터를 함께 전송하는 것을 말함
multipart/form-data
: Web form에서 파일 업로드 시 사용
multipart/byteranges
: 응답 메시지가 여러 종류 데이터를 포함한 경우 사용
파트마다 헤더 필드가 포함된다.
Content-Type
헤더 필드는 필수
바운더리 문자열로 각 엔티티를 구분한다.
범위를 지정해서 리퀘스트를 송신하는 기법
네트워크가 광대역이 아니던 시절, 데이터 다운로드 중 연결이 끊긴 상황을 고려한 기술
Range: bytes=범위
헤더 필드를 이용
클라이언트 상황에 따라 서로 다른 리소스를 제공하기 위한 기법
Accept
, Accept-Charset
, Accept-Encoding
, Accept-Language
, Content-Language
등의 헤더를 이용하여 적합한 리소스를 제공
Server-driven Negotiation
서버에서 리퀘스트 헤더 필드 정보에 따라 리소스를 선정하는 것
사용자의 선택이 아니라 확실하다고 볼 수는 없음
Agent-driven Negotiation
클라이언트 측에서 수동으로 네고시에이션
Transparent Negotiation
서버와 클라이언트가 각각 콘텐츠 네고시에이션을 수행
서버가 수행한 Response에 대하여 그 결과가 어떻게 되었는지 알려주는 역할
상태 코드는 세 자리 숫자와 설명으로 이루어진다.
이 중 첫 번째 자리는 Response Class를 의미하며 다음과 같이 분류된다.
또한 여기에는 대표적으로 사용되는 약 14개의 상태 코드가 있다.
200 OK
: 정상 처리. 리소스 반환
204 No Content
: 정상 처리. 그러나 리소스가 없음
반드시 어떠한 entity body도 포함해서는 안 됨
206 Partial Content
: 부분적 GET 요청에 대한 정상 처리
3xx 응답을 받은 경우 브라우저 측에서 특별한 처리(리다이렉트 등)를 수행해야 한다.
301 Move Permanently
: 해당 리소스에 영구적으로 새 URI가 부여된 경우
Location 이라는 헤더 필드에 리다이렉트할 새 URI가 지정됨
302 Found
: 해당 리소스에 일시적으로 새 URI가 부여된 경우
303 See Other
: 새 URI가 부여되었으며 이를 GET 요청을 통해 얻어야 함
304 Not Modified
: 접근할 수 있는 리소스지만 조건이 안 맞음
이 경우 반드시 Response Body가 비어있어야 함
307 Temporary Redirect
: 302와 같으나 내부 구현이 다름 (네이버는 이걸 쓰고 있다)
400 Bad Request
: 잘못된 리퀘스트
리퀘스트 재검토 후 재송신해야
브라우저는 이를 200 OK와 동일하게 취급
401 Unauthorized
: 해당 리소스에 접근하기 위해서는 인증 정보가 필요함
Response Message에 WWW-Authenticate 헤더 필드를 포함해야 함
클라이언트 대응1 - 인증 페이지를 띄움
클라이언트의 대응2 - 대응 1이 이미 이루어진 경우 인증 실패 메시지를 표시
403 Forbidden
: 액세스할 수 없는 리소스
파일 시스템의 퍼미션이 부여되지 않은 경우
액세스 권한 문제(허가되지 않은 IP 등)
404 Not Found
: 존재하지 않는 리소스
500 Internal Server Error
: 서버에서 리퀘스트 처리 중 에러 발생 (서버 살아있긴 함)
503 Service Unavailable
: 서버가 아예 죽음 (과부하, 점검 등의 이유로)
결국 도메인명은 DNS에 의하여 IP주소로 변환되어 전달되기 때문에 어느 쪽에 대한 액세스인지 알 수 없게 된다.
호스트명과 도메인 명을 완전하게 포함한 URI를 지정하거나 Host 헤더 필드에 URI를 지정하여 호스트를 분리할 수 있게 된다.
프록시
게이트웨이
터널
서버, 클라이언트 역할을 모두 수행하는 중계 프로그램
캐시를 위해서 사용하거나 액세스 관련 목적으로 사용
해당 프록시 서버를 공유할 때마다 via: 프록시 서버명
헤더를 추가해야 함
캐싱 여부, 메시지 변경 여부로 나뉜다.
캐싱 프록시: 프록시 서버상에 리소스 캐시를 보존
투명 프록시: 중계 시 메시지를 변경하지 않는 프록시
비투과 프록시: 중계 시 메시지를 변경하는 프록시
클라이언트와 HTTP 이외의 서버 간 중계 프로그램
게이트웨이는 DB Server 등과의 연결 시 암호화 등을 통해 안전성을 높이기 위해 사용된다.
단순 통로 역할을 수행 (메시지를 해석하지 않음)
SSL 등의 암호화 통신을 위해 사용된다.
캐시 서버는 중계 시 프록시 서버에 리소스 사본을 보존
클라이언트가 오리진 서버까지 갈 필요가 없다는 장점이 존재
그러나 오래된(유효 기간이 지난) 캐시라면 오리진 서버로 가야 함
동작 과정은 위와 동일
가장 다양한 정보를 담고 있다.
리퀘스트/리스폰스 메시지에 모두 존재한다.
일반적 헤더 필드
리퀘스트 헤더 필드
리스폰스 헤더 필드
엔티티 헤더 필드
리퀘스트/리스폰스 메시지 둘 다 이용
Cache-Control
캐싱 동작을 지정. no-cached나 max-age 등이 주로 사용
Connection
프록시에 더 이상 전송하지 않는 헤더 필드를 지정
프록시 서버를 이용하는 경우 다음과 같이 Connection 헤더를 사용할 수 있다.
Connection: Upgrade
라고 지정하면 Upgrade 헤더는 오리진 서버까지 가지는 않는 것
지속적 접속 관리
HTTP/1.1은 지속 연결이 default이지만 HTTP/1.0의 경우 Connection: Keep-Alive
가 있을 것
지속적 연결의 경우 서버에서 먼저 연결을 끊고 싶다면 Connection: Close
라고 명시 해줘야 한다.
Date
HTTP 메시지의 생성 시각을 나타냄
Pragma
HTTP/1.0과의 호환을 위해 사용되는 헤더 필드
Pragma: no-cache
라는 한 가지만 지정 가능하며
이는 HTTP/1.0으로 구성된 서버에서 Cache-Control: no-cache
와 동일하게 동작한다.
그래서 주로 다음과 같이 둘 다 쓴다.
Trailer
메시지 바디 이후에 헤더가 존재하는 경우 (청크 전송 인코딩을 사용한 경우) 이 헤더를 지정하여
메시지 바디 이후에도 헤더가 있다는 것을 알리는 용도로 사용
Transfer-Encoding
메시지 바디의 전송 코딩 형식을 지정
HTTP/1.1에서는 청크 전송만 정의되어 있어 Transfer-Encoding: chunked
만 사용 가능
Upgrade
HTTP 및 다른 프로토콜의 새로운 버전이 통신에 이용되는 경우에 사용
헤더 필드에 의해 업그레이드되는 대상은 오직 클라이언트와 인접한 서버 뿐이기 때문에
Connection: Upgrade
와 함께 사용해야 함
또한 서버는 이 헤더에 대한 응답으로 101 Switching Protocols
를 전송
Via
리퀘스트/리스폰스 경로를 알기 위해 사용
프록시, 게이트웨이를 지날 때 이들은 자신의 서버 정보를 Via 헤더 필드에 추가한 뒤 메시지를 전송
리퀘스트 메시지에만 사용 (클라이언트가 서버에게 하고 싶은 말)
리퀘스트 정보, 클라이언트 정보, 리스폰스 컨텐츠의 우선순위 등
Accept
클라이언트가 처리할 수 있는 미디어 타입과 그 우선 순위를 전달
타입/서브 타입
으로 나타낸다.
복수 지정하고 우선순위를 부여할 시 타입;q=품질 계수
로 나타낸다.
q를 생략하면 자동으로 1.0(최우선)으로 부여된다.
Accept-Charset
클라이언트가 처리할 수 있는 문자셋과 그 우선순위
Accept
와 동일하게 동작
Accept-Encoding
클라이언트가 처리할 수 있는 콘텐츠 코딩과 그 우선순위
콘텐츠 코딩의 종류
gzip, compress, deflate, identity
Accept-Language
클라이언트가 처리할 수 있는 자연어 세트(언어)와 그 우선순위
Accept
와 동일하게 동작
Authorization
클라이언트의 인증 정보를 전달
Expect
서버에게 특정 동작 요구를 전달
서버는 이를 만족하지 못할 시 417 Expectation Failed
를 보냄
From
클라이언트의 메일 주소를 전달
(User-Agent 헤더에 있는 경우도 있음)
Host
가상 호스트 구조 때문에 필수 헤더 필드로 사용
리퀘스트가 서버에 오면 도메인 → IP로 변환되기 때문에 동일 IP 내에 복수의 도메인이 적용되어 있다면 이 필드의 내용을 참조하여 어떤 서버에 대한 리퀘스트인지 찾는다.
조건부 헤더 필드
If-Match
: 지정된 조건과 ETag가 동일 ?
응답: 200 OK 또는 412 Precondition Failed
If-Modified-Since
: 지정된 조건 이후에 갱신된 리소스 ?
응답: 200 OK & Last Modified {날짜} 또는 304 Not Modified
If-None-Match
If-Range
If-Unmodified-Since
Max-Forwards
서버를 경유할 때마다 1씩 줄어든다.
필드 값이 0인 리퀘스트를 받은 서버에서 리스폰스를 전송한다.
프록시 서버 간 무한 루프에 빠진 경우 원인을 알기 위해 사용
Proxy-Authorization
클라이언트 ↔ 프록시 서버 간 인증 절차에 사용
프록시 서버에서 인증 요구를 받아들인 경우 인증에 필요한 클라이언트 정보를 전달
Range
리소스의 일부만 취득하고자 하는 Range Request를 할 때에 사용
Referer
리퀘스트가 발생한 본래 리소스의 URI를 전달
잘못된 철자이지만 그대로 사용되고 있다고 함
리스폰스 메시지에만 사용
리스폰스 정보, 서버 정보, 클라이언트의 추가 정보 요구 등
Accept-Ranges
Range Request의 수신 가능 여부를 지정
가능이면 'bytes', 안 받을거면 'none'
Age
얼마나 오래 전에 오리진 서버에서 이 리스폰스가 생성되었는지 전달 (생략 가능)
리스폰스한 서버가 캐시 서버면 캐시 리스폰스가 실증된 때 (필수)
단위는 초단위
ETag
엔티티 태그. 랜덤 생성 문자열.
같은 리소스라도 때에 따라 다른 값이 부여
리소스를 특정해야 하는 경우 (이것만 다시 다운로드) 를 위해 사용됨
Location
리퀘스트 URI 이외의 리소스로의 액세스를 유도하기 위해 (리다이렉션) 사용
대부분 브라우저는 이를 받으면 이 헤더에 명시된 리소스 주소로 강제 리다이렉트
Proxy-Authenticate
프록시 서버에서의 인증 요구를 클라이언트에 전달
Retry-After
지정된 시간 후에 다시 리퀘스트를 보내라는 의미로 사용
주로 503 Service Unavailable
또는 3xx Redirect
와 함께 사용
날짜나 초단위로 지정 가능
Server
서버 정보
Vary
Vary: 리퀘스트 헤더 필드명
을 통해 해당 헤더 필드에 대한 캐시 컨트롤을 할 수 있음
예를 들어
위와 같은 상황이라면 프록시 서버는 en-us로 요청이 온 경우에만 캐시를 반환할 수 있음
WWW-Authenticate
HTTP 액세스 인증에 사용되는 헤더
리퀘스트/리스폰스 메시지에 포함된 엔티티(entity)에 사용되는 헤더
콘텐츠 갱신 시간 등
Allow
리퀘스트 URI에 지정된 리소스가 제공하는 메소드 목록
405 Method Not Allowed 리스폰스와 함께 반드시 전달
Content-Encoding
서버가 엔티티 바디에 대해 실시한 콘텐츠 코딩 형식
Content-Language
엔티티 바디에 사용된 언어
Content-Length
엔티티 바디의 크기
Content-Location
엔티티 바디의 리소스 URI
Content-Range
Range Request 시 사용
Content-Type
엔티티 바디의 타입
Expires
리소스의 유효 기간 날짜
캐시 서버는 이 날짜까지 리퀘스트에 캐시로 응답하고 이 날짜가 지나면 오리진 서버에 리소스를 얻으러 감
캐시를 원하지 않으면 Expires
== Date
로 하면 된다.
다만 Cache-Control
헤더에 max-age
가 있으면 Expires
는 무시된다.
Last-Modified
리소스가 마지막으로 갱신된 날짜
리퀘스트 메시지의 Cookie
리스폰스 메시지의 Set-Cookie
문제
TCP/IP 구조의 통신은 모든 통신 경로에서 도청 가능성이 존재
WireShark와 같은 패킷 캡처 도구를 통해 리퀘스트/리스폰스 메시지도 볼 수 있음
신용 카드 정보 등이 메시지에 그대로 담기면?
해결책 - 도청을 피하기 위한 암호화
통신 암호화
HTTP
+ SSL or TLS (안전한 통신로)
→ 통신 내용 암호화
이를 HTTPS
라고 부른다.
콘텐츠 암호화
클라이언트/서버가 암호화, 복호화를 수행
결국 복호화 구조를 클라이언트가 들고 있으니 위험한 건 마찬가지
문제
리퀘스트 메시지가 의도한 서버에게 가는가?
리스폰스 메시지가 의도한 클라이언트(리퀘스트를 보낸)에게 가는가?
악의를 가진 누군가가 대량의 리퀘스트에의한 DoS 공격(서비스 불능 공격)을 한다면?
해결책 - 상대를 확인하는 증명서
SSL을 이용한 상대 확인
신뢰 가능한 제3자
가 발급한 위조가 어려운 증명서를 확인함으로써 식별
문제
발신 == 수신 여부를 확인할 수 없다.
해결책
현재로서는 확실하고 편리한 방법이 HTTP에는 존재하지 않음
따라서 HTTPS
를 이용하여 보증
HTTP + 암호화 + 인증 + 완전성 보호 ⇒ HTTPS
HTTP의 소켓 부분을 SSL(or TLS)로 대체
안전하지만 SSL은 느리다는 것과 증명서를 이용하는 데에는 비용이 든다는 단점 존재
세계적으로 사용 중인 네트워크 보안 기술
대칭키(공통키) 암호 (Symmetric-key Cryptography)
한 개의 키를 통해 암호화, 복호화를 모두 수행하는 방식
키가 도난당하면 망한다는 점은 변함이 없음
공개키 암호 (Public-key cryptography)
공개키, 비밀키(public key와 private key)를 사용
공개된 공개키로는 암호화만 가능. 복호화는 비밀키로 수행
HTTPS에서는 둘 다 사용. (왜? 공개키 방식은 느림)
따라서 키를 교환하는 곳에서는 공개키 암호를, 이후 통신에서는 공통키 암호를 사용
인증 기관의 등장
공개키 방식에도 문제점이 有
공격자가 공개키를 바꿔 보내고, 자기가 받아 자기 비밀키로 복호화하면 여전히 정보 유출이 발생
따라서 공개키의 증명을 위해 인증 기관을 이용
서버가 자기 공개키를 인증 기관에 등록
인증 기관의 비밀키로 서버의 공개키에 디지털 서명으로 증명서 작성
리퀘스트에 대한 응답을 받은 클라이언트는 서버의 공개키 증명서를 사전에 브라우저에 내장된 인증 기관의 공개키로 검증
클라이언트는 이 서버의 공개키로 암호화를 해서 리퀘스트를 날림
서버는 이를 받아 자신의 비밀키로 복호화
※ 핵심은 인증기관은 비밀키로 암호화, 공개키로 복호화하게 되어있다는 것
서버가 누가 액세스하고 있는지 알기 위해 취하는 동작
BASIC 인증
DIGEST 인증
SSL 클라이언트 인증
폼 베이스 인증
BASIC 인증
웹 서버, 그에 대응하는 클라이언트 간에 이루어지는 통신
클라이언트가 리퀘스트 송신
인증이 필요한 요청이라면 서버는 다음과 같이 응답
유저는 ID와 패스워드를 Base64로 인코딩하여 송신
이를 받은 서버는 인증 성공 시 200, 실패 시 다시 401로 응답
복호화 로직(Base64)은 누구나 쓸 수 있으므로 도청 가능
유저가 원하는 때에 로그아웃 할 수 없음
DIGEST 인증
챌린지 리스폰스 방식을 이용
클라이언트의 인증 요구
서버는 WWW-Authenticate
헤더에 챌린지 코드(nonce)를 담아 리스폰스
클라이언트는 이 코드로 챌린지 리스폰스를 계산해 리스폰스 코드(response)를 얻고, 이를 WWW-Authenticate
헤더에 챌린지 코드와 함께 송신
이를 받은 서버는 인증 성공 시 200, 실패 시 다시 401로 응답
매번 바뀌는 챌린지코드를 통해 도청은 방지하지만 위장은 방지하지 못함
SSL 클라이언트 인증
패스워드를 이용한 인증 시 이 패스워드를 아는 사용자는 누구나 어디에서든 인증에 성공할 수 있다는 단점(위장 위험성)
이 있다.
이를 보완하기 위해 클라이언트 증명서를 이용하는 SSL 클라이언트 인증이 등장했다.
클라이언트의 인증 요구
서버는 증명서를 요구하는 "Certificate Request"
메시지를 송신
유저가 송신할 클라이언트 증명서를 선택
클라이언트는 "Client Certificate"
라는 메시지와 함께 증명서를 송신
서버는 이를 검증하여 옳다면 클라이언트의 공개키를 취득
SSL만 단독으로 사용하기보다는 다른 인증(ex: 폼 베이스 인증)과 함께 사용한다. 주로 다음의 절차를 거친다.
SSL로 클라이언트의 컴퓨터를 인증
패스워드를 통해 유저 본인 확인
비용 때문에 잘 이용하지 않는다.
클라이언트 증명서는 다운받아서 가지고 있어야 한다. 이 과정에서
인증 기관에서 인증서를 받는 비용 or 서버의 운영자가 인증 기관을 만들어서 운용하는 비용이 상당하다.
폼 베이스 인증
우리가 주로 보게 되는 인증 방법
표준 사양이 결정되어 있지 않아 웹 사이트마다 구현 방식이 다르다. (비밀번호 정보를 받아 평문으로 저장하는 사람들조차 있다.)
클라이언트가 자격 정보(ID, 패스워드) 송신 (주로 POST로 이루어짐)
Set-Cookie
로 세션 ID를 발행하고 인증 상태를 서버에 기록 (요즘은 Token 방식을 선호하기도 함)
클라이언트가 세션 ID와 함께 요청을 보내면 이를 통해 검증
최초의 HTTP는 단순히 HTML로 작성된 문서를 주고받기 위해 만들어졌음
그러나 현대의 웹은 쇼핑, SNS 등 다양한 용도로 사용됨. 따라서 HTTP만으로는 한계가 있음
그렇다고 새 프로토콜을 만들자니 HTTP는 웹 브라우저 환경을 장악하고 있기 때문에 HTTP + 새로운 프로토콜 체제가 굳혀진 것
SNS를 예로 들어보자. 페이스북에서 수천만 명의 유저가 동시에 메시지를 작성하면 이를 갱신하는 데에 대량의 통신이 요구된다.
이를 최대한 빨리 반영하기 위해 실시간성이 요구되는데 HTTP 자체에서는 불가능하다. HTTP에서는 클라이언트 → 서버의 단방향 통신만 가능하기 때문.
HTTP 자체에서 실시간성을 구현하기 위해서는 반복적으로 리퀘스트, 리스폰스가 오가야되는데 이는 HTTP가 가진 다음과 같은 사양 때문에 병목 현상을 불러 일으킨다.
1 커넥션 1 리퀘스트
리퀘스트/리스폰스 헤더는 압축되지 않은 채 송신됨
장황한 헤더
데이터 압축은 강제가 아닌 선택 사항
Ajax
Comet
SPDY
⭐ WebSocket
JavaScript나 DOM 조작을 활용하여 웹 페이지의 일부만 갱신하는 방법.
리스폰스로 전송되는 데이터 양은 줄어듦.
그러나 여전히 대량의 리퀘스트/리스폰스가 발생한다.
또한 HTTP 자체의 문제를 해결하지는 못한다.
서버에서 콘텐츠 갱신이 일어날 때까지 리스폰스를 지연함.
Server Push를 유사하게 구현한 방식. 위의 문제는 해결하지만 커넥션을 유지하는 시간이 길어지기 때문에 대량의 리소스를 소비한다.
또한 HTTP 자체의 문제를 해결하지는 못한다.
결국 HTTP 자체의 문제를 해결하기 위해서는 프로토콜 레벨에서의 개선이 필요
TCP/IP의 애플리케이션 계층과 트랜스포트 계층 사이에 SPDY라는 세션 계층을 추가하는 형태
다중화 스트림: 단일 TCP 접속으로 복수의 HTTP 요청을 처리
리퀘스트 우선순위 부여
HTTP 헤더 압축
서버 푸시 기능
서버 힌트 기능: 클라이언트에게 리퀘스트할 리소스를 제안 가능
SPDY는 한 개의 도메인과의 통신을 다중화할 뿐이기 때문에 복수의 도메인 사용 시 효과가 한정적
또한 병목 현상 이외에도 웹의 고속화 문제, 웹 콘텐츠 제작의 개선 문제 등이 많아 잘 사용하지는 않는다.
병목 현상 + 웹 고속화의 문제를 모두 해결하기 위해서 새로운 프로토콜 + 새로운 API를 도입
웹 브라우저와 웹 서버를 위한 양방향 통신 규격
웹 클라이언트의 접속 → 서버의 수락 → Connect → 이후에는 어느 쪽에서든 먼저 송신 가능!
서버 푸시 기능
통신량 삭감: 웹소켓 통신은 한 번 확립되면 접속을 유지하며, 헤더 사이즈가 작다.
핸드쉐이크/리퀘스트: Upgrade: websocket
헤더를 사용하여 핸드쉐이크를 실시
핸드쉐이크/리스폰스: 핸드쉐이크 요청에 대하여 101 Switching Protocol
로 응답
핸드쉐이크 요청/응답까지는 HTTP 프로토콜로의 통신이지만
커넥션이 확립된 후에는 웹소켓의 독자적인 데이터 프레임을 이용해 통신한다.
결국 HTTP/1.1이 현재의 웹에 적합한 프로토콜이라고 보기에는 어렵기 때문에 언젠가는 HTTP/2.0이 보급될 것으로 보임.
HTTP/1.1을 확장한 프로토콜. 직접 파일 복사나 편집 등을 할 수 있는 분산 파일 시스템
HTTP/1.1 에서는 가상 호스트 라는 기능을 통해 하나의 HTTP 서버에 여러 웹 사이트를 올릴 수 있다.