๐Ÿš€ ๋งˆ์ดํฌ๋กœํ”„๋ก ํŠธ์—”๋“œ ์•„ํ‚คํ…์ฒ˜: Module Federation ํ™œ์šฉํ•˜๊ธฐ ๐Ÿš€

์ฝ˜ํ…์ธ  ๋Œ€ํ‘œ ์ด๋ฏธ์ง€ - ๐Ÿš€ ๋งˆ์ดํฌ๋กœํ”„๋ก ํŠธ์—”๋“œ ์•„ํ‚คํ…์ฒ˜: Module Federation ํ™œ์šฉํ•˜๊ธฐ ๐Ÿš€

 

 

์•ˆ๋…•ํ•˜์„ธ์š”, ์—ฌ๋Ÿฌ๋ถ„! ์˜ค๋Š˜์€ ์ •๋ง ํ•ซํ•œ ์ฃผ์ œ๋กœ ์ฐพ์•„์™”์–ด์š”. ๋ฐ”๋กœ ๋งˆ์ดํฌ๋กœํ”„๋ก ํŠธ์—”๋“œ ์•„ํ‚คํ…์ฒ˜์™€ Module Federation์— ๋Œ€ํ•ด ์•Œ์•„๋ณผ ๊ฑฐ์˜ˆ์š”. ์ด ์ฃผ์ œ, ๋“ฃ๊ธฐ๋งŒ ํ•ด๋„ ๋จธ๋ฆฌ๊ฐ€ ์•„ํ”„์ฃ ? ใ…‹ใ…‹ใ…‹ ๊ฑฑ์ • ๋งˆ์„ธ์š”! ์ œ๊ฐ€ ์‰ฝ๊ณ  ์žฌ๋ฐŒ๊ฒŒ ์„ค๋ช…ํ•ด๋“œ๋ฆด๊ฒŒ์š”. ๋งˆ์น˜ ์นดํ†ก์œผ๋กœ ์ˆ˜๋‹ค ๋–จ๋“ฏ์ด ๋ง์ด์ฃ ! ๐Ÿ˜‰

์šฐ๋ฆฌ๊ฐ€ ์ด ์ฃผ์ œ๋ฅผ ํŒŒํ—ค์น˜๋‹ค ๋ณด๋ฉด, ์—ฌ๋Ÿฌ๋ถ„๋„ ๋ชจ๋ฅด๋Š” ์‚ฌ์ด์— ์›น ๊ฐœ๋ฐœ์˜ ๊ณ ์ˆ˜๊ฐ€ ๋˜์–ด ์žˆ์„ ๊ฑฐ์˜ˆ์š”. ์–ด์ฉŒ๋ฉด ์žฌ๋Šฅ๋„ท์—์„œ ํ”„๋ก ํŠธ์—”๋“œ ๊ฐœ๋ฐœ ์žฌ๋Šฅ์„ ๊ณต์œ ํ•˜๊ฒŒ ๋ ์ง€๋„ ๋ชจ๋ฅด๊ฒ ์–ด์š”! ๐ŸŽจโœจ ์ž, ๊ทธ๋Ÿผ ์‹œ์ž‘ํ•ด๋ณผ๊นŒ์š”?

๐Ÿ’ก ์ž ๊น! ์•Œ๊ณ  ๊ฐ€์„ธ์š”: ๋งˆ์ดํฌ๋กœํ”„๋ก ํŠธ์—”๋“œ๋Š” ๋ณต์žกํ•œ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์ž‘์€ ์กฐ๊ฐ์œผ๋กœ ๋‚˜๋ˆ„๋Š” ์•„ํ‚คํ…์ฒ˜ ์Šคํƒ€์ผ์ด์—์š”. Module Federation์€ ์ด๋Ÿฐ ์กฐ๊ฐ๋“ค์„ ํšจ์œจ์ ์œผ๋กœ ๊ด€๋ฆฌํ•˜๊ณ  ํ†ตํ•ฉํ•˜๋Š” ์›นํŒฉ์˜ ๊ธฐ๋Šฅ์ด์ฃ . ์–ด๋ ต๊ฒŒ ๋“ค๋ฆฌ์‹œ๋‚˜์š”? ๊ฑฑ์ • ๋งˆ์„ธ์š”, ์ฒœ์ฒœํžˆ ์„ค๋ช…ํ•ด๋“œ๋ฆด๊ฒŒ์š”!

๐Ÿ—๏ธ ๋งˆ์ดํฌ๋กœํ”„๋ก ํŠธ์—”๋“œ๋ž€ ๋ญ์•ผ? ๐Ÿค”

์ž, ์—ฌ๋Ÿฌ๋ถ„! ๋งˆ์ดํฌ๋กœํ”„๋ก ํŠธ์—”๋“œ๋ผ๋Š” ๋ง, ๋“ค์–ด๋ณด์…จ๋‚˜์š”? ์•ˆ ๋“ค์–ด๋ณด์…จ๋‹ค๊ณ ์š”? ๊ดœ์ฐฎ์•„์š”, ์ง€๊ธˆ๋ถ€ํ„ฐ ํ•จ๊ป˜ ์•Œ์•„๊ฐ€ ๋ด์š”! ๐Ÿ˜Š

๋งˆ์ดํฌ๋กœํ”„๋ก ํŠธ์—”๋“œ๋Š” ๋ง ๊ทธ๋Œ€๋กœ '์ž‘์€ ํ”„๋ก ํŠธ์—”๋“œ'๋ฅผ ์˜๋ฏธํ•ด์š”. ๊ทผ๋ฐ ์™œ '์ž‘์€' ํ”„๋ก ํŠธ์—”๋“œ์ผ๊นŒ์š”? ๐Ÿง

์ƒ์ƒํ•ด๋ณด์„ธ์š”. ์—ฌ๋Ÿฌ๋ถ„์ด ๊ฑฐ๋Œ€ํ•œ ์‡ผํ•‘๋ชฐ ์›น์‚ฌ์ดํŠธ๋ฅผ ๋งŒ๋“ค๊ณ  ์žˆ๋‹ค๊ณ  ํ•ด๋ณผ๊ฒŒ์š”. ์ด ์‚ฌ์ดํŠธ์—๋Š” ์ƒํ’ˆ ๋ชฉ๋ก, ์žฅ๋ฐ”๊ตฌ๋‹ˆ, ๊ฒฐ์ œ ์‹œ์Šคํ…œ, ์‚ฌ์šฉ์ž ๋ฆฌ๋ทฐ ๋“ฑ ์ •๋ง ๋งŽ์€ ๊ธฐ๋Šฅ์ด ์žˆ๊ฒ ์ฃ ? ์ด๊ฑธ ์ „๋ถ€ ํ•˜๋‚˜์˜ ํฐ ํ”„๋กœ์ ํŠธ๋กœ ๋งŒ๋“ ๋‹ค๋ฉด... ์–ด๋–จ๊นŒ์š”?

  • ์ฝ”๋“œ๊ฐ€ ์—„์ฒญ ๋ณต์žกํ•ด์งˆ ๊ฑฐ์˜ˆ์š”. ๐Ÿ˜ต
  • ์—ฌ๋Ÿฌ ํŒ€์ด ๋™์‹œ์— ์ž‘์—…ํ•˜๊ธฐ ์–ด๋ ค์›Œ์งˆ ๊ฑฐ๊ณ ์š”. ๐Ÿšง
  • ํ•œ ๋ถ€๋ถ„์„ ์ˆ˜์ •ํ•˜๋ฉด ๋‹ค๋ฅธ ๋ถ€๋ถ„์— ์˜ํ–ฅ์„ ์ค„ ์ˆ˜ ์žˆ์–ด์š”. ๐Ÿ˜ฑ
  • ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•˜๊ฑฐ๋‚˜ ์—…๋ฐ์ดํŠธํ•˜๋Š” ๊ฒŒ ์ •๋ง ํž˜๋“ค์–ด์งˆ ๊ฑฐ์˜ˆ์š”. ๐Ÿ’ฆ

