renderToString
renderToString
์ React ํธ๋ฆฌ๋ฅผ HTML ๋ฌธ์์ด๋ก ๋ ๋๋งํฉ๋๋ค.
const html = renderToString(reactNode)
๋ ํผ๋ฐ์ค
renderToString(reactNode)
์๋ฒ์์ renderToString
์ ์คํํ๋ฉด ์ฑ์ HTML๋ก ๋ ๋๋งํฉ๋๋ค.
import { renderToString } from 'react-dom/server';
const html = renderToString(<App />);
ํด๋ผ์ด์ธํธ์์ hydrateRoot
์ ํธ์ถํ๋ฉด ์๋ฒ์์ ์์ฑ๋ HTML์ ์ํธ์์ฉํ๊ฒ ๋ง๋ญ๋๋ค.
์๋์์ ๋ ๋ง์ ์์๋ฅผ ์ฐธ๊ณ ํ์ธ์.
๋งค๊ฐ๋ณ์
reactNode
: HTML๋ก ๋ ๋๋งํ React ๋ ธ๋์ ๋๋ค. ์๋ฅผ ๋ค์ด<App />
๊ณผ ๊ฐ์ JSX ๋ ธ๋์ ๋๋ค.
๋ฐํ
HTML ๋ฌธ์์ด.
์ฃผ์์ฌํญ
-
renderToString
๋ Suspense ์ง์์ ํ๊ณ๊ฐ ์์ต๋๋ค. ์ปดํฌ๋ํธ๊ฐ ์ค๋จ๋๋ค๋ฉดrenderToString
๋ ์ฆ์ ํด๋น ํด๋ฐฑ์ HTML๋ก ๋ณด๋ ๋๋ค. -
renderToString
์ ๋ธ๋ผ์ฐ์ ์์ ๋์ํ์ง๋ง, ํด๋ผ์ด์ธํธ ์ฝ๋์์ ์ฌ์ฉํ๋ ๊ฒ์ ๊ถ์ฅํ์ง ์์ต๋๋ค.
์ฌ์ฉ๋ฒ
React ํธ๋ฆฌ๋ฅผ HTML ๋ฌธ์์ด๋ก ๋ ๋๋งํ๊ธฐ
์๋ฒ ์๋ต๊ณผ ํจ๊ป ๋ณด๋ผ ์ ์๋ HTML ๋ฌธ์์ด๋ก ์ฑ์ ๋ ๋๋งํ๋ ค๋ฉด renderToString
์ ํธ์ถํ์ธ์:
import { renderToString } from 'react-dom/server';
// ๋ผ์ฐํธ ํธ๋ค๋ฌ ๊ตฌ๋ฌธ์ ๋ฐฑ์๋ ํ๋ ์์ํฌ์ ๋ฐ๋ผ ๋ค๋ฆ
๋๋ค
app.use('/', (request, response) => {
const html = renderToString(<App />);
response.send(html);
});
์ด๋ ๊ฒ ํ๋ฉด React ์ปดํฌ๋ํธ์ ์ด๊ธฐ ๋น๋ํํ HTML ์ถ๋ ฅ์ด ์์ฑ๋ฉ๋๋ค. ํด๋ผ์ด์ธํธ์์ ์๋ฒ์์ ์์ฑ๋ HTML์ hydrateํ์ฌ ์ํธ์์ฉํ ์ ์๋๋ก hydrateRoot
๋ฅผ ์คํํด์ผ ํฉ๋๋ค.
๋์
์๋ฒ์์ renderToString
์ ์คํธ๋ฆฌ๋ฐ ํจ์๋ก ๋ง์ด๊ทธ๋ ์ด์
renderToString
์ ๋ฌธ์์ด์ ์ฆ์ ๋ฐํํ๋ฏ๋ก ์คํธ๋ฆฌ๋ฐ์ด๋ ๋ฐ์ดํฐ ๋๊ธฐ๋ฅผ ์ง์ํ์ง ์์ต๋๋ค.
๊ฐ๋ฅํ๋ฉด ๋ค์๊ณผ ๊ฐ์ ์์ ํ ๊ธฐ๋ฅ์ ๊ฐ์ถ ๋์์ ์ฌ์ฉํ๋ ๊ฒ์ ๊ถ์ฅํฉ๋๋ค:
- Node.js๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ [โrenderToPipeableStreamโ]์ ์ฌ์ฉํ์ธ์. (/reference/react-dom/server/renderToPipeableStream)
- Deno์ ์ต์ ์ฃ์ง ๋ฐํ์์์ Web Streams์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ
renderToReadableStream
์ ์ฌ์ฉํ์ธ์
์๋ฒ ํ๊ฒฝ์์ ์คํธ๋ฆผ์ ์ง์ํ์ง ์๋ ๊ฒฝ์ฐ์๋ renderToString
์ ๊ณ์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
ํด๋ผ์ด์ธํธ ์ฝ๋์์ renderToString
์ ๊ฑฐํ๊ธฐ
ํด๋ผ์ด์ธํธ์์ ์ผ๋ถ ์ปดํฌ๋ํธ๋ฅผ HTML๋ก ๋ณํํ๊ธฐ ์ํด renderToString
์ ์ฌ์ฉํ๊ธฐ๋ ํฉ๋๋ค.
// ๐ฉ ๋ถํ์: ํด๋ผ์ด์ธํธ์์ renderToString ์ฌ์ฉํ๊ธฐ
import { renderToString } from 'react-dom/server';
const html = renderToString(<MyIcon />);
console.log(html); // ์๋ฅผ ๋ค์ด, "<svg>...</svg>"
ํด๋ผ์ด์ธํธ์์ react-dom/server
๋ฅผ ๊ฐ์ ธ์ค๋ฉด ๋ถํ์ํ๊ฒ ๋ฒ๋ค ํฌ๊ธฐ๊ฐ ์ปค์ง๋ฏ๋ก ํผํด์ผ ํฉ๋๋ค. ๋ธ๋ผ์ฐ์ ์์ ์ผ๋ถ ์ปดํฌ๋ํธ๋ฅผ HTML๋ก ๋ ๋๋งํด์ผ ํ ๊ฒฝ์ฐ createRoot
์ ์ฌ์ฉํ๊ณ DOM์์ HTML์ ์ฝ์ผ์ธ์:
import { createRoot } from 'react-dom/client';
import { flushSync } from 'react-dom';
const div = document.createElement('div');
const root = createRoot(div);
flushSync(() => {
root.render(<MyIcon />);
});
console.log(div.innerHTML); // ์๋ฅผ ๋ค์ด, "<svg>...</svg>"
flushSync
ํธ์ถ์ innerHTML
์์ฑ์ ์ฝ๊ธฐ ์ ์ DOM์ ์
๋ฐ์ดํธํ๊ธฐ ์ํด ํ์ํฉ๋๋ค.
๋ฌธ์ ํด๊ฒฐ
์ปดํฌ๋ํธ๊ฐ ์ผ์ ์ค๋จ๋๋ฉด HTML์ ํญ์ ํด๋ฐฑ์ ํฌํจํฉ๋๋ค.
renderToString
์ Suspense๋ฅผ ์๋ฒฝํ๊ฒ ์ง์ํ์ง ์์ต๋๋ค.
์ผ๋ถ ์ปดํฌ๋ํธ๊ฐ ์ผ์ ์ค๋จ๋๊ฑฐ๋ (์๋ฅผ ๋ค์ด, lazy
์ ํจ๊ป ์ ์๋๊ฑฐ๋ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ฌ ๋) renderToString
์ ์ฝํ
์ธ ๊ฐ ํด๊ฒฐ๋ ๋๊น์ง ๊ธฐ๋ค๋ฆฌ์ง ์์ต๋๋ค. renderToString
๋ ๊ทธ ์์ ๊ฐ์ฅ ๊ฐ๊น์ด <Suspense>
๊ฒฝ๊ณ๋ฅผ ์ฐพ์ fallback
ํ๋กํผํฐ๋ฅผ HTML์ ๋ ๋๋งํฉ๋๋ค. ๋ด์ฉ์ ํด๋ผ์ด์ธํธ ์ฝ๋๊ฐ ๋ก๋๋ ๋๊น์ง ๋ํ๋์ง ์์ต๋๋ค.
์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ๊ถ์ฅํ๋ ์คํธ๋ฆฌ๋ฐ ์๋ฃจ์ ์ค ํ๋๋ฅผ ์ฌ์ฉํ์ธ์. ์ฌ์ฉ์๊ฐ ํด๋ผ์ด์ธํธ ์ฝ๋๊ฐ ๋ก๋๋๊ธฐ ์ ์ ํ์ด์ง๊ฐ ์ ์ง์ ์ผ๋ก ์ฑ์์ง๋ ๊ฒ์ ๋ณผ ์ ์๋๋ก ์๋ฒ์์ ํด๊ฒฐํ ๋ ์ปจํ ์ธ ๋ฅผ ์ฒญํฌ๋ก ์คํธ๋ฆฌ๋ฐํ ์ ์์ต๋๋ค.