React 매뉴얼의 “Dangerously Set innerHTML” 페이지에 따르면, React에서는 cross-site scripting (XSS) 공격을 막기 위하여, 렌더링 메소드 내부에서 html 태그가 담겨있는 string 형태를 렌더링하면, 태그가 안 먹히고 문자열 그대로 렌더링되게 됩니다:
만약에 저 문자열에 태그가 적용된 상태로 렌더링이 된다면, 사용자가 임의로 웹페이지에 스크립트를 먹일수도있게되서 취약점이 생기겠지요.
React.js 에선 이 취약점을 원천차단하기위하여 그냥 무조건 텍스트형태로만 렌더링하게 설정되었습니다. (물론, 이 취약점은 클라이언트측이나 서버측에서 escape 를 잘해서 보안에 신경을 쓰면 큰 문제는 발생하지 않을것입니다)
만약에 여러분이 “난 문자열을 html 형태로 렌더링하게되면 취약한걸 알고있어. 그리고 여기에 난 대비하고 있으니까 걱정 마!” 라고 생각하신다면, React가 경고했음에도 불구하고, 쌩까고 하는 방법이 있습니다. 바로 ‘dangerouslySetInnerHTML’ 인데요.
사용법은 간단합니다. 아래 코드를 살펴보세요:
한번 이러한 상황에 대하여 생각해봅시다..
우리가 렌더링 해야되는 문자열이, 뭐 특별한 HTML 태그는 필요가 없는데 newline ( <BR/> ) 이 필요 할 경우엔 어떻게 해야할까요?
겨우 여러줄을 렌더링하고싶을 뿐인데 서버측에서 html escape 를 구현하고 dangerouslySetInnerHTML 를 사용 할 필요가 있을까요?
우선, 보통 여러줄의 문자열을 JSON 형태로 담을 땐 newline 을 위하여 \n 문자를 사용하죠?
이걸 그대로 렌더링하면.. 새로운 줄이 생기는게 아니라 그냥 space 만 있을 뿐입니다.
그리고 아무생각없이.. JavaScript 의 replace 기능을 사용하여 \n 을 <BR/> 로 변환한다면? 될리가없죠.
이런 상황에서, 윗 부분에서 알려드린 dangerouslySetInnerHTML 를 써도 되겠지만 더 괜찮은 트릭이 있습니다.
React.js 강좌 6-1편에서 다뤘던 컴포넌트 Mapping 을 통하여 이 문제를 아주 쉽게 해결 할 수 있습니다.
{ data.split('\n').map( line => { return (<span>{line}<br/></span>) }) }
이런식으로, 문자열을 ‘\n’ 으로 split 하면 각 line 이 있는 배열이 생성되겠죠?
그 배열을 사용하여 매핑 기능을 통하여 컴포넌트 배열을 새로 생성후 렌더링하면 해결됩니다.