์ด๋Ÿฐ ๋ฌธ์ œ๋“ค์„ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ๋‚˜์˜จ ๊ฒŒ ๋ฐ”๋กœ ๋งˆ์ดํฌ๋กœํ”„๋ก ํŠธ์—”๋“œ์˜ˆ์š”! ๐ŸŽ‰

๐Ÿšจ ์ฃผ์˜: ๋งˆ์ดํฌ๋กœํ”„๋ก ํŠธ์—”๋“œ๊ฐ€ ๋ชจ๋“  ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•ด์ฃผ๋Š” ๋งˆ๋ฒ• ๊ฐ™์€ ํ•ด๊ฒฐ์ฑ…์€ ์•„๋‹ˆ์—์š”. ์ ์ ˆํ•œ ์ƒํ™ฉ์—์„œ ์‚ฌ์šฉํ•ด์•ผ ํšจ๊ณผ์ ์ด๋ž๋‹ˆ๋‹ค!

๋งˆ์ดํฌ๋กœํ”„๋ก ํŠธ์—”๋“œ๋Š” ํฐ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์ž‘์€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์œผ๋กœ ๋‚˜๋ˆ„๋Š” ๋ฐฉ์‹์ด์—์š”. ๋งˆ์น˜ ๋ ˆ๊ณ  ๋ธ”๋ก์ฒ˜๋Ÿผ ๊ฐ ๋ถ€๋ถ„์„ ๋…๋ฆฝ์ ์œผ๋กœ ๊ฐœ๋ฐœํ•˜๊ณ , ๋‚˜์ค‘์— ์กฐ๋ฆฝํ•ด์„œ ํ•˜๋‚˜์˜ ํฐ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋งŒ๋“œ๋Š” ๊ฑฐ์ฃ ! ๐Ÿ˜Ž

๋งˆ์ดํฌ๋กœํ”„๋ก ํŠธ์—”๋“œ ๊ตฌ์กฐ ์ƒํ’ˆ ๋ชฉ๋ก ์žฅ๋ฐ”๊ตฌ๋‹ˆ ๊ฒฐ์ œ ์‹œ์Šคํ…œ ์‚ฌ์šฉ์ž ๋ฆฌ๋ทฐ ๊ธฐํƒ€ ๊ธฐ๋Šฅ

์ด๋ ‡๊ฒŒ ๋‚˜๋ˆ„๋ฉด ์–ด๋–ค ์žฅ์ ์ด ์žˆ์„๊นŒ์š”? ๐Ÿค—

  • ๊ฐ ํŒ€์ด ๋…๋ฆฝ์ ์œผ๋กœ ๊ฐœ๋ฐœํ•  ์ˆ˜ ์žˆ์–ด์š”. ๐Ÿ‘จโ€๐Ÿ’ป๐Ÿ‘ฉโ€๐Ÿ’ป
  • ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•˜๊ฑฐ๋‚˜ ์—…๋ฐ์ดํŠธํ•˜๊ธฐ ์‰ฌ์›Œ์ ธ์š”. ๐Ÿ†•
  • ํ•œ ๋ถ€๋ถ„์— ๋ฌธ์ œ๊ฐ€ ์ƒ๊ฒจ๋„ ์ „์ฒด ์‚ฌ์ดํŠธ์— ์˜ํ–ฅ์„ ๋œ ์ค˜์š”. ๐Ÿ›ก๏ธ
  • ๊ธฐ์ˆ  ์Šคํƒ์„ ์œ ์—ฐํ•˜๊ฒŒ ์„ ํƒํ•  ์ˆ˜ ์žˆ์–ด์š”. ๋‹ค์–‘ํ•œ ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์ฃ ! ๐Ÿ”ง

์žฌ๋Šฅ๋„ท ๊ฐ™์€ ํ”Œ๋žซํผ์—์„œ๋„ ์ด๋Ÿฐ ๋งˆ์ดํฌ๋กœํ”„๋ก ํŠธ์—”๋“œ ๊ตฌ์กฐ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ข‹์„ ๊ฒƒ ๊ฐ™์•„์š”. ์˜ˆ๋ฅผ ๋“ค์–ด, ์žฌ๋Šฅ ๊ฑฐ๋ž˜ ๋ถ€๋ถ„, ์ปค๋ฎค๋‹ˆํ‹ฐ ๋ถ€๋ถ„, ๊ฒฐ์ œ ์‹œ์Šคํ…œ ๋“ฑ์„ ๊ฐ๊ฐ ๋…๋ฆฝ์ ์ธ ๋งˆ์ดํฌ๋กœํ”„๋ก ํŠธ์—”๋“œ๋กœ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๊ฒ ์ฃ ? ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๊ฐ ๋ถ€๋ถ„์„ ๋” ํšจ์œจ์ ์œผ๋กœ ๊ด€๋ฆฌํ•˜๊ณ  ์—…๋ฐ์ดํŠธํ•  ์ˆ˜ ์žˆ์„ ๊ฑฐ์˜ˆ์š”! ๐Ÿ‘

ํ•˜์ง€๋งŒ ๋งˆ์ดํฌ๋กœํ”„๋ก ํŠธ์—”๋“œ๊ฐ€ ์žฅ์ ๋งŒ ์žˆ๋Š” ๊ฑด ์•„๋‹ˆ์—์š”. ๋ช‡ ๊ฐ€์ง€ ๋‹จ์ ๋„ ์žˆ์ฃ .

  • ์ดˆ๊ธฐ ์„ค์ •์ด ๋ณต์žกํ•  ์ˆ˜ ์žˆ์–ด์š”. ๐Ÿ˜“
  • ์ „์ฒด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์ผ๊ด€์„ฑ์„ ์œ ์ง€ํ•˜๊ธฐ ์–ด๋ ค์šธ ์ˆ˜ ์žˆ์–ด์š”. ๐ŸŽจ
  • ์ค‘๋ณต ์ฝ”๋“œ๊ฐ€ ์ƒ๊ธธ ์ˆ˜ ์žˆ์–ด์š”. ๐Ÿ”„
  • ์„ฑ๋Šฅ ์ตœ์ ํ™”๊ฐ€ ๋” ์–ด๋ ค์›Œ์งˆ ์ˆ˜ ์žˆ์–ด์š”. โšก

๊ทธ๋ž˜์„œ ๋งˆ์ดํฌ๋กœํ”„๋ก ํŠธ์—”๋“œ๋ฅผ ๋„์ž…ํ•  ๋•Œ๋Š” ์‹ ์ค‘ํ•˜๊ฒŒ ๊ฒฐ์ •ํ•ด์•ผ ํ•ด์š”. ํ”„๋กœ์ ํŠธ์˜ ๊ทœ๋ชจ, ํŒ€์˜ ๊ตฌ์กฐ, ๊ธฐ์ˆ ์ ์ธ ์š”๊ตฌ์‚ฌํ•ญ ๋“ฑ์„ ์ž˜ ๊ณ ๋ คํ•ด๋ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๐Ÿค”

๐Ÿ’ก ๊ฟ€ํŒ: ๋งˆ์ดํฌ๋กœํ”„๋ก ํŠธ์—”๋“œ๋ฅผ ์ฒ˜์Œ ์‹œ๋„ํ•ด๋ณธ๋‹ค๋ฉด, ์ž‘์€ ๊ทœ๋ชจ์˜ ํ”„๋กœ์ ํŠธ๋ถ€ํ„ฐ ์‹œ์ž‘ํ•ด๋ณด๋Š” ๊ฒŒ ์ข‹์•„์š”. ๊ฒฝํ—˜์„ ์Œ“์•„๊ฐ€๋ฉด์„œ ์ ์  ๋” ํฐ ํ”„๋กœ์ ํŠธ์— ์ ์šฉํ•ด๋ณผ ์ˆ˜ ์žˆ์ฃ !

์ž, ์—ฌ๊ธฐ๊นŒ์ง€ ๋งˆ์ดํฌ๋กœํ”„๋ก ํŠธ์—”๋“œ์— ๋Œ€ํ•ด ์•Œ์•„๋ดค์–ด์š”. ์–ด๋•Œ์š”? ์ƒ๊ฐ๋ณด๋‹ค ์–ด๋ ต์ง€ ์•Š์ฃ ? ใ…‹ใ…‹ใ…‹ ์ด์ œ ์šฐ๋ฆฌ์˜ ์ฃผ์ธ๊ณต Module Federation์— ๋Œ€ํ•ด ์•Œ์•„๋ณผ ์ฐจ๋ก€์˜ˆ์š”! ๐Ÿš€

