대상: Next.js 앱을 운영하는 사람(App Router 상정). 여기서는 공격 절차를 다루지 않습니다 — 이 글은 하드닝을 위한 실무 레퍼런스입니다: 우선순위별 체크리스트, 영역별 지침, 자기 검증. 프레임워크 전반의 그림은 프레임워크별 보안 허브를 참조하세요.
우선순위별 하드닝 체크리스트
이 표를 위에서부터 실행하세요. P0가 전제, P1이 가장 잦은 사고의 원천, P2가 지속적인 유지 관리입니다.
P0 ── 전제 (먼저 할 것)
시크릿(API 키 등)을 브라우저에 노출하지 않기 / 의존성 CVE 모니터링 + 빠른 패치 / 견고한 프로덕션 설정
P1 ── 사고의 최대 원천
Server Actions/Route Handlers 인가 + 입력 검증 / 서버 fetch의 SSRF
P2 ── 지속적인 유지 관리
헤더/CSP / 인증, 세션, 쿠키 / 레이트 제한
| 우선순위 | 통제 | 구체(Next.js) |
|---|---|---|
| P0 | 시크릿을 브라우저에 노출하지 않기 | NEXT_PUBLIC_은 브라우저에 안전한 값에만. 시크릿은 Server Component/Action/Route Handler 안에서만 |
| P0 | 의존성 CVE | npm audit/osv-scanner로 모니터링. 가동 버전으로 판단하고 빠르게 패치. 본체 RCE에 추종 |
| P0 | 프로덕션 설정 | 프로덕션 빌드로 구동. 오류로 내부(스택/환경 변수)를 흘리지 않음 |
| P1 | 액션 인가 | 모든 Server Action/Route Handler에 인증 + 소유자 스코프 인가 |
| P1 | 입력 검증 | 입력을 스키마 검증(형/범위/허용값). 클라이언트를 신뢰하지 않음 |
| P1 | SSRF 방어 | 서버 측 URL 취득을 허용 목록으로 제한 + 내부 IP/메타데이터 차단. 이미지 리모트 패턴을 제한 |
| P2 | 헤더/CSP | next.config에 보안 헤더 + HSTS. App Router에서 nonce 기반 CSP 검토 |
| P2 | 인증/쿠키 | 세션 쿠키에 Secure/HttpOnly/SameSite. 인가를 미들웨어에만 맡기지 않음 |
| P2 | 레이트 제한 | 인증, Server Actions, Route Handlers에 제한 |
1. 서버/클라이언트 경계와 환경 변수(P0)
Next.js 최대의 사고 원천은 서버 전용이어야 할 시크릿이 클라이언트로 흘러 들어가는 것입니다.
- 브라우저에 안전한 값에만
NEXT_PUBLIC_을 붙인다. API 키나 접속 정보에는 절대 붙이지 않는다(NEXT_PUBLIC_값은 빌드 시점에 클라이언트 번들에 포함되어 방문자에게 보인다). - 시크릿은 Server Component / Server Actions / Route Handlers 안에서만 읽고,
props와 응답(직렬화되는 값)에 섞지 않는다. - 서버 전용 모듈이 클라이언트에 import되지 않도록 유지한다(실수로 포함되면 시크릿이 번들될 수 있음). .env 파일과 시크릿을 참조하세요.
2. 의존성 CVE와 본체(P0)
- 의존성(npm) CVE를 기계 모니터링한다(
npm audit이나 osv-scanner로). 가동 중인 버전으로 판단하고 빠르게 패치한다(package.json 선언이 아니라 실제로 설치된 것으로 판단). - Next.js 본체는 심각한 RCE가 있었으므로, 공개되면 빠르게 추종한다. 운영 규율은 CVE에 뒤처지지 않기, 실무는 취약점 대응 플레이북을 참조.
- Node/Next를 지원 버전으로 유지하고 EOL 버전을 방치하지 않는다.
3. Server Actions / Route Handlers(인가 + 검증, P1)
이들은 누구나 호출할 수 있는 서버 측 함수입니다. 호출할 수 있다고 해서 허용된 것은 아닙니다.
흔함(위험)
- 액션을 "로그인 = 허용"으로 취급
- 미들웨어 인증에만 의존하고 소유자 검사가 없음
- 입력을 검증하지 않고 DB나 외부 호출로 넘김
- 클라이언트가 제공한 값(ID, 플래그)을 그대로 신뢰
올바름
- 인증에 더해 모든 액션/핸들러에서 소유자/권한 스코프 인가
- 미들웨어에 맡기지 않는다(데이터에 가까운 곳에서 인가)
- 입력을 스키마 검증(형/범위/허용값)
- ID 교체가 통하지 않도록 서버에서 재검증
IDOR란을 참조하세요. 모든 조회/갱신/삭제 경로에서 소유자 검사를 합니다.
4. SSRF와 서버 측 fetch(P1)
서버 측에서 사용자가 제공한 URL을 가져오는 처리(이미지 프록시, 웹훅, 메타데이터 취득)는 SSRF가 일어나기 쉬운 곳입니다.
- 취득 대상을 허용 목록으로 제한하고, 접속 시점에 프라이빗 IP와 클라우드 메타데이터(169.254.169.254)에 도달하는 것을 차단한다.
- 이미지 최적화의 리모트 패턴을 최소한으로 유지한다(임의 호스트의 취득을 허용하지 않음).
- SSRF란을 참조하세요. 본 사이트는 외부 fetch를 SSRF 안전 게이트웨이를 통해 보냅니다.
5. 인젝션과 출력
- XSS: React는 기본적으로 출력을 이스케이프한다.
dangerouslySetInnerHTML에 사용자 입력을 넘기지 않는다(정말 필요하면 새니타이즈한 뒤에만). XSS란을 참조하세요. - SQL/인젝션: ORM/플레이스홀더로 바인딩하고, 문자열 연결로 쿼리를 만들지 않는다(→ SQL 인젝션이란).
eval같은 위험한 평가에 외부 입력을 넘기지 않는다.
6. 보안 헤더와 CSP(P2)
next.config에 보안 헤더(X-Content-Type-Options 등)와 HSTS를 설정한다. 자기 사이트는 보안 헤더 진단으로 확인.- App Router에서는 nonce 기반 CSP를 검토한다(인라인 스크립트의 무제한 허용을 피한다). 분석/광고 태그와의 공존에는 설계가 필요하다는 점에 유의.
7. 인증, 세션, 쿠키(P2)
- 세션 쿠키에 Secure / HttpOnly / SameSite를 설정한다.
- 인가를 미들웨어 인증에만 위임하지 않는다. 미들웨어는 보완이고, 실제 판단은 액션/핸들러/데이터 계층에서 확인한다(경로에 따라 미들웨어를 우회할 수 있음).
- 로그인 시 세션을 적절히 재생성하고 만료시킨다.
8. 레이트 제한(P2)
- 인증, Server Actions, Route Handlers에 시도/처리량 제한을 걸어 무차별 대입, 남용, DoS를 억제한다.
검증: 당신의 Next.js는 실제로 하드닝되어 있는가
만드는 것으로 끝이 아니라 점검해야 비로소 완료입니다. 아래는 자기 사이트/환경에 대한 방어적 자기 점검입니다.
시크릿이 클라이언트로 새지 않는다
NEXT_PUBLIC_을 붙이지 않았는지 확인.프로덕션이 오류로 내부를 흘리지 않는다
액션 인가가 유지된다
헤더, 의존성, SSRF
npm audit/osv가 깨끗한지, 외부 fetch가 내부 IP에 도달할 수 없는지 확인.본 사이트의 관점: 서버/클라이언트 경계와 의존성에 집중한다
본 사이트는 Next.js로 구동되며, 중점은 특별한 설정이 아니라 서버/클라이언트 경계와 의존성을 최신으로 유지하는 것에 있습니다. 시크릿은 서버에 남기고, 누구나 호출할 수 있는 함수(Server Actions/Route Handlers)에는 항상 인가와 입력 검증을 두며, 의존성은 매 배포 전에 CVE 감사를 받습니다. 본 사이트는 패치되지 않은 CVE가 자동으로 악용된 사고를 계기로 시작되었으므로, 의존성 기계 모니터링은 최우선 습관입니다. 외부 URL fetch는 SSRF 안전 게이트웨이를 통과해 내부 IP나 메타데이터에 도달할 수 없게 합니다.
다음에 읽기
- 허브: 프레임워크별 보안 · Laravel 보안
- 의존성: CVE에 뒤처지지 않기 · 취약점 대응 플레이북
- 용어: IDOR란 · SSRF란 · .env 파일과 시크릿 · XSS
- 도구: 보안 헤더 진단
출처와 확인 범위
아래 1차 자료는 위의 설정·영향 범위·대응을 뒷받침하며 링크는 2026년 10월 23일 확인했습니다. 자료의 버전·구성 조건을 확인하세요. 점검 우선순위와 교훈은 이 사이트의 정리이며 글 전체의 재검증이나 안전 보증이 아닙니다.