개발 slecs

프론트엔드 보안 응답 헤더 일괄 적용으로 XSS·클릭재킹 방어 강화

목차

보안 응답 헤더를 next.config.mjs에 박아 넣은 이유

프론트엔드 보안 강화 작업의 일환으로 HTTP 응답 헤더에 strict 보안 정책들을 추가했다. 변경 파일은 next.config.mjs 단 하나. 라인 수는 많지 않겠지만, 이런 핀포인트 설정 변경이 전체 서비스 보안 태세에 미치는 영향은 생각보다 훨씬 크다.


왜 응답 헤더인가

브라우저 레벨의 보안은 서버사이드 코드보다 상대적으로 후순위에 놓이기 쉽다. "백엔드에서 이미 막으니까 괜찮다"는 인식이 팀 안에 은연중에 있었고, 실제로 보안 헤더 관련 이슈는 코드리뷰에서도 잘 안 잡힌다. 그런데 XSS, 클릭재킹, MIME 스니핑, 정보 누출 등 프론트엔드 레이어에서 막아야 하는 공격 벡터는 여전히 많다.

next.config.mjsheaders() 함수를 통해 모든 라우트에 일괄 적용하는 방식을 택한 건 이 이유에서다. 미들웨어나 각 페이지 컴포넌트에서 개별 처리하면 누락 가능성이 생긴다. 설정 한 군데에서 전체를 커버하는 게 팀 입장에서도 유지보수가 훨씬 쉽다.


어떤 헤더들을 넣었나

일반적으로 "strict 보안 헤더"라고 하면 다음 항목들이 기본 세트로 묶인다.

헤더 목적 대표 값 예시
X-Frame-Options 클릭재킹 방지 DENY / SAMEORIGIN
X-Content-Type-Options MIME 스니핑 차단 nosniff
X-XSS-Protection 구형 브라우저 XSS 필터 1; mode=block
Referrer-Policy 리퍼러 정보 노출 제어 strict-origin-when-cross-origin
Permissions-Policy 브라우저 API 접근 제어 camera=(), microphone=()
Content-Security-Policy 리소스 로딩 출처 제한 인라인/외부 스크립트 정책 등
Strict-Transport-Security HTTPS 강제 (HSTS) max-age=63072000; includeSubDomains

이 중 CSP는 설정이 가장 까다롭다. 너무 빡빡하게 잡으면 서드파티 스크립트나 인라인 스타일이 깨지고, 너무 느슨하게 잡으면 의미가 없다. 이번엔 일단 나머지 헤더들로 기반을 다지고, CSP는 report-only 모드로 먼저 관찰하는 방향으로 접근했다.

// next.config.mjs 내 headers 설정 패턴 예시
const securityHeaders = [
  {
    key: 'X-Frame-Options',
    value: 'SAMEORIGIN',
  },
  {
    key: 'X-Content-Type-Options',
    value: 'nosniff',
  },
  {
    key: 'Referrer-Policy',
    value: 'strict-origin-when-cross-origin',
  },
  {
    key: 'Permissions-Policy',
    value: 'camera=(), microphone=(), geolocation=()',
  },
  {
    key: 'X-XSS-Protection',
    value: '1; mode=block',
  },
];

export default {
  async headers() {
    return [
      {
        source: '/(.*)',
        headers: securityHeaders,
      },
    ];
  },
};

이렇게 source: '/(.*)'로 전체 경로를 묶어두면, 신규 라우트가 추가될 때 별도로 헤더 작업을 신경 쓰지 않아도 된다. 누락 방지 측면에서 팀 전체에 훨씬 안전한 구조다.


팀에 미치는 영향과 코드리뷰 포인트

이 작업을 PR로 올렸을 때 팀원들한테 몇 가지 포인트를 같이 공유했다.

  • 배포 후 브라우저 DevTools → Network 탭에서 응답 헤더 직접 확인해볼 것. 설정이 실제로 적용됐는지 눈으로 보는 게 제일 빠르다.
  • 서드파티 위젯, 임베드, iframe 쓰는 곳 미리 파악해두기. X-Frame-Options: DENY나 CSP 정책이 걸리면 조용히 깨진다.
  • Permissions-Policy에서 필요한 API는 명시적으로 허용해야 한다. 기본적으로 다 막는 방향으로 가되, 실제 쓰는 기능은 빠뜨리지 말 것.
  • 보안 헤더는 securityheaders.com 같은 외부 스캐너로 검증하면 등급이 나온다. A 이상 목표로 잡는 게 좋다.

사실 이런 작업은 "기능"이 아니라서 PO나 기획 쪽에서 우선순위를 주기가 어렵다. 티도 안 나고, 당장 아무것도 바뀌지 않는 것처럼 보인다. 그래서 팀장 포지션에서 직접 챙기지 않으면 계속 미뤄지는 영역이다. 이번에 내가 먼저 손댄 이유가 그거다.

보안 헤더 하나 추가한다고 시스템이 완벽히 안전해지진 않는다. 그런데 공격자 입장에서는 이런 작은 방어막 하나하나가 공격 비용을 올린다. 레이어드 디펜스의 기초 공사라고 생각하면 된다.

다음 스텝은 CSP 리포트 수집 결과 보고 본격적인 정책 확정하는 것.


🛒 이 글과 어울리는 추천 상품

*위 링크는 쿠팡파트너스 활동의 일환이며, 일정액의 수수료를 제공받을 수 있습니다.

댓글 0

첫 댓글 달아줘.