๐Ÿงฉ Module Federation: ๋งˆ์ดํฌ๋กœํ”„๋ก ํŠธ์—”๋“œ์˜ ์Šˆํผํžˆ์–ด๋กœ! ๐Ÿฆธโ€โ™‚๏ธ

์ž, ์ด์ œ ์šฐ๋ฆฌ์˜ ํžˆ์–ด๋กœ Module Federation์„ ์†Œ๊ฐœํ•  ์‹œ๊ฐ„์ด์—์š”! ๐ŸŽญ Module Federation, ์ด๋ฆ„๋ถ€ํ„ฐ ๋ญ”๊ฐ€ ๋Œ€๋‹จํ•ด ๋ณด์ด์ฃ ? ใ…‹ใ…‹ใ…‹

Module Federation์€ ์›นํŒฉ 5์—์„œ ์ƒˆ๋กญ๊ฒŒ ๋“ฑ์žฅํ•œ ๊ธฐ๋Šฅ์ด์—์š”. ์ด ๊ธฐ๋Šฅ์€ ๋งˆ์ดํฌ๋กœํ”„๋ก ํŠธ์—”๋“œ๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐ ์ •๋ง ํฐ ๋„์›€์„ ์ค˜์š”. ์–ด๋–ป๊ฒŒ ๋„์™€์ฃผ๋Š”์ง€ ํ•จ๊ป˜ ์•Œ์•„๋ณผ๊นŒ์š”? ๐Ÿ•ต๏ธโ€โ™€๏ธ

๐ŸŽˆ ์•Œ์ญ๋‹ฌ์ญ ํฌ์ธํŠธ: Module Federation์€ '๋ชจ๋“ˆ ์—ฐํ•ฉ'์ด๋ผ๊ณ  ๋ฒˆ์—ญํ•  ์ˆ˜ ์žˆ์–ด์š”. ์—ฌ๋Ÿฌ ๊ฐœ์˜ ๋…๋ฆฝ์ ์ธ ๋นŒ๋“œ๊ฐ€ ํ•˜๋‚˜์˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ฃผ๋Š” ๊ฑฐ์ฃ !

Module Federation์˜ ํ•ต์‹ฌ ์•„์ด๋””์–ด๋Š” ์ด๊ฑฐ์˜ˆ์š”:

  • ์—ฌ๋Ÿฌ ๊ฐœ์˜ ๋…๋ฆฝ์ ์ธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์„œ๋กœ์˜ ์ฝ”๋“œ๋ฅผ ์‹ค์‹œ๊ฐ„์œผ๋กœ ๊ณต์œ ํ•  ์ˆ˜ ์žˆ์–ด์š”. ๐Ÿค
  • ๊ฐ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ๋…๋ฆฝ์ ์œผ๋กœ ๊ฐœ๋ฐœํ•˜๊ณ  ๋ฐฐํฌํ•  ์ˆ˜ ์žˆ์–ด์š”. ๐Ÿš€
  • ํ•„์š”ํ•œ ์ฝ”๋“œ๋งŒ ๋กœ๋“œํ•ด์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด์š”. ๋ถˆํ•„์š”ํ•œ ์ฝ”๋“œ๋Š” ๊ฐ€์ ธ์˜ค์ง€ ์•Š์ฃ ! ๐ŸŽฏ

์ด๊ฒŒ ๋ฌด์Šจ ๋ง์ด๋ƒ๊ณ ์š”? ์‰ฝ๊ฒŒ ์„ค๋ช…ํ•ด๋“œ๋ฆด๊ฒŒ์š”! ๐Ÿ˜Š

์ƒ์ƒํ•ด๋ณด์„ธ์š”. ์—ฌ๋Ÿฌ๋ถ„์ด ๊ฑฐ๋Œ€ํ•œ ์˜จ๋ผ์ธ ์‡ผํ•‘๋ชฐ์„ ๋งŒ๋“ค๊ณ  ์žˆ๋‹ค๊ณ  ํ•ด๋ณผ๊ฒŒ์š”. ์ด ์‡ผํ•‘๋ชฐ์€ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์ž‘์€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์œผ๋กœ ๊ตฌ์„ฑ๋˜์–ด ์žˆ์–ด์š”.

  • ์ƒํ’ˆ ๋ชฉ๋ก ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๐Ÿ›๏ธ
  • ์žฅ๋ฐ”๊ตฌ๋‹ˆ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๐Ÿ›’
  • ๊ฒฐ์ œ ์‹œ์Šคํ…œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๐Ÿ’ณ
  • ์‚ฌ์šฉ์ž ๋ฆฌ๋ทฐ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ โญ

๊ฐ๊ฐ์˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ๋…๋ฆฝ์ ์œผ๋กœ ๊ฐœ๋ฐœ๋˜๊ณ  ์žˆ์–ด์š”. ๊ทผ๋ฐ ๋ฌธ์ œ๊ฐ€ ํ•˜๋‚˜ ์žˆ์–ด์š”. ๋ฐ”๋กœ '๊ณตํ†ต ์ปดํฌ๋„ŒํŠธ'์˜ˆ์š”!

์˜ˆ๋ฅผ ๋“ค์–ด, '๋ณ„์ ' ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์žˆ๋‹ค๊ณ  ํ•ด๋ณผ๊ฒŒ์š”. ์ด ์ปดํฌ๋„ŒํŠธ๋Š” ์ƒํ’ˆ ๋ชฉ๋ก์—์„œ๋„ ํ•„์š”ํ•˜๊ณ , ์‚ฌ์šฉ์ž ๋ฆฌ๋ทฐ์—์„œ๋„ ํ•„์š”ํ•ด์š”. ๊ทธ๋Ÿผ ์–ด๋–ป๊ฒŒ ํ•ด์•ผ ํ• ๊นŒ์š”? ๐Ÿค”

Module Federation์ด ์—†๋‹ค๋ฉด, ์ด๋Ÿฐ ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ–ˆ์„ ๊ฑฐ์˜ˆ์š”:

  1. ๋ณ„์  ์ปดํฌ๋„ŒํŠธ๋ฅผ npm ํŒจํ‚ค์ง€๋กœ ๋งŒ๋“ค์–ด์„œ ๋ฐฐํฌํ•˜๊ธฐ ๐Ÿ“ฆ
  2. ๊ฐ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ์ด ํŒจํ‚ค์ง€๋ฅผ ์„ค์น˜ํ•˜๊ณ  ์‚ฌ์šฉํ•˜๊ธฐ ๐Ÿ”ง

์ด ๋ฐฉ๋ฒ•๋„ ๋‚˜์˜์ง€ ์•Š์ง€๋งŒ, ๋ช‡ ๊ฐ€์ง€ ๋ฌธ์ œ๊ฐ€ ์žˆ์–ด์š”:

  • ํŒจํ‚ค์ง€๋ฅผ ์—…๋ฐ์ดํŠธํ•  ๋•Œ๋งˆ๋‹ค ๋ชจ๋“  ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋‹ค์‹œ ๋นŒ๋“œํ•˜๊ณ  ๋ฐฐํฌํ•ด์•ผ ํ•ด์š”. ๐Ÿ˜“
  • ๊ฐ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜๋งˆ๋‹ค ๊ฐ™์€ ์ฝ”๋“œ๊ฐ€ ์ค‘๋ณต๋˜์–ด ๋ฒˆ๋“ค ํฌ๊ธฐ๊ฐ€ ์ปค์ ธ์š”. ๐ŸŽˆ

ํ•˜์ง€๋งŒ Module Federation์„ ์‚ฌ์šฉํ•˜๋ฉด ์ด๋Ÿฐ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์–ด์š”! ์–ด๋–ป๊ฒŒ์š”? ๐Ÿ‘€

