보안 가이드

Next.js를 안전하게 운영하기: 공개된 CVE에 뒤처지지 않기

Next.js의 가장 큰 위험은 공개된 CVE를 패치하지 않고 두는 것입니다. 가동 중인 버전 확인, Dependabot·osv-scanner 모니터링, 빠른 업데이트, 최소 권한 운영의 네 가지 실천을 정리합니다.

게시 2026-06-07 업데이트 2026-10-06 9분 읽기
이 페이지에서

대상: Next.js(또는 유사 JS 프레임워크)로 앱을 출시하는 사람, 특히 "AI의 도움으로 만들어 감으로 운영" 중인 경우. 실제 사고에서 추려냈다(→ 방치된 CVSS 10.0).

본 사이트의 견해: 중요한 것은 속도가 아니라 놓치지 않는 시스템이다

인디 개발자가 보안에서 부족한 것은 보통 지식이 아니라, 운영을 지속할 방법이다. CVE 뉴스를 남보다 빨리 읽는 것은 가치가 없다(속도는 벤더와 뉴스에 맡겨라). 통하는 것은 당신과 관련된 CVE를 놓치지 않는 시스템이다. 그래서 이 글은 더 많이 아는 것보다 그런 시스템을 만드는 데 초점을 둔다.

1. 가동 중인 버전으로 판단하라

"내가 위험한 버전에 있는가"를 매니페스트 하한이 아니라 실제로 가동 중인 것으로 측정하라 — 매니페스트 숫자와 가동 버전은 자주 어긋나기 때문이다.

✗ package.json 하한으로 셈

"next": "^16.0.0" → "16.0.0이 취약하니 우리도" — "8개 취약"으로 과대 계상.

✓ 가동 중인 버전으로 셈

npm ls next가 해석된 버전을 보임 → 자동으로 오른 것은 안전, 고정된 것만 뒤처짐. 실제로는 2개.

package.json 하한은 실제로 가동 중인 것과 다를 수 있다. 가동 중인 버전으로 판단하면 위험이 달라진다('취약' 8개가 2개로).
# 실제로 해석된 버전을 보라
npm ls next react react-dom
# 가동 중인 컨테이너 안에서
docker exec <container> npm ls next

캐럿 범위(^16.0.0)는 재빌드 시 자동으로 오르고, 고정된 의존성은 뒤처진다. 여기 나오는 버전으로 판단하라.

직접 확인하는 방법

아래 절차로 앱이 실제로 어떤 버전으로 돌고 있는지, 알려진 CVE가 해당하는지 알 수 있다. 모두 자신의 환경을 들여다보기만 하는 작업이다.

1

로컬 버전을 확인한다

프로젝트 폴더에서 npx next info를 실행한다. next, react, react-dom의 실제 버전과 최신 릴리스에서 얼마나 뒤처졌는지가 표시된다. npx next -v는 Next.js 버전만 출력한다.

2

왜 그 버전인지 본다

npm ls next(또는 pnpm why next)로 어떤 버전이 어떤 패키지를 거쳐 설치됐는지 볼 수 있다. 잠금 파일(package-lock.json이나 pnpm-lock.yaml)을 커밋하지 않았다면 빌드할 때마다 버전이 바뀔 수 있으니, 먼저 커밋하라.

3

운영 환경에서 가동 중인 버전을 확인한다

로컬에서 업데이트해도 예전 이미지로 돌고 있는 서버는 바뀌지 않는다. 컨테이너라면 가동 중인 컨테이너 안에서 next의 package.json의 version 필드를 읽는다(아래 명령). output: 'standalone'에서도 통한다.

4

알려진 CVE와 대조한다

npm audit --omit=dev는 운영에 배포되는 의존성만 검사한다. --audit-level=high를 붙이면 High 이상이 있을 때 0이 아닌 값으로 종료하므로 CI에서 멈출 수 있다. osv-scanner로 잠금 파일을 스캔해도 같은 목적을 이룬다.

