클라이언트와 서버가 서로 통신하는 방법을 표준화하는 인터넷에서 데이터를 주고받기 위해 사용되는 TCP/IP 기반 애플리케이션 계층 통신 프로토콜
클라이언트 - 서버 사이에 이루어지는 요청/응답 프로토콜
`클라이언트(웹 브라우저)와 서버 간의 요청/응답 방식을 정의하는 규칙`
HTTP/1, HTTP/2 에서는 TCP를 사용하나 HTTP/3는 UDP를 사용
비연결성, 무상태를 지향
HTTP의 비연결성
HTTP는 기본적으로 비연결성( Connectionless ) 프로토콜
요청(Request) → 응답(Response) 후 연결을 종료
TCP를 사용하지만, HTTP 계층에서 연결을 유지하지 않기 때문에 비연결성이라고 함
비연결성의 단점
요청마다 TCP 연결을 새로 맺고 끊으면 오버헤드(비효율적인 연결 비용)가 발생
특히, 빈번한 데이터 전송이 필요한 경우 성능 저하가 발생할 수 있음
해결 방법 : HTTP Keep-Alive
HTTP 헤더에서 Keep-Alive 옵션을 사용하면 TCP 연결을 일정 시간 유지할 수 있음
이를 통해 연결 재설정 비용을 줄이고 성능을 향상
HTTP/1.0
비 지속적인 연결
하나의 요청과 응답 후에 연결을 닫는 비 지속적인 방식을 사용하기에 각각의 요청마다 새로운 연결을 맺어야 함 ⇒ 연결과 해제에 대한 오버헤드 발생
+) 하나의 연결 당 여러 요청을 가질 수 없음
요청 메세지의 단순성
요청 메세지가 단순한 구조를 가지고 있어 헤더의 기능이 제한적이고 다양한 요청 형태와
추가 기능에 대한 확장성 부족
상태 코드를 사용
캐싱 기능을 지원하여 동일한 요청에 대한 응답을 캐싱을 사용
보완기능에 대한 내장 지원이 제한적
HTTP/1.1
HTTP/1.0의 단점을 보완하고 성능 확장성을 개선하기 위해 다양한 기능을 도입
HTTP/1.1 부터 keep-alive가 기본으로 설정
하지만 연결을 무한정 유지할 수 없기 때문에 제한이 존재
timeout을 통해 최대로 연결되어 있는 시간을 설정할 수 있음, 설정된 timeout이 끝나면 연결을 종료
max를 통해 최대 요청 건수를 설정할 수 있음. 연결동안 max 이상의 요청이 발생하면 연결을 종료
요청이 빈번하게 이뤄지는 경우 keep-alive를 설정해 연결을 유지하는게 좋고 요청이 자주 일어나지 않는다면 keep-alive를 해제해 오버헤드를 줄일 수 있음
Keep-Alive 연결
Keep-Alive 연결을 지원하여 한 번의 TCP 연결로 여러 요청과 응답을 처리할 수 있음
이를 통해 연결과 해제하는 오버헤드를 줄이고 네트워크 지연 시간을 감소시킴
지속적 연결
비지속적 연결 방식이 아닌, 지속적 연결 방식을 도입하여 클라이언트와 서버 간의 연결을 유지하여 한 번의 연결로 여러 요청과 응답을 처리 ( 동시에 처리는 아님 )
파이프라이닝
여러 요청을 동시에 전송하고 응답을 순차적으로 받을 수 있음
( 모든 서버와 클라이언트에서 지원되지 않아 호환성 문제가 있음 )
HTTP/1.1에서는 지속적인 연결이나 파이프라이닝을 활용하려면 응답에 Content-Length
헤더가 필요하지만, 동적인 데이터의 경우, 서버가 미리 콘텐츠 길이를 알 수 없어 지속적인
연결을 제대로 활용하지 못하는 문제가 발생
이를 해결하기 위해 청크 분할 인코딩을 도입하여, 서버가 Content-Length 없이도
데이터를 청크 단위로 전송할 수 있도록 함
청크 전송 인코딩
대용량 데이터를 작은 청크로 분할하여 전송할 수 있으며, 이를 통해 데이터 전송을
빠르고 효율적으로 처리할 수 있음
가상 호스팅 : 하나의 서버에 여러 도메인을 호스팅 할 수 있는 기능 지원
압축 전송
추가적인 요청 메서드( PUT, DELETE, PATCH, OPTIONS )를 도입
HTTP/1.1의 단점
성능 제한
동시에 여러 요청을 처리하지 못하고, 요청과 응답을 순차척으로 처리하므로 이로 인해
동시에 많은 리소스를 요청하는 경우 성능 저하 발생, 요청마다 새로운 TCP 연결 설정
불필요한 데이터 전송
요청과 응답의 헤더에 중복된 정보를 포함하고 있어서 네트워크 대역폭 낭비
블로킹 현상
한 번에 하나의 요청만 처리하기에 요청을 하나씩 처리 가능
서버 부하
동시에 많은 연결을 유지해야 하므로 서버 부하가 증가
HTTP/2.0
이진 프레임 형식
이진 프레임 형식은 사용하여 데이터를 전송
⇒ 데이터를 더 효율적으로 인코딩하고 압축
이전 버전에서는 텍스트 기반 프로토콜로 데이터를 전송 (ASCII 또는 UTF-8로 인코딩된 텍스트 형식)
다중화와 스트림
스트림 : 하나의 TCP 연결 내에서 독립적으로 흐르는 데이터의 단위
단일 TCP 연결에서 여러 개의 동시 스트림을 지원
⇒ 하나의 TCP 연결에서 여러 요청/응답을 동시에 처리할 수 있음 ( 병렬 요청 처리 & HOLB 문제 해결 )
헤더 압축
헤더 필드를 압축하여 데이터 전송량을 줄임 ( HPACK 압축 알고리즘 사용 )
서버 푸시
서버가 클라이언트 요청에 대한 응답으로 추가적인 리소스를 미리 전송
HTTP/1.1은 요청한 사항에 대해서만 응답을 보낼 수 있는데 HTTP/2는 서버에서 데이터를 능동적으로 보낼 수 있음
Ex) HTML을 요청한후 추가적으로 JS와 CSS 파일을 필요로 하는 상황
⇒ HTTP/1.1에서는 클라이언트가 HTML 문서를 받은 뒤 추가적으로 JS와 CSS 파일을 요청
⇒ HTTP/2에서는 클라이언트가 HTML 문서를 요청하면 서버 푸시 기능을 이용하여 필요로 하는 JS와 CSS을 요청 없이 보낼 수 있음
⇒ 클라이언트의 요청을 줄여 성능이 향상
( HTTP over TLS, HTTP over SSL, HTTP Secure )
HTTP의 보안이 강화된 버전 , HTTPS의 기본 TCP/IP 포트는 443
HTTPS는 소켓 통신에서 일반 텍스트를 이용하는 대신 SSL이나 TLS 프로토콜을 통해 세션 데이터를 암호화
- 공개키(비대칭키) 암호화 방식은 암호화/복호화 과정에서 많은 리소스를 소모
따라서 모든 데이터를 공개키 방식으로 암호화하면 비효율적
`데이터 통신(실제 메시지 전송)은 대칭키(비밀키) 암호화 방식 사용 → 빠르고 효율적`
`대칭키 전달 과정에서만 공개키(비대칭키) 방식 사용 → 보안 강화`
- key
데이터를 암호화하고 복호화하는 존재
- 공개키 ( 비대칭키 )
공개 가능한 키 , 암호화 과정에 참여하는 웹 브라우저, 서버 같은 key 발행자 뿐 아니라
해커 등 다른 사람들이 알아도 상관없는 키
`키를 두 개 사용하기 때문에 암호화/복호화가 복잡하고 리소스를 많이 사용한다는 단점 존재`
`개인키와 쌍을 이루어 존재하며 보통 데이터를 암호화 하는데 사용됨`
`( 복호화도 가능 , 개인키로 암호화 된 것은 공개키로 복호화 가능 )`
- 개인키
key 발행자의 개인 키
공개키와 쌍을 이루어 존재하며 보통 데이터를 복호화 하는데 사용됨
( 개인키로도 데이터를 암호화 가능 )
- 대칭키 ( 비밀키 )
암호화/복호화에 동일한 하나의 키를 사용, 실제 데이터를 암호화/복호화하는데 사용
동일한 키를 사용하기 때문에 빠르지만 대칭키 전달 과정에서 탈취당할 위험이 있음
SSL 인증서 발급 및 HTTPS 통신 과정 정리
서버
서버는 공개키와 개인키( 비대칭키 쌍 )를 생성
서버의 도메인 및 정보와 함께 공개키를 인증기관(CA)에 보내 SSL 인증서를 요청
인증기관(CA)
서버의 정보를 확인하고 SSL 인증서를 발급
인증기관은 자신만의 공개키와 개인키를 생성
인증서 정보를 자신의 개인키로 암호화하여 서버에 전달
웹브라우저 (클라이언트)
서버에서 받은 SSL 인증서의 진위 여부를 검증
인증기관이 공개한 공개키로 SSL 인증서를 복호화
복호화가 성공하면, 인증서가 유효하며 서버가 신뢰할 수 있는 대상임을 확인
동시에 서버의 공개키를 확보
보안 연결을 위한 키 교환
웹브라우저는 서버의 공개키로 자신의 대칭키( 비밀키 )를 암호화하여 서버에 전송
서버는 자신의 개인키로 이를 복호화
암호화된 통신 시작
서버와 웹브라우저는 같은 대칭키(비밀키)를 공유
이후의 데이터는 대칭키 암호화 방식을 사용해 안전하게 주고받음
통신이 끝난 후
데이터 통신이 끝나 연결이 종료되면 생성된 대칭키를 폐기
결과
서버와 클라이언트 간의 보안이 보장된 HTTPS 통신이 가능해짐
이후 모든 데이터는 대칭키로 암호화되어 빠르고 안전하게 전송