안녕하세요. ManVSCloud 김수현입니다.
오늘은 CentOS 6에서 HTTP/2를 적용해보려 합니다.
CentOS 6은 2020년 11월 30일 이미 지원이 중단된 OS지만 아직 쓰고 계시는 사용자들이 많아 CentOS 6부터 적용 방법을 작성하기로 했습니다.
WHAT IS HTTP/2(H2)?
현재 HTTP/3 까지 출시되었으나 아직까지 많은 유저들은 1999년에 출시된 HTTP1.1을 가장 많이 사용하고 있습니다.
최근들어 HTTP/2를 적용하는 분들이 늘어나고 있어 HTTP/2에 대해 소개를 해드리고자 합니다.
우선 HTTP/2는 HTTP/1.1을 대체하는 것이 아닌 확장한 것인데 HTTP 메소드, 상태 코드, URI, 헤더 필드를 사용하여 동일하게 유지되고 있습니다.
HTTP/1.1로 시작하여 클라이언트가 HTTP/2를 지원하면 연결이 업그레이드 되는 방식입니다.

HTTP1.1은 연결 시 하나의 요청과 응답만 처리하기에 동시 데이터 전송이나 여러개의 리소스를 처리하는데에 속도와 성능이 떨어집니다.(전체 용량에 도달하기 전 여러 번의 소규모 전송으로 인한 지연 발생) 또한 서버와 클라이언트 간에 추가 요청이나 메타데이터 교환으로 반복적인 헤더와 쿠키 전송으로 응답 속도가 느려지는 현상이 나타납니다.
HTTP/2를 사용하게되면 이러한 문제를 해결할 수 있습니다. 클라이언트가 단일 TCP 연결을 통해 다수의 모든 요청을 동시에 보낼 수 있게 됩니다.
다만 무조건적으로 HTTP/2가 좋은 것만은 아니기에 내가 운영하는 서비스가 HTTP/2를 사용하기에 적합한지 판단이 필요합니다.
HTTP/2를 사용하게될 경우 단일 연결을 사용하여 동시 요청을 보내게 됩니다. 이는 예측할 수 없는 스파이크가 발생할 수 있는 원인이 될 수 있습니다. 게다가 HTTP/2 Server Push 기법을 이용하여 클라이언트가 요청하기 전에 서버가 클라이언트로 리소스를 보낼 수 있습니다. 이는 리소스를 선점적으로 로드하는데 도움이 되지만 이 또한 재방문자가 캐시된 파일 복사본이 있을 수 있으며 이 경우 서버에서 리소스를 푸시하지 않도록 Push Cache를 인식하도록 해주어야 합니다.(Cache-Control max-age 등 헤더 적용)
HTTP/2 사용은 응답 시간이 중요하지 않은 애플리케이션, 제한된 IoT 장치나 안정적인 연결이 필요한 곳 그리고 WebSockets, Server-Sent Events (SSE), Pub/Sub 메시징과 같이 적절한 기술이 사용되는 경우 등이 적합하다고 볼 수 있겠습니다.

