๐ŸŒŸ Shadow DOM์œผ๋กœ ์Šคํƒ€์ผ ์บก์Šํ™”ํ•˜๊ธฐ: ์›น ๊ฐœ๋ฐœ์˜ ์ˆจ์€ ๋ณด์„ ๐Ÿ’Ž

์ฝ˜ํ…์ธ  ๋Œ€ํ‘œ ์ด๋ฏธ์ง€ - ๐ŸŒŸ Shadow DOM์œผ๋กœ ์Šคํƒ€์ผ ์บก์Šํ™”ํ•˜๊ธฐ: ์›น ๊ฐœ๋ฐœ์˜ ์ˆจ์€ ๋ณด์„ ๐Ÿ’Ž

 

 

์•ˆ๋…•ํ•˜์„ธ์š”, ๊ฐœ๋ฐœ์ž ์—ฌ๋Ÿฌ๋ถ„! ์˜ค๋Š˜์€ ์ •๋ง ํฅ๋ฏธ์ง„์ง„ํ•œ ์ฃผ์ œ๋กœ ์ฐพ์•„์™”์–ด์š”. ๋ฐ”๋กœ Shadow DOM์„ ํ™œ์šฉํ•œ ์Šคํƒ€์ผ ์บก์Šํ™”์— ๋Œ€ํ•ด ๊นŠ์ด ํŒŒํ—ค์ณ๋ณผ ๊ฑฐ์˜ˆ์š”. ์ด๊ฑฐ ์™„์ „ ๋Œ€๋ฐ• ์ฃผ์ œ ์•„๋‹ˆ์—์š”? ใ…‹ใ…‹ใ…‹ ๐Ÿ˜†

์—ฌ๋Ÿฌ๋ถ„, ํ˜น์‹œ ์›น ๊ฐœ๋ฐœํ•˜๋‹ค๊ฐ€ ์Šคํƒ€์ผ์ด ์—‰์ผœ์„œ ๋จธ๋ฆฌ ์•„ํŒ ๋˜ ์  ์žˆ์œผ์‹ ๊ฐ€์š”? CSS ํด๋ž˜์Šค๋ช… ์ง“๋Š๋ผ ๊ณ ๋ฏผํ•˜๋‹ค๊ฐ€ ๋ฐค์ƒˆ์‹  ์ ์€์š”? ๊ทธ๋ ‡๋‹ค๋ฉด ์˜ค๋Š˜ ๋ฐฐ์šธ Shadow DOM์ด ์—ฌ๋Ÿฌ๋ถ„์˜ ๊ตฌ์›์ž๊ฐ€ ๋  ๊ฑฐ์˜ˆ์š”! ๐Ÿ‘ผ

๐ŸŽ“ TIP: Shadow DOM์€ ์›น ์ปดํฌ๋„ŒํŠธ์˜ ํ•ต์‹ฌ ๊ธฐ์ˆ  ์ค‘ ํ•˜๋‚˜๋กœ, HTML, CSS, JavaScript๋ฅผ ์บก์Šํ™”ํ•˜์—ฌ ์™ธ๋ถ€์™€ ๊ฒฉ๋ฆฌ๋œ ๋…๋ฆฝ์ ์ธ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค.

์ž, ์ด์ œ ๋ณธ๊ฒฉ์ ์œผ๋กœ Shadow DOM์˜ ์„ธ๊ณ„๋กœ ๋“ค์–ด๊ฐ€๋ณผ๊นŒ์š”? ์ค€๋น„๋˜์…จ๋‚˜์š”? ๊ทธ๋Ÿผ ๊ณ ๊ณ ์”ฝ~ ๐Ÿš€

๐ŸŒˆ Shadow DOM์ด ๋ญ๊ธธ๋ž˜ ์ด๋ ‡๊ฒŒ ํ•ซํ•œ ๊ฑฐ์•ผ?

Shadow DOM์ด๋ผ... ์ด๋ฆ„๋ถ€ํ„ฐ ์ข€ ๋ฏธ์Šคํ„ฐ๋ฆฌํ•˜์ง€ ์•Š๋‚˜์š”? ใ…‹ใ…‹ใ…‹ ๋งˆ์น˜ ์–ด๋‘  ์†์— ์ˆจ์–ด์žˆ๋Š” ๋น„๋ฐ€ ๊ฐ™์•„์š”. ๊ทผ๋ฐ ์‹ค์ œ๋กœ๋„ ๊ทธ๋ž˜์š”! Shadow DOM์€ ์›น ํŽ˜์ด์ง€์˜ ๋ฉ”์ธ DOM๊ณผ๋Š” ๋ณ„๊ฐœ๋กœ ์กด์žฌํ•˜๋Š” ์ˆจ๊ฒจ์ง„ DOM ํŠธ๋ฆฌ๋ฅผ ๋งŒ๋“ค์–ด๋‚ด๊ฑฐ๋“ ์š”. ๐Ÿ˜ฒ

์‰ฝ๊ฒŒ ๋งํ•ด์„œ, Shadow DOM์€ ์šฐ๋ฆฌ๊ฐ€ ๋งŒ๋“  ์ปดํฌ๋„ŒํŠธ๋ฅผ ์™ธ๋ถ€ ์„ธ๊ณ„๋กœ๋ถ€ํ„ฐ ๋ณดํ˜ธํ•ด์ฃผ๋Š” ๋ฐฉํŒจ ๊ฐ™์€ ๊ฑฐ์˜ˆ์š”. ์ด ๋ฐฉํŒจ ๋•๋ถ„์— ์šฐ๋ฆฌ์˜ ์†Œ์ค‘ํ•œ ์Šคํƒ€์ผ๊ณผ ๋งˆํฌ์—…์ด ์™ธ๋ถ€์˜ CSS์— ์˜ํ–ฅ์„ ๋ฐ›์ง€ ์•Š๊ณ  ์•ˆ์ „ํ•˜๊ฒŒ ๋ณดํ˜ธ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ต๋‹ˆ๋‹ค.

๐Ÿ’ก ์•Œ์“ธ์‹ ์žก: Shadow DOM์ด๋ผ๋Š” ์ด๋ฆ„์€ ์ด DOM์ด ๋ฉ”์ธ ๋ฌธ์„œ DOM์— '๊ทธ๋ฆผ์ž(Shadow)'์ฒ˜๋Ÿผ ๋ถ™์–ด์žˆ๋‹ค๋Š” ๊ฐœ๋…์—์„œ ์™”์–ด์š”. ๋ฉ‹์ง€์ง€ ์•Š๋‚˜์š”?

๊ทธ๋Ÿผ ์ด์ œ Shadow DOM์ด ์–ด๋–ป๊ฒŒ ์ƒ๊ฒผ๋Š”์ง€ ํ•œ๋ฒˆ ๋“ค์—ฌ๋‹ค๋ณผ๊นŒ์š”? ์•„๋ž˜ SVG๋กœ ๊ฐ„๋‹จํ•˜๊ฒŒ ํ‘œํ˜„ํ•ด๋ดค์–ด์š”!

Shadow DOM ๊ตฌ์กฐ ๋ฉ”์ธ DOM Shadow Host Shadow Root Shadow DOM ๋‚ด๋ถ€ (์บก์Šํ™”๋œ ์˜์—ญ) ์™ธ๋ถ€ ์Šคํƒ€์ผ์˜ ์˜ํ–ฅ์„ ๋ฐ›์ง€ ์•Š๋Š” ์˜์—ญ

์šฐ์™€, ๊ทธ๋ฆผ์œผ๋กœ ๋ณด๋‹ˆ๊นŒ ๋” ์ดํ•ด๊ฐ€ ์ž˜ ๋˜์ฃ ? Shadow DOM์€ ๋งˆ์น˜ ๋น„๋ฐ€ ์š”์ƒˆ ๊ฐ™์•„์š”. ์™ธ๋ถ€์˜ ์Šคํƒ€์ผ ๊ณต๊ฒฉ(?)์œผ๋กœ๋ถ€ํ„ฐ ์šฐ๋ฆฌ์˜ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์•ˆ์ „ํ•˜๊ฒŒ ์ง€์ผœ์ฃผ๋Š” ๊ฑฐ์ฃ . ๐Ÿ‘ฎโ€โ™‚๏ธ

์ด๋ ‡๊ฒŒ Shadow DOM์„ ์‚ฌ์šฉํ•˜๋ฉด, ์šฐ๋ฆฌ๊ฐ€ ๋งŒ๋“  ์ปดํฌ๋„ŒํŠธ์˜ ์Šคํƒ€์ผ์ด ๋‹ค๋ฅธ ์š”์†Œ๋“ค๊ณผ ์ถฉ๋Œํ•  ๊ฑฑ์ • ์—†์ด ๋…๋ฆฝ์ ์œผ๋กœ ๋™์ž‘ํ•  ์ˆ˜ ์žˆ์–ด์š”. ์ด๊ฒŒ ๋ฐ”๋กœ ์Šคํƒ€์ผ ์บก์Šํ™”์˜ ํ•ต์‹ฌ์ด์—์š”!

๊ทธ๋Ÿผ ์ด์ œ Shadow DOM์„ ์–ด๋–ป๊ฒŒ ๋งŒ๋“ค๊ณ  ์‚ฌ์šฉํ•˜๋Š”์ง€ ์ž์„ธํžˆ ์•Œ์•„๋ณผ๊นŒ์š”? ์žฌ๋Šฅ๋„ท์—์„œ ๋ฐฐ์šด ์ง€์‹์„ ํ™œ์šฉํ•ด์„œ ์‹ค์ œ๋กœ ์ ์šฉํ•ด๋ณด๋ฉด ๋” ์žฌ๋ฐŒ์„ ๊ฑฐ์˜ˆ์š”! ๐Ÿ˜‰

๐Ÿ› ๏ธ Shadow DOM ๋งŒ๋“ค๊ธฐ: ์ดˆ๋ณด์ž๋„ ํ•  ์ˆ˜ ์žˆ์–ด์š”!

์ž, ์ด์ œ ๋ณธ๊ฒฉ์ ์œผ๋กœ Shadow DOM์„ ๋งŒ๋“ค์–ด๋ณผ ๊ฑฐ์˜ˆ์š”. ๊ฑฑ์ • ๋งˆ์„ธ์š”, ์ƒ๊ฐ๋ณด๋‹ค ์–ด๋ ต์ง€ ์•Š๋‹ต๋‹ˆ๋‹ค! ๐Ÿค—

