๐Ÿ‘‰ react-quill

์ด ์ „์— ํฌ์ŠคํŠธ์—์„œ react-quill์„ ์ด์šฉํ•ด์„œ ๊ฒŒ์‹œ๊ธ€์„ ์ž‘์„ฑํ–ˆ๋Š”๋ฐ, ํ•ด๋‹น ๊ฒŒ์‹œ๊ธ€์˜ ๋‚ด์šฉ์„ ๋ฐฑ์—”๋“œ์— ์ „๋‹ฌํ•ด์ฃผ๊ณ , ๊ทธ ๊ฐ’์„ ๋ฐ›์•„์˜ค๋Š” ๊ณผ์ •์—์„œ error๊ฐ€ ๋ฐœ์ƒํ•ด์„œ ๋ฌธ์ œ์ ์„ ์ฐพ๊ณ  ํ•ด๊ฒฐํ•˜๊ณ ์ž ํ•œ๋‹ค.

๐Ÿ‘‰ dangerouslySetInnerHTML

react-quill์—์„œ ๋ฐฑ์—”๋“œ๋กœ ๋„˜๊ฒจ์ค„ ๋•Œ </> ํƒœ๊ทธ ํ˜•ํƒœ๋กœ ๋„˜๊ฒจ์ฃผ๋Š”๋ฐ, ๋ฐ›์„ ๋•Œ๋„ ํƒœ๊ทธ์— ๋‹ด๊ฒจ์ ธ์„œ ๋“ค์–ด์™”๋‹ค. ์‚ฌ์‹ค ์ด error๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๊ฐ€์žฅ ์ข‹์€ ๋ฐฉ๋ฒ•์€ ๋ฐฑ์—”๋“œ ๋กœ์ง์„ ๋ฐ”๊ฟ”์„œ ํƒœ๊ทธ๊ฐ€ ์žˆ๋Š” ์ƒํƒœ๋กœ api๋ฅผ ๋ณด๋‚ด์ฃผ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ํƒœ๊ทธ๋ฅผ ๋ฒ—๊ธด ์ƒํƒœ๋กœ ๊ฐ’์„ ์ „๋‹ฌํ•ด ์ฃผ๋Š”๊ฒŒ ๊ฐ€์žฅ ์ข‹๋‹ค๊ณ  ํ•œ๋‹ค. ๊ทธ๋Ÿฐ ์ƒํ™ฉ์ด ์•ˆ๋‚˜์˜จ๋‹ค๋ฉด ๋‚˜์ฒ˜๋Ÿผ...

<div dangerouslySetInnerHTML={{ __html: isData.body }} />

์ฒ˜์Œ์—๋Š” ์ด๋ ‡๊ฒŒ divํƒœ๊ทธ๋กœ ์ด๋ฃจ์–ด์ง„ ๊ฐ’์— isData.body์ฆ‰, ๋ณธ๋ฌธ ๋‚ด์šฉ๊ฐ’์„ ๋ฐ›์•˜๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๊ณ  ๋ Œ๋”๋ง์„ ํ•ด๋ณด๋‹ˆ ๋„์šฉ ์—๋Ÿฌ๊ฐ€ ๋งˆ๊ตฌ๋งˆ๊ตฌ ๋œจ๋Š”๊ฒƒ์ด๋‹ค.

