์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค!

React ๊ธฐ๋ฐ˜ ํ”„๋ ˆ์ž„์›Œํฌ์—์„œ๋Š” ๋ฆฌ์†Œ์Šค ๋กœ๋”ฉ์„ ์ž๋™์œผ๋กœ ์ฒ˜๋ฆฌํ•ด์ฃผ๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ๊ธฐ ๋•Œ๋ฌธ์— ์ด API๋ฅผ ์ง์ ‘ ํ˜ธ์ถœํ•  ํ•„์š”๊ฐ€ ์—†์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ ์‚ฌ์šฉํ•˜๋Š” ํ”„๋ ˆ์ž„์›Œํฌ์˜ ๋ฌธ์„œ๋ฅผ ์ฐธ๊ณ ํ•˜์„ธ์š”.

preinitModule์€ ESM ๋ชจ๋“ˆ์„ ๋ฏธ๋ฆฌ ๊ฐ€์ ธ์˜ค๊ณ  ํ‰๊ฐ€(evaluate)ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค.

preinitModule("https://example.com/module.js", {as: "script"});

๋ ˆํผ๋Ÿฐ์Šค

preinitModule(href, options)

ESM ๋ชจ๋“ˆ์„ ์‚ฌ์ „์— preinitํ•˜๋ ค๋ฉด, react-dom ํŒจํ‚ค์ง€์—์„œ preinitModule ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜์„ธ์š”.

import { preinitModule } from 'react-dom';

function AppRoot() {
preinitModule("https://example.com/module.js", {as: "script"});
// ...
}

์•„๋ž˜ ์˜ˆ์‹œ๋ฅผ ๋” ์ฐธ๊ณ ํ•˜์„ธ์š”.

preinitModule ํ•จ์ˆ˜๋Š” ๋ธŒ๋ผ์šฐ์ €์— ํ•ด๋‹น ๋ชจ๋“ˆ์„ ๋‹ค์šด๋กœ๋“œํ•˜๊ณ  ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ํžŒํŠธ๋ฅผ ์ œ๊ณตํ•˜๋ฏ€๋กœ, ๋กœ๋”ฉ ์‹œ๊ฐ„์„ ๋‹จ์ถ•ํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค. preinit๋œ ๋ชจ๋“ˆ์€ ๋‹ค์šด๋กœ๋“œ๊ฐ€ ์™„๋ฃŒ๋˜๋Š” ์ฆ‰์‹œ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.

๋งค๊ฐœ๋ณ€์ˆ˜

  • href: ๋ฌธ์ž์—ด์ž…๋‹ˆ๋‹ค. ๋‹ค์šด๋กœ๋“œํ•˜๊ณ  ์‹คํ–‰ํ•  ๋ชจ๋“ˆ์˜ URL์ž…๋‹ˆ๋‹ค.
  • options: ๊ฐ์ฒด์ž…๋‹ˆ๋‹ค. ๋‹ค์Œ ์†์„ฑ์„ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค:
    • as: ํ•„์ˆ˜ ๋ฌธ์ž์—ด์ž…๋‹ˆ๋‹ค. ๋ฐ˜๋“œ์‹œ 'script'์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.
    • crossOrigin: ๋ฌธ์ž์—ด์ž…๋‹ˆ๋‹ค. ์‚ฌ์šฉํ•  CORS policy์„ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. ๊ฐ€๋Šฅํ•œ ๊ฐ’์€ anonymous ๋˜๋Š” use-credentials์ž…๋‹ˆ๋‹ค.
    • integrity: ๋ฌธ์ž์—ด์ž…๋‹ˆ๋‹ค. ๋ชจ๋“ˆ์˜ ์•”ํ˜ธํ•™์  ํ•ด์‹œ๋กœ, ๋ฌด๊ฒฐ์„ฑ์„ ๊ฒ€์ฆํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
    • nonce: ๋ฌธ์ž์—ด์ž…๋‹ˆ๋‹ค. ์—„๊ฒฉํ•œ Content Security Policy๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ๋ชจ๋“ˆ์„ ํ—ˆ์šฉํ•˜๊ธฐ ์œ„ํ•œ ์•”ํ˜ธํ•™์  nonce์ž…๋‹ˆ๋‹ค.

๋ฐ˜ํ™˜๊ฐ’

