썸네일: Unsplash의Paul Hanaoka
출처 : 웹 성능 최적화 기법
웹 성능 최적화 기법(루비페이퍼 사) 도서에 대한 핵심 내용과 지식을 정리한 포스트입니다. 포스트에 올라오는 내용은 도서의 일부이기 때문에 더 자세한 내용이 궁금하신 분들은 출처에서 도서를 구매해 읽어보시는 것을 추천드립니다.
2.1 웹 최적화란
- 최적화(optimization)란 알맞은 상황으로 맞춘다는 의미이며, 일반적으로 최대 효과를 얻기 위해 최선의 노력을 하는 행위를 일컫는다.
- 웹 사이트는 검색 엔진 최적화(Search Engine Optimization, SEO)를 실행하면 좀 더 빠르게 검색된다.
- 웹 최적화란, 최고의 웹 성능을 구현하기 위해 최고의 조건을 만드는 노력을 의미하며 최고의 성능을 만드는 최적화 조건을 갖추는 것으로 요약할 수 있다.
2.1.1 프론트엔드 최적화
- 프론트엔드 최적화는 웹 UI/UX와 관련된 최적화를 의미하며, 주로 프론트엔드 성능과 관련 있는 HTML, 자바스크립트, CSS, 이미지 파일, 타사 파일 자체나 이들이 어우러져 콘텐츠를 만들어낼 때 최적화를 진행한다.
- 프론트엔드 최적화 기술은 웹 브라우저를 사용하는 사용자 환경에 따라 달라진다. (PC, 태블릿, 스마트폰 등 기기환경, 네트워크 환경 등)
- 프론트엔드 최적화 대표 기술들
- 스크립트를 병합하여 브라우저 호출 개수를 줄임
- 스크립트 크기를 최소화해 바이트(byte) 자체를 줄임
- 스크립트를 gzip 등으로 압축하여 전달
- WebP 등으로 브라우저 이미지 형식을 최적화
- 이미지 손실, 무손실 압축
- Cache-Control 응답 헤더를 통해 브라우저 캐시를 충실히 사용
- 도메인 수를 줄여 DNS 조회를 최소화
- DNS 정보 미리 읽어 오기
- CSS를 HTML 상단에, 자바스크립트를 HTML 하단에 위치시키기
- 페이지 미리 읽어 오기(page prefetching)
- 타사 스크립트가 웹 성능을 방해하지 않도록 조정
2.1.2 백엔드 최적화
- 웹 UI를 로직에 맞게 만드는 백엔드 관련 최적화
- 웹 서버, 웹앱 서버, 데이터베이스, 로드 밸런싱, DNS 서버 등
- 백엔드 최적화 대표 기술들
- DNS 응답이 빨라지도록 서버 증설
- DNS 응답을 빠르게 할 수 있도록 DNS 정보를 최대한 캐싱
- 웹 서버가 있는 데이터 센터의 네트워크 출력(throughput)/대역폭(bandwidth) 증설
- 웹 서버, 웹 애플리케이션 서버의 CPU/RAM 증설
- 프록시 서버를 설정하여 웹 콘텐츠 캐싱
- CDN(Content Delivery Network)을 사용해 인터넷상에 콘텐츠 캐싱
- 데이터베이스 정규화로 디스크 I/O 최적화
- 데이터베이스 캐싱으로 응답을 빠르게
- 로드 밸런싱을 통해 가장 성능이 좋은 웹 서버로 요청을 연결
- 웹 애플리케이션 로직을 가볍고 빠르게 개발
- 백엔드 최적화는 프론트엔드 최적화에 비해 가시적인 효과가 크진 않지만 웹 사이트의 빠른 로딩보다 네트워크를 정상적으로 사용하고 콘텐츠를 전달하기 위해 반드시 필요한 요소
2.1.3 프로토콜 최적화
- 웹 콘텐츠를 전달하는 HTTP/HTTPS 프로토콜 자체의 효과를 극대화하면 웹 서버가 클라이언트에게 콘텐츠를 최대 속도와 최저 지연 시간으로 전달할 수 있다.
2.2 TCP/IP 프로토콜
- 웹에서는 TCP/IP 프로토콜 일종인 HTTP를 사용해 콘텐츠를 전달한다.
- 네트워크 계층 구조를 표준화한 OSI(Open System Interconnection) 7개 계층 모델에서 TCP는 4번째 전송 계층에 속하며, HTTP는 7번째 응용 계층에 속한다.
- 전송 계층 : 네트워크상에서 송신자와 수신자 사이에 데이터 전송 보장
- 응용 계층 : 실제 네트워크 상에서 소프트웨어와 사용자의 상호 연동 담당
- TCP 네트워크를 사용하는 네트워크에 있어 대표적인 성능 지표는 대역폭과 지연 시간이다.
- 대역폭 : 특정 시간 동안 얼마나 많은 트래픽을 보낼 수 있는지. 시간당 전송량
- 지연 시간 : 클라이언트와 서버 간 콘텐츠를 전달하는 물리적 시간을 의미하며 일반적으로는 클라이언트-서버 사이의 요청,전달,응답까지 걸리는 시간을 의미한다.
- 브라우저가 콘텐츠를 해석하고 화면에 렌더링하는 단계는 클라이언트측에서만 실행하므로 지연 시간에는 포함되지 않는다.
- 서버와 클라이언트 두 호스트를 모두 왕복하는 데 걸리는 시간을 Round Trip Time(RTT)이라고 한다.
- RTT는 게임이나 채팅 등을 할 때 품질에 영향을 주므로 스트리밍 관련 회사들은 지연 시간에 따라 전달받은 영상 파일의 품질을 조절하여 버퍼링을 줄일 수 있는 **가변 스트리밍 방식(adaptive streaming)**을 사용한다.
2.2.1 TCP 혼잡 제어
- **TCP 혼잡 제어(congestion control)**는 TCP 네트워크의 통신량을 조절하여 TCP 네트워크가 혼잡해지지 않도록 하는 방식을 의미한다.
- TCP 네트워크의 통신량이 실제 처리량보다 많아서 문제가 발생하는 것을 **TCP 혼잡 붕괴(congestion collapse)**라고 한다.
- TCP 혼잡 붕괴가 발생하는 이유는 인터넷에 연결된 호스트들이 최대한 많은 정보를 전송하려고 많은 네트워크 패킷을 보내기 때문이다.
- TCP 혼잡 제어 기술은 패킷을 보내는 쪽에서 네트워크에서 수용할 수 있는 양을 파악하고 그만큼의 패킷만 보내는 약속으로 TCP 혼잡을 해결한다.
- 받는 쪽은 패킷이 정상적으로 송신되었다는 ACK 패킷을 보내며, 이를 확인한 호스트에서는 지속적으로 패킷을 보낼 수 있다.
- 하지만 처음부터 네트워크가 얼만큼 패킷을 수용 가능한지 정확히 파악하는 것은 어렵고, 그 값도 시간이 지남에 따라 변하기 때문에 호스트가 네트워크 상태를 시시각각 파악하고 전송 속도를 조절하는 기능도 포함된다.
대표적인 혼잡 제어 기술
느린 시작(slow start)
- TCP 연결이 시작되면 전송 가능한 버퍼의 양인 **혼잡 윈도우(Congestion Window, CWND)**의 초깃값을 작게 설정하여 전송한다.
- 패킷이 정상적으로 도착할 때마다 더 많은 패킷을 보내고 **패킷 유실(packet drop)**이 발생하기 전까지 반복하는 방식
- 호스트가 ACK 응답을 받지 못하면 혼잡 윈도우 크기는 더 늘어나지 않으므로, 느린 시작 기술을 통해 네트워크가 수용 가능한 혼잡 윈도우의 크기를 파악하면 그 이상의 패킷을 보내지 않는다.
빠른 재전송(fast retransmit)
- 먼저 도착해야 하는 패킷이 도착하지 않고 다음 패킷이 도착한 경우에도 일단 ACK 패킷을 보내는 방식이다.
- 하지만 중간에 패킷이 하나 손실되면 송신자는 중복된 ACK 패킷을 통해 이를 감지하고 정상적으로 전송되지 않은 패킷을 재전송한다.
- 중복된 패킷을 3개 받으면 반드시 손실된 패킷을 재전송하며, 동시에 혼잡 제어가 필요한 상황임을 인식해 혼잡 윈도우 창 크기를 줄이는 작업을 실행한다.
흐름 제어(flow control)
- 흐름 제어는 TCP 송신자가 데이터를 너무 빠르게 혹은 많이 전송하여 수신자의 버퍼가 **오버플로(overflow)**되는 현상을 방지하는 기술이다.
- 수신자는 수신 버퍼(receive buffer)를 가지고 있어 이로 인해 상위 계층으로 세그먼트를 보내는 애플리케이션 프로세스에서 데이터를 읽는 속도가 느려질 수 있다.
- 그러므로, 송신자가 데이터를 전송하는 속도를 애플리케이션 프로세스를 읽는 속도와 유사한 수준으로 만들어 트래픽 수신 속도를 송신 속도와 일치 시키는 기술이다.
2.3 HTTP 프로토콜
- HTTP는 텍스트 이상 콘텐츠들을 웹에서 전달하기 위해 만들어진 프로토콜로, HTTP 성능을 개선하면 웹 성능도 향상된다.
2.3.1 HTTP 최적화 기술
- HTTP/0.9 버전 이후 HTTP/3 버전까지 HTTP는 크게 여섯 차례 업데이트가 진행되었다.
- HTTP/0.9 버전까지는 클라이언트와 서버의 인터넷 통신 정상화, 가용성, 신뢰성 등 기능에 초점
- HTTP/1.0 버전 부터는 클라이언트 서버 사이 요청과 응답을 빠르게 할 수 있는 연구가 진행
- 웹 환경이 멀티호스트(multi-host) 환경으로 변하면서 HTTP/1.1 버전부터 멀티호스트 기능과 클라이언트와 서버 사이에서 TCP/IP 연결을 재사용하는 기능을 추가 하였다.
- HTTP/1.1 버전부터 적용된 연결 재사용(persistent connection), 파이프라이닝(pipelining) 기법이 연결 기반의 HTTP 최적화 기법이다.
2.3.2 HTTP 지속적 연결
- TCP 통신을 연결하는 3-way handshake 방식은 클라이언트와 서버 사이 SYN, SYN-ACK, ACK의 3번 요청과 응답으로 이루어진다.
- HTTP 초기 버전에서는 통신으로 여러 오브젝트를 요청하고 응답하려면 3-way handshake 방식으로 TCP연결을 맺었다.
- 이 방식은 송신자와 수신자 사이 신뢰할 수 있는 안전한 통신을 추구하는 TCP 알고리즘에서 시작되었다
- 그러나 동시에 많은 웹 콘텐츠를 전달해야 하는 HTTP 통신의 장애물로서도 작용됐다.
- 수많은 HTTP 요청과 응답을 하기 위해서는 매번 TCP 연결을 맺고 끊는 알고리즘을 사용해야 하는데 이는 웹 로딩 시간에 영향을 준다.
- 웹 사이트에 이미지 등 멀티미디어 콘텐츠가 늘어나면서 TCP 연결 재사용이 필요하게 되어 등장한 것이 지속적 연결(keep-alive, 연결 재사용) 기술이다.
- 지속적 연결은 위 그림의 오른쪽 처럼 TCP상에서 한 번 연결되면 둘 사이의 연결이 완전하게 끊어지기 전까지 맺어진 연결을 지속적으로 재사용하는 기술이다.
- 지속적 연결 사용을 원하는 클라이언트가 해당 기능을 지원하는 웹 서버에 HTTP 요청 헤더를 이용하여 Connection 헤더 및 keep-alive 속성으로 지속적 연결을 요청할 수 있게 되었다.
- 이후 지속적 연결을 지원하는 서버는 클라이언트의 요청을 수용하여 동의하는 동일한 헤더를 HTTP 응답에 포함하는 것이 HTTP/1.0 RFC의 규약이 되었다.
- HTTP/1.1에서는 클라이언트와 서버가 HTTP 지속적 연결 기능을 기본으로 지원하며 필요 없는 경우에만 close 요청을 통해 지속적 연결을 사용하지 않겠다고 전달한다.
- 하지만 TCP 연결이 계속 늘어나면 자원이 고갈되어 더 많은 클라이언트가 접속할 때 대처하지 못할 수 있기 때문에 서버의 성능을 고려해 HTTP 지속적 연결 기능을 사용할지 결정해야 한다.
- 한편으론 HTTP 지속적 연결을 사용해 단일 시간 동안의 TCP 연결 수를 줄여 서버의 CPU, 메모리 자원을 절약하고 네트워크 혼잡, 지연을 줄이는 장점도 있다.
- **HTTP 파이프라이닝 기술(동시의 여러 HTTP 요청 및 응답을 병렬처리하는 기술)**을 사용하려면 HTTP 지속적 연결 기능이 지원돼야 한다.
- HTTP/2 버전은 단일 TCP 연결을 통해 클라이언트-서버 응답을 지연 없이 스트림(stream) 형태로 다수의 HTTP 요청과 응답을 주고받을 수 있는 멀티플렉싱(multiplexing) 기술의 토대를 만들었다.
2.3.3 HTTP 파이프라이닝
- HTTP의 선입선출(First In First Out, FIFO) 방식의 단점을 극복하는데서 출발하였다.
- 기존에는 HTTP 요청과 응답이 여럿일 때 하나의 응답이 지연되면 나머지 요청과 응답 모두 지연될 수 밖에 없었다.
- HTTP 파이프라이닝은 먼저 보낸 요청의 응답이 없어도 다음 요청을 병렬적으로 수신자 측에 전송하는 기술이다.
- HTTP 파이프라이닝을 사용하면 중간에 응답 지연이 발생하더라도 클라이언트는 먼저 서버 측 응답을 받을 수 있어 전체적으로 빠른 웹 로딩이 구현된다.