Blog

React는 왜 기본적으로 XSS에 강할까?


서론#

React를 사용하면 XSS 문제가 상대적으로 덜 보이는 경우가 많다.
이 때문에 "React는 XSS를 알아서 막아준다"는 인식이 생기곤 한다.

하지만 정확히 말하면, React는 XSS를 자동으로 제거하는 프레임워크가 아니다.
대신, 위험한 렌더링 방식을 기본에서 배제하는 구조를 가지고 있다.

이 글에서는 React가 왜 기본적으로 XSS에 강해 보이는지,
그리고 언제 다시 취약해질 수 있는지를 정리한다.

XSS가 발생하는 핵심 조건#

XSS는 사용자의 입력이 의도치 않게 코드로 해석될 때 발생한다.

대부분의 경우 흐름은 단순하다.

  1. 외부 입력을 받는다
  2. 그 값을 화면에 출력한다
  3. 출력 과정에서 브라우저가 이를 스크립트로 해석한다.

즉, 문제의 핵심은 "입력 > 출력"이 아니라,
출력 시점에 해당 값이 어떤 방식으로 해석되느냐다.

React가 안전해 보이는 이유#

React에서 XSS가 상대적으로 덜 보이는 이유는
기본 렌더링 방식이 이 위험 지점을 피하도록 설계되어 있기 때문이다.

1. JSX는 문자열을 자동으로 텍스트로 처리한다#

JSX에서 문자열을 렌더링하면,
해당 값을 HTML로 해석되지 않고 텍스트로 처리된다.

이는 브라우저의 보안 기능이 아니라,
React가 의도적으로 선택한 렌더링 방식이다.

이 덕분에 사용자 입력이 그대로 화면에 노출되더라도,
문자열 기반의 XSS는 기본적으로 발생하지 않는다.

React에서 XSS가 다시 생기는 대표 3가지 지점#

React의 기본 보호는 항상 유지되지 않는다.
특정 상황에서는 이 보호가 사라진다.

1. HTML 주입이 필요한 순간#

외부 콘텐츠나 이미 HTML 형태로 존재하는 데이터를
화면에 그대로 렌더링해야 하는 경우가 있다.

이 순간부터 React의 기본 보호는 적용되지 않는다.
문자열이 아닌 HTML을 그대로 DOM에 넣는 선택을 했기 때문이다.

React에서는 이러한 HTML 직접 주입을 위해
dangerouslySetInnerHTML이라는 API를 명시적으로 제공한다.

<div
  dangerouslySetInnerHTML={{
    __html: userInput,
  }}
/>

이 경우 userInput 내부의 스크립트나 이벤트 핸들러는
브라우저에 의해 그대로 해석된다.

이 API는 이름 그대로,
React의 기본적인 XSS 보호 흐름을 벗어나는 선택임을
개발자에게 분명히 인식시키기 위해 설계되었다.

이 경우의 위험성은 React의 문제가 아니라,
HTML을 직접 주입하는 방식 자체의 특성에 가깝다.

2. 속성 기반 주입 (href, src 등)#

JSX에서 문자열이 안전하게 처리되더라도,
모든 속성이 동일하게 안전한 것은 아니다.

특히 href, src와 같은 속성은
브라우저의 동작과 직접적으로 연결된다.

// 악의적인 입력 예시
const link = "javascript:alert('XSS')";
<a href={link}>클릭</a>; // 실행됨

이런 경우에는 단순한 문자열 출력과 달리,
브라우저가 해당 값을 실행 가능한 동작으로 해석할 수 있다.

3. React 밖에서의 DOM 조작#

React는 선언적인 렌더링을 전제로 설계되었다.
하지만 직접 DOM API를 사용하면 이 전제는 깨진다.

innerHTML과 같은 DOM 조작은
React의 보호 영역 밖에서 이루어진다.

React를 사용하고 있더라도,
이런 방식은 일반적인 DOM 기반 XSS와 다르지 않다.

그럼 React만 쓰면 안전한가?#

아니다.

React는 XSS를 자동으로 제거하지 않는다.
다만, 기본적인 사용 흐름이 위험한 패턴은 피하도록 설계되어있다.

React의 기본 흐름을 따르면 비교적 안전하지만,
그 흐름을 벗어나는 순간 책임은 다시 개발자에게 돌아온다.

정리#

  • XSS는 출력 시점에 값이 어떻게 해석되는지에 달려 있다
  • React는 기본 렌더링에서 문자열을 텍스트로 처리한다
  • 이로 인해 문자열 기반 XSS가 기본적으로 줄어든다
  • HTML 주입, 속성 기반 주입, 직접 DOM 조작에서는 다시 위험해진다
  • React는 "안전함"을 보장하지 않고, "안전한 기본값"을 제공한다

참고#

5