HTTP/2를 적용하기 위해서는 조건이 있습니다.
만약 Apache를 사용할 것이라면 Apache 2.4.17버전 이상이 이어야하며 openssl 버전도 1.0.2 이상이 되어야합니다. PHP의 경우 libcurl 사용 즉, cURL을 이용하여 HTTP/2 POST를 요청하기 위해서는cURL 7.43 이상, PHP 버전도 5.5.24 이상의 환경이 필요합니다.
오늘은 간단하게 CentOS6에서 Apache로 http2 사용하기를 준비했습니다.
Using HTTP/2 on CentOS 6
mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo_org vi /etc/yum.repos.d/CentOS-Base.repo
우선 CentOS6은 지원 중단으로 Base repo를 아래와 같이 변경해주었습니다.
# CentOS-Base.repo # # The mirror system uses the connecting IP address of the client and the # update status of each mirror to pick mirrors that are updated to and # geographically close to the client. You should use this for CentOS updates # unless you are manually picking other mirrors. # # If the mirrorlist= does not work for you, as a fall back you can try the # remarked out baseurl= line instead. # # [base] name=CentOS-$releasever - Base release=$releasever&arch=$basearch&repo=os&infra=$infra baseurl=https://vault.centos.org/6.10/os/$basearch/ gpgcheck=1 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6 #released updates [updates] name=CentOS-$releasever - Updates release=$releasever&arch=$basearch&repo=updates&infra=$infra baseurl=https://vault.centos.org/6.10/updates/$basearch/ gpgcheck=1 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6 #additional packages that may be useful [extras] name=CentOS-$releasever - Extras release=$releasever&arch=$basearch&repo=extras&infra=$infra baseurl=https://vault.centos.org/6.10/extras/$basearch/ gpgcheck=1 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6 #additional packages that extend functionality of existing packages [centosplus] name=CentOS-$releasever - Plus release=$releasever&arch=$basearch&repo=centosplus&infra=$infra baseurl=https://vault.centos.org/6.10/centosplus/$basearch/ gpgcheck=1 enabled=0 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6 #contrib - packages by Centos Users [contrib] name=CentOS-$releasever - Contrib release=$releasever&arch=$basearch&repo=contrib&infra=$infra baseurl=https://vault.centos.org/6.10/contrib/$basearch/ gpgcheck=1 enabled=0 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6
만약 위와 같이 Base repo를 변경했는데도 정상적으로 yum 설치가 되지 않는다면
지원이 중단된 다른 repo가 있는지 확인해보신 후 중단된 repo를 제거 및 yum clean all 후 재진행 해보시기 바라며 그 후에도 되지않는다면 /etc/resolv.conf 에 nameserver가 정상적으로 등록되어 있는지 확인해보시기 바랍니다.
[root@manvscloud ~]# yum update -y
[root@manvscloud ~]# yum install wget perl gcc zlib-devel epel-release -y
위는 필수 설치 패키지 입니다.
기존에 운영하고 계시던 서비스가 존재한다면 yum update 전에 update 시 예외처리가 필요한 패키지들을 반드시 exclude해주시기 바랍니다.
yum update –exclude= 방식으로 exclude할 수 있으며 /etc/yum.conf에 exclude 설정을 해줄 수도 있습니다.
Install openssl and upgrade version
<OpenSSL Site>
cryptography software, providing cryptography hooks, or even just
communicating technical details about cryptography software is
illegal in some parts of the world. So when you import this
package to your country, re-distribute it from there or…
openssl부터 설치해보도록 합시다.
CentOS 6은 기본적으로 1.0.1버전의 openssl이 설치되는데 1.0.2를 설치해주기 위해 컴파일 작업을 진행할 것입니다.
// 컴파일 설치 진행 [root@manvscloud ~]# cd /usr/local/src [root@manvscloud src]# wget https://www.openssl.org/source/old/1.0.2/openssl-1.0.2u.tar.gz [root@manvscloud src]# tar zxvf openssl-1.0.2u.tar.gz [root@manvscloud src]# cd openssl-1.0.2u [root@manvscloud openssl-1.0.2u]# ./config --prefix=/usr/local/openssl shared zlib [root@manvscloud openssl-1.0.2u]# make [root@manvscloud openssl-1.0.2u]# make install // ldconfig 및 버전 확인 [root@manvscloud openssl-1.0.2u]# echo "/usr/local/openssl/lib" > /etc/ld.so.conf.d/openssl.conf [root@manvscloud openssl-1.0.2u]# cat /etc/ld.so.conf.d/openssl.conf /usr/local/openssl/lib [root@manvscloud openssl-1.0.2u]# ldconfig [root@manvscloud openssl-1.0.2u]# mv /usr/bin/openssl /usr/bin/openssl-1.0.1 [root@manvscloud openssl-1.0.2u]# ln -s /usr/local/openssl/bin/openssl /usr/bin/openssl [root@manvscloud openssl-1.0.2u]# openssl version OpenSSL 1.0.2u 20 Dec 2019 // 기존 certs 복사 [root@manvscloud certs]# cp -avp /etc/pki/tls/certs /usr/local/openssl/ssl/ `/etc/pki/tls/certs/ca-bundle.crt' -> `/usr/local/openssl/ssl/certs/ca-bundle.crt' `/etc/pki/tls/certs/Makefile' -> `/usr/local/openssl/ssl/certs/Makefile' `/etc/pki/tls/certs/renew-dummy-cert' -> `/usr/local/openssl/ssl/certs/renew-dummy-cert' `/etc/pki/tls/certs/ca-bundle.trust.crt' -> `/usr/local/openssl/ssl/certs/ca-bundle.trust.crt' `/etc/pki/tls/certs/make-dummy-cert' -> `/usr/local/openssl/ssl/certs/make-dummy-cert'
위와 같이 진행해준다면 openssl 버전이 1.0.2로 설치가 된 것입니다!
Apache + apr, apr-util, pcre
yum install -y nghttp2 libnghttp2 libnghttp2-devel gcc-c++ libstdc++-devel expat-devel pcre-devel
이제 HTTP/2 적용을 위한 Apache를 설치해봅시다.
apache 2.4 버전부터는 apr과 apr-util도 설치해주어야하는데 우선 apr 설치 과정입니다.
[root@manvscloud ~]# cd /usr/local/src [root@manvscloud src]# wget http://mirror.apache-kr.org/apache/apr/apr-1.6.5.tar.gz [root@manvscloud src]# tar zxvf apr-1.6.5.tar.gz [root@manvscloud src]# cd apr-1.6.5 [root@manvscloud apr-1.6.5]# ./configure --prefix=/usr/local/apr [root@manvscloud apr-1.6.5]# cp -arp libtool libtoolT [root@manvscloud apr-1.6.5]# make [root@manvscloud apr-1.6.5]# make install
아래는 apr-util 과정입니다.
[root@manvscloud ~]# cd /usr/local/src [root@manvscloud src]# wget http://mirror.apache-kr.org/apache/apr/apr-util-1.6.1.tar.gz [root@manvscloud src]# tar zxvf apr-util-1.6.1.tar.gz [root@manvscloud src]# cd apr-util-1.6.1 [root@manvscloud apr-util-1.6.1]# ./configure --prefix=/usr/local/apr-util --with-apr=/usr/local/apr [root@manvscloud apr-util-1.6.1]# make [root@manvscloud apr-util-1.6.1]# make install
pcre도 설치해줄 건데 이후 modsecurity를 사용하기 위해서도 pcre가 필요합니다.
[root@manvscloud ~]# cd /usr/local/src [root@manvscloud src]# wget https://ftp.pcre.org/pub/pcre/pcre-8.43.tar.gz [root@manvscloud src]# tar zxvf pcre-8.43.tar.gz [root@manvscloud src]# cd pcre-8.43 [root@manvscloud pcre-8.43]# ./configure --prefix=/usr/local/pcre [root@manvscloud pcre-8.43]# make [root@manvscloud pcre-8.43]# make install
Apache 2.4버전을 컴파일할 모든 준비가 되었습니다.
우선 아래 옵션을 보시면 event방식으로 설치했습니다.
[root@manvscloud ~]# cd /usr/local/src [root@manvscloud src]# wget http://archive.apache.org/dist/httpd/httpd-2.4.48.tar.gz [root@manvscloud src]# tar zxvf httpd-2.4.48.tar.gz [root@manvscloud src]# cd httpd-2.4.48 [root@manvscloud httpd-2.4.48]# ./configure --prefix=/usr/local/apache \ --enable-mods-shared=all --enable-http2 \ --enable-ext-filter --enable-ssl --with-ssl=/usr/local/openssl \ --enable-so --enable-cache --enable-proxy \ --enable-deflate --enable-suexec --enable-file-cache \ --with-mpm=event --with-apr=/usr/local/apr \ --with-apr-util=/usr/local/apr-util \ --with-pcre=/usr/local/pcre/bin/pcre-config \ --enable-modules=all --enable-module=shared [root@manvscloud httpd-2.4.48]# make [root@manvscloud httpd-2.4.48]# make install
(event 방식으로 설치 시 event + fcgi proxy + php-fpm 구조가 일반적입니다.)
왜 event 방식으로 설치했느냐?
prefork 방식은 http/2를 지원하지 않습니다.
prefork 방식이 지원되지 않는 이유는 무엇인가?에대한 질문에 대답은 간단합니다.
HTTP/2는 클라이언트가 단일 TCP 연결을 통해 서버에서는 다수의 모든 요청 즉, 동시 요청을 보내야합니다.