Module Federation ๊ตฌ์กฐ ์ƒํ’ˆ ๋ชฉ๋ก ์žฅ๋ฐ”๊ตฌ๋‹ˆ ๊ฒฐ์ œ ์‹œ์Šคํ…œ ์‚ฌ์šฉ์ž ๋ฆฌ๋ทฐ ๋ณ„์  ์ปดํฌ๋„ŒํŠธ

Module Federation์„ ์‚ฌ์šฉํ•˜๋ฉด:

  1. ๋ณ„์  ์ปดํฌ๋„ŒํŠธ๋ฅผ ํ•˜๋‚˜์˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜(์˜ˆ: ์‚ฌ์šฉ์ž ๋ฆฌ๋ทฐ ์•ฑ)์—์„œ ๊ด€๋ฆฌํ•ด์š”. ๐Ÿ 
  2. ๋‹ค๋ฅธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜(์˜ˆ: ์ƒํ’ˆ ๋ชฉ๋ก ์•ฑ)์—์„œ๋Š” ์ด ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋ถˆ๋Ÿฌ์™€ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด์š”. ๐Ÿ”„
  3. ๋ณ„์  ์ปดํฌ๋„ŒํŠธ๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๋ฉด, ์ด๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ชจ๋“  ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ์ž๋™์œผ๋กœ ์ตœ์‹  ๋ฒ„์ „์„ ์‚ฌ์šฉํ•˜๊ฒŒ ๋ผ์š”. ๐Ÿ†•

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์ฝ”๋“œ ์ค‘๋ณต๋„ ์—†๊ณ , ์—…๋ฐ์ดํŠธ๋„ ์‰ฝ๊ณ , ๋ฒˆ๋“ค ํฌ๊ธฐ๋„ ์ž‘์•„์ง€์ฃ ! ์™„์ „ ์ผ์„์‚ผ์กฐ์˜ˆ์š”! ๐Ÿ‘

๐Ÿ’ก ์žฌ๋Šฅ๋„ท ํ™œ์šฉ ํŒ: ์žฌ๋Šฅ๋„ท์—์„œ๋„ ์ด๋Ÿฐ ๋ฐฉ์‹์„ ์ ์šฉํ•  ์ˆ˜ ์žˆ์–ด์š”. ์˜ˆ๋ฅผ ๋“ค์–ด, ์žฌ๋Šฅ ํ‰๊ฐ€ ์‹œ์Šคํ…œ์ด๋‚˜ ์‚ฌ์šฉ์ž ํ”„๋กœํ•„ ์ปดํฌ๋„ŒํŠธ ๊ฐ™์€ ๊ฑธ Module Federation์œผ๋กœ ๊ด€๋ฆฌํ•˜๋ฉด ํšจ์œจ์ ์ผ ๊ฑฐ์˜ˆ์š”!

์ž, ์ด์ œ Module Federation์ด ๋ญ”์ง€ ๋Œ€์ถฉ ๊ฐ์ด ์˜ค์‹œ๋‚˜์š”? ใ…‹ใ…‹ใ…‹ ๊ทผ๋ฐ ์ด๊ฒŒ ์‹ค์ œ๋กœ ์–ด๋–ป๊ฒŒ ๋™์ž‘ํ•˜๋Š”์ง€ ๋” ์ž์„ธํžˆ ์•Œ์•„๋ณผ๊นŒ์š”? ๐Ÿ•ต๏ธโ€โ™‚๏ธ

Module Federation์˜ ํ•ต์‹ฌ ๊ฐœ๋… ๐Ÿง 

Module Federation์—๋Š” ๋ช‡ ๊ฐ€์ง€ ์ค‘์š”ํ•œ ๊ฐœ๋…์ด ์žˆ์–ด์š”. ํ•˜๋‚˜์”ฉ ์‚ดํŽด๋ณผ๊ฒŒ์š”!

  1. Host(ํ˜ธ์ŠคํŠธ): ๋‹ค๋ฅธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๋ชจ๋“ˆ์„ ์‚ฌ์šฉํ•˜๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด์—์š”. ๐Ÿ 
  2. Remote(๋ฆฌ๋ชจํŠธ): ์ž์‹ ์˜ ๋ชจ๋“ˆ์„ ๋‹ค๋ฅธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ์ œ๊ณตํ•˜๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด์—์š”. ๐Ÿ“ก
  3. Shared(๊ณต์œ ): ์—ฌ๋Ÿฌ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ๊ณต์œ ํ•˜๋Š” ๋ชจ๋“ˆ์ด์—์š”. ์˜ˆ๋ฅผ ๋“ค๋ฉด React๋‚˜ lodash ๊ฐ™์€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ๋  ์ˆ˜ ์žˆ์ฃ . ๐Ÿค

์ด ๊ฐœ๋…๋“ค์„ ์ด์šฉํ•ด์„œ Module Federation์ด ์–ด๋–ป๊ฒŒ ๋™์ž‘ํ•˜๋Š”์ง€ step by step์œผ๋กœ ์„ค๋ช…ํ•ด๋“œ๋ฆด๊ฒŒ์š”! ๐Ÿ˜Š

Step 1: ์„ค์ •ํ•˜๊ธฐ โš™๏ธ

๋จผ์ €, ๊ฐ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์›นํŒฉ ์„ค์ •์— ModuleFederationPlugin์„ ์ถ”๊ฐ€ํ•ด์š”.


const { ModuleFederationPlugin } = require('webpack').container;

module.exports = {
  // ... ๋‹ค๋ฅธ ์›นํŒฉ ์„ค์ •๋“ค ...
  plugins: [
    new ModuleFederationPlugin({
      name: 'app1',
      filename: 'remoteEntry.js',
      exposes: {
        './Button': './src/Button',
      },
      shared: ['react', 'react-dom'],
    }),
  ],
};

์ด ์„ค์ •์—์„œ:

  • name์€ ์ด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์ด๋ฆ„์ด์—์š”.
  • filename์€ ์ด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ remote entry ํŒŒ์ผ ์ด๋ฆ„์ด์—์š”.
  • exposes๋Š” ๋‹ค๋ฅธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ๋…ธ์ถœํ•  ๋ชจ๋“ˆ์„ ์ง€์ •ํ•ด์š”.
  • shared๋Š” ๋‹ค๋ฅธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜๊ณผ ๊ณต์œ ํ•  ๋ชจ๋“ˆ์„ ์ง€์ •ํ•ด์š”.

Step 2: ๋ชจ๋“ˆ ๋…ธ์ถœํ•˜๊ธฐ ๐Ÿ“ค

์ด์ œ ๋‹ค๋ฅธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ๋ชจ๋“ˆ์„ ๋…ธ์ถœํ•ด์š”. ์œ„์˜ ์„ค์ •์—์„œ๋Š” Button ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋…ธ์ถœํ–ˆ์–ด์š”.


// src/Button.js
import React from 'react';

const Button = ({ children }) => (
  <button style={{ padding: '10px', backgroundColor: 'blue', color: 'white' }}>
    {children}
  </button>
);

export default Button;

Step 3: ๋ชจ๋“ˆ ์‚ฌ์šฉํ•˜๊ธฐ ๐Ÿ“ฅ

๋‹ค๋ฅธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜(ํ˜ธ์ŠคํŠธ)์—์„œ ์ด ๋ชจ๋“ˆ์„ ์‚ฌ์šฉํ•˜๋ ค๋ฉด, ๋จผ์ € ์›นํŒฉ ์„ค์ •์„ ํ•ด์ค˜์•ผ ํ•ด์š”.


const { ModuleFederationPlugin } = require('webpack').container;

module.exports = {
  // ... ๋‹ค๋ฅธ ์›นํŒฉ ์„ค์ •๋“ค ...
  plugins: [
    new ModuleFederationPlugin({
      name: 'app2',
      remotes: {
        app1: 'app1@http://localhost:3001/remoteEntry.js',
      },
      shared: ['react', 'react-dom'],
    }),
  ],
};

๊ทธ๋ฆฌ๊ณ  ์ด์ œ ์ด ๋ชจ๋“ˆ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด์š”!


