웹 보안 헤더 최소 구성 — 실무에서 먼저 적용해야 할 것들

게시일: 2025년 4월 18일 · 13분 읽기

보안 감사에서 헤더 하나 때문에 통과 못 했다. 아주 간단한 헤더들을 설정하면 점수가 올라간다.

필수 5가지 보안 헤더

1. Content-Security-Policy (CSP)

어떤 리소스를 로드할 수 있는지 제한:

Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self'

의미:

개선 버전 (인라인 제거):

Content-Security-Policy: default-src 'self'; script-src 'self' https://cdn.jsdelivr.net; style-src 'self'; img-src 'self' data:; connect-src 'self' https://api.example.com

Nginx 설정:

server {
    add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self';" always;
}

2. Strict-Transport-Security (HSTS)

항상 HTTPS 사용:

Strict-Transport-Security: max-age=31536000; includeSubDomains; preload

의미:

Nginx:

server {
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
}

3. X-Content-Type-Options

MIME 타입 스니핑 방지:

X-Content-Type-Options: nosniff

예시: 공격자가 .jpg로 된 JavaScript 파일을 올림 → 브라우저가 실행 가능

이 헤더로 방지됨.

4. X-Frame-Options

Clickjacking 공격 방지:

X-Frame-Options: SAMEORIGIN

또는:

X-Frame-Options: DENY  # 모든 iframe 차단

5. Referrer-Policy

Referer 헤더 제어:

Referrer-Policy: strict-origin-when-cross-origin

의미: 같은 도메인에는 전체 URL 전송, 다른 도메인에는 도메인만 전송

전체 Nginx 설정

server {
    listen 443 ssl http2;
    server_name example.com;

    # SSL 인증서
    ssl_certificate /etc/nginx/ssl/cert.pem;
    ssl_certificate_key /etc/nginx/ssl/key.pem;

    # 보안 헤더
    add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self'" always;
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;
    add_header Permissions-Policy "microphone=(), camera=()" always;

    location / {
        proxy_pass http://localhost:3000;
    }
}

# HTTP → HTTPS 리다이렉트
server {
    listen 80;
    server_name example.com;
    return 301 https://$server_name$request_uri;
}

Express.js 설정

helmet 라이브러리 사용 (권장):

npm install helmet

// app.ts
import helmet from 'helmet';

app.use(helmet());

// 커스텀
app.use(helmet.contentSecurityPolicy({
    directives: {
        defaultSrc: ["'self'"],
        scriptSrc: ["'self'", 'https://cdn.jsdelivr.net'],
        styleSrc: ["'self'"],
    },
}));

점수 개선

헤더점수
헤더 없음40/100
기본 5개75/100
CSP + 강화85/100
완전 구성95/100

실무 적용 순서 (운영 중 서비스 기준)

운영 서비스에서 가장 많이 실패하는 건 "한 번에 CSP를 강하게 적용"하는 방식이다. 실제로는 아래 순서가 안전하다.

  1. 1주차: HSTS, nosniff, X-Frame-Options, Referrer-Policy 먼저 적용
  2. 2주차: CSP를 Report-Only로 넣고 위반 로그 수집
  3. 3주차: 인라인 스크립트 제거, 외부 CDN 도메인 화이트리스트 정리
  4. 4주차: CSP 강제 모드로 전환하고 배포 체크리스트에 고정

특히 마케팅 스크립트나 분석 스니펫이 있는 사이트는 2주차 로그 분석이 필수다. 이 단계 없이 강제 모드로 가면 화면이 부분적으로 깨지는 장애가 난다.

배포 후 검증 체크리스트

이 검증을 CI 파이프라인에 넣어두면 이후 릴리즈에서 헤더 누락이 재발하지 않는다.

결론

이 5개 헤더만 적용해도 보안 상태는 눈에 띄게 개선된다. 다만 핵심은 "설정"이 아니라 "운영 중 검증"이다. 점진 적용과 로그 기반 보완까지 완료하면, 실무 감사에서 반복적으로 지적받던 항목을 대부분 정리할 수 있다.

iL
ian.lab

실무 개발자입니다. 현장에서 겪은 문제와 해결 과정을 기록합니다. 오류 제보는 연락처로 보내주세요.