
Vibe Guardian
보안 헤더 6종 한 번에 설정하기 — nginx·Vercel·Cloudflare 예시 코드
ARTICLE CONTENT
1. 보안 헤더가 왜 필요한지부터 이해하기
1) 웹사이트 기본 보안이 생각보다 자주 놓치는 이유
웹사이트를 운영하다 보면 기능 개발이나 디자인 수정에 더 많은 시간을 쓰게 되고, 보안헤더설정처럼 눈에 잘 보이지 않는 부분은 뒤로 밀리기 쉽습니다.
그런데 실제 사고는 이런 기본 설정이 빠진 상태에서 발생하는 경우가 많습니다.
HTTPS는 적용했지만 브라우저가 페이지를 어떻게 처리해야 하는지 알려주는 헤더가 비어 있으면, 예상하지 못한 취약점이 생길 수 있습니다.
그래서 많은 사람들이 “내 사이트는 괜찮을까?”를 확인하려고 보안 헤더를 검색하게 됩니다.
이 글에서는 자주 쓰는 보안 헤더 6종과, 이를 nginx보안헤더, Vercel헤더, Cloudflare헤더 환경에서 어떻게 설정하는지 기본 흐름을 정리해보겠습니다.
2) 보안 헤더가 막아주는 대표적인 문제
보안 헤더는 사이트의 동작을 직접 바꾸기보다, 브라우저에게 “어떻게 해석하고 제한할지”를 알려주는 역할을 합니다.
예를 들어 클릭재킹, 혼합 콘텐츠, XSS, 쿠키 탈취 같은 문제는 헤더 설정만으로도 위험을 줄일 수 있는 경우가 있습니다.
특히 외부 스크립트나 이미지, API를 많이 쓰는 서비스일수록 기본 헤더 점검이 중요합니다.
이런 이유로 보안헤더설정은 대형 서비스뿐 아니라 개인 프로젝트나 스타트업에서도 먼저 확인하는 항목이 되곤 합니다.
보안 도구를 복잡하게 도입하기 전, 기본값부터 정리하는 출발점으로 볼 수 있습니다.
3) 오늘 다룰 내용
이 글에서는 보안 헤더 6종의 역할을 간단히 살펴보고, 실무에서 많이 쓰는 서버 환경별 적용 예시를 함께 확인합니다.
또한 모든 헤더를 무조건 강하게 적용했을 때 생길 수 있는 주의점도 함께 설명합니다.
마지막에는 어떤 상황에서 이런 설정이 유용한지, 그리고 직접 전화로 지원받는 방식과 어떤 차이가 있는지도 정리해보겠습니다.
처음 보안헤더설정을 하는 분이라도 전체 구조를 이해할 수 있도록, 너무 어렵지 않게 풀어보겠습니다.
2. 자주 쓰는 보안 헤더 6종 살펴보기
1) Strict-Transport-Security(HSTS)
HSTS는 브라우저가 해당 사이트를 항상 HTTPS로만 접속하도록 유도하는 헤더입니다.
한 번 적용해두면 사용자가 실수로 HTTP로 들어가더라도 보안 연결을 우선하게 됩니다.
다만 테스트 단계에서 바로 강하게 적용하면 되돌리기 어려울 수 있어 주의가 필요합니다.
특히 서브도메인까지 포함할지, preload를 사용할지 같은 부분은 사이트 구조를 보고 결정하는 편이 좋습니다.
2) Content-Security-Policy(CSP)
CSP는 외부 스크립트, 스타일, 이미지, 폰트 등을 어디서 불러올지 제한하는 역할을 합니다.
XSS 같은 문제를 완전히 막아주지는 않지만, 공격이 실행되는 범위를 크게 줄여주는 경우가 많습니다.
다만 SPA, 분석 도구, 외부 위젯이 많은 사이트에서는 처음부터 너무 강하게 걸면 정상 동작이 깨질 수 있습니다.
그래서 보안헤더설정에서 CSP는 가장 효과적이면서도 가장 신중하게 다뤄야 하는 항목으로 꼽힙니다.
3) X-Frame-Options 또는 frame-ancestors
이 헤더는 내 사이트가 다른 사이트의 iframe 안에 들어가는 것을 제한하는 데 사용됩니다.
클릭재킹 같은 공격을 막는 데 도움이 되며, 로그인 페이지나 결제 페이지에서 특히 중요합니다.
요즘은 CSP의 frame-ancestors와 함께 고려하는 경우가 많습니다.
서비스 구조상 외부 임베드가 필요한지 먼저 확인한 뒤 설정하는 것이 좋습니다.
4) X-Content-Type-Options
이 헤더는 브라우저가 응답의 MIME 타입을 임의로 추측하지 않도록 막는 역할을 합니다.
작은 설정처럼 보이지만, 잘못된 타입 해석으로 이어지는 문제를 줄이는 데 도움이 됩니다.
정적 파일을 많이 제공하는 사이트라면 기본값으로 넣어두는 편이 일반적입니다.
비교적 부작용이 적어서 nginx보안헤더나 CDN 설정에서 먼저 적용하기 쉬운 항목이기도 합니다.
5) Referrer-Policy
Referrer-Policy는 다른 페이지로 이동할 때 어디까지의 URL 정보를 전달할지 정합니다.
예를 들어 상세 페이지 주소나 쿼리 스트링이 외부로 과하게 노출되는 것을 줄일 수 있습니다.
서비스 특성에 따라 strict-origin-when-cross-origin 같은 값이 자주 쓰입니다.
사용자 이동 경로 분석과 개인정보 보호 사이 균형을 보려면 이 헤더도 함께 검토하는 편이 좋습니다.
6) Permissions-Policy
Permissions-Policy는 카메라, 마이크, 위치 정보처럼 브라우저 권한 기능을 제한하는 데 사용됩니다.
필요하지 않은 기능을 기본적으로 꺼두면 공격 표면을 줄이는 데 도움이 됩니다.
서비스가 실제로 어떤 브라우저 기능을 쓰는지 먼저 확인한 뒤 최소 권한 원칙으로 설정하는 것이 좋습니다.
이 항목은 특히 외부 위젯이나 불필요한 권한 요청을 줄이고 싶은 경우 유용합니다.
3. nginx에서 보안 헤더 설정하는 방법
1) nginx보안헤더 기본 예시
nginx에서는 add_header로 보안 헤더를 비교적 간단히 추가할 수 있습니다.
아래는 자주 쓰는 형태의 예시입니다.
server {
listen 443 ssl http2;
server_name example.com;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header Content-Security-Policy "default-src 'self'; img-src 'self' https: data:; script-src 'self' https: 'unsafe-inline'; style-src 'self' https: 'unsafe-inline';" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;
location / {
proxy_pass http://localhost:3000;
}
}
2) 적용할 때 자주 보는 체크포인트
nginx에서는 always를 붙여야 일부 상태 코드에서도 헤더가 빠지지 않습니다.
또한 location 블록이 여러 개면 상위 설정이 덮이거나 누락되는 경우가 있어 실제 응답 헤더를 꼭 확인해야 합니다.
특히 CSP는 서비스마다 리소스 구성이 다르기 때문에, 예시를 그대로 복붙하기보다 현재 사이트의 도메인 구조에 맞춰 수정해야 합니다.
이 단계에서 nginx보안헤더를 점검해두면 이후 배포 때마다 반복 수정하는 일을 줄일 수 있습니다.
3) nginx에서 주의할 점
정적 파일, API, 리다이렉트 응답 등 모든 응답에 헤더가 들어가는지 확인하는 것이 중요합니다.
예외 없이 한 번에 적용하면 편해 보이지만, 운영 중인 사이트에서는 특정 페이지에서만 깨질 수 있습니다.
따라서 처음에는 HSTS, X-Content-Type-Options, Referrer-Policy처럼 비교적 안정적인 항목부터 적용하고, CSP는 점진적으로 강화하는 방식이 자주 쓰입니다.
이런 방식이 보안헤더설정에서 실패 확률을 줄이는 데 도움이 됩니다.
4. Vercel에서 보안 헤더 설정하는 방법
1) Vercel헤더를 정리하는 기본 방식
Vercel에서는 vercel.json의 headers 설정을 이용해 보안 헤더를 추가할 수 있습니다.
프레임워크와 무관하게 적용할 수 있어서, 별도 서버 관리 없이 운영하는 프로젝트에서 활용도가 높습니다.
{
"headers": [
{
"source": "/(.*)",
"headers": [
{ "key": "Strict-Transport-Security", "value": "max-age=31536000; includeSubDomains" },
{ "key": "X-Content-Type-Options", "value": "nosniff" },
{ "key": "Referrer-Policy", "value": "strict-origin-when-cross-origin" },
{ "key": "X-Frame-Options", "value": "SAMEORIGIN" },
{ "key": "Permissions-Policy", "value": "geolocation=(), microphone=(), camera=()" }
]
}
]
}
2) Vercel에서 CSP를 넣을 때 고려할 점
Vercel헤더에서 CSP를 넣는 것도 가능하지만, Next.js나 React 기반 앱은 빌드 방식에 따라 리소스 경로가 달라질 수 있습니다.
특히 개발 환경과 운영 환경에서 외부 스크립트가 다르면 예상치 못한 차이가 발생할 수 있습니다.
그래서 처음부터 완성형 정책을 넣기보다, 먼저 리포트 전용 모드나 느슨한 정책으로 시작하는 경우가 많습니다.
이후 문제가 없는 리소스만 남기면서 점차 좁혀가는 방식이 안정적입니다.
3) Vercel 사용 시 체크하면 좋은 부분
서버 설정 파일이 아니라 배포 설정에서 관리되므로, 프론트엔드 배포 담당자가 비교적 쉽게 반영할 수 있습니다.
다만 API 응답, 이미지 최적화 경로, 정적 리소스 경로가 모두 같은 정책을 따라가는지 확인해야 합니다.
또한 특정 경로만 예외를 둬야 하는 서비스라면 source 패턴을 세분화하는 편이 좋습니다.
정리해두면 보안헤더설정을 배포 과정의 일부로 자연스럽게 포함시킬 수 있습니다.
5. Cloudflare에서 보안 헤더 설정하는 방법
1) Cloudflare헤더를 쓰는 이유
Cloudflare를 CDN이나 프록시로 사용하면, 엣지 단계에서 응답 헤더를 조정할 수 있습니다.
원본 서버를 직접 건드리기 어렵거나 여러 서비스가 한 번에 앞단에 걸려 있는 경우 편리합니다.
특히 운영 중인 사이트가 여러 개일 때 일괄 관리가 필요한 상황에서 활용도가 높습니다.
이때 Cloudflare헤더는 원본 서버와 분리해서 기본 정책을 유지하는 데 도움이 됩니다.
2) 설정 방식 예시
Cloudflare에서는 Transform Rules나 Response Header Modification 같은 기능을 통해 헤더를 추가하거나 수정할 수 있습니다.
구성 화면에서 대상 URL 패턴을 잡고, 필요한 헤더를 추가하는 식으로 운영합니다.
예를 들어 다음과 같은 정책을 넣는 방식이 있습니다.
- HSTS 적용
- X-Content-Type-Options: nosniff
- Referrer-Policy: strict-origin-when-cross-origin
- Permissions-Policy 제한
- 필요 시 CSP 추가
이 방식은 원본 서버 설정을 따로 바꾸기 어려운 경우에 실무적으로 도움이 됩니다.
3) Cloudflare 적용 시 유의사항
Cloudflare는 앞단에서 응답을 수정하므로, 원본 서버와 중복 설정이 생길 수 있습니다.
중복 자체가 항상 문제는 아니지만, 같은 헤더가 서로 다른 값으로 들어가면 예측하기 어려운 결과가 나올 수 있습니다.
특히 HSTS나 CSP는 적용 위치를 하나로 정리해 두는 편이 관리에 유리합니다.
그래서 Cloudflare헤더를 사용한다면 원본과 CDN 중 어디에서 무엇을 관리할지 미리 나누는 것이 좋습니다.
6. 설정할 때 자주 하는 실수와 점검 방법
1) 헤더를 넣었는데 실제 응답에는 없는 경우
설정 파일을 수정했는데도 브라우저에서 헤더가 보이지 않는 경우가 있습니다.
이때는 캐시, 리다이렉트 응답, 다른 서버 블록, CDN 오버라이드 여부를 함께 확인해야 합니다.
특히 nginx와 Cloudflare를 함께 쓰는 환경에서는 어느 계층에서 헤더가 최종적으로 반영되는지 봐야 합니다.
단순히 파일만 수정하는 것으로 끝나지 않는다는 점이 자주 놓입니다.
2) CSP를 너무 강하게 시작하는 경우
CSP는 효과가 좋은 대신, 초기에 강하게 걸면 사이트가 깨지는 일이 많습니다.
외부 분석 도구, 광고 스크립트, 지도, 결제 모듈 등이 있으면 허용 도메인을 세밀하게 추가해야 합니다.
그래서 먼저 현재 사용 중인 리소스를 목록화한 뒤 정책을 만드는 편이 안전합니다.
이 과정은 보안헤더설정을 처음 하는 팀에게 특히 중요합니다.
3) 서비스 구조와 맞지 않는 기본값을 쓰는 경우
예를 들어 iframe 임베드가 필요한데 X-Frame-Options를 너무 제한적으로 잡으면 기능이 막힐 수 있습니다.
또한 API 도메인과 프론트 도메인이 분리된 경우 CORS 설정과 헤더 정책을 함께 봐야 합니다.
즉, 헤더는 “무조건 강하게”보다 “현재 서비스 구조에 맞게”가 핵심입니다.
이 점을 놓치지 않으면 nginx보안헤더, Vercel헤더, Cloudflare헤더 모두 더 안정적으로 운영할 수 있습니다.
4) 브라우저에서 직접 확인하는 습관
설정 후에는 개발자도구의 Network 탭이나 curl로 실제 응답 헤더를 확인하는 것이 좋습니다.
브라우저에서 Mixed Content 경고나 차단 메시지가 뜨는지도 함께 보아야 합니다.
기본 보안 항목은 설정이 쉬운 것 같아도, 실제로는 페이지별 예외가 많아 검증이 필요합니다.
이런 점검이 누적되면 다음 프로젝트에서도 그대로 재사용할 수 있습니다.
7. 어떤 상황에서 도움이 되는지 정리하기
1) 배포 전 기본 보안 점검이 필요한 경우
새로 사이트를 오픈하거나 리뉴얼한 뒤, 가장 먼저 확인해야 할 것 중 하나가 보안 헤더입니다.
기능이 복잡하지 않은 초기 서비스라도 기본 헤더가 빠져 있으면 의외의 문제가 생길 수 있습니다.
이럴 때 보안헤더설정은 빠르게 위험 요소를 확인하는 출발점이 됩니다.
고가의 복잡한 보안 솔루션을 도입하기 전에 기본 상태를 점검하는 용도로 적합한 편입니다.
2) nginx, Vercel, Cloudflare 중 어디서 관리해야 할지 헷갈릴 때
운영 환경에 따라 헤더를 어디에서 관리할지 다를 수 있습니다.
직접 서버를 제어한다면 nginx보안헤더 방식이 익숙할 수 있고, 서버리스 배포라면 Vercel헤더가 편할 수 있습니다.
CDN 앞단에서 일괄 관리해야 한다면 Cloudflare헤더가 더 적합할 수 있습니다.
즉, 서비스 구조에 따라 관리 지점을 나누는 것이 핵심입니다.
3) 직접 전화로 문의하는 방식과 비교했을 때
보안 헤더는 전화로 하나씩 설명받는 방식보다, 먼저 URL 기준으로 현재 상태를 빠르게 확인하는 데 강점이 있습니다.
직접 전화 상담은 상황 설명을 길게 해야 하고, 정리 과정도 사람마다 다를 수 있습니다.
반면 URL만 넣어 기본 보안 상태를 점검하면, HTTPS나 인증서, 보안 헤더, 노출 가능성 같은 항목을 한 번에 훑어볼 수 있습니다.
정리하면 보안헤더설정이 필요한 상황에서는 먼저 자동 점검으로 기본 상태를 확인하고, 세부 조정이 필요할 때 추가로 사람의 판단을 받는 방식이 효율적인 편입니다.
다른 콘텐츠도 함께 보세요
같은 주제에서 이어서 읽기 좋은 글들을 랜덤으로 추천합니다.
사이드 프로젝트를 SaaS로 전환할 때 보안에서 달라지는 것
사이드 프로젝트를 SaaS로 바꾸면 왜 보안을 다시 봐야 할까 1) 개인용 프로젝트와 서비스형 제품은 기준이 다릅니다 사이드프로젝트SaaS로 전환할 때 가장 먼저 달라지는 점은 “내가 쓰는 도구”에서 “다른 사람도 쓰는 서비스”가 된다는 점입니다. 개…
개인정보보호법, 1인 스타트업도 예외 없다 — 의무 사항 요약
1인 스타트업도 개인정보보호법을 신경 써야 하는 이유 1) “작은 사업이니 괜찮겠지”가 위험한 이유 1인 스타트업이나 초기 팀은 보통 서비스 개발, 마케팅, 고객 응대까지 동시에 처리하다 보니 보안이나 법적 이슈를 뒤로 미루는 경우가 많습니다. 하지만…
MVP 출시 전 최소한으로 해야 할 보안 설정 5가지
MVP를 출시할 때 보안이 자주 뒤로 밀리는 이유 1) 기능 개발과 배포 일정이 우선되기 쉽습니다 MVP 단계에서는 보통 “일단 동작하는지”가 가장 중요하게 여겨집니다. 그래서 로그인, 결제, 관리자 기능처럼 눈에 보이는 기능부터 먼저 구현하고, 보안…
브라우저 개발자 도구로 내 서비스 보안 상태 빠르게 확인하기
브라우저에서 보안 상태를 먼저 확인해야 하는 이유 웹서비스를 운영하다 보면 기능 구현에는 집중하지만, 의외로 기본적인 보안 상태는 뒤늦게 점검하는 경우가 많습니다. 특히 화면은 잘 동작해도 실제 브라우저에서 열어보면 HTTPS 설정, 쿠키 정책, 보안…