๋จผ์ €, Shadow DOM์„ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด์„œ๋Š” Shadow Host๋ผ๋Š” ๊ฒƒ์ด ํ•„์š”ํ•ด์š”. ์ด๊ฑด ๊ทธ๋ƒฅ ์ผ๋ฐ˜์ ์ธ HTML ์š”์†Œ์˜ˆ์š”. ์˜ˆ๋ฅผ ๋“ค์–ด ์ด๋ ‡๊ฒŒ์š”:

<div id="shadow-host"></div>

์ด์ œ ์ด Shadow Host์— Shadow DOM์„ ๋ถ™์—ฌ๋ณผ ๊ฑฐ์˜ˆ์š”. JavaScript๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ด๋ ‡๊ฒŒ ํ•  ์ˆ˜ ์žˆ์–ด์š”:

const shadowHost = document.getElementById('shadow-host');
const shadowRoot = shadowHost.attachShadow({mode: 'open'});

์šฐ์™€! ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด Shadow DOM์ด ์ƒ์„ฑ๋˜์—ˆ์–ด์š”. attachShadow ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด์„œ Shadow Root๋ฅผ ๋งŒ๋“  ๊ฑฐ์˜ˆ์š”. ์—ฌ๊ธฐ์„œ {mode: 'open'}์€ ๋ญ˜๊นŒ์š”? ์ด๊ฑด ์™ธ๋ถ€์—์„œ JavaScript๋ฅผ ํ†ตํ•ด Shadow DOM์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ์˜ต์…˜์ด์—์š”.

๐Ÿšจ ์ฃผ์˜: mode๋ฅผ 'closed'๋กœ ์„ค์ •ํ•˜๋ฉด ์™ธ๋ถ€์—์„œ Shadow DOM์— ์ ‘๊ทผํ•  ์ˆ˜ ์—†์–ด์š”. ๋ณด์•ˆ์ด ์ค‘์š”ํ•œ ๊ฒฝ์šฐ์— ์‚ฌ์šฉํ•˜๋ฉด ์ข‹๊ฒ ์ฃ ?

์ด์ œ Shadow DOM ์•ˆ์— ๋‚ด์šฉ์„ ๋„ฃ์–ด๋ณผ๊นŒ์š”? ์ด๋ ‡๊ฒŒ ํ•  ์ˆ˜ ์žˆ์–ด์š”:

shadowRoot.innerHTML = `
  <style>
    p { color: blue; }
  </style>
  <p>์•ˆ๋…•ํ•˜์„ธ์š”, ์ €๋Š” Shadow DOM ์•ˆ์— ์žˆ์–ด์š”!</p>
`;

์งœ์ž”~ ๐ŸŽ‰ ์ด์ œ ์šฐ๋ฆฌ๋งŒ์˜ Shadow DOM์ด ์™„์„ฑ๋˜์—ˆ์–ด์š”! ์ด Shadow DOM ์•ˆ์— ์žˆ๋Š” p ํƒœ๊ทธ๋Š” ํŒŒ๋ž€์ƒ‰์œผ๋กœ ํ‘œ์‹œ๋  ๊ฑฐ์˜ˆ์š”. ๊ทธ๋ฆฌ๊ณ  ์ด ์Šคํƒ€์ผ์€ Shadow DOM ๋ฐ–์˜ ๋‹ค๋ฅธ p ํƒœ๊ทธ์—๋Š” ์ „ํ˜€ ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š์•„์š”. ์™„์ „ ๋Œ€๋ฐ• ์•„๋‹ˆ์—์š”? ใ…‹ใ…‹ใ…‹

์ด๋ ‡๊ฒŒ ๋งŒ๋“  Shadow DOM์„ ์‹œ๊ฐํ™”ํ•ด๋ณด๋ฉด ์ด๋Ÿฐ ๋ชจ์Šต์ด์—์š”:

