본문 바로가기
React

React 개발자가 반드시 알아야 하는 보안 가이드 (XSS, JWT, CSRF, CSP)

by Rogan_Kim 2026. 7. 10.
728x90

React는 대표적인 프론트엔드 라이브러리 중 하나이며, 기본적으로 XSS(Cross Site Scripting)와 같은 대표적인 웹 취약점을 방어하도록 설계되어 있습니다. 그래서 많은 개발자가 "React를 사용하면 보안도 어느 정도 해결된다."라고 생각하기도 합니다.

하지만 실제 서비스에서는 이야기가 조금 다릅니다.

사용자가 작성한 HTML을 출력하거나, JWT를 LocalStorage에 저장하거나, 서버에서 입력값 검증을 하지 않는 순간 React의 기본 보호 기능만으로는 애플리케이션을 안전하게 지킬 수 없습니다.

이번 글에서는 React 프로젝트를 운영하면서 반드시 알고 있어야 하는 보안 요소들을 정리해 보겠습니다.


1. React는 왜 XSS 공격에 비교적 안전할까?

대표적인 웹 공격 중 하나가 XSS(Cross Site Scripting)입니다.

공격자는 댓글이나 게시글 등에 JavaScript 코드를 삽입하여 다른 사용자의 브라우저에서 실행시키려고 합니다.

예를 들어 사용자가 아래와 같은 값을 입력했다고 가정해 보겠습니다.

<script>alert("XSS")</script>

React는 JSX에서 이러한 문자열을 그대로 HTML로 해석하지 않습니다.

function Comment({ text }) {
  return <p>{text}</p>;
}

React는 <, > 같은 특수문자를 자동으로 Escape 처리하기 때문에 브라우저는 이를 JavaScript가 아니라 단순 문자열로 출력합니다.

즉, 일반적인 JSX 렌더링만 사용한다면 대부분의 XSS 공격은 자동으로 차단됩니다.

하지만 여기에는 중요한 예외가 있습니다.


2. dangerouslySetInnerHTML은 React의 보호막을 제거한다

React에서 가장 위험한 API 중 하나가 바로 dangerouslySetInnerHTML입니다.

이 API는 이름 그대로 HTML을 브라우저에 그대로 삽입합니다.

예를 들어 CMS에서 작성한 글이나 Markdown을 HTML 형태로 출력해야 하는 경우 자주 사용됩니다.

문제는 사용자가 입력한 HTML에 아래와 같은 코드가 포함될 수 있다는 것입니다.

<img src="" onerror="alert(document.cookie)">

이 경우 React는 더 이상 보호해 주지 않습니다.

브라우저가 HTML을 직접 해석하면서 악성 스크립트가 실행될 수 있습니다.


3. HTML을 출력해야 한다면 DOMPurify를 사용하자

실무에서는 HTML 출력이 필요한 경우가 생각보다 많습니다.

  • 게시판
  • CMS
  • Markdown Viewer
  • 블로그
  • 이메일 본문

이럴 때 가장 많이 사용하는 라이브러리가 DOMPurify입니다.

DOMPurify는 HTML의 구조는 유지하면서 다음과 같은 위험 요소를 제거합니다.

  • <script>
  • onClick, onError 같은 이벤트 속성
  • javascript: URL
  • 위험한 태그와 속성

즉,

HTML은 살리고, 악성 코드만 제거하는 역할을 합니다.

가능하다면 dangerouslySetInnerHTML 자체를 사용하지 않는 것이 가장 좋으며, 반드시 사용해야 한다면 DOMPurify 같은 Sanitizer를 함께 사용하는 것이 안전합니다.


4. JWT를 LocalStorage에 저장하면 안 되는 이유

React 프로젝트를 보면 아직도 아래와 같은 코드가 자주 등장합니다.

localStorage.setItem("token", token);

처음에는 편리합니다.

새로고침해도 유지되고 구현도 간단합니다.

하지만 XSS 공격이 발생하는 순간 이야기가 달라집니다.

공격자는 브라우저에서 다음과 같이 토큰을 읽을 수 있습니다.

localStorage.getItem("token");

토큰이 탈취되면 로그인한 사용자 권한을 그대로 사용할 수도 있습니다.

그래서 최근에는 HttpOnly Cookie를 사용하는 방식이 권장됩니다.

HttpOnly Cookie는 JavaScript에서 접근 자체가 불가능하기 때문에 XSS를 통한 토큰 탈취를 크게 줄일 수 있습니다.


5. HttpOnly Cookie를 사용해도 끝이 아니다