5

자신의 구성에 맞는 공식 권고를 읽는다

Next.js 권고는 App Router와 Pages Router, 셀프 호스팅과 매니지드에 따라 나뉘기도 한다. 권고에 적힌 수정 버전을 1~3단계에서 확인한 버전과 비교하라.

# local: actual versions and distance from latest
npx next info
# the version running inside the production container
docker exec <container> node -p "require('next/package.json').version"
# check only production dependencies; fail on High or above
npm audit --omit=dev --audit-level=high

운영 방식에 따라 달라지는 것

같은 CVE라도 Next.js를 어떻게 운영하느냐에 따라 영향이 있을 수도, 없을 수도 있다. 과거 두 사례를 배포 형태별로 정리하면 다음과 같다.

운영 방식미들웨어 인증 우회(CVE-2025-29927)RSC RCE(CVE-2025-55182)업데이트하는 사람
매니지드(Vercel, Netlify 등)영향 없음(라우팅이 별도 시스템에서 동작)App Router를 쓰면 영향 있음. 차단 규칙은 있지만 업데이트는 여전히 필요본인(잠금 파일이 다음 버전을 결정)
셀프 호스팅(next start / standalone, Docker 포함)영향 있음App Router를 쓰면 영향 있음본인(이미지 재빌드와 재시작을 통해)
정적 내보내기(output: 'export')영향 없음(서버가 돌지 않음)요청을 받는 서버가 없으므로 일반적으로 닿지 않음본인(빌드 시점 의존성은 여전히 업데이트 필요)

즉 매니지드 호스팅이라도 Next.js 버전을 올리는 것은 당신의 일이다. 호스팅 쪽 보호는 패치 버전으로 올릴 때까지 시간을 벌어 주는 것으로 여겨라.

지원 기간도 확인하라. 공식 지원 정책에 따르면 2026년 10월 기준으로 다음과 같다.

버전 계열상태(2026년 10월)보안 수정
16.xActive LTS(기능, 수정, 보안 패치)있음
15.xMaintenance LTS(최초 릴리스로부터 2년간)치명적인 것만
14.x 이하지원 종료심각한 문제에 한해 드물게, 보장 없음

2. 의존성을 기계로 모니터링하라

CVE를 손으로 추적하는 것은 오래가지 못하고, 그 놓침이 곧 사고가 된다. 도구로 자동 모니터링하라.

무료 의존성 모니터링

osv-scanner scan -L pnpm-lock.yaml

GitHub에서는 Dependabot을 켜라(저장소의 Settings → Advanced Security → Dependabot alerts). 당신의 의존성에 해당하는 CVE에 대해서만 PR을 받는다.

중요한 것은 우선순위 매기기다. 본 사이트의 입장: "악용되고 있는가(KEV)" 곱하기 "CVSS가 얼마나 높은가"로 순위를 매긴다. 쓰지 않는 높은 CVSS는 영향이 작고; 활발히 악용되는 중간 점수가 최우선이다. 그 우선순위 매기기가 작업의 핵심이다.

3. 업데이트: 우회책이 아니라 수정된 버전으로

취약점이 나타나면, 프레임워크를 패치 버전으로 업그레이드해 취약점 자체를 고쳐라.

표면적인 대처(불충분)

  • 리버스 프록시에서 공격처럼 보이는 요청만 차단
  • 과금/증상을 멈추고 "처리됨"으로 친다
  • RCE 취약점 자체는 그대로 둔다

근본 수정(올바름)

  • 프레임워크를 업그레이드해 패치 버전으로
  • 업그레이드 후 로그에서 시그니처가 사라졌는지 확인
  • 피해를 멈추는 것과 근본 원인을 고치는 것을 별개 작업으로 보고, 둘 다 한다

흔한 실패

"과금/증상을 멈췄다" ≠ "처리했다." 피해를 멈추는 것과 취약점을 고치는 것은 다른 작업이다. 둘 다 하라.