prefork의 단일 스레드 요구 사항을 HTTP/2에 매핑하는 것이 불가능한 것입니다.
처리 모델의 충돌이라고 볼 수있죠. (worker와 event는 다중 스레드 지원)
[root@manvscloud ~]# echo "PATH=$PATH:$HOME/bin:/usr/local/apache/bin" >> /etc/profile [root@manvscloud ~]# echo "export PATH" >> /etc/profile [root@manvscloud ~]# tail -n 2 /etc/profile PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin:/root/bin:/usr/local/apache/bin export PATH [root@manvscloud ~]# source /etc/profile
/usr/local/apache/bin 아래 명령어들을 편하게 사용할 수 있게 위와 같이 등록해주었습니다.
이제 apache에서 모듈을 추가해줍시다.
// 모듈 확인 [root@manvscloud ~]# apachectl -M | grep http2 //http2 모듈 확인 [root@manvscloud ~]# cat -n /usr/local/apache/conf/httpd.conf | grep http2 144 #LoadModule http2_module modules/mod_http2.so //주석 제거 [root@manvscloud ~]# sed -i '144s/#LoadModule/LoadModule/g' /usr/local/apache/conf/httpd.conf //모듈 적용 확인 [root@manvscloud ~]# apachectl -M | grep http2 http2_module (shared) // Protocols 추가 [root@manvscloud ~]# cat << EOF >> /usr/local/apache/conf/httpd.conf > <IfModule http2_module> > ProtocolsHonorOrder On > Protocols h2 h2c http/1.1 > </IfModule> > EOF
위 작업 후 apachectl start를 하여 apache를 실행해주고 웹사이트가 정상적으로 잘 출력되는지 확인해보시기 바랍니다. Apache가 정상적으로 실행됐는데 페이지 출력이 안되면 iptables가 실행되어있지 않은지? 상단 방화벽 등 어딘가에 막히는 것이 없는지 확인해보시고 그래도 출력이 안되신다면 /usr/local/apache/logs 아래 생성된 로그를 참고하여 해결이 필요합니다.

