그런데 가장 중요한 사실은 여전히 이것이야.
즉, Apache가 TLS 계층에서 h2를 광고하지 않고 있음.
확인해야 할 것
Apache가 어떤 MPM을 쓰는지 확인해봐.
결과가 아마 둘 중 하나일 거야.
정상
mpm_event_module (shared)또는
mpm_worker_module (shared)문제 가능성
mpm_prefork_module (shared)
gerd@miniboxx:/etc/apache2/conf-available$ sudo apachectl -M | grep mpm
mpm_prefork_module (shared)
원인 찾은 것 같네. 👍
현재 Apache가:
mpm_prefork_module (shared)로 동작 중이야.
mod_http2는 로드되어 있지만, MPM이 prefork이면 HTTP/2 지원이 사실상 비활성화되거나 제한적으로 동작하는 경우가 많아. 네가 본ALPN: server accepted http/1.1와 정확히 일치하는 증상이야.
HTTP/2를 쓰고 싶다면
보통 이런 순서야.
1. PHP-FPM 설치 확인
Ubuntu 24.04 기준 예시:
a2enmod mpm_event2. 필요한 모듈 활성화
sudo a2enmod proxy_fcgi setenvifsudo a2enconf php8.3-fpm(버전은 설치된 PHP에 따라 다름)
3. mod_php 비활성화
예:
sudo a2dismod php8.3
4. prefork → event 전환
sudo a2dismod mpm_preforksudo a2enmod mpm_event
5. Apache 재시작
sudo systemctl restart apache2
여기까지 해서 HTTP2 가 활성화 되었다.
중간에 ChatGPT 가 더 자세히 상황을 살펴 보기 위해 다음과 같은 명령의 실행을 권했다.
curl –http2-prior-knowledge -v https://blog.gerd.kr -o /dev/null
길어서 뒤에 첨부하겠지만, ChatGPT 는 이 명령의 결과를 보고는,
이 출력 덕분에 원인이 거의 확실해졌어.
핵심 줄:
* ALPN: curl offers h2,http/1.1...* ALPN: server accepted http/1.1즉,
클라이언트: HTTP/2가능서버:아니, HTTP/1.1로 할게상태야.
Protocols h2 http/1.1은 설정되어 있는데도 ALPN 협상에서 h2를 광고하지 않고 있어.
이라는 분석을 했다.
gerd@miniboxx:~$ curl --http2-prior-knowledge -v https://blog.gerd.kr -o /dev/null % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0* Host blog.gerd.kr:443 was resolved. * IPv6: (none) * IPv4: 122.43.156.87 * Trying 122.43.156.87:443... * Connected to blog.gerd.kr (122.43.156.87) port 443 * ALPN: curl offers h2,http/1.1 } [5 bytes data] * TLSv1.3 (OUT), TLS handshake, Client hello (1): } [512 bytes data] * CAfile: /etc/ssl/certs/ca-certificates.crt * CApath: /etc/ssl/certs { [5 bytes data] * TLSv1.3 (IN), TLS handshake, Server hello (2): { [122 bytes data] * TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8): { [19 bytes data] * TLSv1.3 (IN), TLS handshake, Certificate (11): { [2054 bytes data] * TLSv1.3 (IN), TLS handshake, CERT verify (15): { [78 bytes data] * TLSv1.3 (IN), TLS handshake, Finished (20): { [52 bytes data] * TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1): } [1 bytes data] * TLSv1.3 (OUT), TLS handshake, Finished (20): } [52 bytes data] * SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384 / X25519 / id-ecPublicKey * ALPN: server accepted h2 * Server certificate: * subject: CN=gerd.kr * start date: May 12 09:38:34 2026 GMT * expire date: Aug 10 09:38:33 2026 GMT * subjectAltName: host "blog.gerd.kr" matched cert's "blog.gerd.kr" * issuer: C=US; O=Let's Encrypt; CN=E8 * SSL certificate verify ok. * Certificate level 0: Public key type EC/prime256v1 (256/128 Bits/secBits), signed using ecdsa-with-SHA384 * Certificate level 1: Public key type EC/secp384r1 (384/192 Bits/secBits), signed using sha256WithRSAEncryption * Certificate level 2: Public key type RSA (4096/152 Bits/secBits), signed using sha256WithRSAEncryption } [5 bytes data] * using HTTP/2 * [HTTP/2] [1] OPENED stream for https://blog.gerd.kr/ * [HTTP/2] [1] [:method: GET] * [HTTP/2] [1] [:scheme: https] * [HTTP/2] [1] [:authority: blog.gerd.kr] * [HTTP/2] [1] [:path: /] * [HTTP/2] [1] [user-agent: curl/8.5.0] * [HTTP/2] [1] [accept: */*] } [5 bytes data] > GET / HTTP/2 > Host: blog.gerd.kr > User-Agent: curl/8.5.0 > Accept: */* > { [5 bytes data] * TLSv1.3 (IN), TLS handshake, Newsession Ticket (4): { [57 bytes data] * TLSv1.3 (IN), TLS handshake, Newsession Ticket (4): { [57 bytes data] * old SSL session ID is stale, removing { [5 bytes data] < HTTP/2 200 < link: ; rel="https://api.w.org/" < server-timing: wp-before-template;dur=58.34 < cache-control: max-age=2592000 < expires: Sat, 18 Jul 2026 15:30:37 GMT < vary: Accept-Encoding < content-type: text/html; charset=UTF-8 < date: Thu, 18 Jun 2026 15:30:37 GMT < server: Apache/2.4.58 (Ubuntu) < { [16160 bytes data] 100 91823 0 91823 0 0 384k 0 --:--:-- --:--:-- --:--:-- 386k * Connection #0 to host blog.gerd.kr left intact gerd@miniboxx:~$