실제 사례: 2025년 12월 React Server Components 취약점

공개된 CVE 대응이 실제로 어떤 모습이었는지, 2025년 12월에 공개된 React Server Components(RSC) 취약점으로 살펴본다. 아래 내용은 모두 React와 Next.js의 공식 발표, CISA의 공개 데이터에 근거한다.

  1. 2025년 12월 3일

    React가 인증 없이 서버에서 코드 실행으로 이어질 수 있는 CVE-2025-55182(CVSS 10.0)를 공개했다. Next.js에서는 15.x, 16.x 및 일부 canary의 App Router 앱이 영향을 받았고(CVE-2025-66478), Pages Router와 Edge Runtime은 해당하지 않았다. 우회책은 없었고, 수정 버전(15.0.5, 15.1.9, 15.2.6, 15.3.6, 15.4.8, 15.5.7, 16.0.7 등)으로의 업그레이드가 필요했다.
  2. 2025년 12월 5일

    CISA가 실제 악용이 확인된 취약점 카탈로그(KEV)에 추가했다.
  3. 2025년 12월 6일

    Next.js는 태평양 시간 12월 4일 오후 1시 시점에 패치되지 않은 채 온라인이었던 앱은 사용 중인 시크릿(API 키 등)을 교체해야 한다고 덧붙였다.
  4. 2025년 12월 11일

    패치를 검토하는 과정에서 같은 메커니즘의 문제 두 건(서비스 거부와 소스 코드 노출)이 추가로 발견되어 패치됐다. 이어 서비스 거부 수정이 불완전한 것으로 드러나 CVE-2025-67779가 발급되었고, 이미 업그레이드한 사람에게도 재업그레이드가 요청됐다.

운영 측면의 교훈은 세 가지다.

  • 한 번의 업데이트로 끝나지 않는다. 같은 코드에 대한 후속 수정이 며칠 간격으로 올 수 있다
  • 호스팅 쪽 차단 규칙은 보조였고, 완전한 해결책은 업그레이드뿐이라고 설명됐다
  • 패치 전에 온라인 상태였다면 업데이트와 함께 시크릿도 교체하라

본 사이트의 견해: 완료는 '업데이트를 실행했다'가 아니라 '운영 버전이 패치됐다'이다

이번처럼 후속 수정이 이어지면 "지난주에 업그레이드했다"는 믿을 수 없게 된다. 완료 여부는 작업 기억이 아니라, 운영 환경에서 가동 중인 버전이 최신 권고의 수정 버전 이상인지로 판단하라. 본 사이트도 컨테이너가 다시 생성됐는지 확인하고 그 안에서 가동 중인 버전을 점검한 뒤에야 업데이트를 완료로 처리한다.

흔한 실수와 고치는 법

  • package.json의 숫자로 판단한다: 설치된 버전은 다를 수 있다. npx next info나 npm ls next로 확인하라.
  • 잠금 파일을 업데이트하고 끝낸다: 운영 이미지를 재빌드하고 재시작할 때까지 예전 버전이 계속 돈다. 운영 환경 안의 버전을 확인하라.
  • 한 번 업데이트하고 안심한다: 후속 권고가 나올 수 있다. Dependabot 등의 알림을 켜 두고 며칠간 권고를 지켜보라.
  • 호스팅 쪽 차단 규칙에 맡긴다: 모든 형태의 공격을 잡지 못할 수 있다. 업그레이드하라.
  • 지원 종료된 계열에 머문다: 14.x 이하는 수정이 보장되지 않는다. 16.x로의 이전을 계획하라.
  • 개발 전용 경고에 묻혀 운영 관련 경고를 놓친다: npm audit --omit=dev로 배포되는 것부터 확인하라.
  • 패치 전 기간을 무시한다: 그 사이 시크릿이 탈취됐을 수 있다. API 키와 데이터베이스 비밀번호를 교체하라(→ .env와 API 키 기초).