Shadow DOM ๊ตฌ์กฐ์™€ ๋‚ด์šฉ ๋ฉ”์ธ DOM Shadow Host (div#shadow-host) Shadow Root <style> p { color: blue; } </style> <p>์•ˆ๋…•ํ•˜์„ธ์š”, ์ €๋Š” Shadow DOM ์•ˆ์— ์žˆ์–ด์š”!</p>

์ด ๊ทธ๋ฆผ์„ ๋ณด๋ฉด Shadow DOM์˜ ๊ตฌ์กฐ๊ฐ€ ํ•œ๋ˆˆ์— ๋“ค์–ด์˜ค์ฃ ? Shadow Host ์•ˆ์— Shadow Root๊ฐ€ ์žˆ๊ณ , ๊ทธ ์•ˆ์— ์šฐ๋ฆฌ๊ฐ€ ์ •์˜ํ•œ ์Šคํƒ€์ผ๊ณผ ๋‚ด์šฉ์ด ๋“ค์–ด์žˆ์–ด์š”. ์ด๋ ‡๊ฒŒ ์บก์Šํ™”๋œ ๊ตฌ์กฐ ๋•๋ถ„์— ์™ธ๋ถ€ ์Šคํƒ€์ผ์˜ ์˜ํ–ฅ์„ ๋ฐ›์ง€ ์•Š๋Š” ๊ฑฐ์˜ˆ์š”!

Shadow DOM์„ ์ด์šฉํ•˜๋ฉด ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์›น ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‰ฝ๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ์–ด์š”. ์˜ˆ๋ฅผ ๋“ค์–ด, ์žฌ๋Šฅ๋„ท์—์„œ ์‚ฌ์šฉ์ž ํ”„๋กœํ•„ ์นด๋“œ๋ฅผ ๋งŒ๋“ ๋‹ค๊ณ  ์ƒ๊ฐํ•ด๋ณผ๊นŒ์š”? Shadow DOM์„ ์ด์šฉํ•˜๋ฉด ํ”„๋กœํ•„ ์นด๋“œ์˜ ์Šคํƒ€์ผ๊ณผ ๊ตฌ์กฐ๋ฅผ ์™„๋ฒฝํ•˜๊ฒŒ ์บก์Šํ™”ํ•  ์ˆ˜ ์žˆ์–ด์š”. ๊ทธ๋Ÿฌ๋ฉด ์‚ฌ์ดํŠธ์˜ ๋‹ค๋ฅธ ๋ถ€๋ถ„์—์„œ ์–ด๋–ค ์Šคํƒ€์ผ์„ ์‚ฌ์šฉํ•˜๋“  ํ”„๋กœํ•„ ์นด๋“œ๋Š” ํ•ญ์ƒ ์ผ๊ด€๋œ ๋ชจ์Šต์„ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ๊ฒ ์ฃ !

๐Ÿ’ก Pro Tip: Shadow DOM์„ ์‚ฌ์šฉํ•  ๋•Œ๋Š” ์„ฑ๋Šฅ์—๋„ ์‹ ๊ฒฝ ์จ์•ผ ํ•ด์š”. ๋„ˆ๋ฌด ๋งŽ์€ Shadow DOM์„ ์‚ฌ์šฉํ•˜๋ฉด ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰์ด ์ฆ๊ฐ€ํ•  ์ˆ˜ ์žˆ์œผ๋‹ˆ ์ ์ ˆํžˆ ์‚ฌ์šฉํ•˜๋Š” ๊ฒŒ ์ข‹์•„์š”!

์—ฌ๊ธฐ๊นŒ์ง€ Shadow DOM์„ ๋งŒ๋“œ๋Š” ๊ธฐ๋ณธ์ ์ธ ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋ดค์–ด์š”. ์ด์ œ Shadow DOM์„ ํ™œ์šฉํ•ด์„œ ์–ด๋–ป๊ฒŒ ์Šคํƒ€์ผ์„ ์บก์Šํ™”ํ•˜๋Š”์ง€ ๋” ์ž์„ธํžˆ ์•Œ์•„๋ณผ๊นŒ์š”? ๐Ÿค”

๐ŸŽจ Shadow DOM์œผ๋กœ ์Šคํƒ€์ผ ์บก์Šํ™”ํ•˜๊ธฐ: CSS์˜ ํ˜๋ช…!

์ž, ์ด์ œ Shadow DOM์„ ์ด์šฉํ•ด์„œ ์–ด๋–ป๊ฒŒ ์Šคํƒ€์ผ์„ ์บก์Šํ™”ํ•˜๋Š”์ง€ ์ž์„ธํžˆ ์•Œ์•„๋ณผ ๊ฑฐ์˜ˆ์š”. ์ด๊ฑด ์ •๋ง CSS ๊ฐœ๋ฐœ์˜ ํ˜๋ช…์ด๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ์–ด์š”! ๐Ÿ˜Ž

๋จผ์ €, ์Šคํƒ€์ผ ์บก์Šํ™”๊ฐ€ ์™œ ์ค‘์š”ํ•œ์ง€ ์ƒ๊ฐํ•ด๋ณผ๊นŒ์š”? ๋Œ€๊ทœ๋ชจ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ฐœ๋ฐœํ•  ๋•Œ, CSS ํด๋ž˜์Šค ์ด๋ฆ„์ด ์ถฉ๋Œํ•˜๊ฑฐ๋‚˜ ์˜๋„์น˜ ์•Š๊ฒŒ ๋‹ค๋ฅธ ์š”์†Œ์— ์˜ํ–ฅ์„ ๋ฏธ์น˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์•„์š”. ์ด๋Ÿฐ ๋ฌธ์ œ๋ฅผ CSS ๋ˆ„์ˆ˜๋ผ๊ณ  ํ•˜๋Š”๋ฐ, Shadow DOM์„ ์‚ฌ์šฉํ•˜๋ฉด ์ด ๋ฌธ์ œ๋ฅผ ์™„๋ฒฝํ•˜๊ฒŒ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์–ด์š”!

Shadow DOM ์•ˆ์— ์ •์˜๋œ ์Šคํƒ€์ผ์€ Shadow DOM ๋ฐ–์œผ๋กœ ์ƒˆ์–ด๋‚˜๊ฐ€์ง€ ์•Š์•„์š”. ๋˜ํ•œ ์™ธ๋ถ€์˜ ์Šคํƒ€์ผ๋„ Shadow DOM ์•ˆ์œผ๋กœ ๋“ค์–ด์˜ค์ง€ ๋ชปํ•ด์š”. ์ด๊ฒŒ ๋ฐ”๋กœ ์Šคํƒ€์ผ ์บก์Šํ™”์˜ ํ•ต์‹ฌ์ด์—์š”!

๐Ÿš€ ๊ฟ€ํŒ: Shadow DOM์„ ์‚ฌ์šฉํ•˜๋ฉด CSS ํด๋ž˜์Šค ์ด๋ฆ„์„ ๊ณ ๋ฏผํ•  ํ•„์š”๊ฐ€ ์—†์–ด์š”. Shadow DOM ์•ˆ์—์„œ๋Š” ์–ด๋–ค ํด๋ž˜์Šค ์ด๋ฆ„์„ ์‚ฌ์šฉํ•ด๋„ ์™ธ๋ถ€์™€ ์ถฉ๋Œํ•  ์ผ์ด ์—†๊ฑฐ๋“ ์š”!

์ž, ๊ทธ๋Ÿผ ์‹ค์ œ๋กœ ์–ด๋–ป๊ฒŒ ์Šคํƒ€์ผ์„ ์บก์Šํ™”ํ•˜๋Š”์ง€ ์˜ˆ์ œ๋ฅผ ํ†ตํ•ด ์•Œ์•„๋ณผ๊นŒ์š”?

const shadowHost = document.getElementById('shadow-host');
const shadowRoot = shadowHost.attachShadow({mode: 'open'});

shadowRoot.innerHTML = `
  <style>
    .container {
      background-color: #f0f0f0;
      padding: 20px;
      border-radius: 8px;
    }
    .title {
      color: #333;
      font-size: 24px;
    }
    .content {
      color: #666;
      font-size: 16px;
    }
  </style>
  <div class="container">
    <h2 class="title">์•ˆ๋…•ํ•˜์„ธ์š”, Shadow DOM!</h2>
    <p class="content">์ด ์Šคํƒ€์ผ์€ ์บก์Šํ™”๋˜์–ด ์žˆ์–ด์š”.</p>
  </div>
`;

์šฐ์™€, ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์™„๋ฒฝํ•˜๊ฒŒ ์บก์Šํ™”๋œ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋งŒ๋“ค์–ด์ ธ์š”! ๐Ÿ‘ ์ด Shadow DOM ์•ˆ์— ์ •์˜๋œ .container, .title, .content ํด๋ž˜์Šค๋Š” ์™ธ๋ถ€ DOM์— ์žˆ๋Š” ๊ฐ™์€ ์ด๋ฆ„์˜ ํด๋ž˜์Šค์™€ ์ „ํ˜€ ์ถฉ๋Œํ•˜์ง€ ์•Š์•„์š”.

์ด๊ฑธ ์‹œ๊ฐํ™”ํ•ด๋ณด๋ฉด ์ด๋Ÿฐ ๋Š๋‚Œ์ด์—์š”:

Shadow DOM ์Šคํƒ€์ผ ์บก์Šํ™” ๋ฉ”์ธ DOM Shadow Host (div#shadow-host) Shadow Root <style> .container { background-color: #f0f0f0; ... } .title { color: #333; ... } .content { color: #666; ... } <div class="container"> <h2 class="title">์•ˆ๋…•ํ•˜์„ธ์š”, Shadow DOM!</h2> <p class="content">์ด ์Šคํƒ€์ผ์€ ์บก์Šํ™”๋˜์–ด ์žˆ์–ด์š”.</p> </div> ์Šคํƒ€์ผ ๊ฒฉ๋ฆฌ

์ด ๊ทธ๋ฆผ์„ ๋ณด๋ฉด Shadow DOM ์•ˆ์˜ ์Šคํƒ€์ผ์ด ์–ด๋–ป๊ฒŒ ์บก์Šํ™”๋˜๋Š”์ง€ ์ž˜ ๋ณด์ด์ฃ ? ์™ธ๋ถ€์—์„œ ์•„๋ฌด๋ฆฌ ๊ฐ™์€ ํด๋ž˜์Šค ์ด๋ฆ„์„ ์‚ฌ์šฉํ•ด๋„ Shadow DOM ์•ˆ์˜ ์Šคํƒ€์ผ์—๋Š” ์˜ํ–ฅ์„ ์ค„ ์ˆ˜ ์—†์–ด์š”. ์™„์ „ ์ฒ ๋ฒฝ ๋ฐฉ์–ด์˜ˆ์š”! ๐Ÿ’ช

์ด๋Ÿฐ ๋ฐฉ์‹์œผ๋กœ ์Šคํƒ€์ผ์„ ์บก์Šํ™”ํ•˜๋ฉด ์ •๋ง ๋งŽ์€ ์ด์ ์ด ์žˆ์–ด์š”:

  • ๐ŸŽฏ ํด๋ž˜์Šค ์ด๋ฆ„ ์ถฉ๋Œ ๋ฐฉ์ง€: ๋” ์ด์ƒ BEM์ด๋‚˜ ๋‹ค๋ฅธ ๋ณต์žกํ•œ ๋„ค์ด๋ฐ ๊ทœ์น™์„ ์‚ฌ์šฉํ•  ํ•„์š”๊ฐ€ ์—†์–ด์š”.
  • ๐Ÿ”’ ์Šคํƒ€์ผ ๊ฒฉ๋ฆฌ: ์ปดํฌ๋„ŒํŠธ์˜ ์Šคํƒ€์ผ์ด ๋‹ค๋ฅธ ์š”์†Œ์— ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š์•„์š”.
  • โ™ป๏ธ ์žฌ์‚ฌ์šฉ์„ฑ ํ–ฅ์ƒ: ์™„๋ฒฝํ•˜๊ฒŒ ์บก์Šํ™”๋œ ์ปดํฌ๋„ŒํŠธ๋Š” ์–ด๋””์—์„œ๋“  ์•ˆ์ „ํ•˜๊ฒŒ ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด์š”.
  • ๐Ÿงน ์ฝ”๋“œ ์ •๋ฆฌ: ์ „์—ญ ์Šค์ฝ”ํ”„๋ฅผ ๋”๋Ÿฝํžˆ์ง€ ์•Š๊ณ  ๊น”๋”ํ•˜๊ฒŒ ์Šคํƒ€์ผ์„ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์–ด์š”.

์žฌ๋Šฅ๋„ท ๊ฐ™์€ ํ”Œ๋žซํผ์„ ๊ฐœ๋ฐœํ•  ๋•Œ ์ด๋Ÿฐ ์Šคํƒ€์ผ ์บก์Šํ™” ๊ธฐ์ˆ ์„ ์‚ฌ์šฉํ•˜๋ฉด ์ •๋ง ํŽธ๋ฆฌํ•  ๊ฑฐ์˜ˆ์š”. ์˜ˆ๋ฅผ ๋“ค์–ด, ์‚ฌ์šฉ์ž ํ”„๋กœํ•„ ์นด๋“œ, ๋ฆฌ๋ทฐ ์ปดํฌ๋„ŒํŠธ, ๊ฒฐ์ œ ํผ ๋“ฑ ๋‹ค์–‘ํ•œ ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์ปดํฌ๋„ŒํŠธ๋ฅผ Shadow DOM์œผ๋กœ ๋งŒ๋“ค ์ˆ˜ ์žˆ์–ด์š”. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์‚ฌ์ดํŠธ์˜ ๋‹ค๋ฅธ ๋ถ€๋ถ„์„ ์ˆ˜์ •ํ•˜๋”๋ผ๋„ ์ด ์ปดํฌ๋„ŒํŠธ๋“ค์€ ํ•ญ์ƒ ์ผ๊ด€๋œ ๋ชจ์Šต์„ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ์ฃ !

๐Ÿ’ก ์žฌ๋Šฅ๋„ท ๊ฐœ๋ฐœ์ž Tip: Shadow DOM์„ ์‚ฌ์šฉํ•  ๋•Œ๋Š” ์„ฑ๋Šฅ ์ตœ์ ํ™”์—๋„ ์‹ ๊ฒฝ ์จ์•ผ ํ•ด์š”. ๋„ˆ๋ฌด ๋งŽ์€ Shadow DOM์„ ์‚ฌ์šฉํ•˜๋ฉด ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰์ด ์ฆ๊ฐ€ํ•  ์ˆ˜ ์žˆ์œผ๋‹ˆ, ๊ผญ ํ•„์š”ํ•œ ๊ฒฝ์šฐ์—๋งŒ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์•„์š”!

์ž, ์—ฌ๊ธฐ๊นŒ์ง€ Shadow DOM์„ ์ด์šฉํ•œ ์Šคํƒ€์ผ ์บก์Šํ™”์— ๋Œ€ํ•ด ์•Œ์•„๋ดค์–ด์š”. ์ด์ œ Shadow DOM์˜ ์žฅ๋‹จ์ ์— ๋Œ€ํ•ด ๋” ์ž์„ธํžˆ ์•Œ์•„๋ณผ๊นŒ์š”? ๐Ÿค”

๐Ÿ‘๐Ÿ‘Ž Shadow DOM์˜ ์žฅ๋‹จ์ : ์–‘๋‚ ์˜ ๊ฒ€?

Shadow DOM์€ ์ •๋ง ๊ฐ•๋ ฅํ•œ ๊ธฐ์ˆ ์ด์ง€๋งŒ, ๋ชจ๋“  ๊ธฐ์ˆ ์ด ๊ทธ๋ ‡๋“ฏ ์žฅ๋‹จ์ ์ด ์žˆ์–ด์š”. ์ด์ œ Shadow DOM์˜ ์žฅ๋‹จ์ ์„ ์ž์„ธํžˆ ์‚ดํŽด๋ณผ๊ฒŒ์š”. ์ด๊ฑธ ์•Œ๋ฉด ์–ธ์ œ Shadow DOM์„ ์‚ฌ์šฉํ•ด์•ผ ํ• ์ง€, ์–ธ์ œ๋Š” ์‚ฌ์šฉํ•˜์ง€ ๋ง์•„์•ผ ํ• ์ง€ ํŒ๋‹จํ•  ์ˆ˜ ์žˆ์„ ๊ฑฐ์˜ˆ์š”!

๐Ÿ‘ Shadow DOM์˜ ์žฅ์ 

  1. ์™„๋ฒฝํ•œ ์Šคํƒ€์ผ ๊ฒฉ๋ฆฌ: ์ด๊ฑด ์ •๋ง ๋Œ€๋ฐ•์ด์—์š”! ์™ธ๋ถ€ ์Šคํƒ€์ผ์˜ ์˜ํ–ฅ์„ ์ „ํ˜€ ๋ฐ›์ง€ ์•Š์•„์š”. CSS ์ง€์˜ฅ์—์„œ ๋ฒ—์–ด๋‚  ์ˆ˜ ์žˆ์–ด์š”! ๐ŸŽ‰
  2. ์ปดํฌ๋„ŒํŠธ ์žฌ์‚ฌ์šฉ์„ฑ ํ–ฅ์ƒ: ํ•œ ๋ฒˆ ๋งŒ๋“ค์–ด ๋†“์œผ๋ฉด ์–ด๋””์„œ๋“  ์“ธ ์ˆ˜ ์žˆ์–ด์š”. ์žฌ๋Šฅ๋„ท์—์„œ ์—ฌ๋Ÿฌ ํŽ˜์ด์ง€์— ๊ฐ™์€ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•  ๋•Œ ์™„์ „ ๊ฟ€์ด๊ฒ ์ฃ ?
  3. ์ฝ”๋“œ ๊ตฌ์กฐํ™”: HTML, CSS, JavaScript๋ฅผ ํ•˜๋‚˜์˜ ๋‹จ์œ„๋กœ ๋ฌถ์„ ์ˆ˜ ์žˆ์–ด์š”. ์ฝ”๋“œ๊ฐ€ ํ›จ์”ฌ ๊น”๋”ํ•ด์ ธ์š”!
  4. ์„ฑ๋Šฅ ์ตœ์ ํ™”: ๋ธŒ๋ผ์šฐ์ €๊ฐ€ Shadow DOM์„ ๋ณ„๋„๋กœ ์ฒ˜๋ฆฌํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ๋ Œ๋”๋ง ์„ฑ๋Šฅ์ด ํ–ฅ์ƒ๋  ์ˆ˜ ์žˆ์–ด์š”.
  5. ๋ณด์•ˆ ๊ฐ•ํ™”: Shadow DOM ๋‚ด๋ถ€์˜ ์š”์†Œ๋Š” ์™ธ๋ถ€์—์„œ ์ ‘๊ทผํ•˜๊ธฐ ์–ด๋ ค์›Œ์š”. XSS ๊ณต๊ฒฉ ๊ฐ™์€ ๋ณด์•ˆ ์œ„ํ˜‘์„ ์ค„์ผ ์ˆ˜ ์žˆ์ฃ .

์šฐ์™€, ์žฅ์ ์ด ์ •๋ง ๋งŽ์ฃ ? ๊ทผ๋ฐ ์ž ๊น, ๋‹จ์ ๋„ ์žˆ์„ ๊ฑฐ์˜ˆ์š”. ํ•œ๋ฒˆ ์‚ดํŽด๋ณผ๊นŒ์š”?

๐Ÿ‘Ž Shadow DOM์˜ ๋‹จ์ 

  1. ํ•™์Šต ๊ณก์„ : ์ฒ˜์Œ ์ ‘ํ•˜๋ฉด ์ข€ ์–ด๋ ค์šธ ์ˆ˜ ์žˆ์–ด์š”. ๊ธฐ์กด DOM๊ณผ๋Š” ๋‹ค๋ฅธ ๊ฐœ๋…์ด๋ผ ์ ์‘์ด ํ•„์š”ํ•ด์š”.
  2. ๋””๋ฒ„๊น…์˜ ์–ด๋ ค์›€: Shadow DOM ๋‚ด๋ถ€๋ฅผ ๋””๋ฒ„๊น…ํ•˜๋Š” ๊ฒŒ ์กฐ๊ธˆ ๊นŒ๋‹ค๋กœ์šธ ์ˆ˜ ์žˆ์–ด์š”. ๊ฐœ๋ฐœ์ž ๋„๊ตฌ์—์„œ Shadow DOM์„ ํ™•์ธํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋”ฐ๋กœ ์•Œ์•„์•ผ ํ•ด์š”.
  3. ์™ธ๋ถ€ ์Šคํƒ€์ผ ์ ์šฉ์˜ ์–ด๋ ค์›€: ๋•Œ๋กœ๋Š” ์™ธ๋ถ€์—์„œ Shadow DOM ๋‚ด๋ถ€ ์Šคํƒ€์ผ์„ ๋ณ€๊ฒฝํ•˜๊ณ  ์‹ถ์„ ๋•Œ๊ฐ€ ์žˆ๋Š”๋ฐ, ์ด๊ฒŒ ์‰ฝ์ง€ ์•Š์•„์š”.
  4. ๋ธŒ๋ผ์šฐ์ € ์ง€์›: ๋Œ€๋ถ€๋ถ„์˜ ์ตœ์‹  ๋ธŒ๋ผ์šฐ์ €๋Š” ์ง€์›ํ•˜์ง€๋งŒ, ์ผ๋ถ€ ๊ตฌํ˜• ๋ธŒ๋ผ์šฐ์ €์—์„œ๋Š” ์ž‘๋™ํ•˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์–ด์š”.
  5. SEO ๋ฌธ์ œ: ๊ฒ€์ƒ‰ ์—”์ง„์ด Shadow DOM ๋‚ด๋ถ€์˜ ์ฝ˜ํ…์ธ ๋ฅผ ์ œ๋Œ€๋กœ ์ธ์‹ํ•˜์ง€ ๋ชปํ•  ์ˆ˜ ์žˆ์–ด์š”.

์Œ... ๋‹จ์ ๋„ ๋งŒ๋งŒ์น˜ ์•Š๋„ค์š”. ๊ทธ๋ž˜๋„ ๊ฑฑ์ • ๋งˆ์„ธ์š”! ์ด๋Ÿฐ ๋‹จ์ ๋“ค์€ ๋Œ€๋ถ€๋ถ„ ์ ์ ˆํ•œ ์‚ฌ์šฉ๊ณผ ์ถ”๊ฐ€์ ์ธ ๊ธฐ์ˆ ๋กœ ๊ทน๋ณตํ•  ์ˆ˜ ์žˆ์–ด์š”. ๐Ÿ˜‰

๐Ÿค” ์ƒ๊ฐํ•ด๋ณด๊ธฐ: ์žฌ๋Šฅ๋„ท์—์„œ Shadow DOM์„ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด ์–ด๋–ค ์žฅ์ ์„ ๊ฐ€์žฅ ํฌ๊ฒŒ ๋ˆ„๋ฆด ์ˆ˜ ์žˆ์„๊นŒ์š”? ๋ฐ˜๋Œ€๋กœ, ์–ด๋–ค ๋‹จ์ ์„ ์ฃผ์˜ํ•ด์•ผ ํ• ๊นŒ์š”?

์ž, ์ด์ œ Shadow DOM์˜ ์žฅ๋‹จ์ ์„ ์ž˜ ์•Œ๊ฒ ์–ด์š”. ์ด์ œ Shadow DOM์˜ ์žฅ๋‹จ์ ์„ ์ž˜ ์ดํ•ดํ•˜์…จ์„ ๊ฑฐ์˜ˆ์š”. ๊ทธ๋Ÿผ ์ด์ œ ์‹ค์ œ๋กœ Shadow DOM์„ ์–ด๋–ป๊ฒŒ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋Š”์ง€, ํŠนํžˆ ์žฌ๋Šฅ๋„ท ๊ฐ™์€ ํ”Œ๋žซํผ์—์„œ ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์„์ง€ ์‚ดํŽด๋ณผ๊นŒ์š”? ๐Ÿš€

๐ŸŒŸ Shadow DOM ์‹ค์ „ ํ™œ์šฉ: ์žฌ๋Šฅ๋„ท์—์„œ์˜ ์‘์šฉ

์ž, ์ด์ œ ์žฌ๋Šฅ๋„ท์—์„œ Shadow DOM์„ ์–ด๋–ป๊ฒŒ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์„์ง€ ๊ตฌ์ฒด์ ์ธ ์˜ˆ์‹œ๋ฅผ ํ†ตํ•ด ์•Œ์•„๋ณผ๊ฒŒ์š”. ์žฌ๋Šฅ๋„ท์€ ๋‹ค์–‘ํ•œ ์‚ฌ์šฉ์ž๋“ค์˜ ์žฌ๋Šฅ์„ ๊ฑฐ๋ž˜ํ•˜๋Š” ํ”Œ๋žซํผ์ด๋‹ˆ๊นŒ, ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ํ•„์š”ํ•  ๊ฑฐ์˜ˆ์š”. ๊ทธ์ค‘์—์„œ '์‚ฌ์šฉ์ž ํ”„๋กœํ•„ ์นด๋“œ'๋ฅผ Shadow DOM์œผ๋กœ ๋งŒ๋“ค์–ด๋ณผ๊นŒ์š”? ๐Ÿ˜Ž

class UserProfileCard extends HTMLElement {
  constructor() {
    super();
    this.attachShadow({mode: 'open'});
  }

  connectedCallback() {
    this.shadowRoot.innerHTML = `
      <style>
        .card {
          background-color: #f0f0f0;
          border-radius: 8px;
          padding: 16px;
          width: 300px;
          box-shadow: 0 4px 8px rgba(0,0,0,0.1);
        }
        .avatar {
          width: 100px;
          height: 100px;
          border-radius: 50%;
          margin-bottom: 10px;
        }
        .name {
          font-size: 24px;
          color: #333;
          margin-bottom: 5px;
        }
        .skill {
          font-size: 16px;
          color: #666;
        }
      </style>
      <div class="card">
        <img class="avatar" src="${this.getAttribute('avatar')}" alt="User Avatar">
        <h2 class="name">${this.getAttribute('name')}</h2>
        <p class="skill">${this.getAttribute('skill')}</p>
      </div>
    `;
  }
}

customElements.define('user-profile-card', UserProfileCard);

์šฐ์™€! ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์™„์ „ํžˆ ์บก์Šํ™”๋œ ์‚ฌ์šฉ์ž ํ”„๋กœํ•„ ์นด๋“œ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋งŒ๋“ค์–ด์ ธ์š”. ์ด์ œ ์ด ์ปดํฌ๋„ŒํŠธ๋ฅผ ์žฌ๋Šฅ๋„ท์˜ ์–ด๋Š ํŽ˜์ด์ง€์—์„œ๋“  ์•„๋ž˜์™€ ๊ฐ™์ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด์š”:

<user-profile-card 
  avatar="https://example.com/avatar.jpg"
  name="๊น€์žฌ๋Šฅ"
  skill="์›น ๊ฐœ๋ฐœ"></user-profile-card>

์ด๋ ‡๊ฒŒ ๋งŒ๋“  ์ปดํฌ๋„ŒํŠธ๋Š” ์žฌ๋Šฅ๋„ท์˜ ๋‹ค๋ฅธ ์Šคํƒ€์ผ์— ์˜ํ–ฅ์„ ๋ฐ›์ง€ ์•Š๊ณ , ํ•ญ์ƒ ์ผ๊ด€๋œ ๋ชจ์Šต์„ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ์–ด์š”. ์ •๋ง ํŽธ๋ฆฌํ•˜์ฃ ? ๐Ÿ˜ƒ

๐Ÿ’ก Pro Tip: Shadow DOM์„ ์‚ฌ์šฉํ•  ๋•Œ๋Š” ์ ‘๊ทผ์„ฑ(accessibility)์—๋„ ์‹ ๊ฒฝ ์จ์•ผ ํ•ด์š”. Screen reader๊ฐ€ Shadow DOM ๋‚ด๋ถ€์˜ ์ฝ˜ํ…์ธ ๋ฅผ ์ œ๋Œ€๋กœ ์ฝ์„ ์ˆ˜ ์žˆ๋„๋ก ์ ์ ˆํ•œ ARIA ์†์„ฑ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์•„์š”!

์ด๋Ÿฐ ๋ฐฉ์‹์œผ๋กœ ์žฌ๋Šฅ๋„ท์˜ ๋‹ค์–‘ํ•œ ์ปดํฌ๋„ŒํŠธ๋ฅผ Shadow DOM์œผ๋กœ ๋งŒ๋“ค ์ˆ˜ ์žˆ์–ด์š”. ์˜ˆ๋ฅผ ๋“ค๋ฉด:

  • ๐ŸŒŸ ๋ฆฌ๋ทฐ ์ปดํฌ๋„ŒํŠธ: ์‚ฌ์šฉ์ž๋“ค์˜ ๋ฆฌ๋ทฐ๋ฅผ ํ‘œ์‹œํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ
  • ๐Ÿ’ฐ ๊ฐ€๊ฒฉ ํ‘œ์‹œ ์ปดํฌ๋„ŒํŠธ: ์žฌ๋Šฅ์˜ ๊ฐ€๊ฒฉ์„ ํ‘œ์‹œํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ
  • ๐Ÿ“… ์ผ์ • ์„ ํƒ ์ปดํฌ๋„ŒํŠธ: ์žฌ๋Šฅ ๊ฑฐ๋ž˜ ์ผ์ •์„ ์„ ํƒํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ
  • ๐Ÿ† ์—…์  ๋ฑƒ์ง€ ์ปดํฌ๋„ŒํŠธ: ์‚ฌ์šฉ์ž์˜ ์—…์ ์„ ํ‘œ์‹œํ•˜๋Š” ๋ฑƒ์ง€ ์ปดํฌ๋„ŒํŠธ

์ด๋ ‡๊ฒŒ Shadow DOM์„ ํ™œ์šฉํ•˜๋ฉด ์žฌ๋Šฅ๋„ท์˜ UI๋ฅผ ๋”์šฑ ๋ชจ๋“ˆํ™”ํ•˜๊ณ  ๊ด€๋ฆฌํ•˜๊ธฐ ์‰ฝ๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ์–ด์š”. ๋˜ํ•œ ๊ฐ ์ปดํฌ๋„ŒํŠธ์˜ ์Šคํƒ€์ผ์ด ์™„๋ฒฝํ•˜๊ฒŒ ์บก์Šํ™”๋˜์–ด ์žˆ์–ด์„œ, ์‚ฌ์ดํŠธ์˜ ์ „์ฒด์ ์ธ ๋””์ž์ธ์„ ๋ณ€๊ฒฝํ•˜๋”๋ผ๋„ ์ด ์ปดํฌ๋„ŒํŠธ๋“ค์€ ์˜ํ–ฅ์„ ๋ฐ›์ง€ ์•Š์•„์š”. ์ •๋ง ํŽธ๋ฆฌํ•˜์ฃ ? ๐Ÿ‘

ํ•˜์ง€๋งŒ ์ฃผ์˜ํ•  ์ ๋„ ์žˆ์–ด์š”. Shadow DOM์„ ๊ณผ๋„ํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜๋ฉด ํŽ˜์ด์ง€์˜ ์ „์ฒด์ ์ธ ์ผ๊ด€์„ฑ์„ ํ•ด์น  ์ˆ˜ ์žˆ์–ด์š”. ๋˜ํ•œ, SEO์—๋„ ์˜ํ–ฅ์„ ์ค„ ์ˆ˜ ์žˆ์œผ๋‹ˆ ์ฃผ์˜ํ•ด์•ผ ํ•ด์š”. ๊ทธ๋ž˜์„œ Shadow DOM์€ ๊ผญ ํ•„์š”ํ•œ ๊ฒฝ์šฐ์—๋งŒ ์„ ๋ณ„์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์•„์š”.

์žฌ๋Šฅ๋„ท์—์„œ์˜ Shadow DOM ํ™œ์šฉ ์žฌ๋Šฅ๋„ท ํŽ˜์ด์ง€ ์‚ฌ์šฉ์ž ํ”„๋กœํ•„ ์นด๋“œ ๋ฆฌ๋ทฐ ์ปดํฌ๋„ŒํŠธ ๊ฐ€๊ฒฉ ํ‘œ์‹œ ์ผ์ • ์„ ํƒ ๋ฉ”์ธ ํŽ˜์ด์ง€ ์Šคํƒ€์ผ (Shadow DOM์— ์˜ํ–ฅ ์—†์Œ)

์ด ๊ทธ๋ฆผ์„ ๋ณด๋ฉด ์žฌ๋Šฅ๋„ท ํŽ˜์ด์ง€์—์„œ Shadow DOM์œผ๋กœ ๋งŒ๋“  ์ปดํฌ๋„ŒํŠธ๋“ค์ด ์–ด๋–ป๊ฒŒ ๋…๋ฆฝ์ ์œผ๋กœ ์กด์žฌํ•˜๋Š”์ง€ ํ•œ๋ˆˆ์— ๋ณผ ์ˆ˜ ์žˆ์–ด์š”. ๊ฐ ์ปดํฌ๋„ŒํŠธ๋Š” ์ž์ฒด์ ์ธ ์Šคํƒ€์ผ์„ ๊ฐ€์ง€๊ณ  ์žˆ์–ด์„œ ๋ฉ”์ธ ํŽ˜์ด์ง€์˜ ์Šคํƒ€์ผ ๋ณ€๊ฒฝ์— ์˜ํ–ฅ์„ ๋ฐ›์ง€ ์•Š์•„์š”. ๋ฉ‹์ง€์ฃ ? ๐Ÿ˜Ž

์ž, ์—ฌ๊ธฐ๊นŒ์ง€ Shadow DOM์„ ์‹ค์ œ๋กœ ์–ด๋–ป๊ฒŒ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์•Œ์•„๋ดค์–ด์š”. ์ด์ œ Shadow DOM์— ๋Œ€ํ•ด ๊ฝค ๋งŽ์ด ์•Œ๊ฒŒ ๋˜์…จ์„ ๊ฒƒ ๊ฐ™์•„์š”. ํ•˜์ง€๋งŒ ์•„์ง ๋” ์•Œ์•„๋ณผ ๊ฒŒ ์žˆ์–ด์š”. Shadow DOM๊ณผ ๊ด€๋ จ๋œ ๋ช‡ ๊ฐ€์ง€ ๊ณ ๊ธ‰ ๊ธฐ์ˆ ์— ๋Œ€ํ•ด ์‚ดํŽด๋ณผ๊นŒ์š”? ๐Ÿš€

๐Ÿ”ฅ Shadow DOM ๊ณ ๊ธ‰ ๊ธฐ์ˆ : ํ•œ ๋‹จ๊ณ„ ๋” ๋‚˜์•„๊ฐ€๊ธฐ

์ž, ์ด์ œ Shadow DOM์— ๋Œ€ํ•ด ๊ธฐ๋ณธ์ ์ธ ๊ฒƒ๋“ค์€ ๋‹ค ๋ฐฐ์› ์–ด์š”. ํ•˜์ง€๋งŒ ๊ฐœ๋ฐœ์˜ ์„ธ๊ณ„๋Š” ๋์ด ์—†์ฃ ! ์ด์ œ Shadow DOM๊ณผ ๊ด€๋ จ๋œ ๋ช‡ ๊ฐ€์ง€ ๊ณ ๊ธ‰ ๊ธฐ์ˆ ์— ๋Œ€ํ•ด ์•Œ์•„๋ณผ๊ฒŒ์š”. ์ด ๊ธฐ์ˆ ๋“ค์„ ์ตํžˆ๋ฉด ์—ฌ๋Ÿฌ๋ถ„์€ ์ง„์ •ํ•œ Shadow DOM ๋งˆ์Šคํ„ฐ๊ฐ€ ๋  ์ˆ˜ ์žˆ์„ ๊ฑฐ์˜ˆ์š”! ๐Ÿ˜Ž

1. ์Šฌ๋กฏ(Slot) ์‚ฌ์šฉํ•˜๊ธฐ

์Šฌ๋กฏ์€ Shadow DOM ๋‚ด๋ถ€์— ์™ธ๋ถ€ ์ฝ˜ํ…์ธ ๋ฅผ ์‚ฝ์ž…ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ๊ฐ•๋ ฅํ•œ ๊ธฐ๋Šฅ์ด์—์š”. ์žฌ๋Šฅ๋„ท์—์„œ ์‚ฌ์šฉ์ž ํ”„๋กœํ•„ ์นด๋“œ๋ฅผ ๋” ์œ ์—ฐํ•˜๊ฒŒ ๋งŒ๋“ค์–ด๋ณผ๊นŒ์š”?

class UserProfileCard extends HTMLElement {
  constructor() {
    super();
    this.attachShadow({mode: 'open'});
  }

  connectedCallback() {
    this.shadowRoot.innerHTML = `
      <style>
        .card { /* ์Šคํƒ€์ผ์€ ์ด์ „๊ณผ ๋™์ผ */ }
      </style>
      <div class="card">
        <slot name="avatar"><img src="default-avatar.jpg" alt="Default Avatar"></slot>
        <h2 class="name"><slot name="name">์ด๋ฆ„ ์—†์Œ</slot></h2>
        <p class="skill"><slot name="skill">์Šคํ‚ฌ ์ •๋ณด ์—†์Œ</slot></p>
        <slot name="extra"></slot>
      </div>
    `;
  }
}

customElements.define('user-profile-card', UserProfileCard);

์ด์ œ ์ด ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ด๋ ‡๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด์š”:

<user-profile-card>
  <img slot="avatar" src="kim.jpg" alt="๊น€์žฌ๋Šฅ์˜ ์•„๋ฐ”ํƒ€">
  <span slot="name">๊น€์žฌ๋Šฅ</span>
  <span slot="skill">์›น ๊ฐœ๋ฐœ</span>
  <p slot="extra">์ €๋Š” ์—ด์ •์ ์ธ ๊ฐœ๋ฐœ์ž์ž…๋‹ˆ๋‹ค!</p>
</user-profile-card>

์šฐ์™€! ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์ปดํฌ๋„ŒํŠธ๋ฅผ ํ›จ์”ฌ ๋” ์œ ์—ฐํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด์š”. ๐Ÿ‘

2. CSS ์ปค์Šคํ…€ ์†์„ฑ ํ™œ์šฉํ•˜๊ธฐ

CSS ์ปค์Šคํ…€ ์†์„ฑ(๋ณ€์ˆ˜)์„ ์‚ฌ์šฉํ•˜๋ฉด Shadow DOM ์™ธ๋ถ€์—์„œ ๋‚ด๋ถ€ ์Šคํƒ€์ผ์„ ์ผ๋ถ€ ์ œ์–ดํ•  ์ˆ˜ ์žˆ์–ด์š”. ์žฌ๋Šฅ๋„ท์˜ ํ…Œ๋งˆ์— ๋”ฐ๋ผ ํ”„๋กœํ•„ ์นด๋“œ์˜ ์ƒ‰์ƒ์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด๋ณผ๊นŒ์š”?

class UserProfileCard extends HTMLElement {
  // ... ์ด์ „ ์ฝ”๋“œ ์ƒ๋žต ...

  connectedCallback() {
    this.shadowRoot.innerHTML = `
      <style>
        .card {
          background-color: var(--card-bg, #f0f0f0);
          color: var(--card-color, #333);
          /* ๋‹ค๋ฅธ ์Šคํƒ€์ผ์€ ์ด์ „๊ณผ ๋™์ผ */
        }
      </style>
      <!-- ์นด๋“œ ๋‚ด์šฉ์€ ์ด์ „๊ณผ ๋™์ผ -->
    `;
  }
}

customElements.define('user-profile-card', UserProfileCard);

์ด์ œ ์™ธ๋ถ€์—์„œ ์ด๋ ‡๊ฒŒ ์Šคํƒ€์ผ์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์–ด์š”:

<style>
  user-profile-card {
    --card-bg: #e1f5fe;
    --card-color: #01579b;
  }
</style>

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์žฌ๋Šฅ๋„ท์˜ ๋‹ค์–‘ํ•œ ํŽ˜์ด์ง€์—์„œ ํ”„๋กœํ•„ ์นด๋“œ์˜ ์Šคํƒ€์ผ์„ ์œ ์—ฐํ•˜๊ฒŒ ์กฐ์ •ํ•  ์ˆ˜ ์žˆ์–ด์š”. ๋ฉ‹์ง€์ฃ ? ๐Ÿ˜Ž

3. ์ด๋ฒคํŠธ ์žฌํƒ€๊ฒŸํŒ…(Retargeting) ์ดํ•ดํ•˜๊ธฐ

Shadow DOM ๋‚ด๋ถ€์—์„œ ๋ฐœ์ƒํ•œ ์ด๋ฒคํŠธ๋Š” Shadow ๋ฐ”์šด๋”๋ฆฌ๋ฅผ ๋„˜์–ด๊ฐˆ ๋•Œ ์žฌํƒ€๊ฒŸํŒ…๋ผ์š”. ์ด๋ฅผ ์ดํ•ดํ•˜๊ณ  ํ™œ์šฉํ•˜๋ฉด ์ปดํฌ๋„ŒํŠธ์™€ ์™ธ๋ถ€ ์„ธ๊ณ„์™€์˜ ์ƒํ˜ธ์ž‘์šฉ์„ ๋” ์ž˜ ์ œ์–ดํ•  ์ˆ˜ ์žˆ์–ด์š”.

class UserProfileCard extends HTMLElement {
  // ... ์ด์ „ ์ฝ”๋“œ ์ƒ๋žต ...

  connectedCallback() {
    // ... ์ด์ „ ์ฝ”๋“œ ์ƒ๋žต ...

    const nameElement = this.shadowRoot.querySelector('.name');
    nameElement.addEventListener('click', (e) => {
      const event = new CustomEvent('nameClicked', {
        bubbles: true,
        composed: true,
        detail: { name: nameElement.textContent }
      });
      this.dispatchEvent(event);
    });
  }
}

// ์‚ฌ์šฉ ์˜ˆ:
document.querySelector('user-profile-card').addEventListener('nameClicked', (e) => {
  console.log(`${e.detail.name}์˜ ํ”„๋กœํ•„์ด ํด๋ฆญ๋˜์—ˆ์Šต๋‹ˆ๋‹ค!`);
});

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด Shadow DOM ๋‚ด๋ถ€์˜ ์ด๋ฒคํŠธ๋ฅผ ์™ธ๋ถ€๋กœ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์–ด์š”. ์žฌ๋Šฅ๋„ท์—์„œ ์‚ฌ์šฉ์ž ์ด๋ฆ„์„ ํด๋ฆญํ–ˆ์„ ๋•Œ ํ”„๋กœํ•„ ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์‰ฝ๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๊ฒ ์ฃ ?

๐Ÿš€ ๊ณ ๊ธ‰ ํŒ: Shadow DOM์„ ์‚ฌ์šฉํ•  ๋•Œ๋Š” ์„ฑ๋Šฅ ์ตœ์ ํ™”์—๋„ ์‹ ๊ฒฝ ์จ์•ผ ํ•ด์š”. ๋„ˆ๋ฌด ๋งŽ์€ Shadow DOM์„ ์‚ฌ์šฉํ•˜๋ฉด ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰์ด ์ฆ๊ฐ€ํ•  ์ˆ˜ ์žˆ์–ด์š”. ํ•„์š”ํ•œ ๊ฒฝ์šฐ์—๋งŒ ์„ ๋ณ„์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์•„์š”!

์ž, ์—ฌ๊ธฐ๊นŒ์ง€ Shadow DOM์˜ ๊ณ ๊ธ‰ ๊ธฐ์ˆ ๋“ค์„ ์‚ดํŽด๋ดค์–ด์š”. ์ด ๊ธฐ์ˆ ๋“ค์„ ์ž˜ ํ™œ์šฉํ•˜๋ฉด ์žฌ๋Šฅ๋„ท ๊ฐ™์€ ๋ณต์žกํ•œ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ๋„ ์ปดํฌ๋„ŒํŠธ๋ฅผ ํšจ๊ณผ์ ์œผ๋กœ ๊ด€๋ฆฌํ•˜๊ณ  ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด์š”. ๐Ÿ‘จโ€๐Ÿ’ป๐Ÿ‘ฉโ€๐Ÿ’ป

Shadow DOM์€ ์ •๋ง ๊ฐ•๋ ฅํ•œ ๋„๊ตฌ์ง€๋งŒ, ๋ชจ๋“  ์ƒํ™ฉ์— ์ ํ•ฉํ•œ ๊ฒƒ์€ ์•„๋‹ˆ์—์š”. ํ•ญ์ƒ ํ”„๋กœ์ ํŠธ์˜ ์š”๊ตฌ์‚ฌํ•ญ๊ณผ ํŠน์„ฑ์„ ๊ณ ๋ คํ•ด์„œ ์ ์ ˆํžˆ ์‚ฌ์šฉํ•ด์•ผ ํ•ด์š”. ๊ทธ๋ฆฌ๊ณ  ์ ‘๊ทผ์„ฑ๊ณผ SEO๋„ ํ•ญ์ƒ ์—ผ๋‘์— ๋‘์–ด์•ผ ํ•œ๋‹ค๋Š” ๊ฑธ ์žŠ์ง€ ๋งˆ์„ธ์š”!

์—ฌ๊ธฐ๊นŒ์ง€ Shadow DOM์— ๋Œ€ํ•ด ์ •๋ง ๊นŠ์ด ์žˆ๊ฒŒ ์•Œ์•„๋ดค์–ด์š”. ์ด์ œ ์—ฌ๋Ÿฌ๋ถ„์€ Shadow DOM์˜ ์ง„์ •ํ•œ ๋งˆ์Šคํ„ฐ๊ฐ€ ๋˜์—ˆ์„ ๊ฑฐ์˜ˆ์š”! ๐Ÿ† ์ด ์ง€์‹์„ ํ™œ์šฉํ•ด์„œ ์žฌ๋Šฅ๋„ท์„ ๋”์šฑ ๋ฉ‹์ง„ ํ”Œ๋žซํผ์œผ๋กœ ๋งŒ๋“ค์–ด๋ณด๋Š” ๊ฑด ์–ด๋–จ๊นŒ์š”? ํ™”์ดํŒ…! ๐Ÿ’ช๐Ÿ˜„

๐ŸŒŸ Shadow DOM ์‹ค์ „ ํ™œ์šฉ: ์žฌ๋Šฅ๋„ท์—์„œ์˜ ์‘์šฉ

์ž, ์ด์ œ ์žฌ๋Šฅ๋„ท์—์„œ Shadow DOM์„ ์–ด๋–ป๊ฒŒ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์„์ง€ ๊ตฌ์ฒด์ ์ธ ์˜ˆ์‹œ๋ฅผ ํ†ตํ•ด ์•Œ์•„๋ณผ๊ฒŒ์š”. ์žฌ๋Šฅ๋„ท์€ ๋‹ค์–‘ํ•œ ์‚ฌ์šฉ์ž๋“ค์˜ ์žฌ๋Šฅ์„ ๊ฑฐ๋ž˜ํ•˜๋Š” ํ”Œ๋žซํผ์ด๋‹ˆ๊นŒ, ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ํ•„์š”ํ•  ๊ฑฐ์˜ˆ์š”. ๊ทธ์ค‘์—์„œ '์‚ฌ์šฉ์ž ํ”„๋กœํ•„ ์นด๋“œ'๋ฅผ Shadow DOM์œผ๋กœ ๋งŒ๋“ค์–ด๋ณผ๊นŒ์š”? ๐Ÿ˜Ž

class UserProfileCard extends HTMLElement {
  constructor() {
    super();
    this.attachShadow({mode: 'open'});
  }

  connectedCallback() {
    this.shadowRoot.innerHTML = `
      <style>
        .card {
          background-color: #f0f0f0;
          border-radius: 8px;
          padding: 16px;
          width: 300px;
          box-shadow: 0 4px 8px rgba(0,0,0,0.1);
        }
        .avatar {
          width: 100px;
          height: 100px;
          border-radius: 50%;
          margin-bottom: 10px;
        }
        .name {
          font-size: 24px;
          color: #333;
          margin-bottom: 5px;
        }
        .skill {
          font-size: 16px;
          color: #666;
        }
      </style>
      <div class="card">
        <img class="avatar" src="${this.getAttribute('avatar')}" alt="User Avatar">
        <h2 class="name">${this.getAttribute('name')}</h2>
        <p class="skill">${this.getAttribute('skill')}</p>
      </div>
    `;
  }
}

customElements.define('user-profile-card', UserProfileCard);

์šฐ์™€! ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์™„์ „ํžˆ ์บก์Šํ™”๋œ ์‚ฌ์šฉ์ž ํ”„๋กœํ•„ ์นด๋“œ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋งŒ๋“ค์–ด์ ธ์š”. ์ด์ œ ์ด ์ปดํฌ๋„ŒํŠธ๋ฅผ ์žฌ๋Šฅ๋„ท์˜ ์–ด๋Š ํŽ˜์ด์ง€์—์„œ๋“  ์•„๋ž˜์™€ ๊ฐ™์ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด์š”:

<user-profile-card 
  avatar="https://example.com/avatar.jpg"
  name="๊น€์žฌ๋Šฅ"
  skill="์›น ๊ฐœ๋ฐœ"></user-profile-card>

์ด๋ ‡๊ฒŒ ๋งŒ๋“  ์ปดํฌ๋„ŒํŠธ๋Š” ์žฌ๋Šฅ๋„ท์˜ ๋‹ค๋ฅธ ์Šคํƒ€์ผ์— ์˜ํ–ฅ์„ ๋ฐ›์ง€ ์•Š๊ณ , ํ•ญ์ƒ ์ผ๊ด€๋œ ๋ชจ์Šต์„ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ์–ด์š”. ์ •๋ง ํŽธ๋ฆฌํ•˜์ฃ ? ๐Ÿ˜ƒ

๐Ÿ’ก Pro Tip: Shadow DOM์„ ์‚ฌ์šฉํ•  ๋•Œ๋Š” ์ ‘๊ทผ์„ฑ(accessibility)์—๋„ ์‹ ๊ฒฝ ์จ์•ผ ํ•ด์š”. Screen reader๊ฐ€ Shadow DOM ๋‚ด๋ถ€์˜ ์ฝ˜ํ…์ธ ๋ฅผ ์ œ๋Œ€๋กœ ์ฝ์„ ์ˆ˜ ์žˆ๋„๋ก ์ ์ ˆํ•œ ARIA ์†์„ฑ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์•„์š”!

์ด๋Ÿฐ ๋ฐฉ์‹์œผ๋กœ ์žฌ๋Šฅ๋„ท์˜ ๋‹ค์–‘ํ•œ ์ปดํฌ๋„ŒํŠธ๋ฅผ Shadow DOM์œผ๋กœ ๋งŒ๋“ค ์ˆ˜ ์žˆ์–ด์š”. ์˜ˆ๋ฅผ ๋“ค๋ฉด:

  • ๐ŸŒŸ ๋ฆฌ๋ทฐ ์ปดํฌ๋„ŒํŠธ: ์‚ฌ์šฉ์ž๋“ค์˜ ๋ฆฌ๋ทฐ๋ฅผ ํ‘œ์‹œํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ
  • ๐Ÿ’ฐ ๊ฐ€๊ฒฉ ํ‘œ์‹œ ์ปดํฌ๋„ŒํŠธ: ์žฌ๋Šฅ์˜ ๊ฐ€๊ฒฉ์„ ํ‘œ์‹œํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ
  • ๐Ÿ“… ์ผ์ • ์„ ํƒ ์ปดํฌ๋„ŒํŠธ: ์žฌ๋Šฅ ๊ฑฐ๋ž˜ ์ผ์ •์„ ์„ ํƒํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ
  • ๐Ÿ† ์—…์  ๋ฑƒ์ง€ ์ปดํฌ๋„ŒํŠธ: ์‚ฌ์šฉ์ž์˜ ์—…์ ์„ ํ‘œ์‹œํ•˜๋Š” ๋ฑƒ์ง€ ์ปดํฌ๋„ŒํŠธ

์ด๋ ‡๊ฒŒ Shadow DOM์„ ํ™œ์šฉํ•˜๋ฉด ์žฌ๋Šฅ๋„ท์˜ UI๋ฅผ ๋”์šฑ ๋ชจ๋“ˆํ™”ํ•˜๊ณ  ๊ด€๋ฆฌํ•˜๊ธฐ ์‰ฝ๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ์–ด์š”. ๋˜ํ•œ ๊ฐ ์ปดํฌ๋„ŒํŠธ์˜ ์Šคํƒ€์ผ์ด ์™„๋ฒฝํ•˜๊ฒŒ ์บก์Šํ™”๋˜์–ด ์žˆ์–ด์„œ, ์‚ฌ์ดํŠธ์˜ ์ „์ฒด์ ์ธ ๋””์ž์ธ์„ ๋ณ€๊ฒฝํ•˜๋”๋ผ๋„ ์ด ์ปดํฌ๋„ŒํŠธ๋“ค์€ ์˜ํ–ฅ์„ ๋ฐ›์ง€ ์•Š์•„์š”. ์ •๋ง ํŽธ๋ฆฌํ•˜์ฃ ? ๐Ÿ‘

ํ•˜์ง€๋งŒ ์ฃผ์˜ํ•  ์ ๋„ ์žˆ์–ด์š”. Shadow DOM์„ ๊ณผ๋„ํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜๋ฉด ํŽ˜์ด์ง€์˜ ์ „์ฒด์ ์ธ ์ผ๊ด€์„ฑ์„ ํ•ด์น  ์ˆ˜ ์žˆ์–ด์š”. ๋˜ํ•œ, SEO์—๋„ ์˜ํ–ฅ์„ ์ค„ ์ˆ˜ ์žˆ์œผ๋‹ˆ ์ฃผ์˜ํ•ด์•ผ ํ•ด์š”. ๊ทธ๋ž˜์„œ Shadow DOM์€ ๊ผญ ํ•„์š”ํ•œ ๊ฒฝ์šฐ์—๋งŒ ์„ ๋ณ„์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์•„์š”.

์žฌ๋Šฅ๋„ท์—์„œ์˜ Shadow DOM ํ™œ์šฉ ์žฌ๋Šฅ๋„ท ํŽ˜์ด์ง€ ์‚ฌ์šฉ์ž ํ”„๋กœํ•„ ์นด๋“œ ๋ฆฌ๋ทฐ ์ปดํฌ๋„ŒํŠธ ๊ฐ€๊ฒฉ ํ‘œ์‹œ ์ผ์ • ์„ ํƒ ๋ฉ”์ธ ํŽ˜์ด์ง€ ์Šคํƒ€์ผ (Shadow DOM์— ์˜ํ–ฅ ์—†์Œ)

์ด ๊ทธ๋ฆผ์„ ๋ณด๋ฉด ์žฌ๋Šฅ๋„ท ํŽ˜์ด์ง€์—์„œ Shadow DOM์œผ๋กœ ๋งŒ๋“  ์ปดํฌ๋„ŒํŠธ๋“ค์ด ์–ด๋–ป๊ฒŒ ๋…๋ฆฝ์ ์œผ๋กœ ์กด์žฌํ•˜๋Š”์ง€ ํ•œ๋ˆˆ์— ๋ณผ ์ˆ˜ ์žˆ์–ด์š”. ๊ฐ ์ปดํฌ๋„ŒํŠธ๋Š” ์ž์ฒด์ ์ธ ์Šคํƒ€์ผ์„ ๊ฐ€์ง€๊ณ  ์žˆ์–ด์„œ ๋ฉ”์ธ ํŽ˜์ด์ง€์˜ ์Šคํƒ€์ผ ๋ณ€๊ฒฝ์— ์˜ํ–ฅ์„ ๋ฐ›์ง€ ์•Š์•„์š”. ๋ฉ‹์ง€์ฃ ? ๐Ÿ˜Ž

์ž, ์—ฌ๊ธฐ๊นŒ์ง€ Shadow DOM์„ ์‹ค์ œ๋กœ ์–ด๋–ป๊ฒŒ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์•Œ์•„๋ดค์–ด์š”. ์ด์ œ Shadow DOM์— ๋Œ€ํ•ด ๊ฝค ๋งŽ์ด ์•Œ๊ฒŒ ๋˜์…จ์„ ๊ฒƒ ๊ฐ™์•„์š”. ํ•˜์ง€๋งŒ ์•„์ง ๋” ์•Œ์•„๋ณผ ๊ฒŒ ์žˆ์–ด์š”. Shadow DOM๊ณผ ๊ด€๋ จ๋œ ๋ช‡ ๊ฐ€์ง€ ๊ณ ๊ธ‰ ๊ธฐ์ˆ ์— ๋Œ€ํ•ด ์‚ดํŽด๋ณผ๊นŒ์š”? ๐Ÿš€

๐Ÿ”ฅ Shadow DOM ๊ณ ๊ธ‰ ๊ธฐ์ˆ : ํ•œ ๋‹จ๊ณ„ ๋” ๋‚˜์•„๊ฐ€๊ธฐ

์ž, ์ด์ œ Shadow DOM์— ๋Œ€ํ•ด ๊ธฐ๋ณธ์ ์ธ ๊ฒƒ๋“ค์€ ๋‹ค ๋ฐฐ์› ์–ด์š”. ํ•˜์ง€๋งŒ ๊ฐœ๋ฐœ์˜ ์„ธ๊ณ„๋Š” ๋์ด ์—†์ฃ ! ์ด์ œ Shadow DOM๊ณผ ๊ด€๋ จ๋œ ๋ช‡ ๊ฐ€์ง€ ๊ณ ๊ธ‰ ๊ธฐ์ˆ ์— ๋Œ€ํ•ด ์•Œ์•„๋ณผ๊ฒŒ์š”. ์ด ๊ธฐ์ˆ ๋“ค์„ ์ตํžˆ๋ฉด ์—ฌ๋Ÿฌ๋ถ„์€ ์ง„์ •ํ•œ Shadow DOM ๋งˆ์Šคํ„ฐ๊ฐ€ ๋  ์ˆ˜ ์žˆ์„ ๊ฑฐ์˜ˆ์š”! ๐Ÿ˜Ž

1. ์Šฌ๋กฏ(Slot) ์‚ฌ์šฉํ•˜๊ธฐ

์Šฌ๋กฏ์€ Shadow DOM ๋‚ด๋ถ€์— ์™ธ๋ถ€ ์ฝ˜ํ…์ธ ๋ฅผ ์‚ฝ์ž…ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ๊ฐ•๋ ฅํ•œ ๊ธฐ๋Šฅ์ด์—์š”. ์žฌ๋Šฅ๋„ท์—์„œ ์‚ฌ์šฉ์ž ํ”„๋กœํ•„ ์นด๋“œ๋ฅผ ๋” ์œ ์—ฐํ•˜๊ฒŒ ๋งŒ๋“ค์–ด๋ณผ๊นŒ์š”?

class UserProfileCard extends HTMLElement {
  constructor() {
    super();
    this.attachShadow({mode: 'open'});
  }

  connectedCallback() {
    this.shadowRoot.innerHTML = `
      <style>
        .card { /* ์Šคํƒ€์ผ์€ ์ด์ „๊ณผ ๋™์ผ */ }
      </style>
      <div class="card">
        <slot name="avatar"><img src="default-avatar.jpg" alt="Default Avatar"></slot>
        <h2 class="name"><slot name="name">์ด๋ฆ„ ์—†์Œ</slot></h2>
        <p class="skill"><slot name="skill">์Šคํ‚ฌ ์ •๋ณด ์—†์Œ</slot></p>
        <slot name="extra"></slot>
      </div>
    `;
  }
}

customElements.define('user-profile-card', UserProfileCard);

์ด์ œ ์ด ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ด๋ ‡๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด์š”:

<user-profile-card>
  <img slot="avatar" src="kim.jpg" alt="๊น€์žฌ๋Šฅ์˜ ์•„๋ฐ”ํƒ€">
  <span slot="name">๊น€์žฌ๋Šฅ</span>
  <span slot="skill">์›น ๊ฐœ๋ฐœ</span>
  <p slot="extra">์ €๋Š” ์—ด์ •์ ์ธ ๊ฐœ๋ฐœ์ž์ž…๋‹ˆ๋‹ค!</p>
</user-profile-card>

์šฐ์™€! ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์ปดํฌ๋„ŒํŠธ๋ฅผ ํ›จ์”ฌ ๋” ์œ ์—ฐํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด์š”. ๐Ÿ‘

2. CSS ์ปค์Šคํ…€ ์†์„ฑ ํ™œ์šฉํ•˜๊ธฐ

CSS ์ปค์Šคํ…€ ์†์„ฑ(๋ณ€์ˆ˜)์„ ์‚ฌ์šฉํ•˜๋ฉด Shadow DOM ์™ธ๋ถ€์—์„œ ๋‚ด๋ถ€ ์Šคํƒ€์ผ์„ ์ผ๋ถ€ ์ œ์–ดํ•  ์ˆ˜ ์žˆ์–ด์š”. ์žฌ๋Šฅ๋„ท์˜ ํ…Œ๋งˆ์— ๋”ฐ๋ผ ํ”„๋กœํ•„ ์นด๋“œ์˜ ์ƒ‰์ƒ์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด๋ณผ๊นŒ์š”?

class UserProfileCard extends HTMLElement {
  // ... ์ด์ „ ์ฝ”๋“œ ์ƒ๋žต ...

  connectedCallback() {
    this.shadowRoot.innerHTML = `
      <style>
        .card {
          background-color: var(--card-bg, #f0f0f0);
          color: var(--card-color, #333);
          /* ๋‹ค๋ฅธ ์Šคํƒ€์ผ์€ ์ด์ „๊ณผ ๋™์ผ */
        }
      </style>
      <!-- ์นด๋“œ ๋‚ด์šฉ์€ ์ด์ „๊ณผ ๋™์ผ -->
    `;
  }
}

customElements.define('user-profile-card', UserProfileCard);

์ด์ œ ์™ธ๋ถ€์—์„œ ์ด๋ ‡๊ฒŒ ์Šคํƒ€์ผ์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์–ด์š”:

<style>
  user-profile-card {
    --card-bg: #e1f5fe;
    --card-color: #01579b;
  }
</style>

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์žฌ๋Šฅ๋„ท์˜ ๋‹ค์–‘ํ•œ ํŽ˜์ด์ง€์—์„œ ํ”„๋กœํ•„ ์นด๋“œ์˜ ์Šคํƒ€์ผ์„ ์œ ์—ฐํ•˜๊ฒŒ ์กฐ์ •ํ•  ์ˆ˜ ์žˆ์–ด์š”. ๋ฉ‹์ง€์ฃ ? ๐Ÿ˜Ž

3. ์ด๋ฒคํŠธ ์žฌํƒ€๊ฒŸํŒ…(Retargeting) ์ดํ•ดํ•˜๊ธฐ

Shadow DOM ๋‚ด๋ถ€์—์„œ ๋ฐœ์ƒํ•œ ์ด๋ฒคํŠธ๋Š” Shadow ๋ฐ”์šด๋”๋ฆฌ๋ฅผ ๋„˜์–ด๊ฐˆ ๋•Œ ์žฌํƒ€๊ฒŸํŒ…๋ผ์š”. ์ด๋ฅผ ์ดํ•ดํ•˜๊ณ  ํ™œ์šฉํ•˜๋ฉด ์ปดํฌ๋„ŒํŠธ์™€ ์™ธ๋ถ€ ์„ธ๊ณ„์™€์˜ ์ƒํ˜ธ์ž‘์šฉ์„ ๋” ์ž˜ ์ œ์–ดํ•  ์ˆ˜ ์žˆ์–ด์š”.

class UserProfileCard extends HTMLElement {
  // ... ์ด์ „ ์ฝ”๋“œ ์ƒ๋žต ...

  connectedCallback() {
    // ... ์ด์ „ ์ฝ”๋“œ ์ƒ๋žต ...

    const nameElement = this.shadowRoot.querySelector('.name');
    nameElement.addEventListener('click', (e) => {
      const event = new CustomEvent('nameClicked', {
        bubbles: true,
        composed: true,
        detail: { name: nameElement.textContent }
      });
      this.dispatchEvent(event);
    });
  }
}

// ์‚ฌ์šฉ ์˜ˆ:
document.querySelector('user-profile-card').addEventListener('nameClicked', (e) => {
  console.log(`${e.detail.name}์˜ ํ”„๋กœํ•„์ด ํด๋ฆญ๋˜์—ˆ์Šต๋‹ˆ๋‹ค!`);
});

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด Shadow DOM ๋‚ด๋ถ€์˜ ์ด๋ฒคํŠธ๋ฅผ ์™ธ๋ถ€๋กœ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์–ด์š”. ์žฌ๋Šฅ๋„ท์—์„œ ์‚ฌ์šฉ์ž ์ด๋ฆ„์„ ํด๋ฆญํ–ˆ์„ ๋•Œ ํ”„๋กœํ•„ ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์‰ฝ๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๊ฒ ์ฃ ?

๐Ÿš€ ๊ณ ๊ธ‰ ํŒ: Shadow DOM์„ ์‚ฌ์šฉํ•  ๋•Œ๋Š” ์„ฑ๋Šฅ ์ตœ์ ํ™”์—๋„ ์‹ ๊ฒฝ ์จ์•ผ ํ•ด์š”. ๋„ˆ๋ฌด ๋งŽ์€ Shadow DOM์„ ์‚ฌ์šฉํ•˜๋ฉด ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰์ด ์ฆ๊ฐ€ํ•  ์ˆ˜ ์žˆ์–ด์š”. ํ•„์š”ํ•œ ๊ฒฝ์šฐ์—๋งŒ ์„ ๋ณ„์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์•„์š”!

์ž, ์—ฌ๊ธฐ๊นŒ์ง€ Shadow DOM์˜ ๊ณ ๊ธ‰ ๊ธฐ์ˆ ๋“ค์„ ์‚ดํŽด๋ดค์–ด์š”. ์ด ๊ธฐ์ˆ ๋“ค์„ ์ž˜ ํ™œ์šฉํ•˜๋ฉด ์žฌ๋Šฅ๋„ท ๊ฐ™์€ ๋ณต์žกํ•œ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ๋„ ์ปดํฌ๋„ŒํŠธ๋ฅผ ํšจ๊ณผ์ ์œผ๋กœ ๊ด€๋ฆฌํ•˜๊ณ  ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด์š”. ๐Ÿ‘จโ€๐Ÿ’ป๐Ÿ‘ฉโ€๐Ÿ’ป

Shadow DOM์€ ์ •๋ง ๊ฐ•๋ ฅํ•œ ๋„๊ตฌ์ง€๋งŒ, ๋ชจ๋“  ์ƒํ™ฉ์— ์ ํ•ฉํ•œ ๊ฒƒ์€ ์•„๋‹ˆ์—์š”. ํ•ญ์ƒ ํ”„๋กœ์ ํŠธ์˜ ์š”๊ตฌ์‚ฌํ•ญ๊ณผ ํŠน์„ฑ์„ ๊ณ ๋ คํ•ด์„œ ์ ์ ˆํžˆ ์‚ฌ์šฉํ•ด์•ผ ํ•ด์š”. ๊ทธ๋ฆฌ๊ณ  ์ ‘๊ทผ์„ฑ๊ณผ SEO๋„ ํ•ญ์ƒ ์—ผ๋‘์— ๋‘์–ด์•ผ ํ•œ๋‹ค๋Š” ๊ฑธ ์žŠ์ง€ ๋งˆ์„ธ์š”!

์—ฌ๊ธฐ๊นŒ์ง€ Shadow DOM์— ๋Œ€ํ•ด ์ •๋ง ๊นŠ์ด ์žˆ๊ฒŒ ์•Œ์•„๋ดค์–ด์š”. ์ด์ œ ์—ฌ๋Ÿฌ๋ถ„์€ Shadow DOM์˜ ์ง„์ •ํ•œ ๋งˆ์Šคํ„ฐ๊ฐ€ ๋˜์—ˆ์„ ๊ฑฐ์˜ˆ์š”! ๐Ÿ† ์ด ์ง€์‹์„ ํ™œ์šฉํ•ด์„œ ์žฌ๋Šฅ๋„ท์„ ๋”์šฑ ๋ฉ‹์ง„ ํ”Œ๋žซํผ์œผ๋กœ ๋งŒ๋“ค์–ด๋ณด๋Š” ๊ฑด ์–ด๋–จ๊นŒ์š”? ํ™”์ดํŒ…! ๐Ÿ’ช๐Ÿ˜„