HttpOnly Cookie는 XSS에는 강하지만 또 다른 공격인 CSRF(Cross Site Request Forgery)를 고려해야 합니다.

브라우저는 쿠키를 자동으로 전송하기 때문에 공격자가 사용자의 브라우저를 이용해 원하지 않는 요청을 보낼 수도 있습니다.

이를 방지하기 위해서는 다음과 같은 설정을 함께 사용하는 것이 좋습니다.

  • HttpOnly
  • Secure
  • SameSite
  • CSRF Token

특히 SameSite=Strict 옵션은 다른 사이트에서 들어오는 요청에 쿠키를 포함하지 않도록 도와주는 중요한 설정입니다.


6. 클라이언트 검증은 UX일 뿐 보안이 아니다

많은 개발자가 Form Validation을 구현하면서 다음과 같은 검증을 작성합니다.

  • required
  • minLength
  • email 형식 검사

사용자 경험을 위해서는 반드시 필요합니다.

하지만 이것만으로는 보안을 보장할 수 없습니다.

공격자는 브라우저를 사용하지 않고 API를 직접 호출할 수 있기 때문입니다.

즉,

클라이언트 검증은 UX를 위한 것이고,

보안은 반드시 서버에서 다시 검증해야 합니다.


7. Zod를 이용한 서버 검증

최근 React와 Next.js에서는 Zod를 많이 사용합니다.

Zod는 입력 데이터의 타입과 형식을 서버에서 안전하게 검증할 수 있도록 도와주는 라이브러리입니다.

예를 들어

  • 이메일 형식
  • 숫자인지 여부
  • 최소값
  • 최대값

등을 서버에서 다시 검사할 수 있습니다.

클라이언트가 어떤 데이터를 보내더라도 서버는 항상 입력을 의심해야 합니다.


8. SQL Injection도 여전히 조심해야 한다

React가 서버 컴포넌트나 Server Action을 많이 사용하게 되면서 프론트엔드 개발자도 SQL Injection을 이해할 필요가 있습니다.

가장 중요한 원칙은 하나입니다.

사용자 입력을 SQL 문자열에 직접 이어 붙이지 않는 것.

대신 Prepared Statement 또는 Parameterized Query를 사용하면 입력값을 SQL 명령이 아닌 데이터로 처리하여 대부분의 SQL Injection을 예방할 수 있습니다.


9. CSP(Content Security Policy)는 마지막 방어선이다

CSP는 브라우저에게

"어떤 리소스만 실행해도 되는지"

를 알려주는 보안 정책입니다.

예를 들어

  • 외부 Script 차단
  • iframe 삽입 차단
  • Flash 같은 플러그인 차단

등을 설정할 수 있습니다.

설령 XSS가 발생하더라도 CSP가 악성 스크립트 실행을 막아주는 마지막 방어막 역할을 합니다.

운영 환경에서는 먼저 Report-Only 모드로 테스트한 뒤 실제 정책을 적용하는 것이 좋습니다.


React 프로젝트 보안 체크리스트

프로젝트를 시작할 때 아래 항목만 확인해도 대부분의 기본적인 보안 실수를 예방할 수 있습니다.

  • JSX 기본 렌더링 사용하기
  • dangerouslySetInnerHTML 최소화하기
  • HTML 출력 시 DOMPurify 적용하기
  • JWT는 LocalStorage보다 HttpOnly Cookie 사용하기
  • SameSite와 CSRF Token 함께 적용하기
  • 서버에서 입력값 다시 검증하기
  • SQL은 Parameterized Query 사용하기
  • CSP 적용하기
  • HTTPS 사용하기
  • npm 패키지 취약점(npm audit, pnpm audit) 정기적으로 확인하기
  • 프론트엔드 환경 변수에 Secret Key 저장하지 않기

마무리

React는 기본적으로 XSS를 방어하도록 설계되어 있지만, 그것만으로 애플리케이션이 안전해지는 것은 아닙니다.

실제 서비스에서는 HTML 렌더링, 인증 방식, 서버 검증, 브라우저 정책까지 함께 고려해야 비로소 안전한 애플리케이션을 만들 수 있습니다.

특히 최근 Next.js의 Server Action, React Server Components처럼 프론트엔드 개발자가 서버 영역까지 담당하는 경우가 많아진 만큼, 이제는 프론트엔드 개발자도 보안을 기본 역량으로 갖춰야 하는 시대가 되었습니다.

React의 기본 보호 기능을 신뢰하되, 그 한계를 이해하고 여러 보안 계층을 함께 적용하는 것이 안전한 서비스를 만드는 가장 좋은 방법입니다.

728x90

댓글