HTTP2.Pro에서 HTTP/2가 잘 적용되었는지 확인해보니 잘 적용되었다고 나오는군요.
해당 사이트는 아래 링크를 통해 바로 접속이 가능합니다.
Nginx
[root@manvscloud ~]# yum list nginx Loaded plugins: fastestmirror Loading mirror speeds from cached hostfile * epel: d2lzkl7pfhq30w.cloudfront.net Available Packages nginx.x86_64 1.10.3-1.el6 epel [root@manvscloud ~]# nginx -V nginx version: nginx/1.10.3 built by gcc 4.4.7 20120313 (Red Hat 4.4.7-23) (GCC) built with OpenSSL 1.0.1e-fips 11 Feb 2013 TLS SNI support enabled configure arguments: --prefix=/usr/share/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --http-client-body-temp-path=/var/lib/nginx/tmp/client_body --http-proxy-temp-path=/var/lib/nginx/tmp/proxy --http-fastcgi-temp-path=/var/lib/nginx/tmp/fastcgi --http-uwsgi-temp-path=/var/lib/nginx/tmp/uwsgi --http-scgi-temp-path=/var/lib/nginx/tmp/scgi --pid-path=/var/run/nginx.pid --lock-path=/var/lock/subsys/nginx --user=nginx --group=nginx --with-file-aio --with-ipv6 --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_addition_module --with-http_xslt_module=dynamic --with-http_image_filter_module=dynamic --with-http_geoip_module=dynamic --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_random_index_module --with-http_secure_link_module --with-http_degradation_module --with-http_slice_module --with-http_stub_status_module --with-http_perl_module=dynamic --with-mail=dynamic --with-mail_ssl_module --with-pcre --with-pcre-jit --with-stream=dynamic --with-stream_ssl_module --with-debug --with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic' --with-ld-opt=' -Wl,-E'
CentOS 6에서 Nginx는 epel에서 1.10.3으로 주네요.
openssl 버전만 맞춰준 뒤에 yum 설치만 해도 됩니다. nginx -V 옵션으로 보면 –with-http_v2_module 옵션이 보이시나요?
단 Nginx에서 http2 적용 테스트 시 주의할 점이 있다면 아래와 같이 HTTPS(443) SSL 설정을 해줍시다.
listen 80 http2 default_server; 으로 설정할 경우 사이트 접속이 안되고 다운로드가 됩니다.?
server {
listen 443 ssl http2 default_server;
listen [::]:443 ssl http2 default_server;
.
. 생략
.
}
CentOS 6에서 Nginx는 크게 어려움이 없을 것으로 보입니다.
Et cetera
나머지는 도움될만한 내용만한 자료만 첨부해두도록 하겠습니다.
cURL은 위 링크를 참고하면 HTTP/2 적용을 위해 cURL을 설치하는 과정이 나와있습니다.
물론 무작정 영상 그대로 따라하기보다 영상에서 주는 옵션을 보며 해당 옵션과 경로가 나의 환경에 맞는지 검토하는 것은 필수입니다.
마지막으로 Tomcat은 className을 org.apache.coyote.http2.Http2Protocol로 설정해주어야합니다.
<Connector port="8080" protocol="HTTP/1.1"> . . //생략 . <UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" /> . . //생략 . </Connector>
Tomcat 역시 버전만 맞춰주면 크게 어려울 것 없어보입니다. ?
Personal Comments
지금까지 CentOS 6에 HTTP/2를 적용에 대해 알아보았습니다.
앞으로 CentOS 7, Rocky 8, Naver Cloud Platform Load Balancer, AWS ELB 등에서 HTTP/2를 적용하는 방법에 대해서도 추가적으로 포스팅 될 예정입니다.
긴 글 읽어주셔서 감사합니다.
