๋ฐ˜์‘ํ˜•

๋ฆฌ์•กํŠธ ํ”„๋กœ์ ํŠธ์—์„œ CSS ๋ฐฉ์‹, dangerouslySetInnerHTML, ๋ณ„๋„์˜ ์ปดํฌ๋„ŒํŠธ ๋ฐฉ์‹ ๋“ฑ์œผ๋กœ ๋ฌธ์ž์—ด ๋ฐ์ดํ„ฐ์˜ ์ค„๋ฐ”๊ฟˆ ์ฒ˜๋ฆฌ๋ฅผ ๊ตฌํ˜„ ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

์ตœ์ข…์ ์œผ๋กœ ๊ถŒ์žฅํ•˜๋Š” ๋ฐฉ์‹์€ ๋ณ„๋„์˜ ์ปดํฌ๋„ŒํŠธ ๋ฐฉ์‹์ด๋‹ค. ์ด ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ด์œ ๋กœ ๊ฐ€์žฅ ์ ํ•ฉํ•˜๋‹ค:

  • ์žฌ์‚ฌ์šฉ์„ฑ: ๊ฐ™์€ ์ค„๋ฐ”๊ฟˆ ๋กœ์ง์„ ์—ฌ๋Ÿฌ ์ปดํฌ๋„ŒํŠธ์—์„œ ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์œ ์ง€๋ณด์ˆ˜: ๋ฉ”์‹œ์ง€ ํฌ๋งคํŒ… ๋กœ์ง์„ ํ•œ ๊ณณ์—์„œ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์–ด, ๋ณ€๊ฒฝ์‚ฌํ•ญ์ด ์žˆ์„ ๋•Œ ๋ชจ๋“  ์ปดํฌ๋„ŒํŠธ์— ์ผ๊ด€๋˜๊ฒŒ ์ ์šฉํ•˜๊ธฐ ์‰ฝ๋‹ค.
  • ํ™•์žฅ์„ฑ: ์ถ”ํ›„์— ๋ฉ”์‹œ์ง€ ์ฒ˜๋ฆฌ ๋กœ์ง์— ์ถ”๊ฐ€์ ์ธ ๋ณ€ํ™˜ ๋กœ์ง(์˜ˆ: ํŠน์ • ๋‹จ์–ด์— ์Šคํƒ€์ผ ์ ์šฉ)์ด ํ•„์š”ํ•  ๋•Œ ์ด ์ปดํฌ๋„ŒํŠธ๋ฅผ ํ™•์žฅํ•˜๊ธฐ ์‰ฝ๋‹ค.

์ด ๋ฐฉ๋ฒ•์€ ๋ณด์•ˆ์ ์œผ๋กœ ์•ˆ์ „ํ•˜๋ฉฐ, dangerouslySetInnerHTML์˜ ๋ณด์•ˆ ์ทจ์•ฝ์  ์—†์ด ์œ ์‚ฌํ•œ ์œ ์—ฐ์„ฑ์„ ์ œ๊ณตํ•œ๋‹ค. CSS ๋ฐฉ์‹์€ ๋งค์šฐ ๋‹จ์ˆœํ•˜์ง€๋งŒ, ๋ฉ”์‹œ์ง€ ์ฒ˜๋ฆฌ์— ์žˆ์–ด ๋‹ค๋ฅธ HTML ํƒœ๊ทธ ์ ์šฉ์ด ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค๋Š” ๋‹จ์ ์ด ์žˆ์–ด ๋ณต์žกํ•œ ์š”๊ตฌ์‚ฌํ•ญ์—๋Š” ์ ํ•ฉํ•˜์ง€ ์•Š๋‹ค.

1. CSS ์‚ฌ์šฉ - ๊ฐ€์žฅ ๊ฐ„๋‹จ

๊ฐ€์žฅ ๊ฐ„๋‹จํ•˜๊ณ  ์ง๊ด€์ ์ธ ๋ฐฉ๋ฒ•์ด๋‹ค. CSS์˜ white-space: pre-line; ์†์„ฑ์„ ์‚ฌ์šฉํ•ด ๋ฌธ์ž์—ด ๋‚ด์˜ ์ค„๋ฐ”๊ฟˆ(\n)์„ HTML์—์„œ ์ธ์‹ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•œ๋‹ค.

interface Props {
  message: string;
}

export default function Intro({ message }: Props) {
  return (
    <div style={{ whiteSpace: 'pre-line' }}>
      {message}
    </div>
  );
}

 

2. dangerouslySetInnerHTML ๋ฐฉ์‹ - ๊ถŒ์žฅ๋˜์ง€ ์•Š์Œ

dangerouslySetInnerHTML๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ HTML๋กœ ๋ฉ”์‹œ์ง€๋ฅผ ์ง์ ‘ ๋ Œ๋”๋งํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค. XSS ๊ณต๊ฒฉ์— ์ทจ์•ฝํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ์‚ฌ์šฉํ•  ๋•Œ ์ฃผ์˜๊ฐ€ ํ•„์š”ํ•˜๋‹ค.

interface Props {
  message: string;
}

export default function Intro({ message }: Props) {
  const formattedMessage = { __html: message.replace(/\n/g, '<br>') };
  return (
    <div dangerouslySetInnerHTML={formattedMessage} />
  );
}

3. ๋ณ„๋„์˜ ์ปดํฌ๋„ŒํŠธ ๋ฐฉ์‹ โญ๊ถŒ์žฅ

๋ฉ”์‹œ์ง€ ๋‚ด์˜ \n์„ <br /> ํƒœ๊ทธ๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ ๋ Œ๋”๋งํ•˜๋Š” ๋ณ„๋„์˜ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค. ๊ฐ€์žฅ ์œ ์—ฐํ•˜๊ณ  ์žฌ์‚ฌ์šฉ์„ฑ์ด ๋†’์€ ๋ฐฉ๋ฒ•์ด๋‹ค.

interface Props {
  message: string;
}

export default function Intro({ message }: Props) {
  const formattedMessage = message.split('\n').map((part, index, array) => (
    <React.Fragment key={index}>
      {part}{index !== array.length - 1 && <br />}
    </React.Fragment>
  ));

  return (
    <div>
      {formattedMessage}
    </div>
  );
}
๋ฐ˜์‘ํ˜•

+ Recent posts