DevToolBox무료
블로그

Content Security Policy (CSP) 완전 가이드: 기초부터 프로덕션까지

12분 읽기by DevToolBox

CSP는 XSS 공격에 대한 가장 효과적인 방어 수단 중 하나입니다. 브라우저에 어떤 리소스를 로드할 수 있는지 알려줌으로써 취약점이 있어도 악성 코드 주입을 방지합니다.

CSP란? 왜 중요한가?

CSP는 브라우저가 로드할 수 있는 리소스를 제어하는 HTTP 응답 헤더입니다.

CSP 작동 원리

브라우저가 CSP 헤더를 받으면 규칙을 위반하는 리소스를 차단합니다:

Browser receives HTTP response:
  Content-Security-Policy: default-src 'self'; script-src 'self' https://cdn.example.com

Browser allows:
  ✅ <script src="/app.js">              (same origin = 'self')
  ✅ <script src="https://cdn.example.com/lib.js">

Browser blocks:
  ❌ <script src="https://evil.com/steal.js">
  ❌ <script>alert('XSS')</script>       (inline = not allowed)

CSP 디렉티브 전체

디렉티브제어 대상예시
default-srcFallback for all resource types'self'
script-srcJavaScript files and inline scripts'self' https://cdn.example.com
style-srcCSS stylesheets and inline styles'self' 'unsafe-inline'
img-srcImages (img, favicon, CSS background)'self' data: https:
font-srcWeb fonts (@font-face)'self' https://fonts.gstatic.com
connect-srcXHR, fetch, WebSocket, EventSource'self' https://api.example.com
media-srcAudio and video elements'self'
frame-srcIframes and embedded frames'self' https://www.youtube.com
object-srcPlugins (Flash, Java applets)'none'
base-uriBase element URLs'self'
form-actionForm submission targets'self'
frame-ancestorsWho can embed this page (anti-clickjacking)'self'
upgrade-insecure-requestsUpgrade HTTP requests to HTTPS(no value needed)

소스 값 설명

소스의미
'self'Same origin (protocol + host + port)
'none'Block all resources of this type
'unsafe-inline'Allow inline scripts/styles (reduces security!)
'unsafe-eval'Allow eval(), Function(), setTimeout(string)
'strict-dynamic'Trust scripts loaded by already-trusted scripts
'nonce-abc123'Allow specific inline script with matching nonce attribute
'sha256-...'Allow inline script matching this hash
https:Allow any HTTPS resource
data:Allow data: URIs (e.g., inline images)
blob:Allow blob: URIs
*.example.comAllow all subdomains of example.com

단계별 구현

1단계: 리포트 전용 모드로 시작

사이트를 깨뜨리지 않고 위반 사항을 식별:

Content-Security-Policy-Report-Only: default-src 'self'; report-uri /csp-report

3단계: 정책 구축

분석 결과를 바탕으로 정책 생성:

Content-Security-Policy:
  default-src 'self';
  script-src 'self' https://cdn.example.com;
  style-src 'self' 'unsafe-inline';
  img-src 'self' data: https:;
  font-src 'self' https://fonts.gstatic.com;
  connect-src 'self' https://api.example.com;
  frame-ancestors 'self';
  base-uri 'self';
  form-action 'self';
  object-src 'none';
  upgrade-insecure-requests

일반적인 CSP 설정

엄격한 정책

Content-Security-Policy:
  default-src 'none';
  script-src 'self';
  style-src 'self';
  img-src 'self';
  font-src 'self';
  connect-src 'self';
  base-uri 'self';
  form-action 'self';
  frame-ancestors 'none';
  object-src 'none';
  upgrade-insecure-requests

중간 (일반 SPA)

Content-Security-Policy:
  default-src 'self';
  script-src 'self' 'unsafe-inline' 'unsafe-eval';
  style-src 'self' 'unsafe-inline';
  img-src 'self' data: blob: https:;
  font-src 'self' https://fonts.gstatic.com;
  connect-src 'self' https://api.example.com wss://ws.example.com;
  frame-ancestors 'self'

Google Analytics 포함

Content-Security-Policy:
  default-src 'self';
  script-src 'self' https://www.googletagmanager.com https://www.google-analytics.com;
  img-src 'self' https://www.google-analytics.com https://www.googletagmanager.com;
  connect-src 'self' https://www.google-analytics.com https://analytics.google.com

구현 방법

Nginx

add_header Content-Security-Policy "default-src 'self'; script-src 'self'" always;

Apache

Header set Content-Security-Policy "default-src 'self'; script-src 'self'"

Express.js

// Using helmet middleware (recommended)
const helmet = require('helmet');
app.use(helmet.contentSecurityPolicy({
  directives: {
    defaultSrc: ["'self'"],
    scriptSrc: ["'self'", "https://cdn.example.com"],
    styleSrc: ["'self'", "'unsafe-inline'"],
    imgSrc: ["'self'", "data:", "https:"],
  }
}));

// Or manually
app.use((req, res, next) => {
  res.setHeader('Content-Security-Policy',
    "default-src 'self'; script-src 'self'");
  next();
});

HTML Meta 태그

<meta http-equiv="Content-Security-Policy"
  content="default-src 'self'; script-src 'self'">

일반적인 실수

실수영향해결
스크립트에 unsafe-inline 사용XSS 보호 무효화nonce 또는 hash 사용
unsafe-eval 사용eval() 허용eval() 없이 코드 리팩토링
script-src에 와일드카드(*)모든 도메인 스크립트 허용특정 도메인만 화이트리스트
인라인 스타일 미고려CSS-in-JS 차단style-src에 unsafe-inline 또는 nonce
리포트 전용 테스트 생략사이트 기능 중단항상 리포트 전용부터 시작
base-uri 미설정base 태그 주입 허용base-uri 'self' 추가

FAQ

CSP는 어떤 공격을 방지하나요?

주로 XSS 공격을 방지합니다. 클릭재킹, 데이터 주입, 혼합 콘텐츠 문제도 방지합니다.

CSP가 입력 검증을 대체하나요?

아니요. CSP는 심층 방어 수단입니다. 모든 사용자 입력의 검증과 새니타이즈는 여전히 필요합니다.

인라인 스크립트에서 CSP를 사용하려면?

nonce(랜덤 토큰) 또는 hash(SHA-256)를 사용합니다. unsafe-inline은 피하세요.

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

아니요. CSP는 브라우저가 실행하며 성능 영향은 무시할 수 있습니다.

𝕏 Twitterin LinkedIn
도움이 되었나요?

최신 소식 받기

주간 개발 팁과 새 도구 알림을 받으세요.

스팸 없음. 언제든 구독 해지 가능.

Try These Related Tools

🛡️CSP Header Generator.ht.htaccess GeneratorNXNginx Config Generator🏷️Meta Tag Generator

Related Articles

Docker Compose 치트시트: 서비스, 볼륨, 네트워크

Docker Compose 레퍼런스: 서비스 정의, 볼륨, 네트워크, 환경 변수, 스택 예시.

CORS 에러 해결 완벽 가이드

CORS 에러를 단계별로 해결하세요. Access-Control-Allow-Origin, preflight, credentials, 서버 설정을 다룹니다.