HTTP/2와 압축은 리소스 전송을 줄여 LCP 같은 로딩 지표를 개선할 수 있습니다. 이것만으로 레이아웃 이동이 해결되거나 검색 순위가 오르는 것은 아닙니다. 전송, 렌더링, 사용자 동작을 따로 확인하세요.
HTTP/2와 HTTPS 구분하기
HTTP/2는 한 연결에서 여러 요청을 다중화해 HTTP 수준의 대기를 줄입니다. 하지만 TCP를 사용하므로 패킷 손실이 여러 스트림을 지연시킬 수 있습니다. HTTP/3도 이미 사용되고 있으며 다른 전송 방식을 씁니다. 호스팅 지원과 측정 결과를 기준으로 선택하세요.
브라우저는 TLS 위에서 HTTP/2를 사용합니다. Vercel 같은 관리형 호스팅에서는 실제로 협상된 프로토콜을 확인하세요. 자체 호스팅에서는 Next.js 앞의 리버스 프록시나 CDN이 TLS와 HTTP/2를 처리할 수 있습니다. Node.js의 https 모듈만으로는 HTTP/2가 활성화되지 않습니다.
localhost에서 HTTPS를 실험할 때 사용할 인증서 생성 예시입니다. 운영 환경용 인증서가 아닙니다.
openssl req -x509 -newkey rsa:4096 -nodes -keyout key.pem -out cert.pem -days 365 -subj '/CN=localhost' -addext 'subjectAltName=DNS:localhost'
다음 커스텀 서버는 HTTP/1.1 기반 HTTPS 예시이며 HTTP/2 배포 예시가 아닙니다. 기존 Next.js 프로젝트가 필요하고 운영 모드에서는 빌드도 완료되어야 합니다. 일반적으로는 표준 서버를 프록시 뒤에서 실행하는 방식을 우선하세요.
import next from 'next'
import fs from 'node:fs'
import https from 'node:https'
const app = next({ dev: process.env.NODE_ENV !== 'production', port: 3000 })
const handle = app.getRequestHandler()
async function startServer() {
await app.prepare()
https
.createServer(
{
cert: fs.readFileSync('./cert.pem'),
key: fs.readFileSync('./key.pem'),
},
async (request, response) => {
await handle(request, response)
},
)
.listen(3000)
console.info(`Ready on https://localhost:3000`)
}
startServer()
실제 프로토콜과 압축 확인하기
Chrome DevTools의 Network에서 Protocol 열을 확인하세요. HTTP/2를 지원하는 curl에서는 첫 명령이 실제 사용된 버전을 보여 줍니다. 다른 버전으로 대체될 수도 있습니다. 두 번째 명령은 Brotli와 gzip 지원을 알린 뒤 GET 응답 헤더를 확인합니다.
curl --http2 -sS -o /dev/null -w '%{http_version}\n' https://your-site.com
curl -sS -D - -o /dev/null -H 'Accept-Encoding: br, gzip' https://your-site.com
Brotli와 gzip
next start를 사용할 때 Next.js는 기본적으로 gzip으로 압축합니다. Brotli가 더 작은 텍스트 응답을 만들 수 있지만 20~25% 절감이 항상 보장되지는 않습니다. 관리형 호스팅에서는 응답을 확인하고, 자체 호스팅에서는 지원되는 프록시나 CDN에 Brotli를 설정하세요.
다른 계층에서 압축을 설정한 뒤에만 Next.js 압축을 비활성화하세요. 이 설정 자체가 Brotli를 켜지는 않습니다.
// next.config.mjs
export default {
compress: false,
}
Brotli 응답 헤더의 예입니다.
Content-Encoding: br
Vary: Accept-Encoding
압축하지 않은 본문에 Content-Encoding을 지정하면 안 됩니다. 대체 응답과 캐시의 Accept-Encoding 처리도 확인하세요. 다음 수치는 설명용이며 실측이나 보장된 압축률이 아닙니다.
| 형식 | 원본 JavaScript | 예시의 압축 크기 |
|---|---|---|
| Gzip | 100 KB | 30 KB |
| Brotli | 100 KB | 22 KB |
프리페치와 Server Push
Next.js의 Link는 경로 리소스를 미리 가져올 수 있습니다. 브라우저가 보내는 요청이며 HTTP/2 Server Push가 아닙니다. Chrome은 버전 106부터 Server Push를 기본적으로 비활성화했습니다. 현재의 최적화가 여기에 의존하지 않도록 하세요.
import Link from 'next/link'
export default function AboutLink() {
return <Link href="/about" prefetch>About</Link>
}
정말 중요한 폰트라면 preload를 고려할 수 있습니다. 예시 URL을 실제 리소스로 바꾸고 형식과 cross-origin 설정을 맞추세요.
<link rel="preload" href="/fonts/site.woff2" as="font" type="font/woff2" crossorigin>
미리 가져오기는 대역폭을 사용합니다. 다섯 개나 여섯 개라는 공통 제한은 없습니다. 로딩이나 이동에 도움이 되는지 측정한 뒤 결정하세요.
이미지
next/image는 설정과 브라우저의 Accept에 따라 최적화 형식을 선택합니다. 기본 출력은 WebP이며 AVIF는 적절한 설정이 필요합니다. 크기를 지정하면 공간을 확보해 레이아웃 이동을 줄일 수 있습니다.
import Image from 'next/image'
export default function ExampleImage() {
return <Image src="/example.jpg" alt="Example" width={800} height={600} quality={75} />
}
아래 크기는 설명용입니다. 실제 값은 이미지, 해상도, 품질에 따라 달라집니다. 고정된 지원 비율 대신 사용자의 브라우저를 확인하세요.
| 형식 | 1920 × 1080 예시 | 지원 확인 |
|---|---|---|
| JPEG | 200 KB | 대상 브라우저 |
| WebP | 120 KB | 대상 브라우저 |
| AVIF | 80 KB | 대상 브라우저 |
흔한 문제와 비교
| 문제 | 확인 사항 |
|---|---|
| 유효한 TLS 인증서 없음 | Let’s Encrypt 등으로 신뢰할 수 있는 운영 인증서를 설정합니다. |
| Brotli가 반환되지 않음 | 요청·응답 헤더, 콘텐츠 유형, 프록시를 확인합니다. |
| 사전 요청이 너무 많음 | 불필요한 prefetch/preload를 제거하고 다시 측정합니다. |
같은 페이지를 동일한 기기, 네트워크, 캐시 조건에서 비교하세요. Speed Scanner와 WebPageTest를 활용할 수 있지만 프로토콜 이름만으로는 개선을 입증할 수 없습니다. 설정과 결과를 저장하세요.

