최근에 몇몇 팀원 분들과 HTTP/2 프로토콜에 대해 스터디를 진행하고 있는데요. HTTP/2 적용 방법에 대해 조사하다 보니 AWS 몇몇 서비스에서 별도 작업 없이 간단한 설정만으로 HTTP/2를 적용할 수 있다는 것을 알게 되었습니다.
이 글에서는 HTTP/2가 HTTP/1의 어떤 문제들을 해결해 주는지 간단히 알아보고 AWS의 CloudFront와 Application Load Balancer에서 HTTP/2를 적용하는 방법에 대해 소개합니다.
HTTP/1
1991년에 처음 세상에 나와서, 1999년에 1.1 버전이 나온 이후로 버전업 없이 20년을 넘게 쓰여왔습니다.
하지만 요즘의 웹 환경은 HTTP/1이 처음 나온 그때와는 많이 달라졌는데, 1996년도 Yahoo 메인 페이지 용량이 34KB 정도인 것에 비해 2022년 평균 웹페이지 용량은 2MB를 넘은 것을 보면 확실히 느낄 수 있습니다.
이러한 상황에서 텍스트 위주의 전송 프로토콜인 HTTP/1 은 아래와 같은 극복하기 어려운 문제점들이 있습니다.
- Head-of-Line(HOL) Blocking
- HTTP/1.1에서는 Pipelining을 도입함으로써, 여러 개의 요청을 한 번에 보낼 수 있게 되었습니다. 하지만 응답은 반드시 요청 순서에 맞추어 전달해야 한다는 규칙이 문제를 일으키는데, 먼저 들어온 요청에 대한 응답이 늦어지면 그 뒤에 모든 요청이 (응답을 당장 할 수 있음에도) 함께 지연돼 HOL Blocking이 발생합니다.
- RTT(Round-Trip Time) 증가
- Client의 요청이 Server에 도달하고, 그 요청에 대한 Server의 응답이 다시 Client로 도달하는 시간을 의미합니다. HTTP/1 은 TCP 기반 프로토콜이기 때문에 연결을 성립할 때마다 3-way Handshaking이 필요하고 이로 인해 RTT가 증가합니다.
- Header 중복 전송
- HTTP/1 헤더에는 (쿠키를 포함한) 많은 메타 정보들을 담고 있는데, 매 요청마다 중복된 헤더 값을 포함하여 전송하다 보니 불필요하게 헤더가 커지는 경우가 많습니다.
이러한 프로토콜 차원의 문제를 극복해 보고자 우리 프론트앤드 개발자들은 부단히 노력해왔습니다.
소스 번들링, 이미지 스프라이트 등을 통해 요청의 개수를 줄이거나, 도메인 샤딩으로 동시에 보낼 수 있는 요청의 개수를 늘리는 식으로요.
SPDY
이러한 HTTP/1의 문제를 해결하고자 구글이 개발한 비표준 프로토콜로써, HTTP/1을 대체하는 것이 아니라 HTTP를 확장하는 것이며 HTTP/2의 근간이 됩니다. (TLS는 SSL의 차기 버전입니다.)
HTTP/2
2015년 IETF 표준으로 채택되어, 현재는 대부분의 브라우저에서 지원합니다.
HTTP/1과의 호환성을 유지하면서 HTTP/1의 문제점을 보완하였으며 그 외에도 몇 가지 기능을 제공합니다.
HTTP/2의 장점은 아래와 같습니다.
- Multiplexing
- 하나의 커넥션에서 다수의 독립적인 스트림을 동시에 처리합니다. 이를 통해서 HTTP/1보다 적은 커넥션으로 다수의 요청/응답을 동시에 처리할 수 있습니다. 또한 독립적으로 처리되기 때문에 HOL Blocking이 발생하지 않습니다.
- Binary Protocol
- 프레임(HTTP/2 통신의 기본 단위)은 텍스트가 아닌 binary로 구성하므로 파싱이 더 빠르고, 오류 발생 가능성이 낮습니다.
- Header Compression
- HTTP/1의 헤더 중복 문제를 해결하고, 헤더의 크기를 줄이기 위해 HPACK으로 압축하여 전송합니다.
- Server Push
- Client의 요청 없이 Server에서 리소스를 전송할 수 있습니다. 이를 통해 클라이언트의 요청을 미리 예측하여 응답을 보낼 수 있습니다. 예를 들어 Client가
page.html
을 요청했을 때, Server는index.js
,index.css
를 요청할 것이라 예측하고 Push함으로써 latency를 줄일 수 있습니다.
- Client의 요청 없이 Server에서 리소스를 전송할 수 있습니다. 이를 통해 클라이언트의 요청을 미리 예측하여 응답을 보낼 수 있습니다. 예를 들어 Client가
- Stream Prioritization
- 한 스트림이 진행 중이더라도 다른 스트림이 끼어드는 것을 허용하고, 우선순위 설정을 통해 그 순서를 정할 수 있습니다. 자세한 내용은 이 글을 참고하시면 좋습니다.
AWS CloudFront에서 HTTP/2 적용
AWS는 2016년부터 CloudFront에서 HTTP/2를 지원하기 시작했습니다.
버튼 하나로 HTTP/1에서 HTTP/2로 변경 가능하며, HTTP/2를 지원하지 않는 환경에서 요청을 받는다면 HTTP/1.1 프로토콜로 응답합니다.
- AWS CloudFront 콘솔에서 변경하고자 하는 Distribution을 선택합니다.
설정 편집
>지원되는 HTTP 버전
(Supported HTTP versions
)에서 HTTP/2를 체크합니다.
3. cURL 테스트
AWS Elastic Beanstalk에서 HTTP/2 적용
AWS가 2016년에 공개한 Application Load Balancer는 L7 어플리케이션 계층에서 작동하면서 WebSocket과 HTTP/2를 지원합니다.
- AWS Elastic Beanstalk에서
새 환경 생성
을웹 서버 환경
으로 진행합니다.
2. 정보 입력 후 하단 추가 옵션 구성
을 클릭합니다.
3. 프리 티어에서는 로드 밸런서 설정이 불가능하므로, 사용자 지정 구성
을 선택합니다.
4. 로드 밸런서 수정
에서 HTTPS(433포트) 리스너를 추가합니다.
5. cURL 테스트
위 과정을 통해서 Client와 직접 연결되는 로드밸런서와의 통신만 HTTP/2로 설정되는데요, 로드밸런서와 웹서버 간의 통신은 HTTP/1으로도 충분합니다. 브라우저의 연결 개수 제한이 없고 RTT가 짧은 서버 간의 Private 네트워크에서는 HTTP/1의 문제들이 큰 이슈가 아니기 때문입니다. 리버스프록시 역할을 해주는 로드밸런서와의 연결만 HTTP/2로 설정해 주면 되니, 웹서버에는 별도 작업이 필요 없습니다.
마무리
브라우저 waterfall 차트에서 HTTP/1과 HTTP/2의 차이를 간단히 확인할 수 있습니다.
이미지 파일 30개를 포함한 페이지로 비교해 보니 DomContentLoaded
시간이 HTTP/1은 14.65초, HTTP/2는 11.45초로 약 20% 빨라진 것을 확인할 수 있습니다.
단순히 프로토콜만 HTTP/2로 바꾸는 것만으로도 성능 향상에 도움이 되기도 하지만, HTTP/1의 문제를 극복하기 위해 적용한 몇 가지 기술들은 HTTP/2에서 오히려 방해가 되는 경우가 있습니다.
예를 들어 출처별로 최대 128개의 요청을 병렬로 처리할 수 있는 HTTP/2에서 이미지 스프라이트는 불필요한 CSS 연산을 야기하고 캐싱을 어렵게 할 수 있습니다. 같은 이유로 도메인 샤딩도 오히려 성능에 안 좋다고 알려져 있는데, HTTP/2의 장점을 극대화하고 불필요한 연산을 줄이기 위해서는 HTTP/1 최적화 방법들은 다시 고민돼야 합니다.
더불어 Server Push, Stream Prioritization 등을 활용하는 HTTP/2만의 최적화 방법도 적용된다면 점점 무거워지는 웹 어플리케이션을 보다 빠르게 서빙할 수 있을 것입니다.TCP
기반으로 통신하는 HTTP/1, HTTP/2와 달리 UDP
를 기반으로 하는 HTTP/3이 도입되고 있는데요, 관심이 있으신 분은 [HTTP/3는 왜 UDP를 선택한 것일까?]를 읽어보시면 좋겠습니다.
더 많은 FE 지식을 나누고 싶다면?! 카카오엔터테인먼트 FE 기술블로그 [바로가기]
'Tech' 카테고리의 다른 글
카카오페이지는 BFF(Backend For Frontend)를 어떻게 적용했을까? (0) | 2022.09.26 |
---|---|
React 합성 컴포넌트로 재사용성 극대화하기 (0) | 2022.09.26 |
GitHub Actions에서 도커 캐시를 적용해 이미지 빌드하기 (0) | 2022.05.31 |
Test Code Why? What? How? (0) | 2022.05.17 |
카카오웹툰은 GitHub Actions를 어떻게 사용하고 있을까? (0) | 2022.03.23 |