본문 바로가기
개발

[Security] 프론트엔드 보안 가이드: XSS와 CSRF 완벽 방어하기

by 돌미나리는야생미나리 2026. 5. 1.

웹 애플리케이션의 복잡도가 높아지면서 프론트엔드 보안의 중요성도 그 어느 때보다 커졌습니다. 보안 사고는 서비스의 신뢰도를 한순간에 무너뜨릴 뿐만 아니라 사용자의 개인정보 유출로 직결됩니다. 오늘은 프론트엔드 개발자가 반드시 알고 있어야 할 두 가지 핵심 공격 기법인 XSSCSRF의 원리를 파악하고, 이를 방어하기 위한 실무 전략을 알아보겠습니다.


1. XSS (Cross-Site Scripting): 내 사이트에 남이 짠 코드가?

XSS는 공격자가 악성 스크립트를 웹 페이지에 삽입하여, 다른 사용자의 브라우저에서 해당 스크립트가 실행되게 만드는 공격입니다.

1.1 공격의 위험성

스크립트가 실행되면 공격자는 사용자의 세션 쿠키를 가로채거나, 사용자를 대신해 게시글을 작성하고, 민감한 정보를 외부 서버로 전송할 수 있습니다.

1.2 프론트엔드 방어 전략

React와 같은 최신 프레임워크는 기본적으로 렌더링 시 데이터를 이스케이프(Escape) 처리하여 XSS를 방지합니다. 하지만 다음 상황에서는 위험에 노출됩니다.

  • dangerouslySetInnerHTML 사용 지양: HTML을 직접 렌더링해야 한다면 반드시 dompurify 같은 라이브러리로 살균(Sanitize) 과정을 거쳐야 합니다.
  • 사용자 입력값 검증: URL 쿼리 스트링이나 폼 입력값을 다룰 때 항상 유효성을 검사하세요.
  • CSP(Content Security Policy) 설정: 브라우저에게 "이 사이트에서 실행할 수 있는 스크립트 출처는 여기뿐이야"라고 알려주는 보안 헤더를 설정하세요.

2. CSRF (Cross-Site Request Forgery): 내가 안 보낸 요청이 서버로?

CSRF는 사용자가 자신의 의지와 무관하게 공격자가 의도한 행위(비밀번호 변경, 결제 등)를 특정 웹사이트에 요청하게 만드는 공격입니다. 사용자가 로그인되어 있는 브라우저의 '쿠키'를 이용하는 것이 핵심입니다.

2.1 공격 원리

사용자가 은행 사이트에 로그인된 상태에서 공격자가 만든 악성 사이트에 접속하면, 그 사이트 내부의 숨겨진 폼이 은행 서버로 '송금 요청'을 보냅니다. 브라우저는 은행 쿠키를 자동으로 함께 전송하므로, 서버는 사용자의 정상적인 요청으로 착각하게 됩니다.

2.2 프론트엔드 방어 전략

  • SameSite 쿠키 속성: 쿠키 설정 시 SameSite=Lax 또는 Strict를 사용하여 타 도메인에서의 쿠키 전송을 제한하세요.
  • CSRF 토큰: 서버에서 발급한 일회용 토큰을 요청 헤더에 담아 보내 서버가 검증하게 하세요.
  • Custom Header 사용: X-Requested-With 같은 커스텀 헤더를 요구하면 브라우저의 기본 폼 제출로는 요청을 보낼 수 없어 방어에 유리합니다.

3. 안전한 토큰 관리: LocalStorage vs Cookie

많은 개발자가 고민하는 주제입니다. "JWT(JSON Web Token)를 어디에 저장해야 할까요?"

3.1 LocalStorage (XSS에 취약)

  • 장점: 사용이 간편하고 CSRF 공격으로부터 자유롭습니다.
  • 단점: 자바스크립트로 접근이 가능하므로 XSS 공격에 노출되면 토큰이 그대로 탈취됩니다.

3.2 HttpOnly Cookie (CSRF에 취약)

  • 장점: 자바스크립트 접근이 불가능하여 XSS로부터 안전합니다.
  • 단점: 브라우저가 자동으로 요청에 포함하므로 CSRF 공격 대상이 됩니다.

최선의 선택: HttpOnly 및 Secure 속성이 적용된 쿠키를 사용하되, SameSite 속성CSRF 토큰을 병행하여 CSRF 공격을 방어하는 것이 가장 견고한 보안 모델로 평가받습니다.


4. HTTPS와 보안 헤더 설정

네트워크 레벨에서의 보안도 필수입니다.

  • HSTS (HTTP Strict Transport Security): 브라우저가 해당 사이트에 항상 HTTPS로만 접속하도록 강제합니다.
  • X-Frame-Options: 내 사이트가 다른 사이트의 <iframe> 안에 들어가는 것을 막아 클릭재킹(Clickjacking) 공격을 방어합니다.

5. 결론: 보안은 체크리스트가 아닌 프로세스입니다

프론트엔드 보안은 단 하나의 라이브러리 설치로 끝나지 않습니다. 코드를 짤 때마다 "이 입력값이 안전한가?", "이 요청이 신뢰할 수 있는가?"를 끊임없이 질문해야 합니다.

오늘의 요약:

  1. XSS 방어: 데이터 이스케이프를 믿되, HTML 직접 삽입 시에는 반드시 살균하세요.
  2. CSRF 방어: SameSite 쿠키와 커스텀 헤더/토큰을 활용하세요.
  3. 저장소 선택: 민감한 정보는 자바스크립트가 만질 수 없는 곳에 두세요.
  4. CSP 도입: 보안 헤더를 통해 브라우저의 방어 능력을 극대화하세요.