4. 피해를 제한하는 최소 권한

앱이 악용되더라도 피해가 제한되도록 설계한다.

1

권한 없는 사용자로 실행

컨테이너 USER를 root로 돌리지 마라. 그러면 침해는 그 사용자에게 허용된 범위까지만 닿는다.
2

DB/Redis를 내부 네트워크에만 바인딩

절대 공개하지 마라. 직접 닿을 수 있는 표면을 줄여라.
3

서비스별로 분리

네트워크와 데이터를 서비스별로 나눠, 한 침해가 전체로 퍼지지 못하게 하라.

이것들이 침해가 "컨테이너 안 환경 탈취"에서 멈추느냐 "호스트 점령"에 닿느냐를 가른다.

본 사이트는 직접 이렇게 한다

본 사이트는 여기 쓴 그대로, 자신의 의존성을 CVE 모니터링한다 — 그래서 이 모든 것을 시작한 종류의 놓침(방치된 공개 CVSS 10.0)을 다시 사람의 주의력에만 맡기지 않는다. "우선순위(KEV + CVSS)로 순위를 매겨라"라고 말하는 이유는, 실제로 그렇게 운영하기 때문이다.

다음으로 읽기

출처

FAQ

QNext.js 보안에서 가장 중요한 것은 무엇인가요?
A

버그를 안 만드는 것 이전에, 프레임워크나 그 의존성의 공개된 CVE를 패치 안 한 채 두지 않는 것입니다. 가장 심각한 침해 대부분은 새로운 공격이 아니라 방치된 알려진 취약점에서 옵니다.

Qpackage.json으로 취약 여부를 알 수 있나요?
A

아니요. package.json의 `^`(하한)은 현실을 반영하지 않습니다 — 캐럿 범위는 재빌드 시 자동으로 올라가고, 고정된 의존성은 뒤처집니다. 항상 실제로 가동 중인 버전으로 판단하세요.

Q혼자라면 가장 먼저 할 한 가지는 무엇인가요?
A

Dependabot(GitHub)이나 osv-scanner를 켜서 의존성의 CVE를 자동으로 모니터링하는 것입니다. 수동 확인은 늘 무언가를 놓칩니다. 계속 돌아가는 시스템이 더 많은 지식보다 가치 있습니다.

Q지금 가동 중인 Next.js 버전은 어떻게 확인하나요?
A

프로젝트 폴더에서 `npx next info`를 실행하면 next, react, react-dom의 실제 버전이 표시됩니다. 운영 환경은 가동 중인 컨테이너나 서버 안에 있는 next의 package.json에서 버전을 읽으세요(본문 확인 절차 3단계). 로컬과 운영이 항상 같지는 않으니 둘 다 확인하세요.

QVercel 같은 플랫폼에서 호스팅해도 업데이트가 필요한가요?
A

필요합니다. 2025년 3월의 미들웨어 인가 우회(CVE-2025-29927)는 Vercel과 Netlify에는 영향이 없었지만, 2025년 12월의 React Server Components RCE(CVE-2025-55182)는 App Router 앱 전반에 영향을 주었습니다. Vercel은 자체 차단 규칙(WAF)을 추가하면서도 모든 변형을 막을 수는 없으며 패치 버전으로의 업그레이드가 필요하다고 밝혔습니다.

QNext.js 14 이하에 머물러도 괜찮나요?
A

권장하지 않습니다. 공식 지원 정책상 14.x 이하는 지원 대상이 아니며, 보안 수정은 심각한 문제에 한해 드물게 나올 뿐 보장되지 않습니다. 2026년 10월 기준 지원 대상은 16.x(Active LTS)와 15.x(Maintenance LTS)입니다. Maintenance는 최초 릴리스로부터 2년간이므로, 15.x를 쓰고 있다면 16.x로의 이전도 계획하세요.