import React from 'react';
const RemoteButton = React.lazy(() => import('app1/Button'));

const App = () => (
  <div>
    <h1>App 2</h1>
    <React.Suspense fallback="Loading Button...">
      <RemoteButton>Click me!</RemoteButton>
    </React.Suspense>
  </div>
);

์™€! ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด app1์˜ Button ์ปดํฌ๋„ŒํŠธ๋ฅผ app2์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋ผ์š”! ๐Ÿ˜ฒ

๐ŸŒŸ ๋†€๋ผ์šด ์ : ์ด ๋ชจ๋“  ๊ณผ์ •์ด ๋Ÿฐํƒ€์ž„์— ์ผ์–ด๋‚˜์š”! ์ฆ‰, app1์ด ์—…๋ฐ์ดํŠธ๋˜๋ฉด app2๋Š” ์ž๋™์œผ๋กœ ์ตœ์‹  ๋ฒ„์ „์˜ Button์„ ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜๋Š” ๊ฑฐ์ฃ !

์ด๋ ‡๊ฒŒ Module Federation์„ ์‚ฌ์šฉํ•˜๋ฉด, ๋งˆ์ดํฌ๋กœํ”„๋ก ํŠธ์—”๋“œ ์•„ํ‚คํ…์ฒ˜๋ฅผ ์ •๋ง ํšจ๊ณผ์ ์œผ๋กœ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์–ด์š”. ๊ฐ ํŒ€์ด ๋…๋ฆฝ์ ์œผ๋กœ ๊ฐœ๋ฐœํ•˜๋ฉด์„œ๋„, ํ•„์š”ํ•œ ๋ถ€๋ถ„์€ ์‰ฝ๊ฒŒ ๊ณต์œ ํ•  ์ˆ˜ ์žˆ๊ฑฐ๋“ ์š”. ๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ

์žฌ๋Šฅ๋„ท ๊ฐ™์€ ํ”Œ๋žซํผ์—์„œ๋„ ์ด๋Ÿฐ ๋ฐฉ์‹์„ ์ ์šฉํ•˜๋ฉด ์ •๋ง ์ข‹์„ ๊ฒƒ ๊ฐ™์•„์š”. ์˜ˆ๋ฅผ ๋“ค์–ด, ์žฌ๋Šฅ ํ‰๊ฐ€ ์‹œ์Šคํ…œ, ๊ฒฐ์ œ ๋ชจ๋“ˆ, ์‚ฌ์šฉ์ž ํ”„๋กœํ•„ ์ปดํฌ๋„ŒํŠธ ๋“ฑ์„ ๊ฐ๊ฐ ๋…๋ฆฝ์ ์ธ ๋งˆ์ดํฌ๋กœํ”„๋ก ํŠธ์—”๋“œ๋กœ ๊ฐœ๋ฐœํ•˜๊ณ , Module Federation์„ ํ†ตํ•ด ํ†ตํ•ฉํ•  ์ˆ˜ ์žˆ์„ ๊ฑฐ์˜ˆ์š”. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๊ฐ ๋ถ€๋ถ„์„ ๋” ์‰ฝ๊ฒŒ ๊ด€๋ฆฌํ•˜๊ณ  ์—…๋ฐ์ดํŠธํ•  ์ˆ˜ ์žˆ๊ฒ ์ฃ ? ๐Ÿš€

์ž, ์—ฌ๊ธฐ๊นŒ์ง€ Module Federation์— ๋Œ€ํ•ด ์•Œ์•„๋ดค์–ด์š”. ์–ด๋•Œ์š”? ์ƒ๊ฐ๋ณด๋‹ค ์žฌ๋ฐŒ์ฃ ? ใ…‹ใ…‹ใ…‹ ์ด์ œ ์šฐ๋ฆฌ๊ฐ€ ๋ฐฐ์šด ๊ฑธ ์‹ค์ œ๋กœ ์–ด๋–ป๊ฒŒ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ๋” ์ž์„ธํžˆ ์•Œ์•„๋ณผ๊นŒ์š”? ๐Ÿค“

๐Ÿ› ๏ธ Module Federation ์‹ค์ „ ์ ์šฉํ•˜๊ธฐ ๐Ÿ’ช

์ž, ์ด์ œ ์šฐ๋ฆฌ๊ฐ€ ๋ฐฐ์šด Module Federation์„ ์‹ค์ œ๋กœ ์–ด๋–ป๊ฒŒ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์•Œ์•„๋ณผ ์ฐจ๋ก€์˜ˆ์š”! ๐ŸŽฌ ์‹ค์ œ ํ”„๋กœ์ ํŠธ์— ์ ์šฉํ•˜๋ฉด์„œ ๊ฒช์„ ์ˆ˜ ์žˆ๋Š” ์ƒํ™ฉ๋“ค๊ณผ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์„ ํ•จ๊ป˜ ์‚ดํŽด๋ณผ๊ฒŒ์š”. ์ค€๋น„๋˜์…จ๋‚˜์š”? Let's go! ๐Ÿš€

1. ํ”„๋กœ์ ํŠธ ๊ตฌ์กฐ ์„ค๊ณ„ํ•˜๊ธฐ ๐Ÿ“

๋จผ์ €, ์šฐ๋ฆฌ์˜ ํ”„๋กœ์ ํŠธ๋ฅผ ์–ด๋–ป๊ฒŒ ๋‚˜๋ˆŒ์ง€ ๊ฒฐ์ •ํ•ด์•ผ ํ•ด์š”. ์˜ˆ๋ฅผ ๋“ค์–ด, ์žฌ๋Šฅ๋„ท ๊ฐ™์€ ํ”Œ๋žซํผ์„ ๋งŒ๋“ ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด๋ณผ๊ฒŒ์š”. ์–ด๋–ป๊ฒŒ ๋‚˜๋ˆŒ ์ˆ˜ ์žˆ์„๊นŒ์š”?

  • ๋ฉ”์ธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ (Host) ๐Ÿ 
  • ์‚ฌ์šฉ์ž ํ”„๋กœํ•„ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๐Ÿ‘ค
  • ์žฌ๋Šฅ ๊ฑฐ๋ž˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๐Ÿ’ผ
  • ๊ฒฐ์ œ ์‹œ์Šคํ…œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๐Ÿ’ณ
  • ๋ฆฌ๋ทฐ ๋ฐ ํ‰๊ฐ€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ โญ

์ด๋ ‡๊ฒŒ ๋‚˜๋ˆ„๋ฉด ๊ฐ ํŒ€์ด ๋…๋ฆฝ์ ์œผ๋กœ ๊ฐœ๋ฐœํ•  ์ˆ˜ ์žˆ์–ด์š”. coolํ•˜์ฃ ? ๐Ÿ˜Ž

2. ์›นํŒฉ ์„ค์ •ํ•˜๊ธฐ โš™๏ธ

๊ฐ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์›นํŒฉ ์„ค์ •์„ ํ•ด์ค˜์•ผ ํ•ด์š”. ์˜ˆ๋ฅผ ๋“ค์–ด, ๋ฉ”์ธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜(Host)์˜ ์„ค์ •์€ ์ด๋ ‡๊ฒŒ ๋  ์ˆ˜ ์žˆ์–ด์š”:


// webpack.config.js
const { ModuleFederationPlugin } = require('webpack').container;

module.exports = {
  // ... ๋‹ค๋ฅธ ์›นํŒฉ ์„ค์ •๋“ค ...
  plugins: [
    new ModuleFederationPlugin({
      name: 'host',
      filename: 'remoteEntry.js',
      remotes: {
        profile: 'profile@http://localhost:3001/remoteEntry.js',
        trade: 'trade@http://localhost:3002/remoteEntry.js',
        payment: 'payment@http://localhost:3003/remoteEntry.js',
        review: 'review@http://localhost:3004/remoteEntry.js',
      },
      shared: ['react', 'react-dom'],
    }),
  ],
};
  code>

๊ฐ Remote ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์„ค์ •๋„ ๋น„์Šทํ•˜๊ฒŒ ํ•ด์ค˜์•ผ ํ•ด์š”. ์˜ˆ๋ฅผ ๋“ค์–ด, ์‚ฌ์šฉ์ž ํ”„๋กœํ•„ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์„ค์ •์€ ์ด๋ ‡๊ฒŒ ๋  ์ˆ˜ ์žˆ์ฃ :


