🕵️♀️금방 리액트에서 HTML태그가 먹히지 않은 문제를 [문제해결]리액트에서 줄바꿈하기
해결하고왔다.. 왜 <br/>
태그가 먹히지 않는지 궁금해졌다.
React 메뉴얼의 "Dangerously Set innerHTML" ( URL : https://reactjs.org/docs/dom-elements.html )페이지에 따르면 React에서는 cross-site scripting(XSS)
공격을 막기 위하여, 렌더링 메소드 내부에서 html태그
가 담겨있는 string
형태를 렌더링하면, 태그가 먹히지 않고 문자열 그대로 렌더링되게 된다.
ex)
class App extends React.Component {
render() {
let codes = "<b>Will This Work?</b>";
return (
<div>
{codes}
</div>
);
}
};
ReactDOM.render(
<App></App>,
document.getElementById("root")
);
만약 위의 👆👆 코드에 문자열 태그가 적용된 상태로 렌더링이 된다면, 사용자가 임의로 웹페이지에 스크립트를 먹일수도 있게 돼서 취약점이 생길수도 있다.
React.js
에서는 이 취약점을 원천차단하기위해 그냥 무조건 텍스트형태로만 렌더링하게 설정이 되었다. (물론, 이 취약점은 클라이언트측이나 서버측에서 escape를 잘해서 보안에 신경을 쓰면 큰 문제는 발생하지 않을것이다.)
만약에 "난 문자열을 html 형태로 렌더링하게 되면 취약한걸 알고있고, 대비를 하고있으니 걱정하지마!" 라고 생각한다면 React가 경고했음에도 불구하고, 하는 방법이 있다. 바로 dangerouslySetInnerHTML
이다.
class App extends React.Component {
render() {
let codes = "<b>Will This Work?</b>";
return (
<div dangerouslySetInnerHTML={ {__html: codes} }>
</div>
);
}
};
ReactDOM.render(
<App></App>,
document.getElementById("root")
);
*<div dangerouslySetInnerHTML={ {__html: codes} }>
우리가 렌더링 해야되는 문자열이 특별한 HTML태그는 필요가 없고 <br/>
이 필요한 경우네는 어떻게 해야할까?
겨우 여러줄을 렌더링하고 싶을 뿐인데 서버측에서 html escape
를 구현하고 dangerouslySetInnerHTML
을 사용 할 필요가 있을까?
보통 여러줄의 문자열을 JSON
형태로 담을 때 줄바꿈을 위해 \n
을 사용한다. 하지만 이걸 그대로 렌더링하게되면 새로운 줄바꿈이 되는게 아니라 그냥 space
만 된다.
ex)
const txt = 'Joo\nSehyeon\nwww.nuyhes.com';
그리고 JavaScript
의 replace
기능을 사용하여 \n
을 <br/>
로 변환한다면? 될리가 없다..
ex)
class App extends React.Component {
render() {
let enters = "All\nI\nwant\nis\nenter";
return (
<div>
{enters}
<br/>
{enters.replace(/\n/g, '<br/>')}
</div>
);
}
};
ReactDOM.render(
<App></App>,
document.getElementById("root")
);
이런 상황에서, 윗 부분에서 알려준 dangerouslySetInnerHTML
를 써도 되겠지만 다른 방법이 있다.
방법 1
{
data.split('\n').map( line => {
return (<span>{line}<br/></span>)
})
}
이런식으로 문자열을 \n
으로 split
하면 각 line이 있는 배열이 생성됨 그 배열을 사용하여 매핑 기능을 통하여 컴포넌트 배열을 새로 생성후 렌더링하면 해결된다.
class App extends React.Component {
render() {
let data = "Try\nenter\nenter\nenter";
return (
<div>
<p>Won't work:</p>
{data.replace(/\n/g, '<br/>')}
<p>This works</p>
{
data.split('\n').map( line => {
return (<span>{line}<br/></span>)
})
}
</div>
);
}
};
ReactDOM.render(
<App></App>,
document.getElementById("root")
);
방법 2
아까 사용한 해결방법인데 단순하게 줄바꿈만 간단하게 쓰고싶어 이방법을 택했는데, 차이점은 모르겠다.
string = '벨\n로그'
<div>{string}</div>
을 렌더링하고 나서 CSS
에서 white-space: pre-wrap
을 하면 줄바꿈이 일어난다.
[출처] https://velopert.com/1896 [React.js] Tip: string 형태의 html을 렌더링하기, newline
(\n)
을 BR 태그로 변환하기
출처를 보고 참고하여 작성하면서 공부가 됐습니다. 감사합니다.