전체 가이드
높음 심각도보안 헤더

Content-Security-Policy (CSP): 무엇이고 어떻게 추가하나요

Content-Security-Policy (CSP)는 브라우저가 어떤 스크립트, 스타일, 기타 콘텐츠 소스를 로드하고 실행할 수 있는지 알려 주는 HTTP 응답 헤더입니다. 좋은 CSP는 크로스 사이트 스크립팅(XSS)에 대한 가장 강력한 방어 수단 중 하나입니다.

무엇인가요

CSP는 브라우저가 적용하는 허용 목록입니다. 서버가 Content-Security-Policy 헤더를 보내면, 브라우저는 정책이 명시적으로 허용하지 않은 것 — 인라인 스크립트, 서드파티 도메인, eval() 등 — 을 로드하거나 실행하기를 거부합니다.

정책은 지시문의 목록입니다. 예를 들어 script-src 'self'는 “내 출처에서 제공된 JavaScript만 실행”을 의미하고, object-src 'none'은 레거시 플러그인을 완전히 차단합니다.

왜 중요한가요

CSP가 없으면 HTML 주입이나 XSS 버그 하나로 공격자가 사용자의 브라우저에서 임의의 JavaScript를 실행할 수 있습니다 — 세션 탈취, 페이지 변조, 데이터 유출.

약한 CSP는 없는 것과 거의 같습니다. 'unsafe-inline'은 공격자가 의존하는 인라인 스크립트를 다시 허용하고, script-src * 같은 와일드카드 소스는 어디서든 스크립트를 로드하게 해 CSP의 의미를 무너뜨립니다.

고치는 방법

Next.js에 기본 정책 추가하기

next.config.js에 헤더를 설정하여 모든 응답에 적용되도록 하세요. 엄격하게 시작하고 필요한 곳에서만 완화하세요.

// next.config.js
const csp = [
  "default-src 'self'",
  "script-src 'self'",
  "style-src 'self' 'unsafe-inline'",
  "img-src 'self' data:",
  "base-uri 'none'",
  "frame-ancestors 'none'",
  "object-src 'none'",
].join("; ");

module.exports = {
  async headers() {
    return [{ source: "/:path*", headers: [{ key: "Content-Security-Policy", value: csp }] }];
  },
};
unsafe-inline을 nonce로 교체하기

인라인 스크립트가 필요하면 'unsafe-inline'을 사용하는 대신 요청마다 nonce를 생성하여 스크립트 태그와 정책 양쪽에 추가하세요(script-src 'self' 'nonce-<value>').

강화 지시문을 항상 설정하기

base-uri 'none', frame-ancestors 'none', object-src 'none'은 흔한 우회(base 태그 주입, 클릭재킹, 플러그인 삽입)를 막아 주며 대부분의 앱에 안전한 기본값입니다.

자주 묻는 질문

CSP가 사이트를 느리게 하나요?

아니요. CSP는 브라우저가 평가하는 헤더일 뿐이며 측정 가능한 지연을 더하지 않습니다. 실제 비용은 인라인 스크립트를 제거하는 엔지니어링 작업입니다.

Content-Security-Policy와 X-Frame-Options의 차이는 무엇인가요?

X-Frame-Options는 프레이밍(클릭재킹)만 제어합니다. CSP의 frame-ancestors 지시문이 이를 대체하며, CSP는 스크립트, 스타일, 이미지 등도 함께 관장합니다.

내 앱도 영향을 받나요?

AppSafe는 이 문제와 수십 가지 다른 문제를 한 번의 무료 스캔으로 점검합니다.

내 앱 무료 스캔