[궁금] 리액트 string 형태의 html을 렌더링(줄바꿈 <br/>태그 문제해결)

JooSehyun·2023년 2월 20일
0

[궁금증]

목록 보기
4/4
post-thumbnail

궁금

🕵️‍♀️금방 리액트에서 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이다.


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';

그리고 JavaScriptreplace기능을 사용하여 \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 태그로 변환하기

출처를 보고 참고하여 작성하면서 공부가 됐습니다. 감사합니다.

0개의 댓글