// webpack.config.js (profile app)
const { ModuleFederationPlugin } = require('webpack').container;

module.exports = {
  // ... ๋‹ค๋ฅธ ์›นํŒฉ ์„ค์ •๋“ค ...
  plugins: [
    new ModuleFederationPlugin({
      name: 'profile',
      filename: 'remoteEntry.js',
      exposes: {
        './ProfileCard': './src/components/ProfileCard',
        './ProfileEdit': './src/components/ProfileEdit',
      },
      shared: ['react', 'react-dom'],
    }),
  ],
};

3. ์ปดํฌ๋„ŒํŠธ ๊ฐœ๋ฐœํ•˜๊ธฐ ๐ŸŽจ

์ด์ œ ๊ฐ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ํ•„์š”ํ•œ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ฐœ๋ฐœํ•ด์š”. ์˜ˆ๋ฅผ ๋“ค์–ด, ์‚ฌ์šฉ์ž ํ”„๋กœํ•„ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ProfileCard ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋งŒ๋“ค์–ด๋ณผ๊ฒŒ์š”:


// src/components/ProfileCard.js
import React from 'react';

const ProfileCard = ({ name, skills, rating }) => (
  <div className="profile-card">
    <h2>{name}</h2>
    <p>Skills: {skills.join(', ')}</p>
    <p>Rating: {rating} / 5</p>
  </div>
);

export default ProfileCard;

4. ์ปดํฌ๋„ŒํŠธ ์‚ฌ์šฉํ•˜๊ธฐ ๐Ÿ”—

์ด์ œ ๋ฉ”์ธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜(Host)์—์„œ ์ด ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด์š”:


// src/App.js in host application
import React, { lazy, Suspense } from 'react';

const ProfileCard = lazy(() => import('profile/ProfileCard'));

const App = () => (
  <div>
    <h1>Welcome to TalentNet!</h1>
    <Suspense fallback={<div>Loading Profile...</div>}>
      <ProfileCard name="John Doe" skills={['React', 'Node.js']} rating={4.5} />
    </Suspense>
  </div>
);

export default App;

๐Ÿ”” ์ฃผ์˜์‚ฌํ•ญ: lazy์™€ Suspense๋ฅผ ์‚ฌ์šฉํ•ด ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋™์ ์œผ๋กœ ๋ถˆ๋Ÿฌ์˜ค๊ณ  ์žˆ์–ด์š”. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ํ•„์š”ํ•  ๋•Œ๋งŒ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋กœ๋“œํ•  ์ˆ˜ ์žˆ์–ด ์„ฑ๋Šฅ์ด ํ–ฅ์ƒ๋ผ์š”!

5. ์Šคํƒ€์ผ ๊ด€๋ฆฌํ•˜๊ธฐ ๐Ÿ’…

๋งˆ์ดํฌ๋กœํ”„๋ก ํŠธ์—”๋“œ์—์„œ ์Šคํƒ€์ผ ๊ด€๋ฆฌ๋Š” ์กฐ๊ธˆ ๊นŒ๋‹ค๋กœ์šธ ์ˆ˜ ์žˆ์–ด์š”. CSS-in-JS ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜, CSS Modules๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์•„์š”. ์˜ˆ๋ฅผ ๋“ค์–ด, styled-components๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด:


// src/components/ProfileCard.js
import React from 'react';
import styled from 'styled-components';

const Card = styled.div`
  border: 1px solid #ddd;
  border-radius: 8px;
  padding: 16px;
  margin: 16px;
`;

const ProfileCard = ({ name, skills, rating }) => (
  <Card>
    <h2>{name}</h2>
    <p>Skills: {skills.join(', ')}</p>
    <p>Rating: {rating} / 5</p>
  </Card>
);

export default ProfileCard;

6. ์ƒํƒœ ๊ด€๋ฆฌํ•˜๊ธฐ ๐Ÿ”„

์—ฌ๋Ÿฌ ๋งˆ์ดํฌ๋กœํ”„๋ก ํŠธ์—”๋“œ ๊ฐ„์— ์ƒํƒœ๋ฅผ ๊ณต์œ ํ•ด์•ผ ํ•  ๋•Œ๊ฐ€ ์žˆ์–ด์š”. ์ด๋Ÿด ๋•Œ๋Š” Redux๋‚˜ MobX ๊ฐ™์€ ์ƒํƒœ ๊ด€๋ฆฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด์š”. ์˜ˆ๋ฅผ ๋“ค์–ด, Redux๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด:


// src/store/index.js in host application
import { createStore } from 'redux';

const initialState = {
  user: null,
};

function reducer(state = initialState, action) {
  switch (action.type) {
    case 'SET_USER':
      return { ...state, user: action.payload };
    default:
      return state;
  }
}

const store = createStore(reducer);
export default store;

๊ทธ๋ฆฌ๊ณ  ์ด ์Šคํ† ์–ด๋ฅผ ๊ฐ ๋งˆ์ดํฌ๋กœํ”„๋ก ํŠธ์—”๋“œ์—์„œ ๊ณต์œ ํ•  ์ˆ˜ ์žˆ์–ด์š”:


// src/index.js in host application
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import App from './App';
import store from './store';

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
);

7. ์—๋Ÿฌ ์ฒ˜๋ฆฌํ•˜๊ธฐ ๐Ÿšจ

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


// src/ErrorBoundary.js
import React from 'react';

class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }

  static getDerivedStateFromError(error) {
    return { hasError: true };
  }

  render() {
    if (this.state.hasError) {
      return <h1>Something went wrong.</h1>;
    }

    return this.props.children;
  }
}

export default ErrorBoundary;

์ด์ œ ์ด ErrorBoundary๋ฅผ ์‚ฌ์šฉํ•ด ๊ฐ ๋งˆ์ดํฌ๋กœํ”„๋ก ํŠธ์—”๋“œ๋ฅผ ๊ฐ์‹ธ์ค„ ์ˆ˜ ์žˆ์–ด์š”:


// src/App.js in host application
import React, { lazy, Suspense } from 'react';
import ErrorBoundary from './ErrorBoundary';

const ProfileCard = lazy(() => import('profile/ProfileCard'));

const App = () => (
  <div>
    <h1>Welcome to TalentNet!</h1>
    <ErrorBoundary>
      <Suspense fallback={<div>Loading Profile...</div>}>
        <ProfileCard name="John Doe" skills={['React', 'Node.js']} rating={4.5} />
      </Suspense>
    </ErrorBoundary>
  </div>
);

export default App;

8. ํ…Œ์ŠคํŒ… ์ „๋žต ๐Ÿงช

๋งˆ์ดํฌ๋กœํ”„๋ก ํŠธ์—”๋“œ์—์„œ์˜ ํ…Œ์ŠคํŒ…์€ ์กฐ๊ธˆ ๋ณต์žกํ•  ์ˆ˜ ์žˆ์–ด์š”. ๊ฐ ๋งˆ์ดํฌ๋กœํ”„๋ก ํŠธ์—”๋“œ๋ฅผ ๋…๋ฆฝ์ ์œผ๋กœ ํ…Œ์ŠคํŠธํ•˜๊ณ , ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ๋„ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•ด์š”.

  • ๋‹จ์œ„ ํ…Œ์ŠคํŠธ: ๊ฐ ์ปดํฌ๋„ŒํŠธ์™€ ํ•จ์ˆ˜๋ฅผ ๋…๋ฆฝ์ ์œผ๋กœ ํ…Œ์ŠคํŠธํ•ด์š”.
  • ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ: ์—ฌ๋Ÿฌ ๋งˆ์ดํฌ๋กœํ”„๋ก ํŠธ์—”๋“œ๊ฐ€ ํ•จ๊ป˜ ์ž‘๋™ํ•˜๋Š” ๊ฒƒ์„ ํ…Œ์ŠคํŠธํ•ด์š”.
  • E2E ํ…Œ์ŠคํŠธ: ์ „์ฒด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ํ๋ฆ„์„ ํ…Œ์ŠคํŠธํ•ด์š”.

