Blog
React는 왜 기본적으로 XSS에 강할까?
서론#
React를 사용하면 XSS 문제가 상대적으로 덜 보이는 경우가 많다.
이 때문에 "React는 XSS를 알아서 막아준다"는 인식이 생기곤 한다.
하지만 정확히 말하면, React는 XSS를 자동으로 제거하는 프레임워크가 아니다.
대신, 위험한 렌더링 방식을 기본에서 배제하는 구조를 가지고 있다.
이 글에서는 React가 왜 기본적으로 XSS에 강해 보이는지,
그리고 언제 다시 취약해질 수 있는지를 정리한다.
XSS가 발생하는 핵심 조건#
XSS는 사용자의 입력이 의도치 않게 코드로 해석될 때 발생한다.
대부분의 경우 흐름은 단순하다.
- 외부 입력을 받는다
- 그 값을 화면에 출력한다
- 출력 과정에서 브라우저가 이를 스크립트로 해석한다.
즉, 문제의 핵심은 "입력 > 출력"이 아니라,
출력 시점에 해당 값이 어떤 방식으로 해석되느냐다.
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개
Next.js에서 보안 헤더를 설정한다는 것의 의미와 한계
Next.js에서 설정할 수 있는 보안 헤더들의 역할과 한계를 정리합니다. 보안 헤더가 무엇을 막아주지 않는지, 프레임워크와 개발자의 책임 경계를 중심으로 설명합니다.
NEXT_PUBLIC_ 환경변수는 왜 env인데 클라이언트에 노출될까
NEXT_PUBLIC_ 환경변수가 왜 클라이언트 번들에 포함되는지, env는 언제 비밀이 되고 언제 설정값이 되는지 Next.js 빌드 구조와 보안 기준으로 정리합니다.
innerHTML을 사용할 때 조심해야 하는 이유
innerHTML이 왜 보안상 주의가 필요한 API인지, XSS 취약점과 안전한 대체 방법(textContent, sanitize)을 통해 정리합니다.
env는 보안인가? 많은 개발자들이 착각하는 이유
env는 보안 기능일까? 이 글에서는 env의 역할과 한계, NEXT_PUBLIC_ 환경 변수의 노출 특성, 프론트엔드에서 노출돼도 되는 값의 기준을 정리합니다.
XSS란 무엇인가: 브라우저에서 실행되는 공격
XSS(Cross-Site Scripting)는 서버가 아닌 사용자의 브라우저를 공격하는 웹 보안 취약점입니다. 이 글에서는 XSS의 개념, 발생 원인, 주요 유형과 위험성을 정리합니다.