ํ•ด๋‹น ์—๋Ÿฌ์—์„œ Hydration์ด๋ผ๊ณ  ๋œฌ๋Š”๋ฐ Hydration์€ ์ž์„ธํ•˜๊ณ  ์ •ํ™•ํ•œ ๋‚ด์šฉ์€ ์ง์ ‘ ์ฐพ์•„๋ณด๊ณ , ์‰ฝ๊ฒŒ ์ด์•ผ๊ธฐ ํ•˜์ž๋ฉด,
ssr์—์„œ ๊ฐ€์ƒdom์—์„œ ๋ Œ๋”๋ง๋œ ํŽ˜์ด์ง€์™€ javascript์ฝ”๋“œ๊ฐ€ ๋‹ด๊ฒจ์ ธ์„œ ์‹ค์ œdom์œ„์—์„œ ๋‹ค์‹œ ๋ Œ๋”๋ง๊ณผ์ •์„ ๊ฑฐ์น˜๋ฉด์„œ ๊ฐ’์„ ํ™•์ธํ•˜๋Š”๋ฐ,
window์— ๊ด€๋ จ๋œ ๊ฐ’์ด ๋“ค์–ด๊ฐ€๋ฉด, ๊ฐ€์ƒdom์—์„œ ๋ Œ๋”๋ง๋œ ๋‚ด์šฉ๊ณผ, ์‹ค์ œdom์—์„œ ๋ Œ๋”๋ง๋œ ๋‚ด์šฉ์ด ๋‹ฌ๋ผ์„œ ๋‚˜๋Š” ์˜ค๋ฅ˜๋ผ๊ณ  ํ•œ๋‹ค.

๐Ÿ‘‰ ํ•ด๊ฒฐ

ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์€ useEffect๋ฅผ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜, next/dynamic์„ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์ธ๋ฐ,
next/dynamic์€ ์ด๋ฏธ react-quill์„ ์ž‘์„ฑํ•˜๋ฉด์„œ ์ ์–ด๋‘์—ˆ๋‹ค.

const QuillWrapper = dynamic(() => import('react-quill'), {
  ssr: false,
  loading: () => <p>Loading ...</p>,
});

๊ทผ๋ฐ ๋‚˜๋Š” ์ด๋ ‡๊ฒŒ ํ–ˆ๋Š”๋ฐ ์•ˆ๋˜๊ธธ๋ž˜ ์—๋ผ ๋ชจ๋ฅด๊ฒ ๋‹ค ํ•˜๊ณ , useEffect๋ฅผ ์‚ฌ์šฉํ•ด ๋ณด์•˜๋‹ค.

์ฒ˜์Œ์— useEffect์— ํƒœ๊ทธ๋ฅผ ์–ด๋–ป๊ฒŒ ํ•˜๋ฉด ๋‹ด์„ ์ˆ˜ ์žˆ์„๊นŒ ์ƒ๊ฐํ•˜๋‹ค๊ฐ€ ๊ทธ๋ƒฅ ๋‹จ์ˆœํ•˜๊ฒŒ boolean๊ฐ’์„ state๋กœ ์„ ์–ธํ•˜๊ณ  ์‚ฌ์šฉํ–ˆ๋‹ค.

const [getState, setState] = useState<boolean>(false);

  useEffect(() => { //๋งˆ์šดํŠธ์™€ ๋™์‹œ์— true๊ฐ’์œผ๋กœ ๋ฐ”๊ฟ”์„œ ssr๋ฌธ์ œ ํ•ด๊ฒฐ!
    setState(true);
  }, []);

...

return ({getState && <div dangerouslySetInnerHTML={{ __html: isData.body }} />});

์ด๋Ÿฐ์‹์œผ๋กœ ์‚ฌ์šฉํ•˜๋‹ˆ๊น ์—๋Ÿฌ๊ฐ€ ์‚ฌ๋ผ์กŒ๋‹ค!

๐Ÿ‘‰ ์ถ”๊ฐ€์ ์ธ ์‚ฌํ•ญ

HTML๊ณผ ํ•จ๊ป˜ ๋ณด๋‚ด๋Š” ๊ฒƒ์ด๊ธฐ์— ํ„ธ๋ฆด ์œ„ํ—˜์ด ์žˆ๋‹ค.
๊ทธ๋ž˜์„œ dompurify๋ฅผ ์‚ฌ์šฉํ•ด์„œ ํ„ธ๋ฆฌ๋Š”๊ฒƒ์„ ๋ฐฉ์ง€ํ–ˆ๋‹ค

profile
๋‚˜์˜ ๋‡Œ๋ฅผ Refactoring

0๊ฐœ์˜ ๋Œ“๊ธ€

Powered by GraphCDN, the GraphQL CDN