์˜ˆ๋ฅผ ๋“ค์–ด, Jest์™€ React Testing Library๋ฅผ ์‚ฌ์šฉํ•œ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๋Š” ์ด๋ ‡๊ฒŒ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์–ด์š”:


// src/components/ProfileCard.test.js
import React from 'react';
import { render, screen } from '@testing-library/react';
import ProfileCard from './ProfileCard';

test('renders profile card with correct information', () => {
  render(<ProfileCard name="John Doe" skills={['React', 'Node.js']} rating={4.5} />);
  
  expect(screen.getByText('John Doe')).toBeInTheDocument();
  expect(screen.getByText('Skills: React, Node.js')).toBeInTheDocument();
  expect(screen.getByText('Rating: 4.5 / 5')).toBeInTheDocument();
});

9. ์„ฑ๋Šฅ ์ตœ์ ํ™” ๐Ÿš€

๋งˆ์ดํฌ๋กœํ”„๋ก ํŠธ์—”๋“œ์—์„œ ์„ฑ๋Šฅ์€ ๋งค์šฐ ์ค‘์š”ํ•ด์š”. ๋ช‡ ๊ฐ€์ง€ ํŒ์„ ๋“œ๋ฆด๊ฒŒ์š”:

  • Code Splitting: ํ•„์š”ํ•œ ์ฝ”๋“œ๋งŒ ๋กœ๋“œํ•˜์„ธ์š”.
  • Lazy Loading: ์ปดํฌ๋„ŒํŠธ๋ฅผ ํ•„์š”ํ•  ๋•Œ๋งŒ ๋กœ๋“œํ•˜์„ธ์š”.
  • Caching: ์ž์ฃผ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š๋Š” ๋ฆฌ์†Œ์Šค๋Š” ์บ์‹ฑํ•˜์„ธ์š”.
  • Prefetching: ์‚ฌ์šฉ์ž๊ฐ€ ํ•„์š”๋กœ ํ•  ๊ฒƒ ๊ฐ™์€ ๋ฆฌ์†Œ์Šค๋ฅผ ๋ฏธ๋ฆฌ ๋กœ๋“œํ•˜์„ธ์š”.

์˜ˆ๋ฅผ ๋“ค์–ด, ์›นํŒฉ์˜ prefetch ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด์š”:


// src/App.js in host application
import React, { lazy, Suspense } from 'react';

const ProfileCard = lazy(() => import(/* webpackPrefetch: true */ 'profile/ProfileCard'));

// ... ๋‚˜๋จธ์ง€ ์ฝ”๋“œ ...

๐Ÿ’ก Pro Tip: ์„ฑ๋Šฅ ์ตœ์ ํ™”๋Š” ์ง€์†์ ์ธ ๊ณผ์ •์ด์—์š”. ํ•ญ์ƒ ๋ชจ๋‹ˆํ„ฐ๋งํ•˜๊ณ  ๊ฐœ์„ ํ•ด ๋‚˜๊ฐ€์„ธ์š”!

10. ๋ฐฐํฌ ์ „๋žต ๐Ÿšข

๋งˆ์ดํฌ๋กœํ”„๋ก ํŠธ์—”๋“œ์˜ ๋ฐฐํฌ๋Š” ์กฐ๊ธˆ ๋ณต์žกํ•  ์ˆ˜ ์žˆ์–ด์š”. ๊ฐ ๋งˆ์ดํฌ๋กœํ”„๋ก ํŠธ์—”๋“œ๋ฅผ ๋…๋ฆฝ์ ์œผ๋กœ ๋ฐฐํฌํ•˜๊ณ , ํ˜ธ์ŠคํŠธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ์ด๋ฅผ ํ†ตํ•ฉํ•ด์•ผ ํ•ด์š”. CI/CD ํŒŒ์ดํ”„๋ผ์ธ์„ ์ž˜ ๊ตฌ์„ฑํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•ด์š”.

์˜ˆ๋ฅผ ๋“ค์–ด, GitHub Actions๋ฅผ ์‚ฌ์šฉํ•œ CI/CD ์„ค์ •์€ ์ด๋ ‡๊ฒŒ ํ•  ์ˆ˜ ์žˆ์–ด์š”:


# .github/workflows/deploy.yml
name: Deploy Microfrontend

on:
  push:
    branches: [ main ]

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - name: Use Node.js
      uses: actions/setup-node@v2
      with:
        node-version: '14.x'
    - run: npm ci
    - run: npm run build
    - name: Deploy to S3
      uses: jakejarvis/s3-sync-action@master
      with:
        args: --acl public-read --follow-symlinks --delete
      env:
        AWS_S3_BUCKET: ${{ secrets.AWS_S3_BUCKET }}
        AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
        AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
        AWS_REGION: 'us-west-1'
        SOURCE_DIR: 'build'

์ž, ์—ฌ๊ธฐ๊นŒ์ง€ Module Federation์„ ์‚ฌ์šฉํ•œ ๋งˆ์ดํฌ๋กœํ”„๋ก ํŠธ์—”๋“œ ๊ตฌํ˜„์— ๋Œ€ํ•ด ์ž์„ธํžˆ ์•Œ์•„๋ดค์–ด์š”. ์–ด๋– ์„ธ์š”? ์ƒ๊ฐ๋ณด๋‹ค ๋ณต์žกํ•˜์ง€๋งŒ, ์ด๋ ‡๊ฒŒ ๊ตฌํ˜„ํ•˜๋ฉด ์ •๋ง ๊ฐ•๋ ฅํ•œ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ์–ด์š”! ๐Ÿš€

์žฌ๋Šฅ๋„ท ๊ฐ™์€ ํ”Œ๋žซํผ์„ ์ด๋Ÿฐ ๋ฐฉ์‹์œผ๋กœ ๊ตฌํ˜„ํ•˜๋ฉด, ๊ฐ ๊ธฐ๋Šฅ์„ ๋…๋ฆฝ์ ์œผ๋กœ ๊ฐœ๋ฐœํ•˜๊ณ  ๋ฐฐํฌํ•  ์ˆ˜ ์žˆ์–ด ์œ ์ง€๋ณด์ˆ˜๊ฐ€ ์‰ฌ์›Œ์ง€๊ณ , ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•˜๊ธฐ๋„ ํŽธํ•ด์งˆ ๊ฑฐ์˜ˆ์š”. ๋˜ํ•œ ํŒ€ ๊ฐ„์˜ ํ˜‘์—…๋„ ๋” ์›ํ™œํ•ด์งˆ ์ˆ˜ ์žˆ์ฃ . ๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ

๋ฌผ๋ก  ์ด ๋ชจ๋“  ๊ฑธ ํ•œ ๋ฒˆ์— ์™„๋ฒฝํ•˜๊ฒŒ ๊ตฌํ˜„ํ•˜๊ธฐ๋Š” ์–ด๋ ค์šธ ๊ฑฐ์˜ˆ์š”. ํ•˜์ง€๋งŒ ์กฐ๊ธˆ์”ฉ ์ ์šฉํ•ด ๋‚˜๊ฐ€๋ฉด์„œ ๊ฒฝํ—˜์„ ์Œ“๋‹ค ๋ณด๋ฉด, ์–ด๋Š์ƒˆ ๊ฐ•๋ ฅํ•˜๊ณ  ์œ ์—ฐํ•œ ๋งˆ์ดํฌ๋กœํ”„๋ก ํŠธ์—”๋“œ ์•„ํ‚คํ…์ฒ˜๋ฅผ ๊ฐ€์ง„ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ์„ ๊ฑฐ์˜ˆ์š”. ํ™”์ดํŒ…! ๐Ÿ’ช๐Ÿ˜Š

๐ŸŽฌ ๋งˆ๋ฌด๋ฆฌ: ๋งˆ์ดํฌ๋กœํ”„๋ก ํŠธ์—”๋“œ์™€ Module Federation์˜ ๋ฏธ๋ž˜ ๐Ÿ”ฎ