preinitModule์€ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์ฃผ์˜ ์‚ฌํ•ญ

  • ๋™์ผํ•œ href๋กœ preinitModule์„ ์—ฌ๋Ÿฌ ๋ฒˆ ํ˜ธ์ถœํ•ด๋„, ํ•œ ๋ฒˆ ํ˜ธ์ถœํ•œ ๊ฒƒ๊ณผ ๋™์ผํ•œ ํšจ๊ณผ๋งŒ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.
  • ๋ธŒ๋ผ์šฐ์ €์—์„œ๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ Œ๋”๋งํ•  ๋•Œ, ์ดํŽ™ํŠธ ์•ˆ์—์„œ, ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ๋“ฑ ์–ด๋–ค ์ƒํ™ฉ์—์„œ๋„ preinitModule์„ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์„œ๋ฒ„ ์ธก ๋ Œ๋”๋ง์ด๋‚˜ Server Components๋ฅผ ๋ Œ๋”๋งํ•  ๋•Œ๋Š”, preinitModule๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ Œ๋”๋งํ•˜๋Š” ์ค‘์ด๊ฑฐ๋‚˜ ๋ Œ๋”๋ง์—์„œ ํŒŒ์ƒ๋œ ๋น„๋™๊ธฐ ์ปจํ…์ŠคํŠธ ๋‚ด์—์„œ ํ˜ธ์ถœํ•œ ๊ฒฝ์šฐ์—๋งŒ ํšจ๊ณผ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ ์™ธ์˜ ํ˜ธ์ถœ์€ ๋ฌด์‹œ๋ฉ๋‹ˆ๋‹ค.

์‚ฌ์šฉ๋ฒ•

๋ Œ๋”๋ง ์ค‘ ์‚ฌ์ „ ๋กœ๋”ฉํ•˜๊ธฐ

ํŠน์ • ๋ชจ๋“ˆ์ด ํ˜„์žฌ ์ปดํฌ๋„ŒํŠธ๋‚˜ ์ž์‹ ์ปดํฌ๋„ŒํŠธ์—์„œ ์‚ฌ์šฉ๋  ๊ฒƒ์ž„์„ ์•Œ๊ณ  ์žˆ๊ณ , ํ•ด๋‹น ๋ชจ๋“ˆ์ด ๋‹ค์šด๋กœ๋“œ ์ฆ‰์‹œ ํ‰๊ฐ€๋˜์–ด ํšจ๊ณผ๋ฅผ ๋ฐœํœ˜ํ•ด๋„ ๊ดœ์ฐฎ๋‹ค๋ฉด, ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ Œ๋”๋งํ•  ๋•Œ preinitModule์„ ํ˜ธ์ถœํ•˜์„ธ์š”.

import { preinitModule } from 'react-dom';

function AppRoot() {
preinitModule("https://example.com/module.js", {as: "script"});
return ...;
}

๋ชจ๋“ˆ์„ ๋‹ค์šด๋กœ๋“œํ•˜๋˜ ์ฆ‰์‹œ ์‹คํ–‰ํ•˜์ง€ ์•Š์œผ๋ ค๋ฉด preloadModule์„ ์‚ฌ์šฉํ•˜์„ธ์š”. ESM ๋ชจ๋“ˆ์ด ์•„๋‹Œ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‚ฌ์ „ ์ดˆ๊ธฐํ™”ํ•˜๋ ค๋ฉด preinit์„ ์‚ฌ์šฉํ•˜์„ธ์š”.

์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ์—์„œ ์‚ฌ์ „ ๋กœ๋”ฉํ•˜๊ธฐ

์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ์—์„œ ๋ชจ๋“ˆ์ด ํ•„์š”ํ•ด์งˆ ํŽ˜์ด์ง€๋‚˜ ์ƒํƒœ๋กœ ์ „ํ™˜ํ•˜๊ธฐ ์ „์— preinitModule์„ ํ˜ธ์ถœํ•˜์„ธ์š”. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์ƒˆ๋กœ์šด ํŽ˜์ด์ง€๋‚˜ ์ƒํƒœ๋ฅผ ๋ Œ๋”๋งํ•  ๋•Œ๋ณด๋‹ค ๋” ์ผ์ฐ ๋กœ๋”ฉ์„ ์‹œ์ž‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

import { preinitModule } from 'react-dom';

function CallToAction() {
const onClick = () => {
preinitModule("https://example.com/module.js", {as: "script"});
startWizard();
}
return (
<button onClick={onClick}>Start Wizard</button>
);
}