์ž, ์—ฌ๋Ÿฌ๋ถ„! ์šฐ๋ฆฌ๊ฐ€ ํ•จ๊ป˜ ๋งˆ์ดํฌ๋กœํ”„๋ก ํŠธ์—”๋“œ์™€ Module Federation์— ๋Œ€ํ•ด ๊นŠ์ด ์žˆ๊ฒŒ ์•Œ์•„๋ดค์–ด์š”. ์–ด๋– ์…จ๋‚˜์š”? ๐Ÿค” ์ฒ˜์Œ์—๋Š” ์ข€ ๋ณต์žกํ•ด ๋ณด์˜€์ง€๋งŒ, ํ•˜๋‚˜์”ฉ ์‚ดํŽด๋ณด๋‹ˆ ์ •๋ง ๊ฐ•๋ ฅํ•˜๊ณ  ์œ ์šฉํ•œ ๊ธฐ์ˆ ์ด๋ผ๋Š” ๊ฑธ ๋Š๋ผ์…จ์ฃ ?

์ด ๊ธฐ์ˆ ๋“ค์€ ์•ž์œผ๋กœ ์›น ๊ฐœ๋ฐœ ์„ธ๊ณ„์—์„œ ๋”์šฑ ์ค‘์š”ํ•œ ์œ„์น˜๋ฅผ ์ฐจ์ง€ํ•˜๊ฒŒ ๋  ๊ฑฐ์˜ˆ์š”. ์™œ ๊ทธ๋Ÿด๊นŒ์š”? ๐Ÿง

  • ๋Œ€๊ทœ๋ชจ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ฐœ๋ฐœ์ด ๋”์šฑ ํšจ์œจ์ ์œผ๋กœ ๋ณ€ํ•  ๊ฑฐ์˜ˆ์š”. ๐Ÿ‘จโ€๐Ÿ’ป๐Ÿ‘ฉโ€๐Ÿ’ป
  • ํŒ€ ๊ฐ„ ํ˜‘์—…์ด ๋”์šฑ ์›ํ™œํ•ด์งˆ ๊ฑฐ์˜ˆ์š”. ๐Ÿค
  • ๊ธฐ์ˆ  ์Šคํƒ์˜ ์œ ์—ฐ์„ฑ์ด ๋†’์•„์งˆ ๊ฑฐ์˜ˆ์š”. ๐Ÿ”ง
  • ์„ฑ๋Šฅ๊ณผ ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์ด ๊ฐœ์„ ๋  ๊ฑฐ์˜ˆ์š”. ๐Ÿš€

ํ•˜์ง€๋งŒ ๋ชจ๋“  ๊ธฐ์ˆ ์ด ๊ทธ๋ ‡๋“ฏ, ๋งˆ์ดํฌ๋กœํ”„๋ก ํŠธ์—”๋“œ์™€ Module Federation๋„ ๋งŒ๋Šฅ ํ•ด๊ฒฐ์ฑ…์€ ์•„๋‹ˆ์—์š”. ํ”„๋กœ์ ํŠธ์˜ ๊ทœ๋ชจ, ํŒ€์˜ ๊ตฌ์กฐ, ๊ธฐ์ˆ ์  ์š”๊ตฌ์‚ฌํ•ญ ๋“ฑ์„ ์ž˜ ๊ณ ๋ คํ•ด์„œ ๋„์ž… ์—ฌ๋ถ€๋ฅผ ๊ฒฐ์ •ํ•ด์•ผ ํ•ด์š”.

๐Ÿ’ก ๋ฏธ๋ž˜๋ฅผ ์œ„ํ•œ ํŒ: ์ด ๊ธฐ์ˆ ๋“ค์„ ๋ฐฐ์šฐ๊ณ  ์‹คํ—˜ํ•ด๋ณด์„ธ์š”. ์ž‘์€ ํ”„๋กœ์ ํŠธ๋ถ€ํ„ฐ ์‹œ์ž‘ํ•ด์„œ ์ ์  ๊ทœ๋ชจ๋ฅผ ํ‚ค์›Œ๋‚˜๊ฐ€๋ฉด ์ข‹์•„์š”. ๊ฒฝํ—˜์ด ์Œ“์ด๋ฉด ์Œ“์ผ์ˆ˜๋ก ๋” ํšจ๊ณผ์ ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์„ ๊ฑฐ์˜ˆ์š”!

์žฌ๋Šฅ๋„ท ๊ฐ™์€ ํ”Œ๋žซํผ์„ ๋งŒ๋“ ๋‹ค๊ณ  ์ƒ๊ฐํ•ด๋ณด์„ธ์š”. ์‚ฌ์šฉ์ž ํ”„๋กœํ•„, ์žฌ๋Šฅ ๊ฑฐ๋ž˜, ๊ฒฐ์ œ ์‹œ์Šคํ…œ, ๋ฆฌ๋ทฐ ์‹œ์Šคํ…œ ๋“ฑ ๋‹ค์–‘ํ•œ ๊ธฐ๋Šฅ์„ ๊ฐ๊ฐ์˜ ๋งˆ์ดํฌ๋กœํ”„๋ก ํŠธ์—”๋“œ๋กœ ๊ฐœ๋ฐœํ•˜๊ณ , Module Federation์œผ๋กœ ํ†ตํ•ฉํ•  ์ˆ˜ ์žˆ์–ด์š”. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๊ฐ ํŒ€์ด ๋…๋ฆฝ์ ์œผ๋กœ ๊ฐœ๋ฐœํ•˜๋ฉด์„œ๋„, ์ „์ฒด์ ์œผ๋กœ๋Š” ํ•˜๋‚˜์˜ ํ†ต์ผ๋œ ์„œ๋น„์Šค๋ฅผ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ๊ฒ ์ฃ ? ๐Ÿ‘

๋งˆ์ง€๋ง‰์œผ๋กœ, ์›น ๊ฐœ๋ฐœ์˜ ์„ธ๊ณ„๋Š” ํ•ญ์ƒ ๋ณ€ํ™”ํ•˜๊ณ  ์žˆ์–ด์š”. ๋งˆ์ดํฌ๋กœํ”„๋ก ํŠธ์—”๋“œ์™€ Module Federation๋„ ๊ณ„์† ๋ฐœ์ „ํ•  ๊ฑฐ์˜ˆ์š”. ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ์ด ์ถ”๊ฐ€๋˜๊ณ , ๋” ๋‚˜์€ ๋ฐฉ์‹์ด ๋“ฑ์žฅํ•  ์ˆ˜๋„ ์žˆ์ฃ . ๊ทธ๋Ÿฌ๋‹ˆ ํ•ญ์ƒ ์ตœ์‹  ํŠธ๋ Œ๋“œ๋ฅผ ์ฃผ์‹œํ•˜๊ณ , ๊ณ„์†ํ•ด์„œ ํ•™์Šตํ•˜๋Š” ์ž์„ธ๊ฐ€ ์ค‘์š”ํ•ด์š”. ๐ŸŒฑ

์—ฌ๋Ÿฌ๋ถ„, ๊ธด ์—ฌ์ •์ด์—ˆ์ง€๋งŒ ํ•จ๊ป˜ ๋๊นŒ์ง€ ์™€์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ด์š”! ์ด์ œ ์—ฌ๋Ÿฌ๋ถ„์€ ๋งˆ์ดํฌ๋กœํ”„๋ก ํŠธ์—”๋“œ์™€ Module Federation์˜ ์ „๋ฌธ๊ฐ€๊ฐ€ ๋˜์…จ์–ด์š”. ์ด ์ง€์‹์„ ํ™œ์šฉํ•ด์„œ ๋” ๋ฉ‹์ง„ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋งŒ๋“ค์–ด๋ณด์„ธ์š”. ์„ธ์ƒ์„ ๋†€๋ผ๊ฒŒ ํ•  ์—ฌ๋Ÿฌ๋ถ„์˜ ํ”„๋กœ์ ํŠธ๋ฅผ ๊ธฐ๋Œ€ํ•˜๊ณ  ์žˆ์„๊ฒŒ์š”! ํ™”์ดํŒ…! ๐Ÿ’ช๐Ÿ˜Š