React: RFC: React 18์˜ ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ ์†์„ฑ/์†์„ฑ ๊ณ„ํš

์— ๋งŒ๋“  2017๋…„ 10์›” 24์ผ  ยท  129์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: facebook/react

์ด๊ฒƒ์€ ์ฃผ์†Œ #7249๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ์ด ๋ฌธ์„œ๋Š” React๊ฐ€ ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ์˜ ์†์„ฑ๊ณผ ์†์„ฑ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋‹ค์–‘ํ•œ ์ ‘๊ทผ ๋ฐฉ์‹์˜ ์žฅ๋‹จ์ ์„ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.

๋ชฉ์ฐจ/์š”์•ฝ

  • ๋ฐฐ๊ฒฝ
  • ์ œ์•ˆ

    • ์˜ต์…˜ 1: ์†์„ฑ๋งŒ ์„ค์ •

    • ์žฅ์ 



      • ์ดํ•ด/๊ตฌํ˜„ ์šฉ์ด


      • ๋ฏธ๋ž˜ ์ „์—ญ ์†์„ฑ๊ณผ์˜ ์ถฉ๋Œ ๋ฐฉ์ง€


      • ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ "์—…๊ทธ๋ ˆ์ด๋“œ" ํ™œ์šฉ


      • ๋‹ค๋ฅธ React ๊ตฌ์„ฑ ์š”์†Œ์ฒ˜๋Ÿผ ์ทจ๊ธ‰๋˜๋Š” ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ



    • ๋‹จ์ 



      • ์•„๋งˆ๋„ ๋ธŒ๋ ˆ์ดํ‚น ์ฒด์ธ์ง€


      • ์†์„ฑ์„ ์„ค์ •ํ•˜๋ ค๋ฉด ์ฐธ์กฐ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.


      • ์„œ๋ฒ„ ์ธก ๋ Œ๋”๋ง์ด ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€ ๋ช…ํ™•ํ•˜์ง€ ์•Š์Œ



    • ์˜ต์…˜ 2: ๊ฐ€๋Šฅํ•œ ๊ฒฝ์šฐ ์†์„ฑ

    • ์žฅ์ 



      • ํ•ต์‹ฌ ๋ณ€๊ฒฝ ์‚ฌํ•ญ



    • ๋‹จ์ 



      • ๊ฐœ๋ฐœ์ž๋Š” ํœด๋ฆฌ์Šคํ‹ฑ์„ ์ดํ•ดํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.


      • ์†์„ฑ์œผ๋กœ ํด๋ฐฑํ•˜๋ฉด ๋ฏธ๋ž˜ ์ „์—ญ๊ณผ ์ถฉ๋Œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.



    • ์˜ต์…˜ 3: ์ธ์žฅ์œผ๋กœ ์†์„ฑ ๊ตฌ๋ณ„ํ•˜๊ธฐ

    • ์žฅ์ 



      • ๊ฐœ๋ฐœ์ž๊ฐ€ ์„ ํƒํ•  ์ˆ˜ ์žˆ๋Š” ํ•ต์‹ฌ ๋ณ€๊ฒฝ ์‚ฌํ•ญ


      • ๋‹ค๋ฅธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์†์„ฑ/์†์„ฑ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ์‹๊ณผ ์œ ์‚ฌ


      • ์‹œ์Šคํ…œ์ด ๋ช…์‹œ์ ์ž…๋‹ˆ๋‹ค.



    • ๋‹จ์ 



      • ์ƒˆ๋กœ์šด ๊ตฌ๋ฌธ์ž…๋‹ˆ๋‹ค


      • ์„œ๋ฒ„ ์ธก ๋ Œ๋”๋ง์ด ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€ ๋ช…ํ™•ํ•˜์ง€ ์•Š์Œ



    • ์˜ต์…˜ 4: ์†์„ฑ ๊ฐœ์ฒด ์ถ”๊ฐ€

    • ์žฅ์ 



      • ์‹œ์Šคํ…œ์ด ๋ช…์‹œ์ ์ž…๋‹ˆ๋‹ค.


      • ํ™•์žฅ ๊ตฌ๋ฌธ์€ ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ ๋ฌธ์ œ๋„ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.



    • ๋‹จ์ 



      • ์ƒˆ๋กœ์šด ๊ตฌ๋ฌธ์ž…๋‹ˆ๋‹ค


      • ํš๊ธฐ์ ์ธ ๋ณ€ํ™”์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค


      • ์ด์ „ ์ œ์•ˆ๋ณด๋‹ค ๋” ํฐ ๋ณ€ํ™”์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.



    • ์˜ต์…˜ 5: ๋งž์ถค ์š”์†Œ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ API

    • ์žฅ์ 



      • ์‹œ์Šคํ…œ์ด ๋ช…์‹œ์ ์ž…๋‹ˆ๋‹ค.


      • ํ•ต์‹ฌ ๋ณ€๊ฒฝ ์‚ฌํ•ญ


      • ๋ฐ˜์‘์— ๊ด€์šฉ์ 



    • ๋‹จ์ 



      • ๋ณต์žกํ•œ ๊ตฌ์„ฑ ์š”์†Œ์˜ ๊ฒฝ์šฐ ๋งŽ์€ ์ž‘์—…์ด ํ•„์š”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


      • ๋ฒˆ๋“ค ํฌ๊ธฐ๊ฐ€ ์ปค์งˆ ์ˆ˜ ์žˆ์Œ


      • ๊ตฌ์„ฑ์€ ๊ตฌ์„ฑ ์š”์†Œ์™€ ๋ณด์กฐ๋ฅผ ๋งž์ถฐ์•ผ ํ•ฉ๋‹ˆ๋‹ค.



๋ฐฐ๊ฒฝ

React๋Š” ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ์— ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•˜๋ ค๊ณ  ํ•  ๋•Œ ํ•ญ์ƒ HTML ์†์„ฑ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.

<x-foo bar={baz}> // same as setAttribute('bar', baz)

์†์„ฑ์€ ๋ฌธ์ž์—ด๋กœ ์ง๋ ฌํ™”๋˜์–ด์•ผ ํ•˜๋ฏ€๋กœ ์ด ์ ‘๊ทผ ๋ฐฉ์‹์€ ์ „๋‹ฌ๋˜๋Š” ๋ฐ์ดํ„ฐ๊ฐ€ ๊ฐœ์ฒด ๋˜๋Š” ๋ฐฐ์—ด์ธ ๊ฒฝ์šฐ ๋ฌธ์ œ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ์ด ์‹œ๋‚˜๋ฆฌ์˜ค์—์„œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋๋‚ฉ๋‹ˆ๋‹ค.

<x-foo bar="[object Object]">

์ด์— ๋Œ€ํ•œ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์€ ref ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์†์„ฑ์„ ์ˆ˜๋™์œผ๋กœ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

<x-foo ref={el => el.bar = baz}>

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

์ด ๋ฌธ์„œ๋Š” ์ด๋ฅผ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด ์–ด๋–ป๊ฒŒ React๋ฅผ ์—…๋ฐ์ดํŠธํ•  ์ˆ˜ ์žˆ๋Š”์ง€์— ๋Œ€ํ•œ ๋ช‡ ๊ฐ€์ง€ ์ œ์•ˆ์„ ๊ฐ„๋žตํ•˜๊ฒŒ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.

์ œ์•ˆ

์˜ต์…˜ 1: ์†์„ฑ๋งŒ ์„ค์ •

์†์„ฑ์ด๋‚˜ ์†์„ฑ์„ ์„ค์ •ํ•ด์•ผ ํ•˜๋Š”์ง€ ๊ฒฐ์ •ํ•˜๋Š” ๋Œ€์‹  React๋Š” ํ•ญ์ƒ ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ์— ์†์„ฑ์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. React๋Š” ์†์„ฑ์ด ์š”์†Œ์— ๋ฏธ๋ฆฌ ์กด์žฌํ•˜๋Š”์ง€ ํ™•์ธ ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค .

์˜ˆ์‹œ:

<x-foo bar={baz}>

์œ„์˜ ์ฝ”๋“œ๋Š” React๊ฐ€ x-foo ์š”์†Œ์˜ .bar ์†์„ฑ์„ baz ๊ฐ’๊ณผ ๋™์ผํ•˜๊ฒŒ ์„ค์ •ํ•˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

camelCased ์†์„ฑ ์ด๋ฆ„์˜ ๊ฒฝ์šฐ React๋Š” ํ˜„์žฌ tabIndex ๊ฐ™์€ ์†์„ฑ์— ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ๊ณผ ๋™์ผํ•œ ์Šคํƒ€์ผ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

<x-foo squidInk={pasta}> // sets .squidInk = pasta

์žฅ์ 

์ดํ•ด/๊ตฌํ˜„ ์šฉ์ด

์ด ๋ชจ๋ธ์€ ๋‹จ์ˆœํ•˜๊ณ  ๋ช…์‹œ์ ์ด๋ฉฐ React์˜ "JavaScript-centric API to DOM" ๊ณผ ๋ฐ€์ ‘ํ•˜๊ฒŒ ์—ฐ๊ด€

Polymer ๋˜๋Š” Skate์™€ ๊ฐ™์€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ ์ƒ์„ฑ๋œ ๋ชจ๋“  ์š”์†Œ๋Š” ๋…ธ์ถœ๋œ ์†์„ฑ์„ ๋’ท๋ฐ›์นจํ•˜๋Š” ์†์„ฑ์„ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์š”์†Œ๋Š” ๋ชจ๋‘ ์œ„์˜ ์ ‘๊ทผ ๋ฐฉ์‹์œผ๋กœ "์ •์ƒ ์ž‘๋™"ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋ฐ”๋‹๋ผ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์ง์ ‘ ์ž‘์„ฑํ•˜๋Š” ๊ฐœ๋ฐœ์ž๋Š” ์†์„ฑ์„ ์‚ฌ์šฉํ•˜์—ฌ ์†์„ฑ ์„ ์ง€์›ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ์ด๋Š” HTML5 ์š”์†Œ( <video> , <audio> ๋“ฑ)๊ฐ€ ์–ผ๋งˆ๋‚˜ ํ˜„๋Œ€์ ์ธ์ง€ (์ฆ‰, <input> ์™€ ๊ฐ™์€ ์ด์ƒํ•œ ๊ฒƒ์ด ์•„๋‹˜)์„ ๋ฐ˜์˜ํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๊ตฌํ˜„๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

๋ฏธ๋ž˜ ์ „์—ญ ์†์„ฑ๊ณผ์˜ ์ถฉ๋Œ ๋ฐฉ์ง€

React๊ฐ€ ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ์— ์†์„ฑ์„ ์„ค์ •ํ•˜๋ฉด HTML์˜ ํ–ฅํ›„ ๋ฒ„์ „์ด ๋น„์Šทํ•œ ์ด๋ฆ„์˜ ์†์„ฑ์„ ์ œ๊ณตํ•˜์—ฌ ๋ฌธ์ œ๋ฅผ ์ผ์œผํ‚ฌ ์œ„ํ—˜์ด ํ•ญ์ƒ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๋ฌธ์ œ๋Š” ์‚ฌ์–‘ ์ž‘์„ฑ์ž์™€ ๋…ผ์˜ ๋˜์—ˆ์ง€๋งŒ ๋ฌธ์ œ์— ๋Œ€ํ•œ ๋ช…ํ™•ํ•œ ํ•ด๊ฒฐ์ฑ…์€ ์—†์Šต๋‹ˆ๋‹ค. ์†์„ฑ์„ ์™„์ „ํžˆ ํ”ผํ•˜๋ฉด(๊ฐœ๋ฐœ์ž๊ฐ€ ref ์‚ฌ์šฉํ•˜์—ฌ ๋ช…์‹œ์ ์œผ๋กœ ์†์„ฑ์„ ์„ค์ •ํ•˜๋Š” ๊ฒฝ์šฐ ์ œ์™ธ) ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ๋” ๋‚˜์€ ์†”๋ฃจ์…˜์„ ์ œ๊ณตํ•  ๋•Œ๊นŒ์ง€ ์ด ๋ฌธ์ œ๋ฅผ ํ”ผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ "์—…๊ทธ๋ ˆ์ด๋“œ" ํ™œ์šฉ

์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ๋Š” ํŽ˜์ด์ง€์—์„œ ๋Š๋ฆฌ๊ฒŒ ์—…๊ทธ๋ ˆ์ด๋“œ ๋  ์ˆ˜ ์žˆ์œผ๋ฉฐ ์ผ๋ถ€ PRPL ํŒจํ„ด์€ ์ด ๊ธฐ์ˆ ์— ์˜์กดํ•ฉ๋‹ˆ๋‹ค. ์—…๊ทธ๋ ˆ์ด๋“œ ํ”„๋กœ์„ธ์Šค ๋™์•ˆ ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ๋Š” React์— ์˜ํ•ด ์ „๋‹ฌ๋œ ์†์„ฑ์— ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ(ํ•ด๋‹น ์†์„ฑ์ด ์ •์˜๊ฐ€ ๋กœ๋“œ๋˜๊ธฐ ์ „์— ์„ค์ •๋˜์—ˆ๋”๋ผ๋„) ์ด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ดˆ๊ธฐ ์ƒํƒœ๋ฅผ ๋ Œ๋”๋งํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‹ค๋ฅธ React ๊ตฌ์„ฑ ์š”์†Œ์ฒ˜๋Ÿผ ์ทจ๊ธ‰๋˜๋Š” ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ

React ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ ์„œ๋กœ ์ „๋‹ฌํ•  ๋•Œ ์ด๋ฏธ ์†์„ฑ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์‚ฌ์šฉ์ž ์ง€์ • ์š”์†Œ๊ฐ€ ๋™์ผํ•œ ๋ฐฉ์‹์œผ๋กœ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.

๋‹จ์ 

์•„๋งˆ๋„ ๋ธŒ๋ ˆ์ดํ‚น ์ฒด์ธ์ง€

๊ฐœ๋ฐœ์ž๊ฐ€ ์†์„ฑ API๋งŒ ์žˆ๋Š” ๋ฐ”๋‹๋ผ ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ๋ฅผ ์ˆ˜๋™์œผ๋กœ ์ž‘์„ฑํ–ˆ๋‹ค๋ฉด ์ฝ”๋“œ๋ฅผ ์—…๋ฐ์ดํŠธํ•ด์•ผ ํ•˜๋ฉฐ ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ์•ฑ์ด ์ค‘๋‹จ๋ฉ๋‹ˆ๋‹ค. ์ˆ˜์ • ์‚ฌํ•ญ์€ ref ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์†์„ฑ์„ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค(์•„๋ž˜ ์„ค๋ช… ์ฐธ์กฐ).

์†์„ฑ์„ ์„ค์ •ํ•˜๋ ค๋ฉด ์ฐธ์กฐ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

์†์„ฑ์ด ์„ ํ˜ธ๋˜๋„๋ก ๋™์ž‘์„ ๋ณ€๊ฒฝํ•˜๋ฉด ๊ฐœ๋ฐœ์ž๊ฐ€ ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ์— ์†์„ฑ์„ ๋ช…์‹œ์ ์œผ๋กœ ์„ค์ •ํ•˜๊ธฐ ์œ„ํ•ด ref ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•จ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

<custom-element ref={el => el.setAttribute('my-attr', val)} />

์ด๊ฒƒ์€ ๊ฐœ๋ฐœ์ž๊ฐ€ ์†์„ฑ์„ ์„ค์ •ํ•˜๊ธฐ ์œ„ํ•ด ref ๊ฐ€ ํ•„์š”ํ•œ ํ˜„์žฌ ๋™์ž‘์˜ ๋ฐ˜์ „์ž…๋‹ˆ๋‹ค. ๊ฐœ๋ฐœ์ž๋Š” ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ์— ์†์„ฑ์„ ์„ค์ •ํ•  ํ•„์š”๊ฐ€ ๊ฑฐ์˜ ์—†์–ด์•ผ ํ•˜๋ฏ€๋กœ ์ด๋Š” ํ•ฉ๋ฆฌ์ ์ธ ์ ˆ์ถฉ์•ˆ์œผ๋กœ ๋ณด์ž…๋‹ˆ๋‹ค.

์„œ๋ฒ„ ์ธก ๋ Œ๋”๋ง์ด ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€ ๋ช…ํ™•ํ•˜์ง€ ์•Š์Œ

์ด ๋ชจ๋ธ์ด ์„œ๋ฒ„ ์ธก ๋ Œ๋”๋ง ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ์— ์–ด๋–ป๊ฒŒ ๋งคํ•‘๋˜๋Š”์ง€๋Š” ํ™•์‹คํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. React๋Š” ์†์„ฑ์ด ์œ ์‚ฌํ•œ ์ด๋ฆ„์˜ ์†์„ฑ์— ๋งคํ•‘๋œ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜๊ณ  ์„œ๋ฒ„์—์„œ ์„ค์ •์„ ์‹œ๋„ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ์ด๊ฒƒ์€ ๋ฐฉํƒ„์ด ์•„๋‹ˆ๋ฉฐ camelCased ์†์„ฑ -> dash-cased ์†์„ฑ๊ณผ ๊ฐ™์€ ๊ฒƒ์— ๋Œ€ํ•œ ๊ฒฝํ—˜์  ๋ฐฉ๋ฒ•์ด ํ•„์š”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์˜ต์…˜ 2: ๊ฐ€๋Šฅํ•œ ๊ฒฝ์šฐ ์†์„ฑ

๋Ÿฐํƒ€์ž„์— React๋Š” ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ์— ์†์„ฑ์ด ์žˆ๋Š”์ง€ ๊ฐ์ง€ํ•˜๋ ค๊ณ  ์‹œ๋„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์†์„ฑ์ด ์žˆ์œผ๋ฉด React๊ฐ€ ์ด๋ฅผ ์‚ฌ์šฉํ•˜๊ณ , ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ์†์„ฑ ์„ค์ •์œผ๋กœ ๋Œ€์ฒดํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ Preact๊ฐ€ ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•˜๋Š” ๋ชจ๋ธ์ž…๋‹ˆ๋‹ค.

์˜์‚ฌ ์ฝ”๋“œ ๊ตฌํ˜„:

if (propName in element) {
  element[propName] = value;
} else {
  element.setAttribute(propName.toLowerCase(), value);
}

๊ฐ€๋Šฅํ•œ ๋‹จ๊ณ„:

  • ์š”์†Œ์— ์ •์˜๋œ ์†์„ฑ์ด ์žˆ์œผ๋ฉด React๊ฐ€ ์ด๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

  • ์š”์†Œ์— ์ •์˜๋˜์ง€ ์•Š์€ ์†์„ฑ์ด ์žˆ๊ณ  React๊ฐ€ ๊ธฐ๋ณธ ๋ฐ์ดํ„ฐ(๋ฌธ์ž์—ด/์ˆซ์ž/๋ถ€์šธ)๋ฅผ ์ „๋‹ฌํ•˜๋ ค๊ณ  ํ•˜๋ฉด ์†์„ฑ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

    • ๋Œ€์•ˆ: ๊ฒฝ๊ณ ํ•˜๊ณ  ์„ค์ •ํ•˜์ง€ ๋งˆ์‹ญ์‹œ์˜ค.
  • ์š”์†Œ์— ์ •์˜๋˜์ง€ ์•Š์€ ์†์„ฑ์ด ์žˆ๊ณ  React๊ฐ€ ๊ฐœ์ฒด/๋ฐฐ์—ด์„ ์ „๋‹ฌํ•˜๋ ค๊ณ  ํ•˜๋ฉด ์†์„ฑ์œผ๋กœ ์„ค์ •๋ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ some-attr="[object Object]"๊ฐ€ ์œ ์šฉํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

    • ๋Œ€์•ˆ: ๊ฒฝ๊ณ ํ•˜๊ณ  ์„ค์ •ํ•˜์ง€ ๋งˆ์‹ญ์‹œ์˜ค.
  • ์š”์†Œ๊ฐ€ ์„œ๋ฒ„์—์„œ ๋ Œ๋”๋ง๋˜๊ณ  React๊ฐ€ ๋ฌธ์ž์—ด/์ˆซ์ž/๋ถ€์šธ์„ ์ „๋‹ฌํ•˜๋ ค๊ณ  ํ•˜๋ฉด ์†์„ฑ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

  • ์š”์†Œ๊ฐ€ ์„œ๋ฒ„์—์„œ ๋ Œ๋”๋ง๋˜๊ณ  React๊ฐ€ ๊ฐœ์ฒด/๋ฐฐ์—ด์„ ์ „๋‹ฌํ•˜๋ ค๊ณ  ํ•˜๋ฉด ์•„๋ฌด ์ž‘์—…๋„ ์ˆ˜ํ–‰ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์žฅ์ 

ํ•ต์‹ฌ ๋ณ€๊ฒฝ ์‚ฌํ•ญ

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

๋‹จ์ 

๊ฐœ๋ฐœ์ž๋Š” ํœด๋ฆฌ์Šคํ‹ฑ์„ ์ดํ•ดํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๊ฐœ๋ฐœ์ž๋Š” React๊ฐ€ ์š”์†Œ๋ฅผ ๋กœ๋“œํ•˜๊ธฐ ์œ„ํ•ด ์„ ํƒํ•œ ๋ฐฉ๋ฒ•์— ๋”ฐ๋ผ ์†์„ฑ ๋Œ€์‹  ์†์„ฑ์„ ์„ค์ •ํ•  ๋•Œ ํ˜ผ๋ž€์Šค๋Ÿฌ์šธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์†์„ฑ์œผ๋กœ ํด๋ฐฑํ•˜๋ฉด ๋ฏธ๋ž˜ ์ „์—ญ๊ณผ ์ถฉ๋Œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Sebastian ์€ in ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์‚ฌ์šฉ์ž ์ง€์ • ์š”์†Œ์˜ ์†์„ฑ์ด ์žˆ๋Š”์ง€ ํ™•์ธํ•˜๋Š” ๋ฐ ์‹ค์ˆ˜๋กœ ์Šˆํผํด๋ž˜์Šค(HTMLElement)์˜ ์†์„ฑ์„ ๊ฐ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์šฐ๋ ค ๋ฅผ

์ด ๋ฌธ์„œ์˜ ์ด์ „ ์—

์˜ต์…˜ 3: ์ธ์žฅ์œผ๋กœ ์†์„ฑ ๊ตฌ๋ณ„ํ•˜๊ธฐ

React๋Š” ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ์— ๋Œ€ํ•œ ์†์„ฑ์„ ๊ณ„์† ์„ค์ •ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ๊ฐœ๋ฐœ์ž๊ฐ€ ๋Œ€์‹  ๋ช…์‹œ์ ์œผ๋กœ ์†์„ฑ์„ ์„ค์ •ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์ธ์žฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ Glimmer.js์—์„œ ์‚ฌ์šฉํ•˜๋Š” ์ ‘๊ทผ ๋ฐฉ์‹ ๊ณผ ์œ ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

ํฌ๋ฏธํ•œ ์˜ˆ:

<custom-img @src="corgi.jpg" @hiResSrc="[email protected]" width="100%">

์œ„์˜ ์˜ˆ์—์„œ @ sigil์€ src ๋ฐ hiResSrc ๊ฐ€ ์†์„ฑ์„ ์‚ฌ์šฉํ•˜์—ฌ ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ์— ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•˜๊ณ  width ๊ฐ€ ์†์„ฑ ๋ฌธ์ž์—ด๋กœ ์ง๋ ฌํ™”๋˜์–ด์•ผ ํ•จ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

React ๊ตฌ์„ฑ ์š”์†Œ๋Š” ์ด๋ฏธ ์†์„ฑ์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฅผ ์„œ๋กœ ์ „๋‹ฌํ•˜๊ธฐ ๋•Œ๋ฌธ์— sigil์„ ์‚ฌ์šฉํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค(๊ทธ๋ ‡๋‹ค๋ฉด ์ž‘๋™ํ•˜์ง€๋งŒ ์ค‘๋ณต๋  ๋ฟ์ž…๋‹ˆ๋‹ค). ๋Œ€์‹  JavaScript ์†์„ฑ์„ ์‚ฌ์šฉํ•˜์—ฌ ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ์— ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•˜๊ธฐ ์œ„ํ•œ ๋ช…์‹œ์  ๋ช…๋ น์œผ๋กœ ์ฃผ๋กœ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

์ด ์ ‘๊ทผ ๋ฐฉ์‹์„ ์ œ์•ˆํ•œ Preact ์˜ @developit์—๊ฒŒ h/t๋ฅผ

์žฅ์ 

๊ฐœ๋ฐœ์ž๊ฐ€ ์„ ํƒํ•  ์ˆ˜ ์žˆ๋Š” ํ•ต์‹ฌ ๋ณ€๊ฒฝ ์‚ฌํ•ญ

๊ธฐ์กด์˜ ๋ชจ๋“  React + ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ ์•ฑ์€ ๊ทธ๋Œ€๋กœ ๊ณ„์† ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ๊ฐœ๋ฐœ์ž๋Š” ์ƒˆ๋กœ์šด sigil ์Šคํƒ€์ผ์„ ์‚ฌ์šฉํ•˜๋„๋ก ์ฝ”๋“œ๋ฅผ ์—…๋ฐ์ดํŠธํ• ์ง€ ์—ฌ๋ถ€๋ฅผ ์„ ํƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‹ค๋ฅธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์†์„ฑ/์†์„ฑ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ์‹๊ณผ ์œ ์‚ฌ

Glimmer์™€ ์œ ์‚ฌํ•˜๊ฒŒ Angular์™€ Vue ๋ชจ๋‘ ์†์„ฑ๊ณผ ์†์„ฑ์„ ๊ตฌ๋ณ„ํ•˜๊ธฐ ์œ„ํ•ด ์ˆ˜์ •์ž๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

๋ทฐ ์˜ˆ์‹œ:

<!-- Vue will serialize `foo` to an attribute string, and set `squid` using a JavaScript property -->
<custom-element :foo="barโ€ :squid.prop=โ€inkโ€>

๊ฐ๋„ ์˜ˆ:

<!-- Angular will serialize `foo` to an attribute string, and set `squid` using a JavaScript property -->
<custom-element [attr.foo]="barโ€ [squid]=โ€inkโ€>

์‹œ์Šคํ…œ์ด ๋ช…์‹œ์ ์ž…๋‹ˆ๋‹ค.

๊ฐœ๋ฐœ์ž๋Š” properties-if-available ์ ‘๊ทผ ๋ฐฉ์‹๊ณผ ๊ฐ™์€ ๊ฒฝํ—˜์  ๋ฐฉ๋ฒ•์— ์˜์กดํ•˜๋Š” ๋Œ€์‹  ์›ํ•˜๋Š” ๊ฒƒ์„ ์ •ํ™•ํžˆ React์— ๋งํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‹จ์ 

์ƒˆ๋กœ์šด ๊ตฌ๋ฌธ์ž…๋‹ˆ๋‹ค

๊ฐœ๋ฐœ์ž๋Š” ์‚ฌ์šฉ ๋ฐฉ๋ฒ•์„ ๋ฐฐ์›Œ์•ผ ํ•˜๋ฉฐ ์ด์ „ ๋ฒ„์ „๊ณผ์˜ ํ˜ธํ™˜์„ฑ์„ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด ์ฒ ์ €ํžˆ ํ…Œ์ŠคํŠธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์„œ๋ฒ„ ์ธก ๋ Œ๋”๋ง์ด ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€ ๋ช…ํ™•ํ•˜์ง€ ์•Š์Œ

sigil์ด ๋น„์Šทํ•œ ์ด๋ฆ„์˜ ์†์„ฑ์„ ์‚ฌ์šฉํ•˜๋„๋ก ์ „ํ™˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๊นŒ?

์˜ต์…˜ 4: ์†์„ฑ ๊ฐœ์ฒด ์ถ”๊ฐ€

React๋Š” ์ž‘์„ฑ์ž๊ฐ€ ๋ช…์‹œ์ ์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์†์„ฑ์œผ๋กœ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋Š” ์ถ”๊ฐ€ ๊ตฌ๋ฌธ์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐœ๋ฐœ์ž๊ฐ€ ์ด ์†์„ฑ ๊ฐœ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ ํ•ด๋‹น ๋ฐ์ดํ„ฐ๋Š” JavaScript ์†์„ฑ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ „๋‹ฌ๋ฉ๋‹ˆ๋‹ค.

์˜ˆ์‹œ:

const bar = 'baz';
const hello = 'World';
const width = '100%';
const ReactElement = <Test
  foo={bar} // uses JavaScript property
  attrs={{ hello, width }} // serialized to attributes
/>;

์ด ์•„์ด๋””์–ด๋Š” ์›๋ž˜ Skate.js ์˜ ์ž‘์„ฑ์ž์ธ @treshugart๊ฐ€ ์ œ์•ˆ ํ–ˆ์œผ๋ฉฐ val ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ ๊ตฌํ˜„๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

์žฅ์ 

์‹œ์Šคํ…œ์ด ๋ช…์‹œ์ ์ž…๋‹ˆ๋‹ค.

๊ฐœ๋ฐœ์ž๋Š” properties-if-available ์ ‘๊ทผ ๋ฐฉ์‹๊ณผ ๊ฐ™์€ ๊ฒฝํ—˜์  ๋ฐฉ๋ฒ•์— ์˜์กดํ•˜๋Š” ๋Œ€์‹  ์›ํ•˜๋Š” ๊ฒƒ์„ ์ •ํ™•ํžˆ React์— ๋งํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ™•์žฅ ๊ตฌ๋ฌธ์€ ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ ๋ฌธ์ œ๋„ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ฐธ๊ณ : ์ด๊ฒƒ์€ ์ด ๋ฌธ์„œ์˜ ๋ฒ”์œ„๋ฅผ ๋ฒ—์–ด๋‚˜์ง€๋งŒ ์–ธ๊ธ‰ํ•  ๊ฐ€์น˜๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. :)

๋ฌธ์ œ #7901 ์€ ์„ ์–ธ์  ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ์— ์ถ”๊ฐ€๋  ๋•Œ React๊ฐ€ ํ•ฉ์„ฑ ์ด๋ฒคํŠธ ์‹œ์Šคํ…œ์„ ์šฐํšŒํ•˜๋„๋ก ์š”์ฒญํ•ฉ๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ ์ด๋ฒคํŠธ ์ด๋ฆ„์€ ์ž„์˜์˜ ๋ฌธ์ž์—ด์ด๋ฏ€๋กœ ์–ด๋–ค ๋ฐฉ์‹์œผ๋กœ๋“  ๋Œ€๋ฌธ์ž๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ค๋Š˜๋‚  ํ•ฉ์„ฑ ์ด๋ฒคํŠธ ์‹œ์Šคํ…œ์„ ์šฐํšŒํ•˜๋ ค๋ฉด JSX์—์„œ addEventListener ์ด๋ฒคํŠธ ์ด๋ฆ„์„ ๋งคํ•‘ํ•˜๊ธฐ ์œ„ํ•œ ๊ฒฝํ—˜์  ๋ฐฉ๋ฒ•์„ ์ฐพ์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค.

// should this listen for: 'foobar', 'FooBar', or 'fooBar'?
onFooBar={handleFooBar}

๊ทธ๋Ÿฌ๋‚˜ ์†์„ฑ์„ ํ—ˆ์šฉํ•˜๋„๋ก ๊ตฌ๋ฌธ์ด ํ™•์žฅ๋˜๋ฉด ์ด๋ฒคํŠธ๋„ ํ—ˆ์šฉํ•˜๋„๋ก ํ™•์žฅ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

const bar = 'baz';
const hello = 'World';
const SquidChanged = e => console.log('yo');
const ReactElement = <Test
  foo={bar}
  attrs={{ hello }}
  events={{ SquidChanged}} // addEventListener('SquidChanged', โ€ฆ)
/>;

์ด ๋ชจ๋ธ์—์„œ ๋ณ€์ˆ˜ ์ด๋ฆ„์€ ์ด๋ฒคํŠธ ์ด๋ฆ„์œผ๋กœ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ํœด๋ฆฌ์Šคํ‹ฑ์ด ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๋‹จ์ 

์ƒˆ๋กœ์šด ๊ตฌ๋ฌธ์ž…๋‹ˆ๋‹ค

๊ฐœ๋ฐœ์ž๋Š” ์‚ฌ์šฉ ๋ฐฉ๋ฒ•์„ ๋ฐฐ์›Œ์•ผ ํ•˜๋ฉฐ ์ด์ „ ๋ฒ„์ „๊ณผ์˜ ํ˜ธํ™˜์„ฑ์„ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด ์ฒ ์ €ํžˆ ํ…Œ์ŠคํŠธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

ํš๊ธฐ์ ์ธ ๋ณ€ํ™”์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค

๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ์ด๋ฏธ attrs ๋˜๋Š” events ๋ผ๋Š” ์†์„ฑ์— ์˜์กดํ•˜๋Š” ๊ฒฝ์šฐ ์†์ƒ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด์ „ ์ œ์•ˆ๋ณด๋‹ค ๋” ํฐ ๋ณ€ํ™”์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

React 17์˜ ๊ฒฝ์šฐ (์ด์ „ ์ œ์•ˆ ์ค‘ ํ•˜๋‚˜์™€ ๊ฐ™์ด) ์ ์ง„์ ์ธ ๋ณ€๊ฒฝ์„ ์ˆ˜ํ–‰ํ•˜๊ณ  ์ด ์ œ์•ˆ์„ ๋‚˜์ค‘์— ๋” ํฐ ๋ฆฌํŒฉํ„ฐ๋ง์„ ์œ„ํ•ด ๊ณ ๋ คํ•ด์•ผ ํ•  ์‚ฌํ•ญ์œผ๋กœ ๋ฐฐ์น˜ํ•˜๋Š” ๊ฒƒ์ด ๋” ์‰ฌ์šธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์˜ต์…˜ 5: ๋งž์ถค ์š”์†Œ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ API

์ด ์ œ์•ˆ์€ React ํŒ€์˜ @sophiebits ์™€ @gaearon ์ด ์ œ์•ˆํ–ˆ์Šต๋‹ˆ๋‹ค.

React๋Š” ์š”์†Œ์˜ ๋™์ž‘์„ ๊ตฌ์„ฑ ๊ฐœ์ฒด์™€ ๋งคํ•‘ํ•˜๋Š” ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ ์ƒˆ API๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์˜์‚ฌ ์ฝ”๋“œ ์˜ˆ:

const XFoo = ReactDOM.createCustomElementType({
  element: โ€˜x-fooโ€™,
  โ€˜my-attrโ€™: // something that tells React what to do with it
  someRichDataProp: // something that tells React what to do with it
});

์œ„์˜ ์ฝ”๋“œ๋Š” ์ œ๊ณตํ•˜๋Š” ๊ตฌ์„ฑ์— ๋”ฐ๋ผ ์‚ฌ์šฉ์ž ์ง€์ • ์š”์†Œ์— ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ๊ณ  ์žˆ๋Š” ํ”„๋ก์‹œ ๊ตฌ์„ฑ ์š”์†Œ XFoo ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž ์ง€์ • ์š”์†Œ๋ฅผ ์ง์ ‘ ์‚ฌ์šฉํ•˜๋Š” ๋Œ€์‹  ์•ฑ์—์„œ ์ด ํ”„๋ก์‹œ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

์‚ฌ์šฉ ์˜ˆ:

<XFoo someRichDataProp={...} />

์žฅ์ 

์‹œ์Šคํ…œ์ด ๋ช…์‹œ์ ์ž…๋‹ˆ๋‹ค.

๊ฐœ๋ฐœ์ž๋Š” React์—๊ฒŒ ๊ทธ๋“ค์ด ์›ํ•˜๋Š” ์ •ํ™•ํ•œ ๋™์ž‘์„ ๋งํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ•ต์‹ฌ ๋ณ€๊ฒฝ ์‚ฌํ•ญ

๊ฐœ๋ฐœ์ž๋Š” ๊ฐœ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก ์„ ํƒํ•˜๊ฑฐ๋‚˜ ํ˜„์žฌ ์‹œ์Šคํ…œ์„ ๊ณ„์† ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฐ˜์‘์— ๊ด€์šฉ์ 

์ด ๋ณ€๊ฒฝ์€ ์ƒˆ๋กœ์šด JSX ๊ตฌ๋ฌธ์„ ํ•„์š”๋กœ ํ•˜์ง€ ์•Š์œผ๋ฉฐ React์˜ ๋‹ค๋ฅธ API์ฒ˜๋Ÿผ ๋Š๊ปด์ง‘๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, PropTypes(์ž์ฒด ํŒจํ‚ค์ง€๋กœ ์ด๋™๋˜๋”๋ผ๋„)๋Š” ๋‹ค์†Œ ์œ ์‚ฌํ•œ ์ ‘๊ทผ ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

๋‹จ์ 

๋ณต์žกํ•œ ๊ตฌ์„ฑ ์š”์†Œ์˜ ๊ฒฝ์šฐ ๋งŽ์€ ์ž‘์—…์ด ํ•„์š”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Polymer์˜ paper-input ์š”์†Œ์—๋Š” 37๊ฐœ์˜ ์†์„ฑ์ด ์žˆ์œผ๋ฏ€๋กœ ๋งค์šฐ ํฐ ๊ตฌ์„ฑ์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ๊ฐœ๋ฐœ์ž๊ฐ€ ์•ฑ์—์„œ ๋งŽ์€ ์‚ฌ์šฉ์ž ์ง€์ • ์š”์†Œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ ์ž‘์„ฑํ•ด์•ผ ํ•˜๋Š” ๊ตฌ์„ฑ์ด ๋งŽ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฒˆ๋“ค ํฌ๊ธฐ๊ฐ€ ์ปค์งˆ ์ˆ˜ ์žˆ์Œ

์œ„์˜ ์š”์ ๊ณผ ๊ด€๋ จํ•˜์—ฌ ๊ฐ ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ ํด๋ž˜์Šค๋Š” ์ด์ œ ์ •์˜ ๋น„์šฉ + ๊ตฌ์„ฑ ๊ฐœ์ฒด ํฌ๊ธฐ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค.

์ฐธ๊ณ : ์ด๊ฒƒ์ด ์‚ฌ์‹ค์ธ์ง€ 100% ํ™•์‹ ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

๊ตฌ์„ฑ์€ ๊ตฌ์„ฑ ์š”์†Œ์™€ ๋ณด์กฐ๋ฅผ ๋งž์ถฐ์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ์ƒˆ ์†์„ฑ์„ ์ถ”๊ฐ€ํ•˜๋Š” ๋งˆ์ด๋„ˆ ๋ฒ„์ „ ๊ฐœ์ •์„ ์ˆ˜ํ–‰ํ•  ๋•Œ๋งˆ๋‹ค ๊ตฌ์„ฑ๋„ ์—…๋ฐ์ดํŠธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์–ด๋ ต์ง€๋Š” ์•Š์ง€๋งŒ ์œ ์ง€ ๊ด€๋ฆฌ๊ฐ€ ์ถ”๊ฐ€๋ฉ๋‹ˆ๋‹ค. ์†Œ์Šค์—์„œ ๊ตฌ์„ฑ์„ ์ƒ์„ฑํ•˜๋Š” ๊ฒฝ์šฐ ๋ถ€๋‹ด์ด ๋œํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ์ด๋Š” ๊ฐ ์›น ๊ตฌ์„ฑ ์š”์†Œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ๋Œ€ํ•œ ๊ตฌ์„ฑ์„ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•ด ์ƒˆ ๋„๊ตฌ๋ฅผ ์ƒ์„ฑํ•ด์•ผ ํ•จ์„ ์˜๋ฏธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

cc @sebmarkbage @gaearon @developit @treshugart @justinfagnani

DOM Discussion

๊ฐ€์žฅ ์œ ์šฉํ•œ ๋Œ“๊ธ€

์—ฌ๋Ÿฌ๋ถ„, ๊ธฐ๋‹ค๋ฆฌ๋Š” ๋™์•ˆ React https://www.npmjs.com/package/reactify-wc ์—์„œ ์›น ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ๋ž˜ํ•‘ํ•˜๊ธฐ ์œ„ํ•œ shim์„ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค.

import React from "react";
import reactifyWc from "reactify-wc";

// Import your web component. This one defines a tag called 'vaadin-button'
import "@vaadin/vaadin-button";

const onClick = () => console.log('hello world');

const VaadinButton = reactifyWc("vaadin-button");

export const MyReactComponent = () => (
  <>
    <h1>Hello world</h1>
    <VaadinButton onClick={onClick}>
      Click me!
    </VaadinButton>
  </>
)

์ด๊ฒƒ์ด ๋„์›€์ด ๋˜๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค.

(์ด๊ฒƒ์€ ๋‚ด๊ฐ€ OSS์— ์ฒ˜์Œ์œผ๋กœ ์ง„์ถœํ•œ ๊ฒƒ์ด๊ณ , ์‚ฌ๋ฌด์‹ค ๋ฐ–์—์„œ ๋ฌด์–ธ๊ฐ€๋ฅผ ๊ณต๊ฐœํ•œ ์ตœ์ดˆ์˜ ๊ฒƒ ์ค‘ ํ•˜๋‚˜์ž…๋‹ˆ๋‹ค. ๊ฑด์„ค์ ์ธ ๋น„ํŒ์€ ๋”ํ•  ๋‚˜์œ„ ์—†์ด ํ™˜์˜์ž…๋‹ˆ๋‹ค ๐Ÿ˜„ )

๋ชจ๋“  129 ๋Œ“๊ธ€

๊ธด ๊ธ€์„ ์ฝ์–ด์„œ ์ฃ„์†กํ•˜์ง€๋งŒ ๊ฐ ์˜ต์…˜์„ ์ฒ ์ €ํžˆ ์กฐ์‚ฌํ•˜๊ณ  ์žˆ๋Š”์ง€ ํ™•์ธํ•˜๊ณ  ์‹ถ์—ˆ์Šต๋‹ˆ๋‹ค. ์ œ ์˜๊ฒฌ์œผ๋กœ ๋„ˆ๋ฌด ํŽธํ–ฅ๋˜๊ณ  ์‹ถ์ง€๋Š” ์•Š์ง€๋งŒ, ๋งŒ์•ฝ ์ œ๊ฐ€ ์„ ํƒ์˜ ์—ฌ์ง€๊ฐ€ ์žˆ๋‹ค๋ฉด 3๋ฒˆ์„ ํƒํ•  ๊ฒƒ ๊ฐ™์•„์š”.

์˜ต์…˜ 3์€ ์ด์ „ ๋ฒ„์ „๊ณผ ํ˜ธํ™˜๋˜๊ณ  ์„ ์–ธ์ ์ด๋ฉฐ ๋ช…์‹œ์ ์ž…๋‹ˆ๋‹ค. ๋Œ€์ฒด ํœด๋ฆฌ์Šคํ‹ฑ์„ ์œ ์ง€ํ•  ํ•„์š”๊ฐ€ ์—†์œผ๋ฉฐ ๋‹ค๋ฅธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ์ด๋ฏธ ์œ ์‚ฌํ•œ ๊ธฐํ˜ธ/์ˆ˜์ •์ž๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

๊ธด ๊ธ€์„ ์ฝ์–ด์„œ ์ฃ„์†กํ•˜์ง€๋งŒ ๊ฐ ์˜ต์…˜์„ ์ฒ ์ €ํžˆ ์กฐ์‚ฌํ•˜๊ณ  ์žˆ๋Š”์ง€ ํ™•์ธํ•˜๊ณ  ์‹ถ์—ˆ์Šต๋‹ˆ๋‹ค. ์ œ ์˜๊ฒฌ์œผ๋กœ ๋„ˆ๋ฌด ํŽธํ–ฅ๋˜๊ณ  ์‹ถ์ง€๋Š” ์•Š์ง€๋งŒ, ๋งŒ์•ฝ ์ œ๊ฐ€ ์„ ํƒ์˜ ์—ฌ์ง€๊ฐ€ ์žˆ๋‹ค๋ฉด 3๋ฒˆ์„ ํƒํ•  ๊ฒƒ ๊ฐ™์•„์š”.
์˜ต์…˜ 3์€ ์ด์ „ ๋ฒ„์ „๊ณผ ํ˜ธํ™˜๋˜๊ณ  ์„ ์–ธ์ ์ด๋ฉฐ ๋ช…์‹œ์ ์ž…๋‹ˆ๋‹ค. ๋Œ€์ฒด ํœด๋ฆฌ์Šคํ‹ฑ์„ ์œ ์ง€ํ•  ํ•„์š”๊ฐ€ ์—†์œผ๋ฉฐ ๋‹ค๋ฅธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ์ด๋ฏธ ์œ ์‚ฌํ•œ ๊ธฐํ˜ธ/์ˆ˜์ •์ž๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

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

์˜ต์…˜ 3์€ ์„ ์–ธ์  ํŠน์„ฑ์œผ๋กœ ์ธํ•ด ๋งค๋ ฅ์ ์œผ๋กœ ๋ณด์ด์ง€๋งŒ JSX ์ฝ”๋“œ๋ฅผ ์ฝ๋Š” ๋™์•ˆ ์ƒˆ๋กœ ์˜ค๋Š” ๊ฐœ๋ฐœ์ž๋Š” ์š”์†Œ๋ฅผ ๋ Œ๋”๋งํ•  ๋•Œ React๊ฐ€ ์ˆ˜ํ–‰ํ•˜๋Š” ์ž‘์—…์„ ์ฆ‰์‹œ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์˜ต์…˜ 2์— ๋Œ€ํ•œ ์˜๊ฒฌ

๊ฐœ๋ฐœ์ž๋Š” React๊ฐ€ ์š”์†Œ๋ฅผ ๋กœ๋“œํ•˜๊ธฐ ์œ„ํ•ด ์„ ํƒํ•œ ๋ฐฉ๋ฒ•์— ๋”ฐ๋ผ ์†์„ฑ ๋Œ€์‹  ์†์„ฑ์„ ์„ค์ •ํ•  ๋•Œ ํ˜ผ๋ž€์Šค๋Ÿฌ์šธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ์˜ ์†Œ๋น„์ž๋Š” ์ด ๊ตฌ๋ถ„์„ ์ดํ•ดํ•  ํ•„์š”๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ? ์•„๋‹ˆ๋ฉด ์ปค์Šคํ…€ ์š”์†Œ์˜ ์ž‘์„ฑ์ž์—๊ฒŒ๋งŒ ์ค‘์š”ํ•œ๊ฐ€์š”? DOM์—์„œ ๋ณต์žกํ•œ ๊ฐ’์ด๋‚˜ ์†์„ฑ ๊ฐ€์ ธ์˜ค๊ธฐ/์„ค์ •์„ ์ง€์›ํ•˜๋ ค๋ฉด ์š”์†Œ ์ž‘์„ฑ์ž๊ฐ€ HTML(HTML ์‚ฌ์šฉ์—์„œ ๋ฐ์ดํ„ฐ๊ฐ€ ์ „๋‹ฌ๋˜๋Š” ์œ ์ผํ•œ ๋ฐฉ๋ฒ•์ด๊ธฐ ๋•Œ๋ฌธ์—) ๋ฐ ์†์„ฑ์— ์‚ฌ์šฉ๋˜๋Š” ๋ชจ๋“  ์†์„ฑ์„ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•  ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์ž‘์„ฑ์ž๊ฐ€ ์ฒ˜์Œ์— ์†์„ฑ์œผ๋กœ ๊ตฌํ˜„ํ•œ ๋‹ค์Œ ๋‚˜์ค‘์— ๋™์ผํ•œ ์ด๋ฆ„์˜ ์†์„ฑ์„ ์ถ”๊ฐ€ํ•˜์—ฌ ๋ณด๋‹ค ์œ ์—ฐํ•œ ๋ฐ์ดํ„ฐ ์œ ํ˜•์„ ์ง€์›ํ•˜๊ณ  ์†์„ฑ์— ์ €์žฅ๋œ ๊ฐ’์œผ๋กœ ์†์„ฑ์„ ๋ฐฑ์—…ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฏธ๋ž˜์˜ HTMLElement ์†์„ฑ ๋ฐ ์†์„ฑ๊ณผ์˜ ์ด๋ฆ„ ์ถฉ๋Œ์€ ๋ฐ”์ธ๋”ฉ ์ ‘๊ทผ ๋ฐฉ์‹์— ๊ด€๊ณ„์—†์ด ์˜ค๋ฅ˜๋ฅผ ์œ ๋ฐœํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ผ๋ฐ˜์ ์œผ๋กœ ์›น ๊ตฌ์„ฑ ์š”์†Œ ํ‘œ์ค€์˜ ์•ฝ์ ์œผ๋กœ ๋ณด์ž…๋‹ˆ๋‹ค.

์š”์†Œ์— ์ •์˜๋˜์ง€ ์•Š์€ ์†์„ฑ์ด ์žˆ๊ณ  React๊ฐ€ ๊ฐœ์ฒด/๋ฐฐ์—ด์„ ์ „๋‹ฌํ•˜๋ ค๊ณ  ํ•˜๋ฉด ์†์„ฑ์œผ๋กœ ์„ค์ •๋ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ some-attr="[object Object]"๊ฐ€ ์œ ์šฉํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

๊ฐ’์— ๋”ฐ๋ผ ๋‹ค๋ฅด๊ฒŒ ๋ฐ”์ธ๋”ฉํ•˜๋Š” ๊ฒƒ์€ ํ˜ผ๋ž€์Šค๋Ÿฌ์šธ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์š”์†Œ ์ž‘์„ฑ์ž๊ฐ€ ๊ฐ’์„ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ์†์„ฑ getter/setter๋ฅผ ์ง€์ •ํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ ์†์„ฑ์„ ์„ค์ •ํ•˜๋ฉด ์š”์†Œ๊ฐ€ ๊ฐ’์ด ์ง€์ •๋˜์ง€ ์•Š์€ ๊ฒƒ์ฒ˜๋Ÿผ ์ž‘๋™ํ•˜์—ฌ ๋””๋ฒ„๊ทธํ•˜๊ธฐ ๋” ์–ด๋ ค์šธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์˜ต์…˜ 3์— ๋Œ€ํ•œ ์˜๊ฒฌ

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

์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ์˜ ์†Œ๋น„์ž๋Š” ์ด ๊ตฌ๋ถ„์„ ์ดํ•ดํ•  ํ•„์š”๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ? ์•„๋‹ˆ๋ฉด ์ปค์Šคํ…€ ์š”์†Œ์˜ ์ž‘์„ฑ์ž์—๊ฒŒ๋งŒ ์ค‘์š”ํ•œ๊ฐ€์š”?

๋‹น์‹ ์ด ์ง€์ ํ–ˆ๋“ฏ์ด ์š”์†Œ ์ž‘์„ฑ์ž๊ฐ€ ๊ธฐ๋ณธ ๊ฐ’์— ๋Œ€ํ•œ ์†์„ฑ๊ณผ ์†์„ฑ์„ ์ •์˜ํ•˜๊ณ  ๋‘˜ ๋‹ค์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜๋ฝํ•ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ด๊ฒƒ์ด ์‹ค์ œ๋กœ ํฐ ๋ฌธ์ œ์ธ์ง€ ์˜์‹ฌ์Šค๋Ÿฝ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ ์†์„ฑ๊ณผ ์†์„ฑ์„ ๋™๊ธฐํ™” ์ƒํƒœ๋กœ ์œ ์ง€ํ•ด์•ผ ํ•œ๋‹ค๊ณ  ๋ง๋ถ™์˜€์Šต๋‹ˆ๋‹ค(ํ•˜๋‚˜๋ฅผ ์„ค์ •ํ•˜๋ฉด ๋‹ค๋ฅธ ํ•˜๋‚˜๊ฐ€ ์„ค์ •๋จ).

๋ฏธ๋ž˜์˜ HTMLElement ์†์„ฑ ๋ฐ ์†์„ฑ๊ณผ์˜ ์ด๋ฆ„ ์ถฉ๋Œ์€ ๋ฐ”์ธ๋”ฉ ์ ‘๊ทผ ๋ฐฉ์‹์— ๊ด€๊ณ„์—†์ด ์˜ค๋ฅ˜๋ฅผ ์œ ๋ฐœํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ผ๋ฐ˜์ ์œผ๋กœ ์›น ๊ตฌ์„ฑ ์š”์†Œ ํ‘œ์ค€์˜ ์•ฝ์ ์œผ๋กœ ๋ณด์ž…๋‹ˆ๋‹ค.

๋™์˜ํ•˜์ง€๋งŒ ์ด๊ฒƒ์ด React๊ฐ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ ํ•ด๊ฒฐํ•ด์•ผ ํ•  ์‚ฌํ•ญ์ธ์ง€ ํ™•์‹คํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ปค์Šคํ…€ ์š”์†Œ ์‚ฌ์–‘์˜ ์ผ๋ถ€๋กœ ํ•ด๊ฒฐํ•ด์•ผ ํ•  ๋ฌธ์ œ์ฒ˜๋Ÿผ ๋Š๊ปด์ง‘๋‹ˆ๋‹ค. ๋‹ค๊ฐ€์˜ค๋Š” TPAC ํ‘œ์ค€ ํšŒ์˜์˜ ์ผ๋ถ€๋กœ ์ด์— ๋Œ€ํ•ด ๋…ผ์˜ํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์š”์†Œ ์ •์˜ ์†์„ฑ์ด HTMLElement์— ์ถ”๊ฐ€๋˜๋Š” ๋ฏธ๋ž˜ ์†์„ฑ์„ ๊ฐ€๋ฆฌ๊ธฐ ๋•Œ๋ฌธ์— ์†์„ฑ์˜ ๊ฒฝ์šฐ ์ด๊ฒƒ์€ ๋‚˜์˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ js ์†์„ฑ์œผ๋กœ ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ์— ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๊ฒฝ์šฐ ๊ณ„์† ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ์ฃผ์š” ๋ฌธ์ œ๋Š” ์†์„ฑ์ด ์ „์—ญ์ ์ด๊ธฐ ๋•Œ๋ฌธ์— ์†์„ฑ๊ณผ ๊ด€๋ จ๋œ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

๊ฐ’์— ๋”ฐ๋ผ ๋‹ค๋ฅด๊ฒŒ ๋ฐ”์ธ๋”ฉํ•˜๋Š” ๊ฒƒ์€ ํ˜ผ๋ž€์Šค๋Ÿฌ์šธ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์š”์†Œ ์ž‘์„ฑ์ž๊ฐ€ ๊ฐ’์„ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ์†์„ฑ getter/setter๋ฅผ ์ง€์ •ํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ ์†์„ฑ์„ ์„ค์ •ํ•˜๋ฉด ์š”์†Œ๊ฐ€ ๊ฐ’์ด ์ง€์ •๋˜์ง€ ์•Š์€ ๊ฒƒ์ฒ˜๋Ÿผ ์ž‘๋™ํ•˜์—ฌ ๋””๋ฒ„๊ทธํ•˜๊ธฐ ๋” ์–ด๋ ค์šธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ๊ฐ€ ์ง€์—ฐ ๋กœ๋“œ๋˜๊ณ  "์—…๊ทธ๋ ˆ์ด๋“œ"๋œ ๊ฒฝ์šฐ ์ฒ˜์Œ์—๋Š” ์ •์˜๋˜์ง€ ์•Š์€ ์†์„ฑ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ํ•ด๋‹น ์š”์†Œ๊ฐ€ ์—ฌ์ „ํžˆ ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜์‹ ํ•˜๊ณ  ์—…๊ทธ๋ ˆ์ด๋“œ ํ›„์—๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜์—ฌ ํ•ด๋‹น ์‚ฌ์šฉ ์‚ฌ๋ก€๋ฅผ ํ•ด๊ฒฐํ•ฉ๋‹ˆ๋‹ค.

์ž‘์„ฑ์ž๊ฐ€ ๊ฐ’์— ๋Œ€ํ•œ getter/setter๋ฅผ ์ •์˜ํ•˜์ง€ ์•Š์œผ๋ฉด ์ด๊ฒƒ์€ ๋งค์šฐ ์œ ์šฉํ•˜์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ my-attr=[object Object] ๊ฐ€ ์žˆ๋Š” ๊ฒƒ๋„ ์œ ์šฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์†์„ฑ์ด ์ •๋ง๋กœ ์ •์˜๋˜์ง€ ์•Š์€ ๊ฒƒ์ธ์ง€ ์•„๋‹ˆ๋ฉด ์ •์˜๊ฐ€ ์ง€์—ฐ ๋กœ๋“œ๋˜๋Š”์ง€ ์•Œ ์ˆ˜ ์—†์œผ๋ฏ€๋กœ ์†์„ฑ์„ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€์žฅ ์•ˆ์ „ํ•ด ๋ณด์ž…๋‹ˆ๋‹ค.

์˜ต์…˜ 3์˜ ๋˜ ๋‹ค๋ฅธ ์ž ์žฌ์ ์ธ ๋‹จ์ ์€ ์‚ฌ์šฉ์ž ์ง€์ • ์š”์†Œ์˜ ์†Œ๋น„์ž๊ฐ€ ์š”์†Œ๊ฐ€ ์†์„ฑ ๋˜๋Š” ์†์„ฑ์œผ๋กœ ๊ตฌํ˜„ํ–ˆ๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ์•Œ์•„์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ ์ž‘์„ฑ์ž๊ฐ€ ์†์„ฑ ๋Œ€์‹  ์†์„ฑ์„ ์ •์˜ํ•˜๋„๋ก ๊ฐ•์ œํ•˜๋Š” ๊ฒƒ์ด ์—†๊ธฐ ๋•Œ๋ฌธ์— ๊ท€ํ•˜๋Š” ์˜ค๋Š˜๋‚  ๋ณธ์งˆ์ ์œผ๋กœ ๊ฐ™์€ ๋ฐฐ์— ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ React์˜ ํ˜„์žฌ ์‹œ์Šคํ…œ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜์‹ ํ•˜์ง€ ์•Š๋Š” ์†์„ฑ ์ „์šฉ API๊ฐ€ ์žˆ๋Š” ์š”์†Œ๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์œผ๋ฉฐ ref ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ js ์†์„ฑ์„ ์ง์ ‘ ์„ค์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ๋Š” ๊ธฐ๋ณธ ์š”์†Œ์ด๋ฏ€๋กœ ํ•ด๋‹น ์†์„ฑ ๋ฐ ์†์„ฑ์„ ๊ฐ•์ œ๋กœ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ์€ ์—†์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์šฐ๋ฆฌ๋Š” ๊ทธ๋ ‡๊ฒŒ ํ•˜๋Š” ๊ฒƒ์„ ๋ชจ๋ฒ” ์‚ฌ๋ก€๋กœ ์žฅ๋ คํ•˜๊ธฐ ์œ„ํ•ด ๋งค์šฐ ์—ด์‹ฌํžˆ ๋…ธ๋ ฅํ•˜๊ณ  ์žˆ์œผ๋ฉฐ, ์˜ค๋Š˜๋‚  ๋‚ด๊ฐ€ ์•Œ๊ณ  ์žˆ๋Š” ๋ชจ๋“  ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ํ•ด๋‹น ์†์„ฑ์— ๋Œ€ํ•œ ์ง€์› ์†์„ฑ์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

[ํŽธ์ง‘ํ•˜๋‹ค]

์ด์ „ ์š”์ ์—์„œ ์–ธ๊ธ‰ํ–ˆ๋“ฏ์ด:

DOM์—์„œ ๋ณต์žกํ•œ ๊ฐ’์ด๋‚˜ ์†์„ฑ ๊ฐ€์ ธ์˜ค๊ธฐ/์„ค์ •์„ ์ง€์›ํ•˜๋ ค๋ฉด ์š”์†Œ ์ž‘์„ฑ์ž๊ฐ€ HTML(HTML ์‚ฌ์šฉ์—์„œ ๋ฐ์ดํ„ฐ๊ฐ€ ์ „๋‹ฌ๋˜๋Š” ์œ ์ผํ•œ ๋ฐฉ๋ฒ•์ด๊ธฐ ๋•Œ๋ฌธ์—) ๋ฐ ์†์„ฑ์— ์‚ฌ์šฉ๋˜๋Š” ๋ชจ๋“  ์†์„ฑ์„ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•  ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

์‚ฌ์šฉ์ž๊ฐ€ ์š”์†Œ์— ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์— ๊ฒฐ๊ตญ ์†์„ฑ-์†์„ฑ ๋Œ€์‘์ด ํ•„์š”ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์˜ต์…˜ 3์ด ์ œ๊ณต๋˜๋ฉด ๋Œ€๋ถ€๋ถ„์˜ ์‚ฌ๋žŒ๋“ค์ด @ ์‚ฌ์šฉํ•˜์—ฌ ๋ชจ๋“  ๊ฒƒ์„ ๋ฌถ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์™œ๋ƒํ•˜๋ฉด ๊ทธ๊ฒƒ์ด ๊ฐ€์žฅ ์‰ฝ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์ด .prop ์ˆ˜์‹์–ด๋ฅผ ๋…ธ์ถœํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์˜ค๋Š˜๋‚  Vue์—์„œ ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ๋กœ ์ž‘์—…ํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.

์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ์˜ ์†Œ๋น„์ž๋Š” ์š”์†Œ๊ฐ€ ์†์„ฑ ๋˜๋Š” ์†์„ฑ์œผ๋กœ ๊ตฌํ˜„ํ–ˆ๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ์•Œ์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋‚ด ์ƒ๊ฐ์—๋Š” Rob์ด ๋งํ–ˆ๋“ฏ์ด React๊ฐ€ ๊ฑฑ์ •ํ•ด์•ผ ํ•  ๋ถ€๋ถ„์ด ์•„๋‹™๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž์—๊ฒŒ ์š”์†Œ๊ฐ€ ์ž‘๋™ํ•˜๋Š” ๋ฐฉ์‹์„ ์•Œ๋ ค์ฃผ๋Š” ๊ฒƒ์€ ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ ์ž‘์„ฑ์ž์˜ ์ฑ…์ž„์ž…๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ์ด๊ฒƒ์€ ์‹ค์ œ๋กœ ์˜ค๋Š˜๋‚  ์šฐ๋ฆฌ๊ฐ€ ํ•ด์•ผ ํ•˜๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด <video> ์š”์†Œ์— ๋Œ€ํ•ด ์ƒ๊ฐํ•ด ๋ณด์‹ญ์‹œ์˜ค. ์ด๋ฅผ ์Œ์†Œ๊ฑฐํ•˜๊ฑฐ๋‚˜ ๊ตฌ์„ฑ ์š”์†Œ ๋‚ด๋ถ€์˜ ํ˜„์žฌ ์‹œ๊ฐ„์„ ๋ณ€๊ฒฝํ•ด์•ผ ํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

muted ๋Š” ๋ถ€์šธ ์†์„ฑ์œผ๋กœ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.

render() {
  return (
    <div className="video--wrapper">
      <video muted={ this.state.muted } />
    </div>
  );
}

ํ˜„์žฌ๋กœ์„œ๋Š” video ์š”์†Œ๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ref ๋ฅผ ๋งŒ๋“ค๊ณ  ์†์„ฑ์„ ๋ณ€๊ฒฝํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

render() {
  return (
    <div className="video--wrapper">
      <video ref={ el => this.video = el } muted={ this.state.muted } />
    </div>
  );
}

๊ทธ๋Ÿฐ ๋‹ค์Œ ์ธ์Šคํ„ด์Šค ๋ฉ”์„œ๋“œ์ธ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ๋งŒ๋“ค๊ณ  ์†์„ฑ์„ DOM ์š”์†Œ๋กœ ์ˆ˜๋™์œผ๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

onCurrenTimeChange(e) {
  this.video.currentTime = e.value;
}

currentTime ๊ฐ€ ๋ž˜ํผ ๊ตฌ์„ฑ ์š”์†Œ์˜ ์ƒํƒœ์ž„์ด ๋ถ„๋ช…ํ•˜๊ธฐ ๋•Œ๋ฌธ์— React ์ž์ฒด๊ฐ€ API ๋ฐ JSX ์ถ”์ƒ ๋ ˆ์ด์–ด๋กœ ๋ถ€๊ณผํ•˜๋Š” ์„ ์–ธ์  ๋ชจ๋ธ์„ ๊นจ๋œจ๋ฆฝ๋‹ˆ๋‹ค. ์†์„ฑ ๋ฐ”์ธ๋”ฉ์„ ์‚ฌ์šฉํ•˜๋ฉด ์—ฌ์ „ํžˆ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ํ•„์š”ํ•˜์ง€๋งŒ JSX ์ถ”์ƒํ™” ๋ชจ๋ธ์€ ๋” ์„ ์–ธ์ ์ด๋ฉฐ refs๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฒฝ์šฐ์—๋งŒ ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

render() {
  return (
    <div className="video--wrapper">
      <video muted={ this.state.muted } @currentTime={ this.state.currentTime } />
    </div>
  );
}

๋‚ด ์š”์ ์€ ๋„ค์ดํ‹ฐ๋ธŒ ๋˜๋Š” ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ์— ์˜์กดํ•˜๋Š”์ง€ ์—ฌ๋ถ€์— ๊ด€๊ณ„์—†์ด ๋ฌธ์„œ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•ด๋‹น ์š”์†Œ๋ฅผ ์šฐํšŒํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ์•„์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋‘ ๋ฒˆ์งธ ๊ฒฝ์šฐ์—๋Š” ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ์˜ ์ž‘์„ฑ์ž๊ฐ€ ์ œ๊ณตํ•ด์•ผ ํ•œ๋‹ค๋Š” ์ฐจ์ด์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

@cjorasch ๋‚ด ๋‘ ์„ผํŠธ :)

์ด์ „ ๋ฒ„์ „๊ณผ์˜ ํ˜ธํ™˜์„ฑ์„ ๊ณ ๋ คํ•  ํ•„์š” ์—†์ด ์ฒ˜์Œ๋ถ€ํ„ฐ ์ด๊ฒƒ์„ ์„ค๊ณ„ํ–ˆ๋‹ค๋ฉด React์˜ "JavaScript-centric API to DOM"์— ๋”ฐ๋ผ ์˜ต์…˜ 1์ด ๊ฐ€์žฅ ๊ด€์šฉ์ ์ผ ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

์„œ๋ฒ„ ์ธก ๋ Œ๋”๋ง๊ณผ ๊ด€๋ จํ•˜์—ฌ ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ ์†์„ฑ์„ ์†์„ฑ์— ๋งคํ•‘ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ React์— ์•Œ๋ฆฌ๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ฝ”๋“œ์šฉ API๋ฅผ ์ œ๊ณตํ•˜์—ฌ ํ•ด๋‹น ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ? ํ”Œ๋žซํผ ์ •์˜ ์†์„ฑ์— ๋Œ€ํ•ด React๊ฐ€ ์ด๋ฏธ ์œ ์ง€ ๊ด€๋ฆฌํ•˜๋Š” ๋งต๊ณผ ์œ ์‚ฌํ•ฉ๋‹ˆ๊นŒ? ์ด API๋Š” ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ ์ด๋ฆ„๋‹น ํ•œ ๋ฒˆ๋งŒ ํ˜ธ์ถœํ•˜๋ฉด ๋˜๋ฉฐ(๊ฐ ์ธ์Šคํ„ด์Šค์— ๋Œ€ํ•ด๊ฐ€ ์•„๋‹˜) ์†์„ฑ๊ณผ์˜ ์ง์ ‘์ ์ธ 1:1 ๋Œ€์‘์„ ๋”ฐ๋ฅด์ง€ ์•Š๋Š” ์†์„ฑ์— ๋Œ€ํ•ด์„œ๋งŒ ํ˜ธ์ถœํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์šฐ๋ฆฌ๊ฐ€ ์ด๊ฒƒ์ด ๋„ˆ๋ฌด ๋งŽ์€ ์ฃผ์š” ๋ณ€๊ฒฝ ์‚ฌํ•ญ์ด๋ผ๊ณ  ์šฐ๋ คํ•œ๋‹ค๋ฉด ์˜ต์…˜ 3๋„ ๊ฝค ๋งค๋ ฅ์ ์ด๋ผ๊ณ  โ€‹โ€‹์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. sigil์ด ์†์„ฑ์„ ์˜๋ฏธํ•˜๋Š” ๊ฒฝ์šฐ "."๋ฅผ ์ œ์•ˆํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฏธ JavaScript์˜ ์†์„ฑ ์ ‘๊ทผ์ž์ด๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ๊ฐ€ ์‚ฌ์šฉ๋˜๋Š” ๋ชจ๋“  ์ธ์Šคํ„ด์Šค๊ฐ€ ์†์„ฑ์„ ์‚ฌ์šฉํ•  ๋•Œ์™€ ์†์„ฑ์„ ์‚ฌ์šฉํ•  ๋•Œ๋ฅผ ์•„๋Š” ์ฑ…์ž„์„ ์ง€๊ฒŒ ํ•˜๋Š” ๊ฒƒ์€ ๋ถˆํ–‰ํ•œ ์ผ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์˜ต์…˜ 1์— ๋Œ€ํ•ด ๋‚ด๊ฐ€ ์„ ํ˜ธํ•˜๋Š” ๊ฒƒ์€ ์†์„ฑ ๋งต์— ๋Œ€ํ•œ ์†์„ฑ์ด ํ•„์š”ํ•˜๋”๋ผ๋„ ํ•ด๋‹น ๋งคํ•‘ ์ฝ”๋“œ๋ฅผ ๋ชจ๋“  JSX ์‚ฌ์šฉ์—์„œ ๊ฒฉ๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ๊ฐ€ ์ง€์—ฐ ๋กœ๋“œ๋˜๊ณ  "์—…๊ทธ๋ ˆ์ด๋“œ"๋œ ๊ฒฝ์šฐ ์ฒ˜์Œ์—๋Š” ์ •์˜๋˜์ง€ ์•Š์€ ์†์„ฑ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ํ•ด๋‹น ์š”์†Œ๊ฐ€ ์—ฌ์ „ํžˆ ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜์‹ ํ•˜๊ณ  ์—…๊ทธ๋ ˆ์ด๋“œ ํ›„์—๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜์—ฌ ํ•ด๋‹น ์‚ฌ์šฉ ์‚ฌ๋ก€๋ฅผ ํ•ด๊ฒฐํ•ฉ๋‹ˆ๋‹ค.

์—…๊ทธ๋ ˆ์ด๋“œ ๊ณผ์ •์„ ์ดํ•ดํ•˜์ง€ ๋ชปํ•˜๋Š” ๊ฒƒ์ผ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์š”์†Œ๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ํด๋ž˜์Šค ํ”„๋กœํ† ํƒ€์ž…์—์„œ getter/setter๋กœ ์ •์˜๋œ ์†์„ฑ์„ ๊ฐ–์Šต๋‹ˆ๋‹ค. propName in element ํ™•์ธํ•˜๋ฉด ์†์„ฑ ๊ฐ’์ด ์•„์ง ์ •์˜๋˜์ง€ ์•Š์€ ๊ฒฝ์šฐ์—๋„ getter/setter๊ฐ€ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— true๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ์—…๊ทธ๋ ˆ์ด๋“œํ•˜๋Š” ๋™์•ˆ ์†์„ฑ ๊ฐ’์ด ์ผ๋ถ€ ์ž„์‹œ ์ธ์Šคํ„ด์Šค์— ์„ค์ •๋˜๊ณ  ๋‚˜์ค‘์— ์ง€์—ฐ ๋กœ๋“œ๊ฐ€ ์™„๋ฃŒ๋˜๋ฉด ์‹ค์ œ ์ธ์Šคํ„ด์Šค์— ๋ณต์‚ฌ๋ฉ๋‹ˆ๊นŒ?

์—…๊ทธ๋ ˆ์ด๋“œ๋Š” ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ๊ฐ€ ํ•ด๋‹น ํด๋ž˜์Šค๋ฅผ ์ˆ˜์‹ ํ•˜๋Š” ํ”„๋กœ์„ธ์Šค์ž…๋‹ˆ๋‹ค. ๊ทธ ์ „์—๋Š” ํ•ด๋‹น ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค๊ฐ€ ์•„๋‹ˆ๋ฏ€๋กœ ์†์„ฑ getter/setters๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

@jeremenichelli

์Œ์†Œ๊ฑฐ๋Š” ๋ถ€์šธ ์†์„ฑ์œผ๋กœ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.

๋ฐฉ๊ธˆ ํ™•์ธํ–ˆ์œผ๋ฉฐ MDN์— ๋ฌธ์„œํ™”๋˜์–ด ์žˆ์ง€ ์•Š์€ ๊ฒƒ ๊ฐ™์ง€๋งŒ ํ•ด๋‹น ์†์„ฑ๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ˜„์žฌ๋กœ์„œ๋Š” ๋น„๋””์˜ค ์š”์†Œ๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ์ฐธ์กฐ๋ฅผ ๋งŒ๋“ค๊ณ  ์†์„ฑ์„ ๋ณ€๊ฒฝํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ, ๋•Œ๋•Œ๋กœ ํ˜„๋Œ€ HTML ์š”์†Œ์—์„œ ์†์„ฑ ์ „์šฉ API๋ฅผ ์ ‘ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. currentTime ๋Š” ๋†’์€ ๋นˆ๋„๋กœ ์—…๋ฐ์ดํŠธ๋˜๋ฏ€๋กœ HTML ์†์„ฑ์— ๋ฐ˜์˜ํ•˜๋Š” ๊ฒƒ์€ ์˜๋ฏธ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

๋‚ด ์š”์ ์€ ๊ธฐ๋ณธ ์š”์†Œ ๋˜๋Š” ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ์— ์˜์กดํ•˜๋“  ๋ฌธ์„œ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์—ฌ์ „ํžˆ ์•Œ์•„์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋„ค, ๋ถˆํ–‰ํžˆ๋„ ๋งŒ๋Šฅ ์†์„ฑ/์†์„ฑ ๊ทœ์น™์€ ์—†์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ผ๋ฐ˜์ ์œผ๋กœ ์†์„ฑ์— ํฌ๊ฒŒ ์˜์กดํ•˜๊ณ  ๊ฐœ๋ฐœ์ž๊ฐ€ ํŠน์ˆ˜ํ•œ ๊ฒฝ์šฐ์— ์†์„ฑ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ตฌ๋ฌธ์„ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

@robdodson yeap, ๋‚˜๋„ ์Œ์†Œ๊ฑฐ๋œ ์†์„ฑ์— ๋Œ€ํ•ด ์•Œ๊ณ  ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค ๐Ÿ˜„ ๋ฐฉ๊ธˆ ์ด ๋‘ ๊ฐ€์ง€๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ด๋ฏธ _์•ผ์ƒ์—์„œ_ ๋‹น์‹ ์ด ์–ธ๊ธ‰ํ•œ ๊ฒƒ๊ณผ ๊ฐ™์ด ํš์ผ์ ์ธ ๊ทœ์น™์ด ์—†๋‹ค๋Š” ๊ฒƒ์„ ์ฆ๋ช…ํ–ˆ์Šต๋‹ˆ๋‹ค.

์šฐ๋ฆฌ๋Š” ๊ธฐ๋ณธ ์š”์†Œ์™€ ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ ๋ชจ๋‘์— ๋Œ€ํ•œ ๋ฌธ์„œ์— ์˜์กดํ•ด์•ผ ํ•˜๋ฏ€๋กœ ์ด ๊ฒฐ์ •์— ๋Œ€ํ•ด ์‹ ๊ฒฝ ์“ฐ์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋งˆ์ง€๋ง‰ ์ฝ”๋“œ ์Šค๋‹ˆํŽซ์„ ์ž‘์„ฑํ•˜๋Š” ๋™์•ˆ ์†์„ฑ ๋ฐ”์ธ๋”ฉ์ด ๋งˆ์Œ์— ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค. ๐Ÿ’Ÿ

@effulgentsia

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

๋‚˜๋Š” ์ด๊ฒƒ์ด ์˜ค๋Š˜๋‚ ์—๋„ ์ด๋ฏธ ๊ทธ๋Ÿฌํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•œ๋‹ค. ์ฃผ์š” ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ(ํด๋ฆฌ๋จธ, ์Šค์ผ€์ดํŠธ, ์•„๋งˆ๋„ ๊ธฐํƒ€?)๋Š” ๋…ธ์ถœ๋œ ๋ชจ๋“  ์†์„ฑ์— ๋Œ€ํ•œ ์ง€์› ์†์„ฑ์„ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•˜๋ฏ€๋กœ ๊ฐœ๋ฐœ์ž๋Š” ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ์˜ ๋ชจ๋“  ์†์„ฑ์— ๋Œ€ํ•ด sigil์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์†์„ฑ ์‚ฌ์šฉ์œผ๋กœ ์ „ํ™˜ํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ๋Š” ๋“œ๋ฌผ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

@cjorasch

RE: ์—…๊ทธ๋ ˆ์ด๋“œ. @effulgentsia๊ฐ€ ์–ธ๊ธ‰ํ–ˆ๋“ฏ์ด ํŽ˜์ด์ง€์— ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์ง€๋งŒ ๋‚˜์ค‘์— ํ•ด๋‹น ์ •์˜๋ฅผ ๋กœ๋“œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. <x-foo> ๋Š” ์ฒ˜์Œ์— HTMLElement ์˜ ์ธ์Šคํ„ด์Šค๊ฐ€ ๋˜๊ณ  ๋‚˜์ค‘์— ์ •์˜๋ฅผ ๋กœ๋“œํ•˜๋ฉด "์—…๊ทธ๋ ˆ์ด๋“œ"๋˜์–ด XFoo ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค๊ฐ€ ๋ฉ๋‹ˆ๋‹ค. ์ด ์‹œ์ ์—์„œ ๋ชจ๋“  ์ˆ˜๋ช… ์ฃผ๊ธฐ ์ฝœ๋ฐฑ์ด ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. ํด๋ฆฌ๋จธ ์Šคํƒ€ํ„ฐ ํ‚คํŠธ ํ”„๋กœ์ ํŠธ์—์„œ ์ด ๊ธฐ์ˆ ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ข…๋ฅ˜:

<app-router>
  <my-view1></my-view1>
  <my-view2></my-view2>
</app-router>

์œ„์˜ ์˜ˆ์—์„œ ๋ผ์šฐํ„ฐ๊ฐ€ ๋ณ€๊ฒฝ๋  ๋•Œ๊นŒ์ง€ my-view2 ๋Œ€ํ•œ ์ •์˜๋ฅผ ๋กœ๋“œํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์š”์†Œ๊ฐ€ ์—…๊ทธ๋ ˆ์ด๋“œ๋˜๊ธฐ ์ „์— ์š”์†Œ์— ์†์„ฑ์„ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์€ ์ „์ ์œผ๋กœ ๊ฐ€๋Šฅํ•˜๋ฉฐ, ์ •์˜๊ฐ€ ๋กœ๋“œ๋˜๋ฉด ์š”์†Œ๋Š” ์ˆ˜๋ช… ์ฃผ๊ธฐ ์ฝœ๋ฐฑ ์ค‘ ํ•˜๋‚˜์—์„œ ํ•ด๋‹น ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ฐœ๋ฐœ์ž๋Š” ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ์˜ ๋ชจ๋“  ์†์„ฑ์— ๋Œ€ํ•ด sigil์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ฐœ๋ฐœ์ž๊ฐ€ ๊ทธ๋ ‡๊ฒŒ ํ•˜๊ธฐ ์‹œ์ž‘ํ–ˆ๋‹ค๋ฉด "ํ•  ์ˆ˜ ์žˆ๊ธฐ" ๋•Œ๋ฌธ์— ์†์„ฑ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ๊ณผ "๋ฐ˜๋“œ์‹œ" ํ•ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์†์„ฑ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ์–ด๋–ป๊ฒŒ ๊ตฌ๋ณ„ํ• ๊นŒ์š”? ๊ทธ๋ฆฌ๊ณ  ๊ทธ๊ฒƒ์ด ์„œ๋ฒ„ ์ธก ๋ Œ๋”๋ง์— ํ•„์š”ํ•œ ์ฐจ๋ณ„ํ™”๊ฐ€ ์•„๋‹๊นŒ์š”?

๊ฐœ๋ฐœ์ž๊ฐ€ ๊ทธ๋ ‡๊ฒŒ ํ•˜๊ธฐ ์‹œ์ž‘ํ–ˆ๋‹ค๋ฉด "ํ•  ์ˆ˜ ์žˆ๊ธฐ" ๋•Œ๋ฌธ์— ์†์„ฑ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ๊ณผ "๋ฐ˜๋“œ์‹œ" ํ•ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์†์„ฑ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ์–ด๋–ป๊ฒŒ ๊ตฌ๋ณ„ํ• ๊นŒ์š”?

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

๊ทธ๋ฆฌ๊ณ  ๊ทธ๊ฒƒ์ด ์„œ๋ฒ„ ์ธก ๋ Œ๋”๋ง์— ํ•„์š”ํ•œ ์ฐจ๋ณ„ํ™”๊ฐ€ ์•„๋‹๊นŒ์š”?

์„œ๋ฒ„์—์„œ sigil์ด ์†์„ฑ์„ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์œผ๋กœ ๋Œ€์ฒด๋˜๋Š” ๊ฒฝ์šฐ์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์„œ๋ฒ„์—์„œ sigil์ด ์†์„ฑ์„ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์œผ๋กœ ๋Œ€์ฒด๋˜๋Š” ๊ฒฝ์šฐ์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

sigil์˜ ์ด์œ ๊ฐ€ ๋น„๋””์˜ค์˜ currentTime ๊ณผ ๊ฐ™์€ ์†์„ฑ์œผ๋กœ ์กด์žฌํ•˜์ง€ ์•Š๋Š” ์†์„ฑ์ธ ๊ฒฝ์šฐ ์ž‘๋™ํ•˜์ง€ ์•Š์„ ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

"ํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์—" ์†์„ฑ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ๊ณผ "ํ•ด์•ผ"ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์†์„ฑ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ๊ตฌ๋ณ„ํ•ฉ๋‹ˆ๋‹ค.

์†์„ฑ์ด๋‚˜ ์†์„ฑ์„ ์ตœ์ ํ™”๋กœ ์‚ฌ์šฉํ•˜๊ธฐ๋กœ ์„ ํƒํ•˜๋Š” ์ด์œ (์˜ˆ: ์†์„ฑ์„ ์„ ํ˜ธํ•˜๋Š” SSR ๋Œ€ ์†์„ฑ์„ ์„ ํ˜ธํ•˜๋Š” ํด๋ผ์ด์–ธํŠธ ์ธก ๋ Œ๋”๋ง)์™€ ์†์„ฑ์œผ๋กœ๋งŒ ์กด์žฌํ•˜๊ฑฐ๋‚˜ ์†์„ฑ์œผ๋กœ๋งŒ ์กด์žฌํ•˜๋Š” ๊ฒƒ์—๋Š” ์™„์ „ํžˆ ๋‹ค๋ฅธ ์ด์œ ๊ฐ€ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ด ์ฐจ๋ณ„ํ™”๊ฐ€ ์ค‘์š”ํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์žฌ์‚ฐ.

์„œ๋ฒ„ ์ธก ๋ Œ๋”๋ง๊ณผ ๊ด€๋ จํ•˜์—ฌ ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ ์†์„ฑ์„ ์†์„ฑ์— ๋งคํ•‘ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ React์— ์•Œ๋ฆฌ๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ฝ”๋“œ์šฉ API๋ฅผ ์ œ๊ณตํ•˜์—ฌ ํ•ด๋‹น ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

๋” ๊ตฌ์ฒด์ ์œผ๋กœ ๋งํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ œ์•ˆํ•ฉ๋‹ˆ๋‹ค.

ReactDOM.defineCustomElementProp(elementName, propName, domPropertyName, htmlAttributeName, attributeSerializer)

์˜ˆ:

// 'muted' can be set as either a property or an attribute.
ReactDOM.defineCustomElementProp('x-foo', 'muted', 'muted', 'muted')

// 'currentTime' can only be set as a property.
ReactDOM.defineCustomElementProp('x-foo', 'currentTime', 'currentTime', null)

// 'my-attribute' can only be set as an attribute.
ReactDOM.defineCustomElementProp('x-foo', 'my-attribute', null, 'my-attribute')

// 'richData' can be set as either a property or an attribute.
// When setting as an attribute, set it as a JSON string rather than "[object Object]".
ReactDOM.defineCustomElementProp('x-foo', 'richData', 'richData', 'richdata', JSON.stringify)

์†์„ฑ( htmlAttributeName ์ด null์ธ ๊ฒฝ์šฐ)์ผ ์ˆ˜ ์žˆ๋Š” ํ•ญ๋ชฉ์˜ ๊ฒฝ์šฐ SSR์€ ๋ Œ๋”๋ง์„ ๊ฑด๋„ˆ๋›ฐ๊ณ  ํด๋ผ์ด์–ธํŠธ์—์„œ ์ˆ˜ํ™”ํ•ฉ๋‹ˆ๋‹ค.

์†์„ฑ( domPropertyName ์ด null์ธ ๊ฒฝ์šฐ)์ผ ์ˆ˜ ์žˆ๋Š” ํ•ญ๋ชฉ์˜ ๊ฒฝ์šฐ React๋Š” ํ˜„์žฌ v16์—์„œ์™€ ๊ฐ™์ด setAttribute() ๋ฅผ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค.

๋‘˜ ๋‹ค์ผ ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ React๋Š” ๊ฐ€์žฅ ์ตœ์ ์˜ ์ „๋žต์„ ์„ ํƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์•„๋งˆ๋„ ๊ทธ๊ฒƒ์€ ํ•ญ์ƒ ํด๋ผ์ด์–ธํŠธ ์ธก์—์„œ ์†์„ฑ์œผ๋กœ ์„ค์ •ํ•˜์ง€๋งŒ ์„œ๋ฒ„ ์ธก ์†์„ฑ์œผ๋กœ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ์•„๋งˆ๋„ ์ฒ˜์Œ์—๋Š” ์š”์†Œ๋ฅผ ์ƒ์„ฑํ•  ๋•Œ ์†์„ฑ์œผ๋กœ ์„ค์ •ํ•˜์ง€๋งŒ ๋‚˜์ค‘์— vdom์—์„œ ํŒจ์น˜ํ•  ๋•Œ ์†์„ฑ์œผ๋กœ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ์•„๋งˆ๋„ ๊ฐ’์ด ์›์‹œ ์œ ํ˜•์ผ ๋•Œ ์†์„ฑ์œผ๋กœ๋งŒ ์„ค์ •ํ•œ๋‹ค๋Š” ์˜๋ฏธ์ผ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด์ƒ์ ์œผ๋กœ React๋Š” ๋‚ด๋ถ€ ๊ตฌํ˜„ ์„ธ๋ถ€ ์‚ฌํ•ญ์œผ๋กœ ์›ํ•  ๋•Œ๋งˆ๋‹ค ์ „๋žต์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

React๊ฐ€ defineCustomElementProp() ๊ฐ€ ํ˜ธ์ถœ๋˜์ง€ ์•Š๊ณ  HTML ์‚ฌ์–‘์— ์ „์—ญ ์†์„ฑ ๋˜๋Š” ์†์„ฑ์œผ๋กœ ์ •์˜๋˜์ง€ ์•Š์€ prop์„ ๋ฐœ๊ฒฌํ•˜๋ฉด React๋Š” ์ผ๋ถ€ ๊ธฐ๋ณธ ๋…ผ๋ฆฌ๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ์•„๋งˆ๋„:

  • ๋ฒ„์ „ 17์—์„œ๋Š” v16์œผ๋กœ BC๋ฅผ ์œ ์ง€ํ•˜๊ณ  ์†์„ฑ์œผ๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
  • ๋ฒ„์ „ 18์—์„œ๋Š” ๋‘˜ ์ค‘ ํ•˜๋‚˜์ผ ์ˆ˜ ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜๊ณ  ์ด์— ๋Œ€ํ•œ ๊ฐ€์žฅ ์ตœ์ ์˜ ์ „๋žต์„ ๋”ฐ๋ฅด์‹ญ์‹œ์˜ค.

๊ทธ๋Ÿฌ๋‚˜ ์–ด์จŒ๋“  ์ด๊ฒƒ์„ ๋ณ„๋„์˜ API๋กœ ์œ ์ง€ํ•จ์œผ๋กœ์จ JSX ๋ฐ props ๊ฐ์ฒด๋Š” React ๊ตฌ์„ฑ ์š”์†Œ ๋ฐ ์‚ฌ์šฉ์ž ์ •์˜๊ฐ€ ์•„๋‹Œ HTML ์š”์†Œ์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ๋‹จ์ผ ๋„ค์ž„์ŠคํŽ˜์ด์Šค ๋‚ด์—์„œ ๊นจ๋—ํ•˜๊ฒŒ ์œ ์ง€๋ฉ๋‹ˆ๋‹ค.

๊ณผ๋„ํ•œ ์˜๊ฒฌ์— ๋Œ€ํ•ด ์œ ๊ฐ์Šค๋Ÿฝ๊ฒŒ ์ƒ๊ฐํ•˜์ง€๋งŒ ์œ„์˜ ์ œ์•ˆ์— ๋Œ€ํ•ด ๊ณต์œ ํ•˜๊ณ  ์‹ถ์€ ๋˜ ๋‹ค๋ฅธ ์ด์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ ReactDOM.defineCustomElementProp() ํ˜ธ์ถœ์€ ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ ์ž‘์„ฑ์ž๊ฐ€ ์œ ์ง€ ๊ด€๋ฆฌํ•˜๋Š” JS ํŒŒ์ผ์—์„œ ์ œ๊ณต๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ๊ฐ€ ์œ ์ง€/๋ฐฐํฌ๋˜๋Š” ์œ„์น˜์™€ ๋™์ผํ•œ ์ €์žฅ์†Œ). ์†์„ฑ/์†์„ฑ์ด ์—„๊ฒฉํ•˜๊ฒŒ 1:1๋กœ ์ผ์น˜ํ•˜๋Š” ์‚ฌ์šฉ์ž ์ง€์ • ์š”์†Œ์—๋Š” ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ด ๊ถŒ์žฅ ์‚ฌํ•ญ์„ ๋”ฐ๋ฅด์ง€ ์•Š๋Š” ์‚ฌ์šฉ์ž ์ง€์ • ์š”์†Œ ์ž‘์„ฑ์ž๋งŒ React ํ†ตํ•ฉ ํŒŒ์ผ์„ ์ œ๊ณตํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ž‘์„ฑ์ž๊ฐ€ ์ œ๊ณตํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ(์˜ˆ: ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ ์ž‘์„ฑ์ž๊ฐ€ React์— ๊ด€์‹ฌ์ด ์—†๊ธฐ ๋•Œ๋ฌธ์—) React ์•ฑ ๋‚ด์—์„œ ํ•ด๋‹น ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์‚ฌ๋žŒ๋“ค์˜ ์ปค๋ฎค๋‹ˆํ‹ฐ๋Š” ํ•ด๋‹น ํ†ตํ•ฉ ํŒŒ์ผ์„ ์ˆ˜์šฉํ•˜๊ธฐ ์œ„ํ•ด ์ค‘์•™ ์ €์žฅ์†Œ๋ฅผ ์ž์ฒด ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ ์ค‘์•™ ์ง‘์ค‘ํ™”์˜ ๊ฐ€๋Šฅ์„ฑ์€ ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ์˜ ๋ชจ๋“  ์‚ฌ์šฉ์ž๊ฐ€ ํ•ญ์ƒ sigil์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ช…์‹œ์ ์ด์–ด์•ผ ํ•˜๋Š” ์†”๋ฃจ์…˜๋ณด๋‹ค ๋ฐ”๋žŒ์งํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

์˜ต์…˜ 3์ด ์„ ํ˜ธ๋˜์ง€๋งŒ ์ด๋Š” ์—„์ฒญ๋‚œ ๋ณ€ํ™”์ž…๋‹ˆ๋‹ค... ๋ฐ˜๋Œ€์˜ ๊ฒฝ์šฐ๋Š” ์–ด๋–ป์Šต๋‹ˆ๊นŒ? ์†์„ฑ์— props๊ฐ€ ์•„๋‹Œ ์ ‘๋‘์‚ฌ๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ?

React์˜ Sigils, ๋‚˜๋Š” ๊ทธ๊ฒƒ์— ๋Œ€ํ•ด ์–ด๋–ป๊ฒŒ ๋Š๋ผ๋Š”์ง€ ๋ชจ๋ฆ…๋‹ˆ๋‹ค. JSX ์‚ฌ์–‘์€ ๋ธŒ๋ผ์šฐ์ € ์‚ฌ์–‘์— ์ง€๋‚˜์น˜๊ฒŒ ์˜์กดํ•˜๊ฑฐ๋‚˜ ์˜์กดํ•˜์ง€ ์•Š๋Š” ๋ณดํŽธ์ ์ธ ๊ฒƒ์œผ๋กœ ๊ฐ„์ฃผ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํŠนํžˆ ์ด์ „ ๋ฒ„์ „๊ณผ์˜ ํ˜ธํ™˜์„ฑ์œผ๋กœ ์ธํ•œ ๋ถˆ๊ทœ์น™์„ฑ์— ๋Œ€ํ•ด์„œ๋Š” ๋” ๊ทธ๋ ‡์Šต๋‹ˆ๋‹ค. obj[prop] = value ์™€ obj.setAttributes(props, value) ๋‹ค๋ฅด๊ฒŒ ๋™์ž‘ํ•˜๋Š” ๊ฒƒ์€ ๋ถˆํ–‰ํ•œ ์ผ์ด์ง€๋งŒ ๋ธŒ๋ผ์šฐ์ € API๋ฅผ ์ „์ฒด์ ์œผ๋กœ ๋ณด๋ฉด ๋†€๋ผ์šด ์ผ์ด ์•„๋‹™๋‹ˆ๋‹ค. @ : [] ๋Š” ๊ตฌํ˜„ ์„ธ๋ถ€ ์‚ฌํ•ญ์„ ํ‘œ๋ฉด์œผ๋กœ ์œ ์ถœํ•˜๊ณ  ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์ค‘์‹ฌ ์ ‘๊ทผ ๋ฐฉ์‹๊ณผ ๋ชจ์ˆœ๋ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๋‹ค์Œ์„ ์ˆ˜ํ–‰ํ•˜๋Š” ์‚ฌ์–‘์ด ์—†์œผ๋ฉด ์ž˜๋ชป๋œ ์ƒ๊ฐ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. const data = <strong i="8">@myFunction</strong> // -> "[object Object]"

์›น ๊ตฌ์„ฑ ์š”์†Œ์— ์˜์กดํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ ์˜๋ฏธ ์ฒด๊ณ„๊ฐ€ React ๋ฐ JSX์—์„œ ์ˆจ๊ฒจ์ง€๊ณ  ์ฃผ์š” ๋ณ€๊ฒฝ ์‚ฌํ•ญ์ด ๋„์ž…๋˜์ง€ ์•Š๋„๋ก ํ•˜๋ฉด ๊ธฐ์  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋ชจ๋“  ์˜ต์…˜์—์„œ ref => ... ๋ฅผ ๊ทธ๋Œ€๋กœ ๋‘๋Š” ๊ฒƒ์ด ๋‚˜์—๊ฒŒ ์œ ๋ฆฌํ•œ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ref ๋Š” ๊ฐœ์ฒด์— ์•ก์„ธ์Šคํ•˜๋„๋ก ํŠน๋ณ„ํžˆ ์„ค๊ณ„๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ ์–ด๋„ ๊ฐœ๋ฐœ์ž๋Š” ๋ฌด์Šจ ์ผ์ด ์ผ์–ด๋‚˜๊ณ  ์žˆ๋Š”์ง€ ์ •ํ™•ํžˆ ์•Œ๊ณ  ์žˆ๊ณ , ์ธ์žฅ ๋ˆ„์ถœ๋„ ์—†๊ณ  ๊ธฐ์กด ํ”„๋กœ์ ํŠธ๋ฅผ ๊นจ๋œจ๋ฆด ์ˆ˜ ์žˆ๋Š” ์ƒˆ๋กœ์šด ์†์„ฑ๋„ ์—†์Šต๋‹ˆ๋‹ค.

@LeeCheneler

์˜ต์…˜ 3์ด ์„ ํ˜ธ๋˜์ง€๋งŒ ์ด๋Š” ์—„์ฒญ๋‚œ ๋ณ€ํ™”์ž…๋‹ˆ๋‹ค... ๋ฐ˜๋Œ€์˜ ๊ฒฝ์šฐ๋Š” ์–ด๋–ป์Šต๋‹ˆ๊นŒ? ์†์„ฑ์— props๊ฐ€ ์•„๋‹Œ ์ ‘๋‘์‚ฌ๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ?

์™œ ํš๊ธฐ์ ์ธ ๋ณ€ํ™”๊ฐ€ ๋ ๊นŒ์š”? ๊ธฐ๋ณธ๊ฐ’์ธ ์†์„ฑ์˜ ํ˜„์žฌ ๋™์ž‘์€ ๊ทธ๋Œ€๋กœ ์œ ์ง€๋ฉ๋‹ˆ๋‹ค. sigil์€ ์˜ตํŠธ์ธ์ด๋ฉฐ ๊ฐœ๋ฐœ์ž๋Š” ํ˜„์žฌ ref ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ์— JS ์†์„ฑ์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•˜๋Š” ์ฝ”๋“œ์˜ ๋ถ€๋ถ„์„ ๋Œ€์ฒดํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

@drcmda

๊ธฐ์กด ํ”„๋กœ์ ํŠธ๋ฅผ ์ค‘๋‹จ์‹œํ‚ฌ ์ˆ˜ ์žˆ๋Š” ์ƒˆ๋กœ์šด ์†์„ฑ๋„ ์—†์Šต๋‹ˆ๋‹ค.

์ด๊ฒƒ์ด ๋ฌด์—‡์„ ์˜๋ฏธํ–ˆ๋Š”์ง€ ๋ช…ํ™•ํžˆ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

์ฐธ๊ณ ๋กœ ํ† ๋ก ์„ ๋”ฐ๋ฅด๋Š” ์‚ฌ๋žŒ์„ ์œ„ํ•ด React ํŒ€ ๊ตฌ์„ฑ์›์ด ์ œ์•ˆํ•œ ๋‹ค์„ฏ ๋ฒˆ์งธ ์˜ต์…˜์œผ๋กœ RFC๋ฅผ ์—…๋ฐ์ดํŠธํ–ˆ์Šต๋‹ˆ๋‹ค.

@robdodson

๋‚˜๋Š” ์ด๊ฒƒ์„ ์–ธ๊ธ‰ํ•˜๊ณ  ์žˆ์—ˆ๋‹ค:

์˜ต์…˜ 4: ์†์„ฑ ๊ฐœ์ฒด ์ถ”๊ฐ€
๋‹จ์ 
ํš๊ธฐ์ ์ธ ๋ณ€ํ™”์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค

์˜ต์…˜ 5๊ฐ€ ๊ฐ€์žฅ ์•ˆ์ „ํ•œ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์ƒํƒœ๊ณ„๊ฐ€ ์•„์ง "ํŒŒ์•…" ๋‹จ๊ณ„์— ์žˆ๊ธฐ ๋•Œ๋ฌธ์— "์•”์‹œ์ " API์— ๋Œ€ํ•œ ๊ฒฐ์ •์„ ๋‚ด๋ฆด ํ•„์š” ์—†์ด ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ํ•ญ์ƒ ๋ช‡ ๋…„ ์•ˆ์— ๊ทธ๊ฒƒ์„ ๋‹ค์‹œ ๋ฐฉ๋ฌธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Polymer์˜ paper-input ์š”์†Œ์—๋Š” 37๊ฐœ์˜ ์†์„ฑ์ด ์žˆ์œผ๋ฏ€๋กœ ๋งค์šฐ ํฐ ๊ตฌ์„ฑ์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ๊ฐœ๋ฐœ์ž๊ฐ€ ์•ฑ์—์„œ ๋งŽ์€ ์‚ฌ์šฉ์ž ์ง€์ • ์š”์†Œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ ์ž‘์„ฑํ•ด์•ผ ํ•˜๋Š” ๊ตฌ์„ฑ์ด ๋งŽ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‚ด ์ธ์ƒ์€ React์˜ ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ ์‚ฌ์šฉ์ž๊ฐ€ ๊ฒฐ๊ตญ ์•ฑ๋ณ„ ๋™์ž‘/์‚ฌ์šฉ์ž ์ •์˜๋ฅผ ์œ„ํ•ด ์ผ๋ถ€ ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ๋ฅผ React ๊ตฌ์„ฑ ์š”์†Œ๋กœ ๋ž˜ํ•‘ํ•˜๊ธฐ๋ฅผ ์›ํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋ชจ๋‘๊ฐ€ ์ด๋ฏธ ์ผœ์ ธ์žˆ๋Š” ๊ฒฝ์šฐ๋Š”์ด ๊ฒฝ์šฐ์— ๋” ์ข‹์€ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ์ „๋žต ๊ตฌ์„ฑ ์š”์†Œ, ์˜ˆ๋ฅผ ๋“ค๋ฉด ๋ฐ˜์ž‘์šฉ

import XButton from './XButton';

์— ์˜ํ•ด ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.

export default ReactDOM.createCustomElementType(...)

์ด๋ฅผ ํ†ตํ•ด React ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ํŠน์ • ์‹œ์ ์— ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š”(๋˜๋Š” ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”) ์‚ฌ์šฉ์ž ์ •์˜ ๊ตฌ์„ฑ ์š”์†Œ๋กœ ๊ต์ฒดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ์‚ฌ๋žŒ๋“ค์ด ์ƒํ˜ธ ์šด์šฉ์„ฑ ์ง€์ ์—์„œ React ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ๋งŒ๋“ค๋ ค๋Š” ๊ฒฝ์šฐ ๊ฐ•๋ ฅํ•œ ๋„์šฐ๋ฏธ๋ฅผ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ ์‚ฌ๋žŒ๋“ค์ด ์‚ฌ์šฉํ•˜๋Š” ์‚ฌ์šฉ์ž ์ง€์ • ์š”์†Œ์— ๋Œ€ํ•œ ๊ตฌ์„ฑ์„ ๊ณต์œ ํ•  ๊ฐ€๋Šฅ์„ฑ๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ๊ถ๊ทน์ ์œผ๋กœ ์ƒํƒœ๊ณ„๊ฐ€ ์•ˆ์ •ํ™”๋˜๋ฉด ๊ตฌ์„ฑ ์—†๋Š” ์ ‘๊ทผ ๋ฐฉ์‹์„ ์ฑ„ํƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์—์„œ ๋‹ค์Œ ๋‹จ๊ณ„๋Š” ๋ชจ๋“  ์ผ๋ฐ˜์ ์ธ ์‚ฌ์šฉ ์‚ฌ๋ก€๋ฅผ ์ถฉ์กฑํ•˜๊ธฐ ์œ„ํ•ด ๊ตฌ์„ฑ์ด ์–ด๋–ป๊ฒŒ ๋ณด์—ฌ์•ผ ํ•˜๋Š”์ง€์— ๋Œ€ํ•œ ์ž์„ธํ•œ ์ œ์•ˆ์„ ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ + React ์‚ฌ์šฉ์ž์—๊ฒŒ ์ถฉ๋ถ„ํžˆ ๋งค๋ ฅ์ ์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์™œ๋ƒํ•˜๋ฉด ๊ทธ๊ฒƒ์ด ์ผ๋ฐ˜์ ์ธ ์‚ฌ์šฉ ์‚ฌ๋ก€(์˜ˆ: ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ)์— ์‘๋‹ตํ•˜์ง€ ์•Š์œผ๋ฉด ๊ธฐ๋Šฅ์ด ์žฅํ™ฉํ•จ์„ ์ƒ์‡„ํ•  ์ถฉ๋ถ„ํ•œ ์ด์ ์„ ์ œ๊ณตํ•˜์ง€ ๋ชปํ•˜๋Š” ๋ฆผ๋ณด์— ๋น ์ง€๊ฒŒ ๋  ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. .

๋‚ด ์ด์ „ ์˜๊ฒฌ์„ ๋ฐ”ํƒ•์œผ๋กœ ์ž‘์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

const XFoo = ReactDOM.createCustomElementType('x-foo', {
  propName1: {
    propertyName: string | null,
    attributeName: string | null,
    attributeSerializer: function | null,
    eventName: string | null,
  }
  propName2: {
  }
  ...
});

๊ทธ๋Ÿฌ๋ฉด ๋…ผ๋ฆฌ๋Š” XFoo ์ธ์Šคํ„ด์Šค์˜ ๊ฐ React ์†Œํ’ˆ์— ๋Œ€ํ•ด ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  1. ํ•ด๋‹น prop์— ๋Œ€ํ•œ eventName ๊ฐ€ null์ด ์•„๋‹Œ ๊ฒฝ์šฐ prop ๊ฐ’(ํ•จ์ˆ˜๋กœ ๊ฐ€์ •)์„ ํ˜ธ์ถœํ•˜๋Š” ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋กœ ๋“ฑ๋กํ•ฉ๋‹ˆ๋‹ค.
  2. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ํด๋ผ์ด์–ธํŠธ ์ธก ๋ Œ๋”๋ง ๋ฐ propertyName ๊ฐ€ null์ด ์•„๋‹Œ ๊ฒฝ์šฐ ์š”์†Œ ์†์„ฑ์„ prop ๊ฐ’์œผ๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
  3. ๊ทธ๋ ‡์ง€ ์•Š๊ณ  attributeName ๊ฐ€ null์ด ์•„๋‹Œ ๊ฒฝ์šฐ ์š”์†Œ ์†์„ฑ์„ ๋ฌธ์ž์—ดํ™”๋œ prop ๊ฐ’์œผ๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. attributeSerializer ๊ฐ€ null์ด ์•„๋‹Œ ๊ฒฝ์šฐ ์ด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ prop ๊ฐ’์„ ๋ฌธ์ž์—ดํ™”ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด '' + propValue ๋ฉ๋‹ˆ๋‹ค.

Polymer์˜ paper-input ์š”์†Œ์—๋Š” 37๊ฐœ์˜ ์†์„ฑ์ด ์žˆ์œผ๋ฏ€๋กœ ๋งค์šฐ ํฐ ๊ตฌ์„ฑ์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

๊ตฌ์„ฑ์€ outlier props์—๋งŒ ํ•„์š”ํ•˜๋‹ค๊ณ  ์ œ์•ˆํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. ๊ตฌ์„ฑ์— ํฌํ•จ๋˜์ง€ ์•Š์€ XFoo ์ธ์Šคํ„ด์Šค์˜ ๋ชจ๋“  ์†Œํ’ˆ์— ๋Œ€ํ•ด ๊ธฐ๋ณธ์ ์œผ๋กœ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

  • ๊ฐ’์ด ํ•จ์ˆ˜์ธ ๊ฒฝ์šฐ:
eventName: the prop name,
  • ๋˜ ๋‹ค๋ฅธ:
propertyName: the prop name,
attributeName: camelCaseToDashCase(the prop name),

๋˜๋Š” ์ด๋ฒคํŠธ๋ฅผ ๋ณ„๋„์˜ ๋„ค์ž„์ŠคํŽ˜์ด์Šค์— ๋ณด๊ด€ํ•˜๋Š” ๊ฒƒ์ด ํ•ฉ๋ฆฌ์ ์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ ๋งˆ์ง€๋ง‰ ์ฃผ์„์—์„œ eventName ์™€ ๊ด€๋ จ๋œ ๋ชจ๋“  ๊ฒƒ์„ ์ œ๊ฑฐํ•˜๊ณ  ๋Œ€์‹  ์ด๋ฒคํŠธ๋ฅผ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋“ฑ๋กํ•ฉ๋‹ˆ๋‹ค.

<XFoo prop1={propValue1} prop2={propValue2} events={event1: functionFoo, event2: functionBar}>
</XFoo>

@gaearon @effulgentsia ์˜ต์…˜ 1๊ณผ ์˜ต์…˜ 5์˜ ์กฐํ•ฉ์— ๋Œ€ํ•ด ์–ด๋–ป๊ฒŒ ์ƒ๊ฐํ•˜์‹œ๋‚˜์š”?

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

์˜ต์…˜ 5๋Š” ์•ฑ ์ „์ฒด์—์„œ ์ข…์ด ์ž…๋ ฅ๊ณผ ๊ฐ™์€ ๊ฒƒ์„ ์‚ฌ์šฉํ•˜๊ณ  ์ „์ฒด API๋ฅผ ํŒ€์˜ ๋ชจ๋“  ์‚ฌ๋žŒ์—๊ฒŒ ๊ณต๊ฐœํ•˜๋ ค๋Š” ์‚ฌ๋žŒ๋“ค์„ ์œ„ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์˜ต์…˜ 1์˜ SSR์˜ ๊ฒฝ์šฐ ๋ฐœ๊ฒฌ์  ๋ฐฉ๋ฒ•์€ ์„œ๋ฒ„์—์„œ ๋ Œ๋”๋งํ•˜๋Š” ๊ฒฝ์šฐ ํ•ญ์ƒ ์†์„ฑ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. camelCase ์†์„ฑ์€ dash-case ์†์„ฑ์œผ๋กœ ๋ณ€ํ™˜๋ฉ๋‹ˆ๋‹ค. ์ด๋Š” ์›น ๊ตฌ์„ฑ ์š”์†Œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ „๋ฐ˜์— ๊ฑธ์ณ ๊ฝค ์ผ๋ฐ˜์ ์ธ ํŒจํ„ด์ธ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

๋‚˜๋Š” option1 + option5 ์กฐํ•ฉ์˜ ์•„์ด๋””์–ด๋ฅผ ์•„์ฃผ ์ข‹์•„ํ•ฉ๋‹ˆ๋‹ค. ๋Œ€๋ถ€๋ถ„์˜ ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ์— ๋Œ€ํ•ด ๋‹ค์Œ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

<x-foo prop1={propValue1}>

์˜ˆ์ƒ๋Œ€๋กœ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. prop1์€ ์†์„ฑ ํด๋ผ์ด์–ธํŠธ ์ธก ๋ฐ (๋Œ€์‹œ ๋Œ€์†Œ๋ฌธ์ž) ์„œ๋ฒ„ ์ธก ์†์„ฑ์œผ๋กœ ์„ค์ •๋ฉ๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ์‚ฌ๋žŒ๋“ค์€ ์œ„์˜ ๋‚ด์šฉ์ด ์ž์‹ ์—๊ฒŒ ์ ํ•ฉํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ ์˜ต์…˜ 5๋กœ ์ „ํ™˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

React 16์ด ์ž‘๋™ํ•˜๋Š” ๋ฐฉ์‹์—์„œ ํš๊ธฐ์ ์ธ ๋ณ€ํ™”๊ฐ€ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ํŒŒ์†์„ ๊ฒฝํ—˜ํ•œ ์‚ฌ๋žŒ์€(์˜ˆ: ์†์„ฑ์ด ์ง€์›๋˜์ง€ ์•Š๋Š” ์†์„ฑ์„ ๊ฐ€์ง„ ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋Š” ๊ฒฝ์šฐ) ์˜ต์…˜ 5๋กœ ์ „ํ™˜ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ์—ฌ์ „ํžˆ ์ค‘๋‹จ์ž…๋‹ˆ๋‹ค. ๋‚˜๋Š” ๊ทธ๊ฒƒ์ด ์ˆ˜์šฉ ๊ฐ€๋Šฅํ•œ์ง€ ๊ฒฐ์ •ํ•˜๊ธฐ ์œ„ํ•ด React ํŒ€์— ๋งก๊น๋‹ˆ๋‹ค.

์•„, ๊ธฐ์ฐจ @robdodson ๐Ÿคฆโ€โ™‚๏ธ ์—์„œ ๋นจ๋ฆฌ ์ฝ์–ด์„œ

์˜ต์…˜ 5๋Š” ํ•ฉ๋ฆฌ์ ์ด๊ณ  ๊ฐ„๋‹จํ•ด ๋ณด์ž…๋‹ˆ๋‹ค.

@effulgentsia ๊ฐ€ ํ–ฅํ•˜๊ณ  ์žˆ๋Š” ๋“ญ๋‹ˆ๋‹ค . ํ•  ์ˆ˜ ์—†๋Š” ์ด์œ ๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ?

const XFoo = ReactDOM.createCustomElementType('x-foo', {
  propName1: T.Attribute,
  propName2: T.Event,
  propName3: T.Prop
})

์•„๋‹ˆ๋ฉด ๋‹จ์ผ ์†Œํ’ˆ์—์„œ ์—ฌ๋Ÿฌ ์œ ํ˜•์„ ์ง€์›ํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€์น˜๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ?

๋‚˜๋Š” @effulgentsia๋ฅผ ํ†ตํ•ด ์ด ํ๋ฆ„์„ ์ฃผ์ €ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ฐ’์ด ํ•จ์ˆ˜์ธ ๊ฒฝ์šฐ:
eventName: ์†Œํ’ˆ ์ด๋ฆ„,
๋˜ ๋‹ค๋ฅธ:
propertyName: ์†Œํ’ˆ ์ด๋ฆ„,
attributeName: camelCaseToDashCase(์†Œํ’ˆ ์ด๋ฆ„),

ํ•จ์ˆ˜ ์†Œํ’ˆ์ด ์ด๋ฒคํŠธ๋กœ ๊ธฐ๋ณธ ์„ค์ •๋˜๋Š” ๊ฒƒ์„ ์›ํ•˜์ง€ ์•Š๊ณ  propertyName๊ณผ attributeName์„ ๋ชจ๋‘ ํ• ๋‹นํ•˜๋Š” ๊ฒƒ์ด ํ•ฉ๋ฆฌ์ ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๊นŒ? ์œ„์˜ ์งˆ๋ฌธ์„ ๋ชจ๋ฐฉํ•˜๊ธฐ ์œ„ํ•ด ์–ธ์ œ ๋‘˜ ๋‹ค ์ง€์›๋˜๊ธฐ๋ฅผ ์›ํ•˜์‹ญ๋‹ˆ๊นŒ? ๐Ÿ™‚

@LeeCheneler :

๋ฌธ์ œ ์š”์•ฝ์˜ ์˜ต์…˜ 1 ์ฐฌ์„ฑ์—์„œ ์ธ์šฉ:

Polymer ๋˜๋Š” Skate์™€ ๊ฐ™์€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ ์ƒ์„ฑ๋œ ๋ชจ๋“  ์š”์†Œ๋Š” ๋…ธ์ถœ๋œ ์†์„ฑ์„ ๋’ท๋ฐ›์นจํ•˜๋Š” ์†์„ฑ์„ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์š”์†Œ๋Š” ๋ชจ๋‘ ์œ„์˜ ์ ‘๊ทผ ๋ฐฉ์‹์œผ๋กœ "์ •์ƒ ์ž‘๋™"ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋ฐ”๋‹๋ผ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์ง์ ‘ ์ž‘์„ฑํ•˜๋Š” ๊ฐœ๋ฐœ์ž๋Š” ์†์„ฑ์„ ์‚ฌ์šฉํ•˜์—ฌ ์†์„ฑ ์„ ์ง€์›ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ์ด๋Š” HTML5 ์š”์†Œ( <video> , <audio> ๋“ฑ)๊ฐ€ ์–ผ๋งˆ๋‚˜ ํ˜„๋Œ€์ ์ธ์ง€(์ฆ‰, <input> ์™€ ๊ฐ™์€ ์ด์ƒํ•œ ๊ฒƒ์ด ์•„๋‹˜)์„ ๋ฐ˜์˜ํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๊ตฌํ˜„๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

์ด๊ฒƒ์ด propertyName๊ณผ attributeName์„ ๋ชจ๋‘ ํ• ๋‹นํ•˜๋Š” ๊ฒƒ์ด ํ•ฉ๋ฆฌ์ ์ธ ์ด์œ ์ž…๋‹ˆ๋‹ค. ๋ชจ๋ฒ” ์‚ฌ๋ก€๋ฅผ ๋”ฐ๋ฅด๋Š” ์š”์†Œ์˜ ์‹ค์ œ ์‚ฌ๋ก€๋ฅผ ๋ฐ˜์˜ํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  React๊ฐ€ ์ด๋ฅผ ์ธ์‹ํ•˜๊ฒŒ ํ•จ์œผ๋กœ์จ React๋Š” ์ƒํ™ฉ์— ๋”ฐ๋ผ ์–ด๋–ค ๊ฒƒ์„ ์‚ฌ์šฉํ• ์ง€ ๊ฒฐ์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ชจ๋ฒ” ์‚ฌ๋ก€๋ฅผ ๋”ฐ๋ฅด์ง€ ์•Š๊ณ  ํ•ด๋‹น ์†์„ฑ์ด ์—†๋Š” ์ผ๋ถ€ ์†์„ฑ ๋ฐ/๋˜๋Š” ํ•ด๋‹น ์†์„ฑ์ด ์—†๋Š” ์ผ๋ถ€ ์†์„ฑ์ด ์žˆ๋Š” ์‚ฌ์šฉ์ž ์ง€์ • ์š”์†Œ์˜ ๊ฒฝ์šฐ React๋Š” ์ด๋ฅผ ์ธ์‹ํ•ด์•ผ SSR ๋ฐ ์†์„ฑ ์ค‘์— ์†์„ฑ์ด ์—†๋Š” ์†์„ฑ์ด ๋ Œ๋”๋ง๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. -less-attributes๋Š” ํด๋ผ์ด์–ธํŠธ ์ธก ๋ Œ๋”๋ง ์ค‘์— setAttribute()๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ท€ํ•˜์˜ ์ œ์•ˆ์œผ๋กœ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋น„ํŠธ ๊ฒฐํ•ฉ ํ”Œ๋ž˜๊ทธ๋กœ ์ž ์žฌ์ ์œผ๋กœ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

propName1: T.Property | T.Attribute,

๊ทธ๋Ÿฌ๋‚˜ ์ด๋Š” ์†์„ฑ ์ด๋ฆ„์ด ์†์„ฑ ์ด๋ฆ„๊ณผ ๋‹ค๋ฅด๋‹ค๋Š” ๊ฒƒ์„ ํ‘œํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค(์˜ˆ: camelCase์—์„œ dash-case๋กœ). ๋˜ํ•œ SSR ๋™์•ˆ ๋ฆฌ์น˜ ๊ฐœ์ฒด๋ฅผ ์†์„ฑ์œผ๋กœ ์ง๋ ฌํ™”ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ํ‘œํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•๋„ ์ œ๊ณตํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค("[object Object]"์˜ ํ˜„์žฌ ๋™์ž‘์€ ์œ ์šฉํ•˜์ง€ ์•Š์Œ).

ํ•จ์ˆ˜ ์†Œํ’ˆ์ด ์ด๋ฒคํŠธ๋กœ ๊ธฐ๋ณธ ์„ค์ •๋˜๋Š” ๊ฒƒ์„ ์›ํ•˜์ง€ ์•Š๋Š”๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

๋„ค, ์ €๋„ ๊ทธ ๋ง์— ๋™์˜ํ•˜๋Š” ๊ฒƒ ๊ฐ™์œผ๋‹ˆ, ํ›„์† ๋Œ“๊ธ€ ์ž…๋‹ˆ๋‹ค. ๋‚ด ์ฃผ์ €๋ฅผ ํ™•์ธ ์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค!

์ด์ „ ์ œ์•ˆ ์˜ ๋œ ์žฅํ™ฉํ•œ ๋ฒ„์ „์— ๋Œ€ํ•œ ์ƒ๊ฐ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

const XFoo = ReactDOM.createCustomElementType('x-foo', {
  UNREFLECTED_ATTRIBUTES: [
    'my-attr-1',
    'my-attr-2',
  ],
  UNREFLECTED_PROPERTIES: [
    'myProp1',
    'myProp2',
  ],
  REFLECTED_PROPERTIES: {
    // This is default casing conversion, so could be omitted.
    someVeryLongName1: 'some-very-long-name-1',

    // In case anyone is still using all lowercase without dashes.
    someVeryLongName2: 'someverylongname2',

    // When needing to define a function for serializing a property to an attribute.
    someRichData: ['some-rich-data', JSON.stringify],
  },
});

๊ทธ๋ฆฌ๊ณ  ์œ„์˜ ์ฝ”๋“œ ์ฃผ์„์— ๋”ฐ๋ผ ๋ชจ๋“  ๋ฐ˜์˜๋œ ์†์„ฑ์„ ์ •์˜ํ•  ํ•„์š”๊ฐ€ ์—†์œผ๋ฉฐ ์†์„ฑ ์ด๋ฆ„์ด ๋Œ€์‹œ ๋Œ€์†Œ๋ฌธ์ž ๋ฒ„์ „์ธ ๋ฐ˜์˜๋œ ์†์„ฑ์œผ๋กœ ์ž๋™์œผ๋กœ ์ •์˜๋˜์ง€ ์•Š์€ ๋ชจ๋“  ์†์„ฑ์„ ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.

์ดํ•ด๊ฐ€ ๋˜๋„ค์š” @effulgentsia ๐Ÿ‘

๋‚˜๋Š” ๋‹น์‹ ์˜ ๋‘ ๋ฒˆ์งธ ์˜ˆ๋ฅผ ์ข‹์•„ํ•˜์ง€๋งŒ ๋” ๋งŽ์€ ์œ ํ˜•์ด ์ถ”๊ฐ€๋˜๋ฉด ์กฐํ•ฉ ํญ๋ฐœ์— ์—ด๋ ค ์žˆ์ง€ ์•Š์Šต๋‹ˆ๊นŒ?

- UNREFLECTED_ATTRIBUTES
- UNREFLECTED_PROPERTIES
- UNREFLECTED_EVENTS
- REFLECTED_PROPERTIES_ATTRIBUTES
- REFLECTED_PROPERTIES_EVENTS
- REFLECTED_ATTRIBUTES_EVENTS
- REFLECTED_PROPERTIES_ATTRIBUTES_EVENTS
...

์–ด์จŒ๋“  ์ด๋ฒคํŠธ๋ฅผ ์†Œํ’ˆ์ด๋‚˜ ์†์„ฑ๊ณผ ํ˜ผํ•ฉํ•˜๊ณ  ์‹ถ์ง€ ์•Š๋‹ค๊ณ  ์ƒ๊ฐํ•˜์ง€๋งŒ ๐Ÿค” ์†์„ฑ๊ณผ ์†Œํ’ˆ์€ ์•„๋งˆ๋„ ๋ชจ๋ฐฉํ•˜๊ณ  ์‹ถ์€ ์œ ์ผํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

React์™€ Web Component ์ปค๋ฎค๋‹ˆํ‹ฐ ๋ชจ๋‘๊ฐ€ ๋ชจ๋ฒ” ์‚ฌ๋ก€์— ๋ถ€ํ•ฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐํšŒ๊ฐ€ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. React๊ฐ€ ์—ฌ๊ธฐ์—์„œ ์˜๊ฒฌ์„ ๊ฐ–๋Š” ๊ฒƒ์€ ๊ด‘๋ฒ”์œ„ํ•œ ์ฑ„ํƒ๊ณผ ์˜๊ฒฌ์ด ์ˆ˜๋ฐ˜ํ•˜๋Š” ๋ฌด๊ฒŒ๋กœ ์ธํ•ด ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ ์ž‘์„ฑ์ž๊ฐ€ ์˜ฌ๋ฐ”๋ฅธ ๋ฐฉํ–ฅ์œผ๋กœ ์•ˆ๋‚ด๋˜๋Š” ๋ฐ ํฐ ๋„์›€์ด ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์˜ต์…˜ 4์˜ ๊ตฌํ˜„์„ ์ž‘์„ฑํ–ˆ์ง€๋งŒ ์†์„ฑ๊ณผ ์ด๋ฒคํŠธ๋ฅผ ์†์„ฑ์—์„œ ๋ถ„๋ฆฌํ•ด์•ผ ํ•˜๋Š” ๋ฌธ์ œ์— ํ•ญ์ƒ ์‚ฌ๋กœ์žกํ˜€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด์ƒ์ ์œผ๋กœ๋Š” ์˜ต์…˜ 1์„ ์„ ํ˜ธํ•ฉ๋‹ˆ๋‹ค. ์‹ค์ œ๋กœ๋Š” ํƒˆ์ถœ๊ตฌ๊ฐ€ ์žˆ๋Š” ์˜ต์…˜ 2๋ฅผ ์„ ํ˜ธํ•ฉ๋‹ˆ๋‹ค.

์˜ต์…˜ 1์ด ์ด์ƒ์ ์ด์ง€๋งŒ ํ•ด๋‹น ์†์„ฑ(aria / data)์ด ์—†๋Š” ๋งŽ์€ ์œ ํ˜•์˜ ์†์„ฑ์ด ์žˆ์œผ๋ฏ€๋กœ ์ด๋Ÿฌํ•œ ์†์„ฑ์— ๋Œ€ํ•œ ์ถ”๊ฐ€ ๋ฐœ๊ฒฌ์  ๋ฐฉ๋ฒ•์ด ํ•„์š”ํ•˜๊ณ  ์š”์†Œ์— ์†์„ฑ์ด ์žˆ์–ด์•ผ ํ•˜๋Š”

์˜ต์…˜ 2๋Š” ์ฃผ์š” ๋ณ€๊ฒฝ ์‚ฌํ•ญ์ด ์•„๋‹ˆ๋ฏ€๋กœ ์„ ํ˜ธ๋ฉ๋‹ˆ๋‹ค. ์ธ์Šคํ„ด์Šค๊ฐ€ ์ƒ์„ฑ๋˜๊ธฐ ์ „์— ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ ์ •์˜๊ฐ€ ๋“ฑ๋ก๋˜๋Š”(๋˜๋Š” ์†์„ฑ์ด ์„ค์ •๋˜๊ธฐ ์ „์— ๋กœ๋“œ๋˜๋Š”) ๋ชจ๋“  ์ƒํ™ฉ์—์„œ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ์ด ์˜ต์…˜์— ๋Œ€ํ•œ ์„ ํ–‰ ๊ธฐ์ˆ ์€ Preact(cc @developit)์ด๋ฉฐ ์ง€๊ธˆ๊นŒ์ง€ ์ž˜ ์ž‘๋™ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด ๊ฒฝ๋กœ๋ฅผ ๋”ฐ๋ผ๊ฐ€๋ฉด ์„ฑ๊ณต์ ์ธ React ๋ณ€ํ˜•์œผ๋กœ ์ž…์ฆ๋˜์—ˆ์œผ๋ฉฐ ๋Œ€๋ถ€๋ถ„์˜ ์ƒํ™ฉ์—์„œ ์ž‘๋™ํ•˜๋Š” ํ•ฉ๋ฆฌ์ ์œผ๋กœ ๊ฐ•๋ ฅํ•˜๊ณ  ์ค‘๋‹จ๋˜์ง€ ์•Š๋Š” ๊ตฌํ˜„์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ์–ด์จŒ๋“ , ๊ทธ๊ฒƒ์€ React์— ๋‹จ๊ธฐ์ ์ธ ์†”๋ฃจ์…˜์„ ์ œ๊ณตํ•˜๋Š” ๋ฐ˜๋ฉด ๋” ๋‚˜์€ ์†”๋ฃจ์…˜์€ ์žฅ๊ธฐ์ ์œผ๋กœ ํ‰๊ฐ€๋ฉ๋‹ˆ๋‹ค.

์ด๊ฒƒ์ด ์ž‘๋™ํ•˜์ง€ ์•Š๋Š” ์ƒํ™ฉ(์ƒํ™ฉ s ?)์˜ ๊ฒฝ์šฐ - ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ ์ •์˜์˜ ์ง€์—ฐ ๋กœ๋”ฉ ๋ฐ ์šฐ๋ฆฌ๊ฐ€ ๋‹ค๋ฃจ์ง€ ์•Š์€ ๋‹ค๋ฅธ ๋ชจ๋“  ๊ฒƒ - Incremental DOM์ด ์ˆ˜ํ–‰ํ•œ ๊ฒƒ๊ณผ ๊ฐ™์€ ํƒˆ์ถœ ํ•ด์น˜๊ฐ€ ๊ตฌํ˜„๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ @effulgentsia ๊ฐ€ ์ œ์•ˆํ•˜๋Š” ๊ฒƒ๊ณผ ์œ ์‚ฌํ•˜์ง€๋งŒ x ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ ์ˆ˜๋กœ ํ™•์žฅํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ์†Œ๋น„์ž๊ฐ€ ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ๋ณ„๋กœ ์ด๋ฅผ ์ˆ˜ํ–‰ํ•˜๊ธฐ๋ฅผ ์›ํ•˜๋ฉด ์—ฌ์ „ํžˆ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์™œ๋ƒํ•˜๋ฉด ๊ทธ๊ฒƒ์€ ๋‹จ์ง€ ๊ธฐ๋Šฅ์ด๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด React๋Š” ๋ชจ๋“  ์—ฃ์ง€ ์ผ€์ด์Šค์— ๋Œ€ํ•œ ์ฑ…์ž„์„ ์†Œ๋น„์ž์—๊ฒŒ ๋„˜๊น€์œผ๋กœ์จ ์˜๊ฒฌ์„ ๊ฐ–๊ณ  ํ•ด์น˜๋ฅผ ๋ฒ—์–ด๋‚˜ ๋ชจ๋“  ์‚ฌ์šฉ ์ผ€์ด์Šค๋ฅผ ๋งŒ์กฑ์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ์ด์ „์— @developit ๊ณผ ๋…ผ์˜ํ•œ ๋‚ด์šฉ์ด๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ Preact / React ๊ฐ„์˜ ์ •๋ ฌ์€ ํฐ ์Šน๋ฆฌ๊ฐ€ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋ฏธ๋ž˜์˜ HTML ์†์„ฑ์— ๋Œ€ํ•œ ์šฐ๋ ค์— ๋Œ€ํ•ด ์ด๊ฒƒ์€ ์šฐ๋ฆฌ๊ฐ€ ํ•ด๊ฒฐํ•  ์ˆ˜ ์—†๋Š” ๊ฒƒ์ด๋ฏ€๋กœ ์—ฌ๊ธฐ์„œ ์šฐ๋ฆฌ๊ฐ€ ๊ทธ๊ฒƒ์— ๋Œ€ํ•ด ๊ณ ๋ฏผํ•ด์•ผ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ ReactDOM.defineCustomElementProp() ํ˜ธ์ถœ์€ ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ ์ž‘์„ฑ์ž๊ฐ€ ์œ ์ง€ ๊ด€๋ฆฌํ•˜๋Š” JS ํŒŒ์ผ์—์„œ ์ œ๊ณต๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

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

์‚ฌ์šฉ์ž๊ฐ€ ์‹ค์ œ๋กœ ์‚ฌ์šฉํ•˜๋Š” ์†์„ฑ/์†์„ฑ๋งŒ์œผ๋กœ ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ์˜ ์‚ฌ์šฉ์ž๊ฐ€ ์ด๋Ÿฌํ•œ API๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ์„ ์ •์˜ํ•˜๋Š” ๊ฒƒ์€ ์œ ์ง€ ๊ด€๋ฆฌํ•  ์ฝ”๋“œ๊ฐ€ ์ ๊ณ  ํ‘œํ˜„๋ ฅ์ด ๋›ฐ์–ด๋‚ฉ๋‹ˆ๋‹ค.

๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ž‘์„ฑ์ž๊ฐ€ React๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋”๋ผ๋„ ํ•ด๋‹น ์›น ๊ตฌ์„ฑ ์š”์†Œ์˜ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์†์„ฑ ๊ตฌ์„ฑ์„ ํ•œ ๋ฒˆ ์ •์˜ํ•œ ๋‹ค์Œ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋” ๋‚˜์€ UX๋ผ๊ณ  ์ฃผ์žฅํ•ฉ๋‹ˆ๋‹ค.

์†์„ฑ์ด ํ•„์š”ํ•œ ์›น ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์ฒ˜์Œ ์‚ฌ์šฉํ•  ๋•Œ๋Š” sigil์„ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ๋งŒํผ ์–ด๋ ต์ง€๋งŒ(๋” ์žฅํ™ฉํ•˜์ง€๋งŒ ๋” ๋ช…์‹œ์ ) ๋‚˜์ค‘์— ์‚ฌ์šฉํ•  ๋•Œ๋Š” ์ด์— ๋Œ€ํ•ด ์ƒ๊ฐํ•  ํ•„์š”๊ฐ€ ์—†๊ธฐ ๋•Œ๋ฌธ์— ๋” ์‰ฝ์Šต๋‹ˆ๋‹ค. ํ•ด๋‹น ๊ตฌ์„ฑ ์š”์†Œ์˜ ๋ชจ๋“  ๋‹จ์ผ ํ˜ธ์ถœ ์‚ฌ์ดํŠธ. ๋‘ ๊ฒฝ์šฐ ๋ชจ๋‘ ์ƒˆ ์›น ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์ฑ„ํƒํ•  ๋•Œ ์†์„ฑ/์†์„ฑ ์ฐจ์ด๋ฅผ ์ดํ•ดํ•ด์•ผ ํ•˜์ง€๋งŒ ๋‹จ์ผ ๊ณต์œ  ๊ตฌ์„ฑ์„ ์‚ฌ์šฉํ•˜๋ฉด ๋™์ผํ•œ ์•ฑ ๋‚ด์—์„œ ํ•ด๋‹น ๊ตฌ์„ฑ ์š”์†Œ์˜ ๋ชจ๋“  ์‚ฌ์šฉ์ž๊ฐ€ ๊ทธ๊ฒƒ์— ๋Œ€ํ•ด ์ƒ๊ฐํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

๋” ๋งŽ์€ React ๊ด€์šฉ๊ตฌ ์ด๋ฆ„์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋„๋ก ํ•ด๋‹น ๊ตฌ์„ฑ์—์„œ ์†์„ฑ ์ด๋ฆ„์„ ๋‹ค์‹œ ๋งคํ•‘ํ•˜๋Š” ๊ฒƒ์„ ์ž ์žฌ์ ์œผ๋กœ ํ—ˆ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•„์š”ํ•œ ๊ฒฝ์šฐ XFoo๋ฅผ ํ•„์š”ํ•œ ๋ฉ‹์ง„ ๋ฒˆ์—ญ ๋…ผ๋ฆฌ๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š” ์‚ฌ์šฉ์ž ์ •์˜ React ๊ตฌ์„ฑ ์š”์†Œ๋กœ ๊ต์ฒดํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๋ณด๋‹ค ์ •๊ตํ•œ ๋ž˜ํผ๋กœ์˜ ์—…๊ทธ๋ ˆ์ด๋“œ ๊ฒฝ๋กœ๋„ ๋” ์›ํ™œํ•ฉ๋‹ˆ๋‹ค.

๊ธฐ๋ณธ์ ์œผ๋กœ ์‚ฌ๋žŒ๋“ค์ด ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ๋งˆ๋‹ค ์†์„ฑ ๊ตฌ์„ฑ์— ๋Œ€ํ•ด ์ƒ๊ฐํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์ด ๊ฐ€๋Šฅํ•˜๋‹ค๋ฉด ๊ทธ ์ ‘๊ทผ ๋ฐฉ์‹์„ ์„ ํ˜ธํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ 5๋ฒˆ ์˜ต์…˜์„ ์ œ์•ˆํ–ˆ์Šต๋‹ˆ๋‹ค. 3๋ฒˆ๊ณผ 4๋ฒˆ๋ณด๋‹ค ์ธ์ฒด๊ณตํ•™์ ์ด๋ฉด์„œ ๋™์‹œ์— ์œ ์—ฐํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

์˜ต์…˜ 1๊ณผ 2๋Š” ์„œ๋ฒ„ ๋ Œ๋”๋ง(HTML ์ƒ์„ฑ)์—์„œ ์ž˜ ์ž‘๋™ํ•˜์ง€ ์•Š์œผ๋ฉฐ ์˜ต์…˜ 2๋Š” ๋˜ํ•œ ์›น ๊ตฌ์„ฑ ์š”์†Œ ์ž‘์„ฑ์ž์—๊ฒŒ ์—…๊ทธ๋ ˆ์ด๋“œ ์œ„ํ—˜์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ ๊ธฐ์กด ์†์„ฑ๊ณผ ๋™์ผํ•œ ์ด๋ฆ„์„ ๊ฐ€์ง„ ์†์„ฑ์„ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์€ ์ฃผ์š” ๋ณ€๊ฒฝ ์‚ฌํ•ญ์ž…๋‹ˆ๋‹ค. SSR์ด ์œ ์šฉํ•˜์ง€ ์•Š๋‹ค๊ณ  ๊ฒฐ์ •ํ•˜๋ฉด ์˜ต์…˜ 1์ด React ๊ด€์ ์—์„œ ๊ฝค ๋งค๋ ฅ์ ์ž…๋‹ˆ๋‹ค. ์‹ค์ œ๋กœ ์ถฉ๋ถ„ํžˆ ํฌ๊ด„์ ์ธ์ง€๋Š” ์ž˜ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค. ๊ตฌ์„ฑ ์š”์†Œ ์ž‘์„ฑ์ž๊ฐ€ ์†์„ฑ์„ ํ†ตํ•ด ๋ชจ๋“  ๊ฒƒ์„ ๋…ธ์ถœํ•ฉ๋‹ˆ๊นŒ?

@treshugart ์ž์ „๊ฑฐ ์„ธ๋‹จ ์— ๋„ˆ๋ฌด ๊นŠ์ด ๋“ค์–ด

@sophiebits๋‹˜์ด ๋‹ต๊ธ€์„ ์ด์ œ์„œ์•ผ ๋ณด๊ฒŒ ๋˜์–ด ์ฃ„์†กํ•ฉ๋‹ˆ๋‹ค. ๋‚˜๋Š” ๊ทธ๊ฒƒ์„ ๋ช‡ ๋ฒˆ ๋” ์ฝ์€ ํ›„์— ๋ช‡ ๊ฐ€์ง€ ์š”์ ์— ์‘๋‹ตํ•˜๊ณ  ์‹ถ์ง€๋งŒ ์ด๊ฒƒ์— ์‹ ์†ํ•˜๊ฒŒ ์‘๋‹ตํ•˜๊ณ  ์‹ถ์—ˆ์Šต๋‹ˆ๋‹ค.

์‹ค์ œ๋กœ ์ถฉ๋ถ„ํžˆ ํฌ๊ด„์ ์ธ์ง€๋Š” ์ž˜ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค. ๊ตฌ์„ฑ ์š”์†Œ ์ž‘์„ฑ์ž๊ฐ€ ์†์„ฑ์„ ํ†ตํ•ด ๋ชจ๋“  ๊ฒƒ์„ ๋…ธ์ถœํ•ฉ๋‹ˆ๊นŒ?

Polymer ๋˜๋Š” Skate๋กœ ๊ตฌ์ถ•๋œ ๋ชจ๋“  ๊ตฌ์„ฑ ์š”์†Œ๋Š” ์†์„ฑ์„ ํ†ตํ•ด ๋ชจ๋“  ๊ฒƒ์„ ๋…ธ์ถœํ•ฉ๋‹ˆ๋‹ค. ๋ช‡ ๊ฐ€์ง€ ๋“œ๋ฌธ ์ด์ƒ์น˜๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ์ง€๋งŒ(์Šคํƒ€์ผ ์ง€์ •์„ ์œ„ํ•œ ์†์„ฑ ์„ค์ • ๋“ฑ) ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ํ•ญ์ƒ ์†์„ฑ์ด ๋’ท๋ฐ›์นจํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๋‚˜๋Š” ๋Œ€๋ถ€๋ถ„์˜ ํ”„๋กœ๋•์…˜ ์›น ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ์ด ๋‘ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ค‘ ํ•˜๋‚˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ตฌ์ถ•๋œ๋‹ค๊ณ  ํ™•์‹ ํ•ฉ๋‹ˆ๋‹ค.

๋ˆ„๊ตฐ๊ฐ€๊ฐ€ ๋ฐ”๋‹๋ผ ์›น ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์ˆ˜๋™์œผ๋กœ ์ž‘์„ฑํ•˜๋Š” ๊ฒฝ์šฐ ์†์„ฑ์„ ํ†ตํ•ด ๋ชจ๋“  ๊ฒƒ์„ ๋…ธ์ถœํ•˜๋„๋ก ๊ฐ•์š”ํ•˜๋Š” ๊ฒƒ์€ ์—†์ง€๋งŒ ๋ชจ๋ฒ” ์‚ฌ๋ก€ ๋ฌธ์„œ ๋ฐ ์˜ˆ์ œ ์—์„œ ๊ทธ๋ ‡๊ฒŒ ํ•˜๋„๋ก ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋งŒํ•œ ๊ฐ€์น˜๊ฐ€ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์†์„ฑ์„ ์‚ฌ์šฉํ•˜๋„๋ก ๊ฐ•์š”ํ•˜๋Š” ๊ฒƒ๋„ ์—†์Šต๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ ์ •์˜๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ ์›ํ•˜๋Š” ๋ชจ๋“  ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋Š” ํด๋ž˜์Šค์ผ ๋ฟ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์‹ค์ œ๋กœ ๋Œ€๋ถ€๋ถ„์˜ ์‚ฌ๋žŒ๋“ค์€ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•ด Polymer ๋˜๋Š” Skate์™€ ๊ฐ™์€ ์ถ”์ƒํ™”๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ์„ ํ˜ธํ•˜๋ฏ€๋กœ ์†์„ฑ API๋ฅผ ๋ฌด๋ฃŒ๋กœ ๋ฐ›์Šต๋‹ˆ๋‹ค.

์•„๋งˆ๋„ ๊ฐ€์žฅ ์ข‹์€ ๋ฐฉ๋ฒ•์€ ํ•ญ์ƒ ํด๋ผ์ด์–ธํŠธ ์ธก์—์„œ ์†์„ฑ์„ ์ˆ˜ํ–‰ํ•œ ๋‹ค์Œ ์•ฑ์—์„œ SSR์„ ์ง€์›ํ•˜๋ ค๋Š” ์‚ฌ๋žŒ๋“ค์„ ์œ„ํ•ด ๊ธฐ๋ณธ ์†์„ฑ ์ด๋ฆ„์— ๋Œ€ํ•œ ์˜ต์…˜ 5 ์Šคํƒ€์ผ ๊ตฌ์„ฑ ๋งต์„ ์†์„ฑ ์ด๋ฆ„์œผ๋กœ ์ง€์›ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

@sophiebits : ์†์„ฑ ์ด๋ฆ„์„ ์‚ฌ์šฉํ•˜์—ฌ React ์•ฑ์„ ์ž‘์„ฑํ•œ ์‚ฌ๋žŒ๋“ค์—๊ฒŒ ํš๊ธฐ์ ์ธ ๋ณ€ํ™”๋ผ๋Š” ์ ์„ ์ œ์™ธํ•˜๊ณ ๋Š” ์ข‹์€ ์•„์ด๋””์–ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด:

<x-foo long-name={val} />

๊ทธ๋Ÿฌ๋‚˜ propname์— ๋Œ€์‹œ๊ฐ€ ์—†์œผ๋ฉด "do ์†์„ฑ"์— ๋Œ€ํ•œ ๊ทœ์น™๊ณผ ๋Œ€์‹œ๊ฐ€ ์žˆ์œผ๋ฉด "do ์†์„ฑ"์— ๋Œ€ํ•œ ๊ทœ์น™์€ ์–ด๋–ป์Šต๋‹ˆ๊นŒ?

@robdodson : ๋Œ€์‹œ๋ฅผ ํฌํ•จํ•˜์ง€ ์•Š๊ณ  ํ•ด๋‹น ์†์„ฑ์˜ ์†์„ฑ ๋Œ€์†Œ๋ฌธ์ž๊ฐ€ ๋‹ค๋ฅธ ์‚ฌ์šฉ์ž ์ง€์ • ์š”์†Œ ํ”„๋ ˆ์ž„์›Œํฌ ๋˜๋Š” ๊ด€ํ–‰์„ ์•Œ๊ณ  ์žˆ์Šต๋‹ˆ๊นŒ? ์ฆ‰, longname ์†์„ฑ์ด ์žˆ๋Š” longName ์†์„ฑ? ๊ทธ๊ฒƒ์€ ์‹ค์ œ๋กœ ๋‚ด์žฅ HTML ์š”์†Œ์™€ ์ „์—ญ ์†์„ฑ(์˜ˆ: contenteditable => contentEditable )์„ ์‚ฌ์šฉํ•˜๋Š” ํ›จ์”ฌ ๋” ์ผ๋ฐ˜์ ์ธ ํŒจํ„ด์ธ ๊ฒƒ ๊ฐ™์ง€๋งŒ ์ด์ œ ์ถฉ๋ถ„ํžˆ ๊ถŒ์žฅ๋˜์ง€ ์•Š๋Š”์ง€ ํ™•์‹คํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. Polymer ๋ฐ Skate ๋•๋ถ„์— ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ ์†์„ฑ์— ๋Œ€ํ•ด. ์—ฌ์ „ํžˆ ๋ฌธ์ œ์ธ ๊ฒฝ์šฐ ๋‹ค์Œ์ด ํฌํ•จ๋œ ๊ธฐ์กด JSX:

<x-foo longname={val} />

์†์„ฑ์ด longName ์ด๋ฉด ์†์„ฑ ์ง‘ํ•ฉ์œผ๋กœ ์‹คํŒจํ•ฉ๋‹ˆ๋‹ค.

@effulgentsia ์ €๋Š” Skate์— ๋Œ€ํ•ด์„œ๋งŒ ๋งํ•  ์ˆ˜ ์žˆ์ง€๋งŒ HTML์„ ์ž‘์„ฑํ•˜๋Š” ๊ฒฝ์šฐ์—๋งŒ ์†์„ฑ API๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ๋ชจ๋“  ์˜๋„์™€ ๋ชฉ์ ์„ ์œ„ํ•ด ์„œ๋ฒ„ ๋ Œ๋”๋ง์œผ๋กœ๋„ ๋ถ„๋ฅ˜๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. JS๋ฅผ ํ†ตํ•ด ๋ฌด์—‡์ด๋“  ํ•˜๊ณ  ์žˆ๋‹ค๋ฉด props๋ฅผ ์„ค์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์šฐ๋ฆฌ์˜ props API๋Š” ์†์„ฑ์—์„œ ์ž๋™์œผ๋กœ ๋‹จ๋ฐฉํ–ฅ ๋™๊ธฐํ™”/์—ญ์ง๋ ฌํ™”๋ฅผ ์ˆ˜ํ–‰ํ•˜๊ณ  ์†์„ฑ ์ด๋ฆ„์„ ๋Œ€์‹œ๋กœ ๊ตฌ๋ถ„ํ•˜์—ฌ ์†์„ฑ ์ด๋ฆ„์„ ํŒŒ์ƒํ•ฉ๋‹ˆ๋‹ค(camelCase๋Š” camel-case ๋“ฑ). ์ด ๋™์ž‘์€ ์ „์ฒด์ ์œผ๋กœ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ์•ž์„œ ์–ธ๊ธ‰ํ•œ ๋ชจ๋ฒ” ์‚ฌ๋ก€๋ฅผ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค.

๋งŽ์€ ์‚ฌ๋žŒ๋“ค์ด ๋งํ–ˆ๋“ฏ์ด props๋Š” SSR์„ ์–ด๋ ต๊ฒŒ ๋งŒ๋“ค๊ณ  ์ด๊ฒƒ์€ ์œ ํšจํ•œ ์šฐ๋ ค์ž…๋‹ˆ๋‹ค. ๋Œ€๋ถ€๋ถ„์ด ์˜ต์…˜ 1์„ ์„ ํ˜ธํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋“ค๋ฆฌ๋ฏ€๋กœ @sophiebits ์˜ ํด๋ผ์ด์–ธํŠธ์— ์†Œํ’ˆ์„ ์„ค์ •ํ•˜๋Š” ๋™์‹œ์— ํด๋ฐฑ/๋งคํ•‘์„ ์ œ๊ณตํ•˜๋Š” ์ œ์•ˆ์„

์˜ˆ๋ฅผ ์œ„ํ•ด, ์—ฌ๊ธฐ ๋‹น์‹ ์ด ๊ตฌํ˜„ ์Šค์ผ€์ดํŠธ์™€ ํด๋ผ์ด์–ธํŠธ (๋ฐ ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ๊ฐ€ ์„œ๋ฒ„๋กœ๋ถ€ํ„ฐ ์ƒํƒœ ๋ฐ ์†Œํ’ˆ์„ ํ†ตํ•ด ์ˆ˜ํ–‰ ๊ตฌํ˜„ํ•  ์ˆ˜์žˆ๋Š” ๋ฐฉ๋ฒ•์„ renderedCallback() ๋ฐ props ๋ฐ / ๋˜๋Š” state setters. ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ ์ˆ˜์ค€์—์„œ ๊ทธ๋ ‡๊ฒŒ ํ•˜๋Š” ๊ฒƒ์€ ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค. React๊ฐ€ ์„œ๋ฒ„์—์„œ ์†์„ฑ์„ ์„ค์ •ํ•˜๋Š” ๊ธธ์„ ๊ฐ”๋‹ค๋ฉด, ์žฌ์ˆ˜ํ™”๋Š” ๋ณธ์งˆ์ ์œผ๋กœ ๋™์ผํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. Skate ๊ตฌ์„ฑ ์š”์†Œ ์ž‘์„ฑ์ž๋Š” ์‹ค์ œ๋กœ ์šฐ๋ฆฌ์ฒ˜๋Ÿผ ์•„๋ฌด ๊ฒƒ๋„ ํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ์ด๋ฏธ ๊ทธ๋“ค์—๊ฒŒ ์—ญ์ง๋ ฌํ™” ๋…ผ๋ฆฌ๋ฅผ ์ œ๊ณตํ–ˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

@robdodson ๋‚˜๋Š” Incremental DOM์ด ํ•˜๋Š” ๊ฒƒ๊ณผ ๋น„์Šทํ•œ ์ผ์„ ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ณด์ผ ๊ฒƒ์ž…๋‹ˆ๋‹ค:

const isBrowser = true; // this would actually do the detection
const oldAttributeHook = ReactDOM.setAttribute;

// This is much like the IDOM impl but with an arguably more clear name.
ReactDOM.setAttribute = (element, name, value) => {
  // This is essentially option 2, but with the added browser check
  // to keep attr sets on the server.
  if (isBrowser && name in element) {
    element[name] = value;
  } else {
    oldAttributeHook(element, name, value);
  }
};

@sophiebits

์˜ต์…˜ 2๋Š” ๋˜ํ•œ ๊ธฐ์กด ์†์„ฑ๊ณผ ์ด๋ฆ„์ด ๊ฐ™์€ ์†์„ฑ์„ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์ด ์ฃผ์š” ๋ณ€๊ฒฝ ์‚ฌํ•ญ์ธ ์›น ๊ตฌ์„ฑ ์š”์†Œ ์ž‘์„ฑ์ž์—๊ฒŒ ์—…๊ทธ๋ ˆ์ด๋“œ ์œ„ํ—˜์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

์†์„ฑ์ด ํ”Œ๋žซํผ์—์„œ ์ž‘๋™ํ•˜๋Š” ๋ฐฉ์‹์„ ๊ณ ๋ คํ•  ๋•Œ ์ด๊ฒƒ์ด ๋ถˆ๊ฐ€ํ”ผํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž ์ง€์ • ์š”์†Œ๋ฅผ SSRํ•˜์—ฌ ์†์„ฑ์— ์จ์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ ํ–ฅํ›„ ํ”Œ๋žซํผ์—์„œ ์œ ์‚ฌํ•œ ์ด๋ฆ„์˜ ์†์„ฑ์„ ์ œ๊ณตํ•  ์œ„ํ—˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. @treshugart๊ฐ€ ์ด์ „ ์—

์ด๊ฒƒ์ด ์˜ต์…˜ 2์— ๋Œ€ํ•ด ๋งˆ์Œ์ด ๋ฐ”๋€Œ์—ˆ๋Š”์ง€ ํ™•์‹ ํ•  ์ˆ˜ ์—†์ง€๋งŒ ์˜ต์…˜ 2์—๋Š” ๋ช‡ ๊ฐ€์ง€ ๋ฉ‹์ง„ ๋ณด๋„ˆ์Šค๊ฐ€ ์žˆ๊ณ  Preact๊ฐ€ ์‹ค์ œ๋กœ ๊ทธ๊ฒƒ์„ ์ฆ๋ช…ํ•˜๋Š” ๊ฒƒ ๊ฐ™๊ธฐ ๋•Œ๋ฌธ์— ์–ธ๊ธ‰ํ•˜๊ณ  ์‹ถ์—ˆ์Šต๋‹ˆ๋‹ค.

์•„๋งˆ๋„ ๊ฐ€์žฅ ์ข‹์€ ๋ฐฉ๋ฒ•์€ ํ•ญ์ƒ ํด๋ผ์ด์–ธํŠธ ์ธก์—์„œ ์†์„ฑ์„ ์ˆ˜ํ–‰ํ•œ ๋‹ค์Œ ์•ฑ์—์„œ SSR์„ ์ง€์›ํ•˜๋ ค๋Š” ์‚ฌ๋žŒ๋“ค์„ ์œ„ํ•ด ๊ธฐ๋ณธ ์†์„ฑ ์ด๋ฆ„์— ๋Œ€ํ•œ ์˜ต์…˜ 5 ์Šคํƒ€์ผ ๊ตฌ์„ฑ ๋งต์„ ์†์„ฑ ์ด๋ฆ„์œผ๋กœ ์ง€์›ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

+1, ์ €๋Š” ์ด ๋ฐฉํ–ฅ์œผ๋กœ ๊ณ„์† ๋‚˜์•„๊ฐ€๋Š” ๊ฒƒ์„ ์ง€์ง€ํ•ฉ๋‹ˆ๋‹ค.


@effulgentsia

์†์„ฑ ์ด๋ฆ„์„ ์‚ฌ์šฉํ•˜์—ฌ React ์•ฑ์„ ์ž‘์„ฑํ•œ ์‚ฌ๋žŒ๋“ค์—๊ฒŒ ํš๊ธฐ์ ์ธ ๋ณ€ํ™”๋ผ๋Š” ์ ์„ ์ œ์™ธํ•˜๊ณ ๋Š” ํ›Œ๋ฅญํ•œ ์•„์ด๋””์–ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

์˜ต์…˜ 2๋Š” ๊ทธ๊ฒƒ์„ ํ•ด๊ฒฐํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค :)
๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ๋Œ€์‹œ ์ผ€์ด์Šค ์†์„ฑ์„ camelCased ์†์„ฑ์— ๋งคํ•‘ํ•˜๋Š” ์˜ต์…˜ 1๊ณผ ๊ฒฐํ•ฉ๋œ ๊ฒฝํ—˜์  ๋ฐฉ๋ฒ•์ด ํ•„์š”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ propname์— ๋Œ€์‹œ๊ฐ€ ์—†์œผ๋ฉด "do ์†์„ฑ"์— ๋Œ€ํ•œ ๊ทœ์น™๊ณผ ๋Œ€์‹œ๊ฐ€ ์žˆ์œผ๋ฉด "do ์†์„ฑ"์— ๋Œ€ํ•œ ๊ทœ์น™์€ ์–ด๋–ป์Šต๋‹ˆ๊นŒ?

์ด๋ฆ„์— ๋Œ€์‹œ๊ฐ€ ์žˆ์œผ๋ฉด Preact ๊ฐ€ ์†์„ฑ์„ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ž…๋‹ˆ๋‹ค. ๋‚˜๋Š” ๊ทธ๋“ค์ด ์˜ต์…˜ 2๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  long-name ๊ฐ€ in ๊ฒ€์‚ฌ๋ฅผ ํ†ต๊ณผํ•˜์ง€ ๋ชปํ•˜์—ฌ ์†์„ฑ( source )์œผ๋กœ ๋Œ€์ฒด๋˜๊ธฐ ๋•Œ๋ฌธ์ด๋ผ๊ณ  ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค.

๋‚˜๋Š” ๊ฐœ์ธ์ ์œผ๋กœ ์ด ๋™์ž‘์„ ์ข‹์•„ํ•˜์ง€๋งŒ ์†์„ฑ์„ ์„ค์ •ํ•˜๋Š” ์˜์—ญ๊ณผ ๋ฏธ๋ž˜์— ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ์ถฉ๋Œ๋กœ ๋Œ์•„๊ฐ€๋ฏ€๋กœ @sophiebits ๊ฐ€ ๋ฌด๊ฒŒ๋ฅผ

๋Œ€์‹œ๋ฅผ ํฌํ•จํ•˜์ง€ ์•Š๊ณ  ํ•ด๋‹น ์†์„ฑ์˜ ์†์„ฑ ๋Œ€์†Œ๋ฌธ์ž๊ฐ€ ๋‹ค๋ฅธ ์‚ฌ์šฉ์ž ์ง€์ • ์š”์†Œ ํ”„๋ ˆ์ž„์›Œํฌ ๋˜๋Š” ๊ด€ํ–‰์„ ์•Œ๊ณ  ์žˆ์Šต๋‹ˆ๊นŒ?

๋‚ด๊ฐ€ ์•Œ๊ธฐ๋กœ๋Š” ์•„๋‹ˆ์•ผ. ๋Œ€์‹œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋„์„œ๊ด€์—์„œ ๋‚™ํƒ€ ์ผ€์ด์Šค์˜ ์œ„์น˜๋ฅผ โ€‹โ€‹์‰ฝ๊ฒŒ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฐ”๋‹๋ผ ์›น ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์ˆ˜๋™์œผ๋กœ ์ž‘์„ฑํ•˜๋Š” ๊ฒฝ์šฐ longname/longName ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ longname ์†์„ฑ์„ ์ฐพ์ง€ ๋ชปํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์˜ต์…˜ 2๋งŒ ์ €์žฅ๋˜์ง€๋งŒ ์ด์ „์— ์‚ฌ์šฉ๋œ ๊ตฌ์„ฑ ์š”์†Œ๋กœ ๋Œ€์ฒด๋ฉ๋‹ˆ๋‹ค. longname ์†์„ฑ.

๊ทธ๋งŒํ•œ ๊ฐ€์น˜๊ฐ€ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— Preact๋Š” ์ตœํ›„์˜ ์ˆ˜๋‹จ ์œผ๋กœ ์†์„ฑ ์„ ์„ค์ •ํ•˜๊ธฐ ์ „์— <x-foo longName={bar}/> SSRํ•˜๋Š” ๊ฒฝ์šฐ longname="" ์†์„ฑ์œผ๋กœ๋„ ์ ์ ˆํ•˜๊ฒŒ ํด๋ฐฑ๋ฉ๋‹ˆ๋‹ค.


@treshugart

๋Œ€์ฒด/๋งคํ•‘์„ ์ œ๊ณตํ•˜๋ฉด์„œ ํด๋ผ์ด์–ธํŠธ์— ์†Œํ’ˆ์„ ์„ค์ •ํ•˜์ž๋Š” @sophiebits ์˜ ์ œ์•ˆ์„

์˜ˆ, ์˜ˆ.

๋‚˜๋Š” Incremental DOM์ด ํ•˜๋Š” ๊ฒƒ๊ณผ ๋น„์Šทํ•œ ์ผ์„ ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋ชจ๋“  ์š”์†Œ(๋˜๋Š” ๊ธฐ๋ณธ ํด๋ž˜์Šค)๊ฐ€ ์ด๊ฒƒ์„ ํ˜ผํ•ฉํ•ด์•ผ ํ•œ๋‹ค๋Š” ์•„์ด๋””์–ด์ž…๋‹ˆ๊นŒ?

btw, ํ† ๋ก ์— ๊ณ„์† ์ฐธ์—ฌํ•ด ์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ๊ฝค ์˜ค๋ž˜๋˜์—ˆ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค โค๏ธ

https://github.com/facebook/react/issues/11347#issuecomment -339858314์˜ ๋งˆ์ง€๋ง‰ ์˜ˆ๋ฅผ ์ดํ•ดํ–ˆ๋Š”์ง€ ํ™•์‹คํ•˜์ง€ ์•Š์ง€๋งŒ ์ด์™€ ๊ฐ™์€ ์ „์—ญ ์žฌ์ •์˜ ๊ฐ€๋Šฅํ•œ ํ›„ํฌ๋ฅผ ์ œ๊ณตํ•  ๊ฐ€๋Šฅ์„ฑ์€ ๊ฑฐ์˜ ์—†์Šต๋‹ˆ๋‹ค.

@gaearon ๋‚˜๋Š” Trey๊ฐ€ ์›์ˆญ์ด ํŒจ์น˜๋กœ ์ˆœ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ๋ณด์—ฌ์ฃผ๊ณ  ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์•„๋งˆ๋„ ReactDOM ๊ตฌํ˜„ ์ž์ฒด์— ์ž‘์„ฑ๋˜์—ˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ตœ๊ทผ ์˜๊ฒฌ์„ ๋ฐ”ํƒ•์œผ๋กœ ์ด ์ œ์•ˆ์— ๋Œ€ํ•ด ์–ด๋–ป๊ฒŒ ์ƒ๊ฐํ•˜์‹ญ๋‹ˆ๊นŒ?

  1. BC์˜ ๊ฒฝ์šฐ React์—์„œ ์†Œ๋ฌธ์ž ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ๊ฐ€ ์ž‘๋™ํ•˜๋Š” ๋ฐฉ์‹์— ๋Œ€ํ•ด ์•„๋ฌด ๊ฒƒ๋„ ๋ณ€๊ฒฝํ•˜์ง€ ๋งˆ์‹ญ์‹œ์˜ค. ์ฆ‰, <x-foo ... /> ์™€ ๊ฐ™์€ JSX๋Š” React 16์—์„œ์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ React 17์—์„œ๋„ ๊ณ„์† ๋™์ผํ•œ ๋ฐฉ์‹์œผ๋กœ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ๋˜๋Š” _์‚ฌ์†Œํ•œ_ ๋ฒ„๊ทธ ์ˆ˜์ •์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ ๋ณ„๋„์˜ ๋ฌธ์ œ๋ฅผ ์—ด์–ด ์ด์— ๋Œ€ํ•ด ๋…ผ์˜ํ•˜์„ธ์š”.

  2. ๋” ๋‚˜์€ ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ ์˜๋ฏธ ์ฒด๊ณ„๋กœ React ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•ด config-less API๋ฅผ ์ถ”๊ฐ€ํ•˜์‹ญ์‹œ์˜ค. ์˜ˆ: const XFoo = ReactDOM.customElement('x-foo'); .

  3. ์œ„์—์„œ ๋งŒ๋“  ๊ตฌ์„ฑ ์š”์†Œ์— ๋Œ€ํ•ด ๋‹ค์Œ ์˜๋ฏธ ์ฒด๊ณ„๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

  4. ์˜ˆ์•ฝ๋œ React prop ์ด๋ฆ„( children , ref , ๊ธฐํƒ€?)์ธ XFoo์˜ ๋ชจ๋“  prop์— ๋Œ€ํ•ด ์ผ๋ฐ˜์ ์ธ React ์˜๋ฏธ ์ฒด๊ณ„๋ฅผ ์ ์šฉํ•ฉ๋‹ˆ๋‹ค(์†์„ฑ์ด๋‚˜ ์†์„ฑ์œผ๋กœ ์„ค์ •ํ•˜์ง€ ๋งˆ์‹ญ์‹œ์˜ค. ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ DOM ๋…ธ๋“œ์—์„œ).
  5. HTML ์‚ฌ์–‘์— ์˜ํ•ด ์ •์˜๋œ HTMLElement ์ „์—ญ ์†์„ฑ ๋˜๋Š” ์†์„ฑ ( data-* ๋ฐ aria-* )์— ๋Œ€ํ•ด div ์— ์žˆ๋Š” ๊ฒฝ์šฐ React์—์„œ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ๊ณผ ๋™์ผํ•œ ์ž‘์—…์„ ํ•ด๋‹น ์†Œํ’ˆ์œผ๋กœ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค <XFoo data-x={} className={} contentEditable={} /> ์˜ props๋ฅผ DOM ๋…ธ๋“œ์— ์ ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์€ <div data-x={} className={} contentEditable={} /> (ํด๋ผ์ด์–ธํŠธ ์ธก ๋ฐ SSR ๋ชจ๋‘)์— ์ ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•๊ณผ ๋™์ผํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  6. ๋Œ€์‹œ๋ฅผ ํฌํ•จํ•˜๋Š” XFoo์˜ ๋ชจ๋“  ์†Œํ’ˆ(์œ„์—์„œ ํ—ˆ์šฉ๋œ ์ „์—ญ ์†์„ฑ ์ œ์™ธ)์— ๋Œ€ํ•ด ๊ฒฝ๊ณ ๋ฅผ ๋‚ด๋ณด๋‚ด๊ณ (๊ฐœ๋ฐœ์ž์—๊ฒŒ XFoo๊ฐ€ ์†์„ฑ ์ค‘์‹ฌ API๊ฐ€ ์•„๋‹ˆ๋ผ ์†์„ฑ ์ค‘์‹ฌ์ž„์„ ์•Œ๋ฆฌ๊ธฐ ์œ„ํ•ด) ์•„๋ฌด ๊ฒƒ๋„ ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค(๋‘˜ ๋ชจ๋‘ ์†์„ฑ ๋˜๋Š” ์†์„ฑ์œผ๋กœ ์„ค์ •).
  7. ๋ฐ‘์ค„์ด๋‚˜ ๋Œ€๋ฌธ์ž ASCII ๋ฌธ์ž๋กœ ์‹œ์ž‘ํ•˜๋Š” XFoo์˜ ๋ชจ๋“  ์†Œํ’ˆ์— ๋Œ€ํ•ด์„œ๋Š” ์•„๋ฌด ๊ฒƒ๋„ ํ•˜์ง€ ๋งˆ์‹ญ์‹œ์˜ค(๊ทธ๋ฆฌ๊ณ  ๊ฒฝ๊ณ ๋ฅผ ํ‘œ์‹œํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค). ๋‘˜ ๋‹ค ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ์˜ ์†์„ฑ ์ด๋ฆ„์„ ์ง€์ •ํ•˜๋Š” ๋ฐ ๊ถŒ์žฅ๋˜๋Š” ๋ฐฉ๋ฒ•์ด ์•„๋‹ˆ๋ฏ€๋กœ ํ–ฅํ›„ ์˜๋ฏธ ์ฒด๊ณ„๋ฅผ ์œ„ํ•ด ํ•ด๋‹น ๋„ค์ž„์ŠคํŽ˜์ด์Šค๋ฅผ ์˜ˆ์•ฝํ•˜์‹ญ์‹œ์˜ค(์˜ˆ: ์•„๋ž˜ #4 ์ฐธ์กฐ).
  8. XFoo์˜ ๋‹ค๋ฅธ ๋ชจ๋“  ์†Œํ’ˆ์˜ ๊ฒฝ์šฐ ํด๋ผ์ด์–ธํŠธ ์ธก์„ ๋ Œ๋”๋งํ•  ๋•Œ DOM ๋…ธ๋“œ์—์„œ ์†์„ฑ์œผ๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. SSR์˜ ๊ฒฝ์šฐ ๊ฐ’์ด ๊ธฐ๋ณธ์ด๋ฉด ์†์„ฑ์œผ๋กœ ๋ Œ๋”๋งํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ์ด ์•„๋‹Œ ๊ฒฝ์šฐ ๋ Œ๋”๋ง์„ ๊ฑด๋„ˆ๋›ฐ๊ณ  ์ˆ˜ํ™” ์ค‘์— ํด๋ผ์ด์–ธํŠธ ์ธก ์†์„ฑ์œผ๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. ์†์„ฑ์œผ๋กœ SSR ๋ Œ๋”๋ง์˜ ๊ฒฝ์šฐ camelCaseToDashCase ์ด๋ฆ„์ž…๋‹ˆ๋‹ค.

  9. ์œ„ #2์˜ API๋ฅผ ํ†ตํ•ด ์ƒ์„ฑ๋œ ๊ตฌ์„ฑ ์š”์†Œ์˜ ๊ฒฝ์šฐ ์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ์— ์‚ฌ์šฉํ•  ์†Œํ’ˆ ์ด๋ฆ„์„ ์˜ˆ์•ฝํ•˜์‹ญ์‹œ์˜ค. ์˜ˆ: 'events' ๋˜๋Š” 'eventListeners' . ๋˜๋Š” ์ž ์žฌ์ ์ธ ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ ์†์„ฑ ์ด๋ฆ„๊ณผ ์ถฉ๋Œํ•˜์ง€ ์•Š์œผ๋ ค๋ฉด '_eventListeners' ๋˜๋Š” 'EventListeners' . XFoo ์˜ ReactDom ์ƒ์„ฑ ๊ตฌํ˜„์€ ์ด๋Ÿฌํ•œ ์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ๋ฅผ DOM ๋…ธ๋“œ์— ์ž๋™์œผ๋กœ ๋“ฑ๋กํ•ฉ๋‹ˆ๋‹ค.

  10. ๊ทน๋‹จ์ ์ธ ๊ฒฝ์šฐ(์˜ˆ: ์œ„์˜ ๊ตฌํ˜„์ด ๋ฐ”๋žŒ์งํ•˜์ง€ ์•Š๊ฑฐ๋‚˜ ์ถฉ๋ถ„ํ•˜์ง€ ์•Š์€ ์‚ฌ์šฉ์ž ์ง€์ • ์š”์†Œ ์‚ฌ์šฉ)์˜ ๊ฒฝ์šฐ ์•ฑ ๊ฐœ๋ฐœ์ž๋Š” ํ•„์š”ํ•œ ๋ชจ๋“  ํŠน๋ณ„ํ•œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๊ธฐ ์œ„ํ•ด ์ž์ฒด React ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ฆ‰, ReactDOM.customElement() ๋ฅผ ์‚ฌ์šฉํ•  ํ•„์š”๊ฐ€ ์—†๊ฑฐ๋‚˜ ํ™•์žฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  11. ์œ„์˜ ๋ชจ๋“  ๋™์ž‘์„ ์›ํ•˜์ง€๋งŒ HTML ์ž‘์„ฑ์— ์ต์ˆ™ํ•œ ์‚ฌ๋žŒ๋“ค์ด <div> ์„ ํ˜ธํ•˜๋Š” ๋น„์Šทํ•œ ์ด์œ ๋กœ JSX๊ฐ€ ์†Œ๋ฌธ์ž ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ ์ด๋ฆ„( <x-foo /> ๋Œ€์‹  <XFoo /> , <div> over <Div> ), ๊ทธ๋“ค์€ React.createElement()๋ฅผ ์›์ˆญ์ด ํŒจ์น˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์•„์ฃผ ๊ฐ„๋‹จํ•œ ์›์ˆญ์ด ํŒจ์น˜๊ฐ€ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ฒซ ๋ฒˆ์งธ ์ธ์ˆ˜๋ฅผ ์ทจํ•˜๊ณ  ์ด๊ฒƒ์ด ์›ํ•˜๋Š” ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ ์ด๋ฆ„๊ณผ ์ผ์น˜ํ•˜๋Š” ๊ฒฝ์šฐ(ํŠน์ • ๋ชฉ๋ก์ด๋“  ๋ชจ๋“  ์†Œ๋ฌธ์ž์™€ ํ•˜๋‚˜ ์ด์ƒ์˜ ๋Œ€์‹œ๊ฐ€ ํฌํ•จ๋œ ๋ฌธ์ž์—ด์ด๋“  ์ƒ๊ด€์—†์ด) ReactDOM.customElement() ๋ฅผ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค ReactDOM.customElement() ๋ฅผ ์ž…๋ ฅํ•˜๊ณ  ๊ฒฐ๊ณผ์™€ ๋‚˜๋จธ์ง€ ์ธ์ˆ˜๋ฅผ ์›๋ž˜ React.createElement() ํ•ฉ๋‹ˆ๋‹ค.

@developit @gaearon ๋‘˜ ์ค‘ ํ•˜๋‚˜์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. "๋งคํ•‘"์ด ํ•„์š”ํ–ˆ๋‹ค๋ฉด ํ›„ํฌ๊ฐ€ ๋” ์ง€์† ๊ฐ€๋Šฅํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ด๊ฒƒ์€ ๋˜ํ•œ Jason์ด ์ง€์ ํ•œ ๊ฒƒ์ฒ˜๋Ÿผ ReactDOM์˜ ์ฝ”์–ด์—์„œ ๊ตฌํ˜„๋˜๋Š” ๊ฒฝ์šฐ ์ˆœ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ๋ณด์—ฌ์ฃผ๊ธฐ ์œ„ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

BC์˜ ๊ฒฝ์šฐ React์—์„œ ์†Œ๋ฌธ์ž ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ๊ฐ€ ์ž‘๋™ํ•˜๋Š” ๋ฐฉ์‹์— ๋Œ€ํ•ด ์•„๋ฌด ๊ฒƒ๋„ ๋ณ€๊ฒฝํ•˜์ง€ ๋งˆ์‹ญ์‹œ์˜ค. ์ฆ‰, JSX๋Š” React 16์—์„œ์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ React 17์—์„œ๋„ ๊ณ„์† ๋™์ผํ•œ ๋ฐฉ์‹์œผ๋กœ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ๋˜๋Š” ์‚ฌ์†Œํ•œ ๋ฒ„๊ทธ ์ˆ˜์ •์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ ๋ณ„๋„์˜ ๋ฌธ์ œ๋ฅผ ์—ด์–ด ์ด์— ๋Œ€ํ•ด ๋…ผ์˜ํ•˜์„ธ์š”.

๊ฐœ์ธ์ ์œผ๋กœ ์ €๋Š” <x-foo> ์š”์†Œ๋ฅผ ์žˆ๋Š” ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉํ•˜๊ณ  ๋จผ์ € ๋ž˜ํ•‘ํ•  ํ•„์š” ์—†์ด ์†์„ฑ์„ ์‰ฝ๊ฒŒ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๊ธฐ๋ฅผ ์›ํ•ฉ๋‹ˆ๋‹ค.

๊ฐ€๋Šฅํ•˜๋‹ค๋ฉด @sohpiebits ์˜ ์˜ต์…˜ 1(ํด๋ผ์ด์–ธํŠธ ์ธก ์†์„ฑ) ๋ฐ 5(SSR์šฉ ๊ตฌ์„ฑ)๋ฅผ ์ œ์•ˆ ํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. ๋‚˜๋Š” ์—ฌ์ „ํžˆ ์‚ฌ๋žŒ๋“ค์ด ์ด์ „ ๋ฒ„์ „๊ณผ์˜ ํ˜ธํ™˜์„ฑ ๋ณด๋„ˆ์Šค์— ๋Œ€ํ•ด option2(์•„๋งˆ๋„ ์˜ต์…˜ 2 + 5?)๋ฅผ ์žฌ๊ณ ํ•  ๊ฒƒ์ด๋ผ๋Š” ํฌ๋ง์„ ํ’ˆ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

@gaearon Trey์˜ ์ œ์•ˆ์ด ReactDOM ์ฝ”์–ด์˜ ์ผ๋ถ€๋ผ๋ฉด ์˜๊ฒฌ์ด ๋ฐ”๋€Œ๋‚˜์š”? ๋„์›€์ด ๋œ๋‹ค๋ฉด ์˜ˆ์ œ๋ฅผ ๋” ๊ตฌ์ฒดํ™”ํ•  ์ˆ˜ ์žˆ์ง€ ์•Š์„๊นŒ์š”?

์˜ต์…˜ 5์— ๋Œ€ํ•œ ๋‚˜์˜ ์ฃผ์š” ๊ด€์‹ฌ์‚ฌ๋Š” ์ƒํ˜ธ ์šด์šฉ์„ฑ์„ ํ—ˆ์šฉํ•˜๊ธฐ ์œ„ํ•ด ๋งŽ์€ ์ƒ์šฉ๊ตฌ๋ฅผ ๋งŒ๋“ค๊ณ  DX๋ฅผ ๊นจ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋ชจ๋“  React ํ•ต์‹ฌ ํŒ€๊ณผ ๊ธฐ์—ฌ์ž๊ฐ€ ์›ํ•˜๋Š” ์˜ํ–ฅ์„ ๋ฏธ์น˜์ง€ ์•Š์„ ๋ณ€๊ฒฝ์— ๋งŽ์€ ์‹œ๊ฐ„์„ ๋ณด๋‚ด๋Š” ๊ฒƒ์€ ๋ถ€๋„๋Ÿฌ์šด ์ผ์ž…๋‹ˆ๋‹ค.

๋‚˜๋Š” React ํŒ€์ด _PropTypes_์™€ ๊ฐ™์€ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ์˜ ๋งˆ์ง€๋ง‰ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ •๋ง ์ข‹์•„ํ–ˆ์Šต๋‹ˆ๋‹ค. ํ•˜๋‚˜ ์ด์ƒ์˜ ์Šค์œ„์น˜๋ฅผ ํฌํ•จํ•˜๋Š” ๊ณ„ํš์„ ์ƒ๊ฐํ•˜๋Š” ๊ฒƒ์ด ์ข‹์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ฐœ๋ฐœ์ž์—๊ฒŒ ํ–ฅํ›„ ์‚ฌ์šฉ์ž ์ง€์ •์ด ์•„๋‹Œ ์‚ฌ์šฉ์ž ์ง€์ •์— ๋Œ€ํ•ด ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ๊ต์œกํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ง‘๋‹จ.

์šฐ๋ฆฌ ๋ชจ๋‘๋ฅผ ๋งŒ์กฑ์‹œํ‚ฌ ์†”๋ฃจ์…˜์€ ์ด ์˜ต์…˜ ์ค‘ ์ผ๋ถ€๋ฅผ _steps_, API ์ถ”๊ฐ€, ๊ฒฝ๊ณ  ๋ฐ ์‚ฌ์šฉ ์ค‘๋‹จ ๋˜๋Š” ๋™์ž‘ ๋ณ€๊ฒฝ์œผ๋กœ ๊ฒฐํ•ฉํ•˜๋Š” ์†”๋ฃจ์…˜์ด ๋  ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

์˜ต์…˜ 5(๊ฒฝ๊ณ  ํฌํ•จ), ์ดํ›„ ์˜ต์…˜ 2(ํ•„์š”ํ•œ ๋ž˜ํผ ์‚ฌ์šฉ ์ค‘๋‹จ ํฌํ•จ).

์˜ต์…˜ 5(๊ฒฝ๊ณ  ํฌํ•จ), ์ดํ›„ ์˜ต์…˜ 2(ํ•„์š”ํ•œ ๋ž˜ํผ ์‚ฌ์šฉ ์ค‘๋‹จ ํฌํ•จ).

๋‚˜๋Š” ์‹ค์ œ๋กœ ๊ทธ ๋ฐ˜๋Œ€๋กœ ํ•˜๋Š” ๊ฒƒ์ด ๋” ๋‚˜์€ ์ผ๋ จ์˜ ๋‹จ๊ณ„๊ฐ€ ๋  ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ•˜๊ณ  ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ์˜ต์…˜ 1 ๋˜๋Š” 2๋Š” ๊ทน์ ์ธ ๋ณ€ํ™”๊ฐ€ ์ ๊ธฐ ๋•Œ๋ฌธ์— ์„ ํƒํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ทธ๊ฒƒ์ด ์–ด๋–ป๊ฒŒ ์ง„ํ–‰๋˜๊ณ  SSR ์Šคํ† ๋ฆฌ๊ฐ€ ์›น ๊ตฌ์„ฑ ์š”์†Œ์— ๋Œ€ํ•ด ์–ด๋–ป๊ฒŒ ๋ณด์ด๊ธฐ ์‹œ์ž‘ํ•˜๋Š”์ง€ ์ธก์ •ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ ์ƒˆ API์™€ ํ”„๋ก์‹œ/๋ž˜ํผ ๊ตฌ์„ฑ ์š”์†Œ ๊ฐœ๋…์„ ์ถ”๊ฐ€ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์˜ต์…˜ 5๋กœ ํ›„์† ์กฐ์น˜๋ฅผ ์ทจํ•ฉ๋‹ˆ๋‹ค.

์˜ต์…˜ 1์˜ ์ฃผ์š” ๋ฌธ์ œ๋Š” BC ๋ธŒ๋ ˆ์ดํฌ๊ฐ€ ๊ฝค ํฌ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์˜ต์…˜ 2์˜ ์ฃผ์š” ๋ฌธ์ œ๋Š” ์š”์†Œ ์—…๊ทธ๋ ˆ์ด๋“œ๊ฐ€ ์™„๋ฃŒ๋œ ์‹œ์ ์— ๋”ฐ๋ผ ๊ฒฝ์Ÿ ์กฐ๊ฑด์ด ์žˆ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. React๋งŒํผ ๋„๋ฆฌ ์‚ฌ์šฉ๋˜๋Š” ํ”„๋กœ์ ํŠธ์— ๋‘˜ ์ค‘ ํ•˜๋‚˜๊ฐ€ ์ง„์ •์œผ๋กœ ์ˆ˜์šฉ ๊ฐ€๋Šฅํ•œ์ง€ ํ™•์‹ ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

์˜ต์…˜ 5์˜ ๊ฐ€์šฉ์„ฑ์„ ๊ฐ์•ˆํ•  ๋•Œ ์˜ต์…˜ 5๊ฐ€ ์•„๋‹Œ ์‚ฌ์šฉ์„ ํ›จ์”ฌ ๋” ์•ˆ์ „ํ•˜์ง€๋งŒ ์—ฌ์ „ํžˆ ์œ ์šฉํ•˜๊ฒŒ ๊ฐœ์„ ํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ๊ถ๊ธˆํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ์˜ต์…˜ 4์˜ ์—ญ์€ ์–ด๋–ป์Šต๋‹ˆ๊นŒ: domProperties ๋ฐ eventListeners ์†Œํ’ˆ์„ ๋„์ž…ํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

<x-foo 
  my-attr1={...} 
  domProperties={{myRichDataProperty: ...}} 
  eventListeners={{'a-custom-element-event':  e => console.log('yo')}} 
/>

๋Œ€๋ฌธ์ž๋กœ ์ธํ•ด domProperties ๋ฐ eventListeners ๋Š” ์œ ํšจํ•œ ์†์„ฑ ์ด๋ฆ„ ์ด ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ด๊ฒƒ์€ ์™„์ „ํžˆ ์—ญํ˜ธํ™˜

BC๋ฅผ ๋ณด์กดํ•˜๋Š” ๊ฒƒ ์™ธ์—๋„ ์ด ์ ‘๊ทผ ๋ฐฉ์‹์€ ์ดํ•ดํ•˜๊ธฐ ์‰ฝ์Šต๋‹ˆ๋‹ค. ์†์„ฑ ์ค‘์‹ฌ(React props๊ฐ€ ์š”์†Œ ์†์„ฑ์œผ๋กœ ์ฒ˜๋ฆฌ๋จ์„ ์˜๋ฏธ)์œผ๋กœ, ์š”์†Œ ์ด๋ฆ„ ์ž์ฒด๊ฐ€ ๋ชจ๋‘ ์†Œ๋ฌธ์ž์ด๊ณ  ๋Œ€์‹œ๊ฐ€ ์žˆ์œผ๋ฏ€๋กœ HTML ์ค‘์‹ฌ์ด๋ผ๋Š” ์ ์„ ๊ฐ์•ˆํ•  ๋•Œ ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ domProperties ๋Š” ๋ฆฌ์น˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๊ฒƒ๊ณผ ๊ฐ™์ด ์†์„ฑ์„ ์ „๋‹ฌํ•ด์•ผ ํ•˜๋Š” ๋น„๊ต์  ๋“œ๋ฌธ ๊ฒฝ์šฐ๋ฅผ ์œ„ํ•ด ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค.

๋ฉ˜ํƒˆ ๋ชจ๋ธ์„ ์†์„ฑ ์ค‘์‹ฌ์œผ๋กœ ์ „ํ™˜ํ•˜๋ ค๋Š” ์‚ฌ๋žŒ๋“ค(์˜ต์…˜ 1)์„ ์œ„ํ•ด ์˜ต์…˜ 5 ์Šคํƒ€์ผ API๊ฐ€ ํ•„์š”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

const XFoo = ReactDOM.customElement('x-foo');
<XFoo prop1={} prop2={} data-foo={} aria-label={} />

์ด ๊ตฌ๋ฌธ์„ ์‚ฌ์šฉํ•˜๋ฉด ๋ชจ๋“  ์†Œํ’ˆ์ด ์†์„ฑ์œผ๋กœ ์ฒ˜๋ฆฌ๋ฉ๋‹ˆ๋‹ค(์˜ต์…˜ 1). "name"(XFoo) ์š”์†Œ๋„ JS ์ค‘์‹ฌ ๊ทœ์น™์„ ๋”ฐ๋ฅด๊ธฐ ๋•Œ๋ฌธ์— ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค. ๋‚˜๋Š” ์šฐ๋ฆฌ๊ฐ€ ์ตœ์†Œํ•œ data-* ๋ฐ aria-* props๋ฅผ ์†์„ฑ์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๊ธฐ๋ฅผ ์›ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์ด ์†์„ฑ๋งŒ ์ œํ•œํ•˜๊ฑฐ๋‚˜ ๋Œ€์‹œ๊ฐ€ ์žˆ๋Š” ๋ชจ๋“  prop์„ ์†์„ฑ์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๋„๋ก ์ผ๋ฐ˜ํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ธฐ์ธํ•˜๋‹ค.

ํ•œํŽธ, SSR์˜ ์˜ต์…˜ 5 ๊ตฌ์„ฑ์„ ์ง€์›ํ•˜๊ธฐ ์œ„ํ•ด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ตฌ์„ฑ API๋ฅผ ReactDOM.customElement ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

const XFoo = ReactDOM.customElement('x-foo', ssrConfiguration);

์•„๋งˆ๋„ ssrConfiguration ๋Š” @treshugart ์˜ ์ฝ”๋ฉ˜ํŠธ ์— ์žˆ๋Š” ReactDOM.setAttribute ์™€ ์œ ์‚ฌํ•œ ์ฝœ๋ฐฑ ํ•จ์ˆ˜๊ฐ€ ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

์–ด๋–ป๊ฒŒ ์ƒ๊ฐํ•˜๋‚˜์š”?

@effulgentsia ๋‚˜๋Š” ๋‹น์‹ ์˜ ์ƒ๊ฐ์ด ์–ด๋””๋กœ ๊ฐ€๋Š”์ง€ ์ข‹์•„ํ•ฉ๋‹ˆ๋‹ค. ์•ฝ๊ฐ„์˜ ์ด๋ฆ„ ๋ณ€๊ฒฝ: domProps / domEvents . ์ด๊ฒƒ์€ ์˜ต์…˜ 4์— ๋งค์šฐ ๊ฐ€๊น์Šต๋‹ˆ๋‹ค.

WRT SSR, ๋‚˜๋Š” React๊ฐ€ ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ์ถ”์ ํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ ์ž์ฒด์ ์œผ๋กœ ๋ณ€๊ฒฝ๋˜๋Š” ์†์„ฑ์„ ์กด์ค‘ํ•  ์ˆ˜ ์žˆ๋Š” ํ•œ ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ ์ž์ฒด์—์„œ SSR์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์ด์ „์— ์š”์ง€๋ฅผ ๊ฒŒ์‹œํ–ˆ์ง€๋งŒ ํŽธ์˜์ƒ ๋‹ค์‹œ ์—ฌ๊ธฐ์— ์žˆ์Šต๋‹ˆ๋‹ค. https://gist.github.com/treshugart/6eff0da3c0bea886bb56589f743b78a6. ๊ธฐ๋ณธ์ ์œผ๋กœ ๊ตฌ์„ฑ ์š”์†Œ๋Š” ์„œ๋ฒ„์—์„œ ๋ Œ๋”๋งํ•œ ํ›„ ์†์„ฑ์„ ์ ์šฉํ•˜๊ณ  ํด๋ผ์ด์–ธํŠธ์—์„œ ๋‹ค์‹œ ์ˆ˜ํ™”ํ•ฉ๋‹ˆ๋‹ค. ์›น ๊ตฌ์„ฑ ์š”์†Œ์— ๋Œ€ํ•œ SSR์€ ๊ฐ€๋Šฅํ•˜์ง€๋งŒ ์†”๋ฃจ์…˜์€ ์—ฌ์ „ํžˆ โ€‹โ€‹ํ‘œ์ค€ ์ˆ˜์ค€์—์„œ ๋…ผ์˜๋˜๊ณ  ์žˆ์œผ๋ฏ€๋กœ ์ œ์•ˆ์˜ ์ด ๋ถ€๋ถ„์„ ๊ธฐ๋‹ค๋ฆฌ๋Š” ๊ฒƒ์ด ๊ฐ€์žฅ ์ข‹์Šต๋‹ˆ๋‹ค.

@effulgentsia ๋‚˜๋„ ๋‹น์‹ ์ด ํ–ฅํ•˜๊ณ  ์žˆ๋Š” ๊ณณ์ด ์ข‹์•„์š”. @sophiebits , @gaearon do
์ด ๋ฐฉํ–ฅ์— ๋Œ€ํ•œ ์ƒ๊ฐ์ด ์žˆ์œผ์‹ ๊ฐ€์š”?

2017๋…„ 10์›” 31์ผ ํ™”์š”์ผ ์˜คํ›„ 7์‹œ 33๋ถ„ Trey Shugart [email protected] ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ผ์Šต๋‹ˆ๋‹ค.

@effulgentsia https://github.com/effulgentsia ๋‚˜๋Š” ๋‹น์‹ ์˜ ์œ„์น˜๋ฅผ โ€‹โ€‹์ข‹์•„ํ•ฉ๋‹ˆ๋‹ค
์ƒ๊ฐ์ด ๊ฐ€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฆ„์„ ์•ฝ๊ฐ„ ๋ณ€๊ฒฝํ•˜๋ฉด ์œ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
domProps / domEvents ๋“ฑ์˜ ์ด๋ฆ„์„ ์ •๋ ฌํ•ฉ๋‹ˆ๋‹ค.

WRT ์˜ต์…˜ 2, ์ตœ์†Œํ•œ ์ด์ „ ๋ฒ„์ „๊ณผ ํ˜ธํ™˜๋˜๋ฉฐ ๋Œ€๋ถ€๋ถ„์˜ ์‚ฌ์šฉ ์‚ฌ๋ก€๋ฅผ ํ•ด๊ฒฐํ•ฉ๋‹ˆ๋‹ค.
๊ทธ๋Ÿฌ๋‚˜ ๋‚˜๋Š” ๋Œ€์•ˆ์„ ์ œ์‹œํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

๋‚˜๋Š” SSR์ด
React๋Š” ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ๋ณ€๊ฒฝ๋˜๋Š” ์†์„ฑ์„ ์กด์ค‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๊ทธ๋“ค์„ ์ถ”์ ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ „์— ์š”์ ์„ ๊ฒŒ์‹œํ–ˆ์ง€๋งŒ ์—ฌ๊ธฐ์— ๋‹ค์‹œ ์žˆ์Šต๋‹ˆ๋‹ค.
ํŽธ์˜:
https://gist.github.com/treshugart/6eff0da3c0bea886bb56589f743b78a6.
๊ธฐ๋ณธ์ ์œผ๋กœ ๊ตฌ์„ฑ ์š”์†Œ๋Š” ์„œ๋ฒ„์—์„œ ๋ Œ๋”๋งํ•œ ํ›„ ์†์„ฑ์„ ์ ์šฉํ•ฉ๋‹ˆ๋‹ค.
ํด๋ผ์ด์–ธํŠธ์— ๋‹ค์‹œ ์ˆ˜๋ถ„์„ ๊ณต๊ธ‰ํ•ฉ๋‹ˆ๋‹ค. ์›น ์ปดํฌ๋„ŒํŠธ์šฉ SSR์€ ๊ฐ€๋Šฅํ•˜์ง€๋งŒ
์†”๋ฃจ์…˜์€ ์—ฌ์ „ํžˆ โ€‹โ€‹ํ‘œ์ค€ ์ˆ˜์ค€์—์„œ ๋…ผ์˜๋˜๊ณ  ์žˆ์œผ๋ฏ€๋กœ
์—ฌ๊ธฐ์—์„œ ์ œ์•ˆ์˜ ์ด ๋ถ€๋ถ„์„ ๊ธฐ๋‹ค๋ฆฌ๋Š” ๊ฒƒ์ด ๊ฐ€์žฅ ์ข‹์Šต๋‹ˆ๋‹ค.

โ€”
๋‹น์‹ ์ด ์–ธ๊ธ‰๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ด๊ฒƒ์„ ๋ฐ›๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
์ด ์ด๋ฉ”์ผ์— ์ง์ ‘ ๋‹ต์žฅํ•˜๊ณ  GitHub์—์„œ ํ™•์ธํ•˜์„ธ์š”.
https://github.com/facebook/react/issues/11347#issuecomment-340960798 ,
๋˜๋Š” ์Šค๋ ˆ๋“œ ์Œ์†Œ๊ฑฐ
https://github.com/notifications/unsubscribe-auth/ABBFDeiQhBWNGXNplbVV1zluYxT-ntFvks5sx9hngaJpZM4QD3Zn
.

์ด๋ฆ„์„ ์•ฝ๊ฐ„ ๋ณ€๊ฒฝ: domProps / domEvents.

๋‚˜๋Š” ๊ทธ๊ฒƒ๋“ค์„ ์ข‹์•„ํ•œ๋‹ค. ๋˜ํ•œ "dom"์˜ ๊ฐœ๋…์„ "ref"์˜ ๊ฐœ๋…์œผ๋กœ ๋Œ€์ฒดํ•˜์—ฌ React์— ๋” ๊ด€์šฉ์ ์œผ๋กœ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ๋Š”์ง€ ๋ธŒ๋ ˆ์ธ์Šคํ† ๋ฐ ์ค‘์ž…๋‹ˆ๋‹ค. ์ฆ‰, refProps / refEvents "ref"์— ์†Œํ’ˆ ๋ฐ ์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ๋ฅผ ์—ฐ๊ฒฐํ•˜๋Š” ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  this.props ๋‚ด๋ถ€์— ์ƒˆ๋กœ์šด ํŠน์ˆ˜ ์ด๋ฆ„์„ ๋„์ž…ํ•˜๋Š” ๋Œ€์‹  ๊ธฐ์กด ref JSX ์†์„ฑ์„ ์˜ค๋ฒ„๋กœ๋“œํ•˜๋ฉด ์–ด๋–จ๊นŒ ํ•˜๋Š” ์ƒ๊ฐ์ด ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค. ํ˜„์žฌ "ref"๋Š” React ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋งˆ์šดํŠธ ๋ฐ ๋งˆ์šดํŠธ ํ•ด์ œ๋  ๋•Œ ํ˜ธ์ถœ๋˜๋Š” ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค. ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ฐ์ฒด๋„ ํ—ˆ์šฉํ•˜๋ฉด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ์š”?

<x-foo my-attr-1={}
  ref={{
    props: ...
    events: ...
    mounted: ...
    unmounted: ...
  }}
/>

๊ทธ๋ƒฅ ์•„์ด๋””์–ด์ž…๋‹ˆ๋‹ค.

์ด ์ ‘๊ทผ ๋ฐฉ์‹์ด ์ •๋ง ๋งˆ์Œ์— ๋“ญ๋‹ˆ๋‹ค. :)

์ด๊ฒƒ์— ๋Œ€ํ•œ ์นœ์ ˆํ•œ ํ•‘. @gaearon @sophiebits @effulgentsia ์˜ ์ตœ๊ทผ ์ œ์•ˆ์— ๋Œ€ํ•ด ์˜๊ฒฌ์ด ์žˆ์œผ์‹  ๊ฐ€์š”? ๊ทธ๊ฒƒ์ด ์•ผ๊ตฌ์žฅ์— ์žˆ๋Š”์ง€ ์•„๋‹ˆ๋ฉด ๋น„์Šคํƒ€ํ„ฐ์— ์žˆ๋Š”์ง€ ๊ถ๊ธˆํ•ฉ๋‹ˆ๋‹ค.

RFC ํ”„๋กœ์„ธ์Šค๋ฅผ ๋ฐฉ๊ธˆ ์—ด์—ˆ์Šต๋‹ˆ๋‹ค. RFC๋กœ ์ œ์ถœํ•˜๋„๋ก ์š”์ฒญํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?
https://github.com/reactjs/rfcs

domProperties ๋ฐ eventListeners "props"(๋˜๋Š” ref={{}} ๊ฐ์ฒด ๋‚ด์—์„œ ์ด์— ์ƒ์‘ํ•˜๋Š” ๊ฒƒ)๋ฅผ ์ถ”๊ฐ€ํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ์™œ๋ƒํ•˜๋ฉด ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋‹ค๋ฅธ ๋ชจ๋“  React ๊ตฌ์„ฑ ์š”์†Œ์™€ ๋‹ฌ๋ฆฌ ๋งค์šฐ ๋ถ€์ž์—ฐ์Šค๋Ÿฝ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๊ตฌ์„ฑ ์š”์†Œ ์‚ฌ์šฉ์ž๊ฐ€ ์†์„ฑ๊ณผ ์†์„ฑ ๋“ฑ์˜ ์ฐจ์ด์ ์„ ์ •ํ™•ํžˆ ์•Œ์•„์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ์—๋Š” ReactDOM.createCustomElementType ์Šคํƒ€์ผ ์†”๋ฃจ์…˜์œผ๋กœ ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์ •ํ™•ํžˆ ํ•œ ๋ฒˆ ์‚ฌ์šฉํ•˜๋ฉด ๋น„์Šทํ•œ ์ž‘์—…๋Ÿ‰(๊ตฌ์„ฑ์„ ์ง€์ •ํ•œ ๋‹ค์Œ ํ•œ ๋ฒˆ ์‚ฌ์šฉ)์ด์ง€๋งŒ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์—ฌ๋Ÿฌ ๋ฒˆ ์‚ฌ์šฉํ•˜๋ฉด ๊ตฌ์„ฑ ๊ฐœ์ฒด์— ๋Œ€ํ•ด ๋งค๋ฒˆ ์ƒ๊ฐํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ๋งค๋ฒˆ ๊ตฌ์„ฑ์„ ์ง€์ •ํ•˜๋„๋ก ์š”๊ตฌํ•˜๋Š” ๊ฒƒ์€ ๋‚ด๊ฐ€ ๋ญ”๊ฐ€๋ฅผ ๋†“์น˜๊ณ  ์žˆ์ง€ ์•Š๋Š” ํ•œ ๊นจ๋—ํ•œ ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ ํ†ตํ•ฉ์„ ๊ฐ–๋Š” ๋ชฉํ‘œ๋ฅผ ๋ฌดํšจํ™”ํ•˜๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

@sophiebits ์ข‹์•„, ๊ทธ๋Ÿฐ ์‹์œผ๋กœ RFC๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. 10์›” 26์ผ ์— ์ฒ˜์Œ์œผ๋กœ ์†์„ฑ์„ ํด๋ผ์ด์–ธํŠธ ์ธก์œผ๋กœ ์ด๋™ํ•˜๊ณ  ์‚ฌ๋žŒ๋“ค์ด SSR์— ๋Œ€ํ•ด ReactDOM.createCustomElementType์„ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๊ฑฐ๋‚˜ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์†์„ฑ/์†์„ฑ์„ ๋งคํ•‘ํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์ •๋ง ์„ธ๋ถ„ํ™”๋œ ์ œ์–ด๋ฅผ ์›ํ•˜๋Š” ๊ฒฝ์šฐ์— ๋Œ€ํ•ด ์–ด๋–ป๊ฒŒ ์ƒ๊ฐํ•˜์‹ญ๋‹ˆ๊นŒ? ?

์ตœ์†Œํ•œ createCustomElementType ์Šคํƒ€์ผ์„ ์‚ฌ์šฉํ•˜๋ฉด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ API๋ฅผ ์‰ฝ๊ฒŒ ๋งคํ•‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ฆ‰, ์šฐ๋ฆฌ์˜ skatejs/renderer-react๋Š” props ์‰ฝ๊ฒŒ ๋ฐ›์•„ React์— ๋Œ€ํ•œ ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ๋ฅผ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฐ ์ข…๋ฅ˜์˜ ๋ฐ”๋‹๋ผ ์‚ฌ๋žŒ๋“ค์€ ์ถ”์ƒํ™” ๋˜๋Š” ์•ฝ๊ฐ„์˜ ์ž‘์—… ์—†์ด๋„ ๋†’๊ณ  ๊ฑด์กฐํ•ฉ๋‹ˆ๋‹ค. ๋‚˜๋Š” ์„ธ๋ถ„ํ™”๋œ ์ œ์–ด๋ฅผ ํ—ˆ์šฉํ•˜๋ฉด์„œ ์•ˆ์ „ํ•œ ๊ธฐ๋ณธ๊ฐ’์— ๋Œ€ํ•œ Rob์˜ ์ œ์•ˆ์„ ์ข‹์•„ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๊ฒŒ ํšจ๊ณผ๊ฐ€ ์žˆ์„๊นŒ์š”?

@robdodson ๋‚˜๋Š” ๊ทธ๊ฒƒ์—

์˜ต์…˜ 3์€ ์ง€๊ธˆ๊นŒ์ง€ ์ตœ๊ณ ์˜ ์˜ต์…˜์ด๋ฉฐ SSR๊ณผ ํ•จ๊ป˜ ์ž‘๋™ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฐฉ๋ฒ•์— ๋Œ€ํ•œ ์•„์ด๋””์–ด๋ฅผ ์„ค๋ช…ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

์ง€๊ธˆ๊นŒ์ง€ 3๊ฐœ๋ฅผ ์ œ์™ธํ•œ ๋ชจ๋“  ์˜ต์…˜์„ ๋‹จ๋…์œผ๋กœ,

  • React ์†Œ์Šค ์™ธ๋ถ€์˜ ๋ชจ๋“  ์‚ฌ๋žŒ์—๊ฒŒ ๋†’์€ ์œ ์ง€ ๊ด€๋ฆฌ ๋ถ€๋‹ด์„ ๊ฐ€์ค‘์‹œํ‚ค๊ฑฐ๋‚˜
  • ๋˜๋Š” ์ „์ฒด ์šฐ์ฃผ์˜ ๋ชจ๋“  ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ ์ž‘์„ฑ์ž๊ฐ€ React ๊ด€๋ จ ๊ทœ์น™์„ ๋”ฐ๋ฅด๋„๋ก ๊ฐ•์ œํ•ฉ๋‹ˆ๋‹ค.

๋‹ค์Œ์€ ์šฐ๋ฆฌ ๋ชจ๋‘๊ฐ€ ๋™์˜ํ•˜๋Š” ๋ณดํŽธ์ ์ธ ๊ทœ์น™์ž…๋‹ˆ๋‹ค.

  • setAttribute ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํŠน์„ฑ์„ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์€ ์„ ์–ธ์  HTML ํŠน์„ฑ๊ณผ 1:1๋กœ ์ผ์น˜ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์š”์†Œ์— ์ „๋‹ฌํ•˜๋Š” ๊ฐ€์žฅ ํ‘œ์ค€์ ์ธ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ์šฐ์ฃผ์˜ ๋ฒ•์น™์œผ๋กœ ํ•ญ์ƒ 100% ์ž‘๋™ํ•ด์•ผ ํ•˜๋ฏ€๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์š”์†Œ์— ์ „๋‹ฌํ•˜๋Š” ์œ ์ผํ•œ 100% ๋ณด์žฅ๋œ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.
  • ์–ด๋–ค ์‚ฌ๋žŒ๋“ค์€ ๊ทธ๊ฒƒ์ด ๋ฌธ์ž์—ด๋งŒ์„ ์œ„ํ•ด ์„ค๊ณ„๋œ ๊ฒƒ์— ๋งŒ์กฑํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  • ์ผ๋ถ€ ์š”์†Œ(๋‚˜๋Š” _์ผ๋ถ€ ์š”์†Œ๋งŒ_ ๋ฐ˜๋ณต)๋Š” ํŠน์ • ์†์„ฑ์— ๋งคํ•‘๋˜๋Š” ๊ฐœ์ฒด ์†์„ฑ์„ ํ†ตํ•ด ๊ฐ’์„ ํ—ˆ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ 100% ์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด _ ์•„๋‹™๋‹ˆ๋‹ค _.
  • ์–ด๋–ค ์‚ฌ๋žŒ๋“ค์€ ๋น„๋ฌธ์ž์—ด์„ ๋ฐ›์•„๋“ค์ผ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ์ฒด ์†์„ฑ์„ ์ข‹์•„ํ•ฉ๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ์ตœ์†Œํ•œ React๊ฐ€ _์šฐ์ฃผ์˜ ๋ชจ๋“  ๋‹จ์ผ ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ๋กœ 100% ์ž‘๋™ํ•˜๊ณ 

  • React๋Š” ๊ทธ๊ฒƒ์ด ์‹ ์ด ์•„๋‹ˆ๋ผ๋Š” ๊ฒƒ์„ ๊นจ๋‹ฌ์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์‚ฌ๋žŒ๋“ค์ด react ์™ธ์— ์‚ฌ์šฉํ•˜๋Š” ๋‹ค๋ฅธ ๋งŽ์€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๋”ฐ๋ผ์„œ ๋ฐ˜์ž‘์šฉ ์ƒค ์šฐ๋“œ _by default_ ๋‹จ์ง€ ํ†ตํ•ด ๋ฐ์ดํ„ฐ ์ „๋‹ฌ setAttribute ์ฆ‰ 100 % ํ‘œ์ค€ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.
  • ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ ์ €์ž / ์—ฐ์žฅ ๋ฎ์–ด ์“ธ ์ˆ˜ ์žˆ๋‹ค๋Š” ์‚ฌ์‹ค์„ ๋ฐ›์•„ ๋“ค์—ฌ์•ผ ๋ฐ˜์‘ setAttribute ๋งŒ๋“ค๊ณ , ์ž์‹ ์˜ ํด๋ž˜์Šค ์ •์˜ ๋ฉ”์†Œ๋“œ๋ฅผ setAttribute ๋ฌธ์ž์—ด์ด ์•„๋‹Œ ๋‹ค๋ฅธ ์ผ์„ ๋™์˜ํ•ฉ๋‹ˆ๋‹ค. ๋Œ€ํ‘œ์ ์ธ ์˜ˆ๋กœ A-frame๊ณผ ๊ฐ™์€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • React๋Š” ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ ์ž‘์„ฑ์ž๊ฐ€ ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ๊ฐ€ _React๋ฟ๋งŒ ์•„๋‹ˆ๋ผ_ ๋ชจ๋“  ๊ฐ€๋Šฅํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์™€ ํ•จ๊ป˜ ์ž‘๋™ํ•˜๊ธฐ๋ฅผ ์›ํ•˜๋Š” ๊ฒฝ์šฐ ํ•ด๋‹น ์ž‘์„ฑ์ž๋Š” setAttribute ์— ์˜์กดํ•˜์—ฌ ๊ธฐ๋ณธ์ ์œผ๋กœ ๋ชจ๋“  ๊ฒƒ๊ณผ ํ˜ธํ™˜๋˜๋Š” ์š”์†Œ๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒ์„ ์ˆ˜๋ฝ ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋ชจ๋“  ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์†์„ฑ์— ์˜์กดํ•˜๋ฉด ์ „์ฒด ์œ ๋‹ˆ๋ฒ„์Šค๊ฐ€ ์„œ๋กœ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. _์ด๊ฒƒ์— ๋Œ€ํ•ด ์–ด๋–ค ๊ฒฝ์šฐ๋„ ์—†๊ณ , ๋ฐ˜๋Œ€๋„ ์—†์Šต๋‹ˆ๋‹ค!_ (w3c/whatwg๊ฐ€ ์•ฝ๊ฐ„์˜ ํฐ ๋ณ€๊ฒฝ์„ ๊ฐ€ํ•˜์ง€ ์•Š๋Š” ํ•œ)

Soooooooo , ์ฆ‰, ์šฐ๋ฆฌ๋Š” ์ตœ์†Œํ•œ

  • https://github.com/facebook/react/issues/10070 ์ˆ˜์ • (๋‚ด๊ฐ€ ๋ฆฌ๋””๋ ‰์…˜ ๋œ ๊ณณ)
  • ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ํ‘œ์ค€์— ๋” ๊ฐ€๊นŒ์›Œ์ง‘๋‹ˆ๋‹ค.

๊ทธ๋Ÿฐ ๋‹ค์Œ ๋•Œ๋•Œ๋กœ ๊ฐ์ฒด ์†์„ฑ API๊ฐ€ ์žˆ๋Š” ์š”์†Œ์˜ ์˜๋ฏธ์— ๋Œ€ํ•ด ์ƒ๊ฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ๊ฐœ๋ฐœ์ž๋Š” setAttribute ๊ฐ€ ํ•ญ์ƒ ์ž‘๋™ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ณ  ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๊ฐœ๋ฐœ์ž๋Š” ๋•Œ๋•Œ๋กœ ๊ฐœ์ฒด ์†์„ฑ์„ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๊ฐœ๋ฐœ์ž๋Š” ํ•ญ์ƒ ์ฃผ์–ด์ง„ ์š”์†Œ(์‚ฌ์šฉ์ž ์ง€์ • ์—ฌ๋ถ€)์— ๋Œ€ํ•ด ๊ฐœ์ฒด ์†์„ฑ ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ์กด์žฌํ•˜๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ์•Œ๊ณ  ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • ๊ฐ์ฒด ์†์„ฑ ์ธํ„ฐํŽ˜์ด์Šค๋Š” ์†์„ฑ๊ณผ 1:1๋กœ ๋งคํ•‘ํ•  ํ•„์š”๊ฐ€ ์—†๋Š” ๋Œ€์ฒด ์ธํ„ฐํŽ˜์ด์Šค์ž…๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ์†์„ฑ๊ณผ ์†์„ฑ์— ๋Œ€ํ•œ ์ด๋Ÿฌํ•œ ์ง€์‹์„ ๋ฐ”ํƒ•์œผ๋กœ _ํ‘œ์ค€์„ 100% ํ™•์žฅํ•˜๊ณ  ์šฐ์ฃผ์˜ ๋ฒ•์น™์„ ์กด์ค‘ํ•˜๊ธฐ ๋ฅผ ๊ณผ ๊ฐ™์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค.

  1. ์†์„ฑ์ด ๊ธฐ๋ณธ์ ์œผ๋กœ 100% ์ž‘๋™ํ•˜๋„๋ก ํ—ˆ์šฉํ•ฉ๋‹ˆ๋‹ค. ๊ทธ์ด ์ˆ˜๋‹จ <x-foo blah="blah" /> ์— default_์ง€๋„ _byํ•œ๋‹ค setAttribute ํ•˜๊ณ  _unchanged_ ๋”ฐ๋ผ ๊ฐ’์„ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ์ค‘๋‹จ๋˜์ง€ ์•Š๋Š” ๋ณ€๊ฒฝ ์‚ฌํ•ญ์ž…๋‹ˆ๋‹ค. ์‚ฌ์‹ค, ์ด๋Š” ์˜๋ฏธ ์—†๋Š” "[object Object]" ๋ฌธ์ž์—ด์ด ์ „๋‹ฌ๋˜๋Š” ๊ฒฐ๊ณผ๋ฅผ ์ดˆ๋ž˜ํ•˜๋Š” ์ˆ˜์ • ๋ณ€๊ฒฝ ์‚ฌํ•ญ์ž…๋‹ˆ๋‹ค.
  2. ์‚ฌ์šฉ์ž๊ฐ€ ์–ด๋–ค ๊ฐ์ฒด ์†์„ฑ ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ์กด์žฌํ•˜๋Š”์ง€ ์•Œ๊ณ  ์žˆ๊ณ  ์ด๋Ÿฌํ•œ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๋ ค๋Š” ๊ฒฝ์šฐ React ์‚ฌ์šฉ์ž๊ฐ€ _ props๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก ํ•˜๋Š” ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์„ ์ƒ๊ฐํ•ด

sigil์„ ์‚ฌ์šฉํ•˜๋Š” ์˜ต์…˜ 3(์ถ”๊ฐ€ ๊ตฌ๋ฌธ์€ ์†”์งํžˆ ๋ฐฐ์šฐ๊ธฐ ์–ด๋ ต์ง€ ์•Š์Œ)์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ด์ƒ์— ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ์†”๋ฃจ์…˜์ธ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์ด SO ์งˆ๋ฌธ์— ๋”ฐ๋ฅด๋ฉด ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์œ ์ผํ•œ ๊ธฐํ˜ธ๋Š” = ์ด์ง€๋งŒ & ( \& ์™€ ๊ฐ™์€ ์ด์Šค์ผ€์ดํ”„ ๊ฐ€๋Šฅํ•œ ํ˜•์‹ ์‚ฌ์šฉ)์™€ ๊ฐ™์€ ํ•ญ๋ชฉ์— ์ •์ฐฉํ•˜๋Š” ๊ฒƒ์ด ๋” ์ฝ๊ธฐ ์‰ฝ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๊ตฌ์ฒด์ ์œผ๋กœ ์†Œํ’ˆ์„ ์›ํ•˜๋Š” ๊ฒฝ์šฐ:

<x-foo &blah="blah" />

WHATWG HTML ๊ตฌ๋ฌธ ์‚ฌ์–‘์—์„œ ๋‹ค๋ฃจ๋Š” ๋Œ€๋ถ€๋ถ„์˜ ๋‹ค๋ฅธ ๋ฌธ์ž๋Š” ์ž‘๋™ํ•ด์•ผ ํ•˜๋ฉฐ ์ž‘๋™ํ•˜๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ด๋Š” ๋‹ค๋ฅธ ์ฃผ์ œ์ž…๋‹ˆ๋‹ค.

์˜ต์…˜ 3์€ ์ง€๊ธˆ๊นŒ์ง€ ์ตœ๊ณ ์˜ ์˜ต์…˜์ž…๋‹ˆ๋‹ค.

ํด๋ผ์ด์–ธํŠธ์—์„œ ์ˆ˜ํ™”๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ๋”ฐ๋ผ์„œ ์†Œํ’ˆ์ด SSR์—์„œ ์˜๋ฏธ๊ฐ€ ์—†๋‹ค๋ฉด ์˜ค ๊ธ€์Ž„์š”. ์ด์ „์—๋Š” ์ž‘๋™ํ•˜์ง€ ์•Š์•˜์œผ๋ฉฐ ์ง€๊ธˆ์€ ์ž‘๋™ํ•˜์ง€ ์•Š์•„๋„ ๋ฉ๋‹ˆ๋‹ค. PHP ์Šคํƒ€์ผ ๋˜๋Š” Java ์Šคํƒ€์ผ SSR์€ ์ˆ˜ํ™” ์—†์ด ์ •์  HTML์„ ์ „์†กํ•˜๋ฉฐ ์†์„ฑ์— 100% ์˜์กดํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, React SSR์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ ํด๋ผ์ด์–ธํŠธ ์ธก ์ˆ˜ํ™”๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์ˆ˜ํ™”๋ฅผ ์›ํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ ์ด ๊ฒฝ์šฐ props๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์•„์•ผ ํ•œ๋‹ค๋Š” ์‚ฌ์‹ค์„ ์•Œ๊ณ  ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. _ ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค. ๋ฐ˜์‘ํ•ด์•ผ ํ•  ๋ชจ๋“  ๊ฒƒ์€ ๋ฌธ์„œ์—์„œ ์ด ๊ฒฝ๊ณ ๋ฅผ ๋ช…ํ™•ํ•˜๊ฒŒ ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค._

ํ•˜์ง€๋งŒ!!! ๊ทธ๊ฒŒ ๋‹ค๊ฐ€ ์•„๋‹ˆ์•ผ! ์‚ฌ๋žŒ๋“ค์—๊ฒŒ ๋” ๋งŽ์€ ์ œ์–ด ๊ถŒํ•œ์„ ์ œ๊ณตํ•˜๊ธฐ ์œ„ํ•ด ์—ฌ์ „ํžˆ ์˜ต์…˜ 5์˜ ๊ธฐ๋Šฅ์„ ํฌํ•จํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ต์…˜ 5์™€ ๊ฐ™์€ API๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด

  • ์–ด๋–ค ์‚ฌ๋žŒ๋“ค์€ ์ผ๋ถ€ ์†์„ฑ์ด props์— ๋งคํ•‘๋˜๋Š” ๋ฐฉ๋ฒ•์„ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๊ทธ๋ฆฌ๊ณ  ์ผ๋ถ€ ์†Œํ’ˆ์ด ์†์„ฑ์— ๋งคํ•‘๋˜๋Š” ๋ฐฉ๋ฒ•. ์ด๊ฒƒ์€ ์‚ฌ๋žŒ๋“ค์ด SSR์ด ์ˆ˜ํ™”๋˜์ง€ ์•Š์€ ์œ ํ˜•์˜ SSR์—๋„ ์ž‘๋™ํ•˜๋„๋ก ๋„์šธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค!
  • ์šฐ๋ฆฌ๋Š” ์‚ฌ๋žŒ๋“ค์ด "์ด ์†์„ฑ์ด ์ž‘์„ฑ๋˜๋ฉด ์‹ค์ œ๋กœ ์ด prop์— ์ „๋‹ฌํ•˜์ง€๋งŒ SSR์ธ ๊ฒฝ์šฐ์—๋Š” prop์— ์ „๋‹ฌํ•˜์ง€ ๋งˆ์‹ญ์‹œ์˜ค" ๋˜๋Š” "SSR ๋™์•ˆ์—๋งŒ ์ด ์†์„ฑ์— ์ด prop์„ ์ „๋‹ฌํ•˜๊ณ  ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ๋ฌด์—‡์„ ํ•ฉ๋‹ˆ๊นŒ?"๋ผ๊ณ  ์ •์˜ํ•˜๋„๋ก ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. sigil" ๋“ฑ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ง€์ •ํ–ˆ์Šต๋‹ˆ๋‹ค.

๊ฒฐ๊ตญ ๋‹ค์Œ์€ ์ž‘๋™ํ•˜๋Š” ์†”๋ฃจ์…˜์ฒ˜๋Ÿผ ๋ณด์ž…๋‹ˆ๋‹ค.

  • setAttribute ์˜ต์…˜ 3์€ ๊ธฐ๋ณธ์ ์œผ๋กœ ๋’ค์—์„œ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
  • React๊ฐ€ ์‚ฌ๋žŒ๋“ค์˜ ๋ฐฉํ•ด๊ฐ€ ๋˜์ง€ ์•Š๋„๋ก #10070์„ ์ˆ˜์ •ํ–ˆ์Šต๋‹ˆ๋‹ค.
  • SSR, ํด๋ผ์ด์–ธํŠธ ๋˜๋Š” ๋‘˜ ๋‹ค๋ฅผ ์กฐ์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ํฌํ•จํ•˜์—ฌ ์‹ค์ œ๋กœ ํ•„์š”ํ•œ ๊ฒฝ์šฐ ์ถ”๊ฐ€ ์กฐ์ •์„ ์œ„ํ•œ ์˜ต์…˜ 5์™€ ๊ฐ™์€ API.

์ƒˆํ•ด ๋ณต ๋งŽ์ด ๋ฐ›์œผ์„ธ์š”!

์œ„์˜ ๋ช‡ ๊ฐ€์ง€ ์‚ฌํ•ญ์— ๋‹ตํ•˜๊ณ  ์‹ถ์ง€๋งŒ ์ด ์Šค๋ ˆ๋“œ๊ฐ€ ์ด๋ฏธ _๋ฏฟ์„ ์ˆ˜ ์—†์„ ์ •๋„๋กœ_ ๊ธธ๋‹ค๋Š” ์‚ฌ์‹ค์ด ๋‘๋ ต์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ๋” ๊ธธ์–ด์ ธ์„œ ์ฃ„์†กํ•ฉ๋‹ˆ๋‹ค :P

๋‹ค์Œ์€ ์šฐ๋ฆฌ ๋ชจ๋‘๊ฐ€ ๋™์˜ํ•˜๋Š” ๋ณดํŽธ์ ์ธ ๊ทœ์น™์ž…๋‹ˆ๋‹ค.

setAttribute๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํŠน์„ฑ์„ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์€ ์„ ์–ธ์  HTML ํŠน์„ฑ๊ณผ 1:1๋กœ ์ผ์น˜ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์š”์†Œ์— ์ „๋‹ฌํ•˜๋Š” ๊ฐ€์žฅ ํ‘œ์ค€์ ์ธ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ์šฐ์ฃผ์˜ ๋ฒ•์น™์œผ๋กœ ํ•ญ์ƒ 100% ์ž‘๋™ํ•ด์•ผ ํ•˜๋ฏ€๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์š”์†Œ์— ์ „๋‹ฌํ•˜๋Š” ์œ ์ผํ•œ 100% ๋ณด์žฅ๋œ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ ์™„์ „ํžˆ ์‚ฌ์‹ค์ด ์•„๋‹™๋‹ˆ๋‹ค. ํ”Œ๋žซํผ์—๋Š” ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ๊ฐ€ ์†์„ฑ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋…ธ์ถœํ•˜๋„๋ก ๊ฐ•์ œํ•˜๋Š” ๊ฒƒ์ด ์—†์Šต๋‹ˆ๋‹ค. JS ์†์„ฑ๋งŒ ํ—ˆ์šฉํ•˜๋Š” ์†์„ฑ์„ ์‰ฝ๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ "๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๋ณด์žฅ๋œ ๋ฐฉ๋ฒ•"์ด ์•„๋‹™๋‹ˆ๋‹ค. ์‹œํ–‰ ๋ฉ”์ปค๋‹ˆ์ฆ˜์ด ์—†๋‹ค๋Š” ๊ฒƒ์€ 100% ํ™•์‹คํ•˜๊ฒŒ ์Šคํƒ€์ผ(HTML ์†์„ฑ ๋˜๋Š” JS ์†์„ฑ)์— ์˜์กดํ•  ์ˆ˜ ์—†๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

์–ด๋–ค ์‚ฌ๋žŒ๋“ค์€ ๊ทธ๊ฒƒ์ด ๋ฌธ์ž์—ด๋งŒ์„ ์œ„ํ•ด ์„ค๊ณ„๋œ ๊ฒƒ์— ๋งŒ์กฑํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
์ผ๋ถ€ ์š”์†Œ(์ผ๋ถ€ ์š”์†Œ๋งŒ ๋ฐ˜๋ณต)๋Š” ํŠน์ • ์†์„ฑ์— ๋งคํ•‘๋˜๋Š” ๊ฐœ์ฒด ์†์„ฑ์„ ํ†ตํ•ด ๊ฐ’์„ ํ—ˆ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ 100% ์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด ์•„๋‹™๋‹ˆ๋‹ค.

์šฐ๋ฆฌ๋Š” ์‚ฌ๋žŒ๋“ค์ด ๊ฐ์ฒด/๋ฐฐ์—ด๊ณผ ๊ฐ™์€ ํ’๋ถ€ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ํ—ˆ์šฉํ•˜๋Š” ์†์„ฑ์— ๋Œ€ํ•œ ์†์„ฑ์„ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ์„ ๊ท€์ฐฎ๊ฒŒ ํ•˜์ง€ ์•Š๋„๋ก ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ์ผ๋ถ€ ๋ฐ์ดํ„ฐ๋ฅผ ์†์„ฑ ๋ฌธ์ž์—ด๋กœ ๋‹ค์‹œ ์ง๋ ฌํ™”ํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๊ฐœ์ฒด ์†์„ฑ ์ค‘ ํ•˜๋‚˜๊ฐ€ DOM ๋…ธ๋“œ์— ๋Œ€ํ•œ ์ฐธ์กฐ์ธ ๊ฒฝ์šฐ ์‹ค์ œ๋กœ ๋ฌธ์ž์—ดํ™”ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ ๊ฐœ์ฒด๋ฅผ ๋ฌธ์ž์—ดํ™”ํ•˜๊ณ  ์žฌ๋ถ„์„ํ•˜๋ฉด ๊ฐœ์ฒด์˜ ID๊ฐ€ ์†์‹ค๋ฉ๋‹ˆ๋‹ค. ์ฆ‰, ๋‹ค๋ฅธ POJO์— ๋Œ€ํ•œ ์ฐธ์กฐ๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ ์™„์ „ํžˆ ์ƒˆ๋กœ์šด ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ํ•ด๋‹น ์ฐธ์กฐ๋ฅผ ์‹ค์ œ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

์–ด๋–ค ์‚ฌ๋žŒ๋“ค์€ ๋น„๋ฌธ์ž์—ด์„ ๋ฐ›์•„๋“ค์ผ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ์ฒด ์†์„ฑ์„ ์ข‹์•„ํ•ฉ๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ React๋Š” 100% ํ‘œ์ค€์ด๊ธฐ ๋•Œ๋ฌธ์— ๊ธฐ๋ณธ์ ์œผ๋กœ setAttribute๋ฅผ ํ†ตํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

JavaScript ์†์„ฑ์€ ํ‘œ์ค€๊ณผ ๋™์ผํ•ฉ๋‹ˆ๋‹ค. ๋Œ€๋ถ€๋ถ„์˜ HTML ์š”์†Œ๋Š” ์†์„ฑ๊ณผ ํ•ด๋‹น ์†์„ฑ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋ชจ๋‘ ๋…ธ์ถœํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ: <img src=""> ๋˜๋Š” HTMLImageElement.src .

React๋Š” Custom Element ์ž‘์„ฑ์ž๊ฐ€ ํด๋ž˜์Šค ์ •์˜์—์„œ setAttribute ๋ฉ”์†Œ๋“œ๋ฅผ ํ™•์žฅ/์žฌ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์‚ฌ์‹ค์„ ๋ฐ›์•„๋“ค์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค. setAttribute๋Š” ๋ฌธ์ž์—ด ์ด์™ธ์˜ ๊ฒƒ์„ ํ—ˆ์šฉํ•ฉ๋‹ˆ๋‹ค.

์ž‘์„ฑ์ž๋Š” ๊ทธ๋ ‡๊ฒŒ ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ์‹ค์ œ๋กœ๋Š” JS ์†์„ฑ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ํ›จ์”ฌ "๋น„ํ‘œ์ค€"์ธ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ ์š”์†Œ ๊ตฌ๋ฌธ ๋ถ„์„ ๋ฐ ๋ณต์ œ์™€ ๊ด€๋ จ๋œ ์ด์ƒํ•œ ๋ฌธ์ œ์— ๋…ธ์ถœ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

React๋Š” ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ ์ž‘์„ฑ์ž๊ฐ€ ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ๊ฐ€ React๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ๋ชจ๋“  ๊ฐ€๋Šฅํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์™€ ํ•จ๊ป˜ ์ž‘๋™ํ•˜๊ธฐ๋ฅผ ์›ํ•˜๋Š” ๊ฒฝ์šฐ ํ•ด๋‹น ์ž‘์„ฑ์ž๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ๋ชจ๋“  ๊ฒƒ๊ณผ ํ˜ธํ™˜๋˜๋Š” ์š”์†Œ๋ฅผ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด setAttribute์— ์˜์กดํ•˜๊ณ  ๊ธฐ๋ณธ์ ์œผ๋กœ ๋ชจ๋“  ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์†์„ฑ์— ์˜์กดํ•˜๋Š” ๊ฒฝ์šฐ ์ˆ˜๋ฝํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. , ๊ทธ๋Ÿฌ๋ฉด ์˜จ ์šฐ์ฃผ๊ฐ€ ์„œ๋กœ ํ˜‘๋ ฅํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด๊ฒƒ์— ๋Œ€ํ•ด์„œ๋Š” if, and, buts๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค! (w3c/whatww๊ฐ€ ํฐ ๋ณ€ํ™”๋ฅผ ์ฃผ์ง€ ์•Š๋Š” ํ•œ)

์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ(์˜ˆ: Angular)์— JS ์†์„ฑ์„ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์„ ์„ ํ˜ธํ•˜๋Š” ๋‹ค๋ฅธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ด ๊ฒฐ๋ก ์— ์–ด๋–ป๊ฒŒ ๋„๋‹ฌํ–ˆ๋Š”์ง€ ์ž˜ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค. ์ตœ๋Œ€์˜ ํ˜ธํ™˜์„ฑ์„ ์œ„ํ•ด ์ž‘์„ฑ์ž๋Š” JS ์†์„ฑ์œผ๋กœ ์†์„ฑ์„ ์ง€์›ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์€ ๊ฐ€๋Šฅํ•œ ์‚ฌ์šฉ์˜ ๊ฐ€์žฅ ํฐ ํ‘œ๋ฉด์ ์„ ๋ฎ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. Polymer๋กœ ์ƒ์„ฑ๋œ ๋ชจ๋“  ์š”์†Œ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ์ด ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

์†์„ฑ์ด ๊ธฐ๋ณธ์ ์œผ๋กœ 100% ์ž‘๋™ํ•˜๋„๋ก ํ—ˆ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค ๊ธฐ๋ณธ์ ์œผ๋กœ setAttribute์— ๋งคํ•‘๋˜๊ณ  ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์€ ๊ฐ’์„ ์ „๋‹ฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ์ค‘๋‹จ๋˜์ง€ ์•Š๋Š” ๋ณ€๊ฒฝ ์‚ฌํ•ญ์ž…๋‹ˆ๋‹ค. ์‚ฌ์‹ค, ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ์˜๋ฏธ ์—†๋Š” "[object Object]" ๋ฌธ์ž์—ด์ด ์ „๋‹ฌ๋˜๋Š” ์ˆ˜์ • ๋ณ€๊ฒฝ ์‚ฌํ•ญ์ž…๋‹ˆ๋‹ค.

๋‚˜๋Š” React๊ฐ€ ์‹ค์ œ๋กœ ๊ฐ’์„ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๊ณ  ์ „๋‹ฌํ•˜๋Š” _is_๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. setAttribute('foo', {some: object}) ํ˜ธ์ถœํ•˜๋ฉด [object Object] ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋“ค์ด ๊ฐœ์ฒด์— ๋Œ€ํ•ด JSON.stringify() ๋ฅผ ํ˜ธ์ถœํ•˜๋„๋ก ์ œ์•ˆํ•˜์ง€ ์•Š๋Š” ํ•œ? ๊ทธ๋Ÿฌ๋‚˜ ๊ทธ ๊ฐ์ฒด๋Š” "๋ณ€๊ฒฝ๋˜์ง€ ์•Š์€" ๊ฒƒ์ด ์•„๋‹™๋‹ˆ๋‹ค. setAttribute() ์„(๋ฅผ) ์žฌ์ •์˜ํ•œ ์ž‘์„ฑ์ž์—๊ฒŒ ์˜์กดํ•˜๊ณ  ์žˆ๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. DOM์„ ์›์ˆญ์ด ํŒจ์น˜ํ•˜๋Š” ๋Œ€์‹  ํ•ด๋‹น JS ์†์„ฑ์„ ์ƒ์„ฑํ•˜๋„๋ก ๊ถŒ์žฅํ•˜๋Š” ๊ฒƒ์ด ๋” ๊ทธ๋Ÿด๋“ฏํ•ฉ๋‹ˆ๋‹ค.

๋‚˜๋Š” React๊ฐ€ ์‹ค์ œ๋กœ ๊ฐ’์„ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๊ณ  ์ „๋‹ฌํ•˜๋Š” _is_๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. setAttribute('foo', {some: object}) ํ˜ธ์ถœํ•˜๋ฉด [object Object]

React๋Š” setAttribute ์ „๋‹ฌํ•˜๊ธฐ ์ „์— ๊ฐ’์„ ๋ฌธ์ž์—ด๋กœ ๊ฐ•์ œ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

https://github.com/facebook/react/blob/4d6540893809cbecb5d7490a77ec7ad32e2aeeb3/packages/react-dom/src/client/DOMPropertyOperations.js#L136

๊ทธ๋ฆฌ๊ณ 

https://github.com/facebook/react/blob/4d6540893809cbecb5d7490a77ec7ad32e2aeeb3/packages/react-dom/src/client/DOMPropertyOperations.js#L166

๋‚˜๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ๋‹น์‹ ์ด ๋งํ•œ ๋ชจ๋“  ๊ฒƒ์— ๋™์˜ํ•ฉ๋‹ˆ๋‹ค.

์šฐ๋ฆฌ๋Š” ์‚ฌ๋žŒ๋“ค์ด ์–‘๋ฐฉํ–ฅ์œผ๋กœ ์ผ์„ ํ•œ๋‹ค๋Š” ๋ฐ ๋™์˜ํ•˜๊ณ  ๋ชจ๋“  ์‚ฌ๋žŒ์ด ์–ด๋Š ํ•œ ๋ฐฉํ–ฅ์œผ๋กœ๋งŒ ํ•˜๋„๋ก ๊ฐ•์š”ํ•˜๋Š” ํ‘œ์ค€์ด ์—†๊ธฐ ๋•Œ๋ฌธ์— ์—ฌ์ „ํžˆ ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

  • setAttribute ๊ฐ€ ๊ธฐ๋ณธ์ ์œผ๋กœ ์‚ฌ์šฉ๋˜๋Š” ์˜ต์…˜ 3๊ณผ ์ธ์Šคํ„ด์Šค ์†์„ฑ์„ ์‚ฌ์šฉํ•˜๋„๋ก ์ง€์ •ํ•˜๊ธฐ ์œ„ํ•œ ์ธ์žฅ,
  • React๊ฐ€ args๋ฅผ ๋ฌธ์ž์—ด๋กœ ๊ฐ•์ œํ•˜์ง€ ์•Š๋„๋ก #10070์„ ์ˆ˜์ •ํ–ˆ์Šต๋‹ˆ๋‹ค.
  • ๋ฐ ์˜ต์…˜ 5, ๋ฏธ์„ธ ์กฐ์ •์„ ์œ„ํ•œ API

์˜ต์…˜ 5๊ฐ€ ์ž˜ ์ˆ˜ํ–‰๋˜๋ฉด SSR ์†”๋ฃจ์…˜์— ๋Œ€ํ•œ ์ˆ˜ํ™”๋Š” ์˜ต์…˜ 5 API๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋Š” ์†์„ฑ ๋˜๋Š” ์†Œํ’ˆ์— ๋ฐ์ดํ„ฐ๋ฅผ ๋งคํ•‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

React๋Š” setAttribute์— ์ „๋‹ฌํ•˜๊ธฐ ์ „์— ๊ฐ’์„ ๋ฌธ์ž์—ด๋กœ ๊ฐ•์ œ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

์•Œ ๊ฒ ์–ด์š”. ๋Œ€๋ถ€๋ถ„์˜ ์‚ฌ๋žŒ๋“ค์€ ์‚ฌ์šฉ์ž ์ •์˜ toString() ์ •์˜ํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ๊ธฐ๋ณธ๊ฐ’์€ [object Object] ์ž…๋‹ˆ๋‹ค.

๋Œ€๋ถ€๋ถ„์˜ ์‚ฌ๋žŒ๋“ค์€ ์‚ฌ์šฉ์ž ์ •์˜ toString() ์ •์˜ํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ๊ธฐ๋ณธ๊ฐ’์€ [object Object] ์ž…๋‹ˆ๋‹ค.

๋งˆ์น˜ ๋‚ด๊ฐ€ ํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ

const div = document.createElement('div')
div.setAttribute('foo', {a:1, b:2, c:3})

๊ฒฐ๊ณผ๋Š”

<div foo="[object Object]"></div>

๋ถ„๋ช…ํžˆ ์›น ๊ฐœ๋ฐœ์ž๋กœ์„œ ์šฐ๋ฆฌ๋Š” ๋น„๋ฌธ์ž์—ด์„ ์š”์†Œ ์†์„ฑ์— ์ „๋‹ฌํ•  ๋•Œ ์–ด๋–ค ์ผ์ด ๋ฐœ์ƒํ•˜๋Š”์ง€ ์•Œ๊ณ  ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๋น„๋ฌธ์ž์—ด์„ A-Frame ์š”์†Œ์— ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ณ  ์žˆ์œผ๋ฉฐ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ๋ฐฉํ•ด๋ฐ›์ง€ ์•Š๊ณ  ์ž์œ ๋กญ๊ฒŒ ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

React๋Š” ๊ทธ๊ฒƒ์ด ์‹ ์ด ์•„๋‹ˆ๋ผ๋Š” ๊ฒƒ์„ ๊นจ๋‹ฌ์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์‚ฌ๋žŒ๋“ค์ด react ์™ธ์— ์‚ฌ์šฉํ•˜๋Š” ๋‹ค๋ฅธ ๋งŽ์€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ ๋ถˆํ•„์š”ํ•˜๊ฒŒ ๋น„๊ผฌ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด ์Šค๋ ˆ๋“œ์—์„œ ์šฐ๋ฆฌ๋Š” ์ด๊ฒƒ์— ๊ด€์‹ฌ์ด ์žˆ์ง€๋งŒ ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ ๋””์ž์ธ์„ ์ทจํ•  ์œ„์น˜์— ๋Œ€ํ•œ ๋‹ค์–‘ํ•œ ์˜ต์…˜๊ณผ ๋น„์ „์ด ์žˆ์Œ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฌด์—‡์„ ํ•ด์•ผ ํ•˜๋Š”์ง€ ๋ถ„๋ช…ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

@sebmarkbage ์ฃ„์†กํ•ฉ๋‹ˆ๋‹ค. ์ €๋Š”

๋‚ด๊ฐ€ ์˜๋ฏธํ•˜๋Š” ๋ฐ”๋Š” React๊ฐ€ ๋งค์šฐ ์ธ๊ธฐ๊ฐ€ ์žˆ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ React๋Š” ๋‹ค๋ฅธ ๊ณณ์—์„œ๋Š” ์ž‘๋™ํ•˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ๋Š” ํŠน์ •ํ•œ ๋ฐฉ์‹์œผ๋กœ ์ผ์„ ํ•˜๋„๋ก ์‚ฌ๋žŒ๋“ค์„ ํ”๋“ค ์ˆ˜ ์žˆ๋Š” ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ์Šต๋‹ˆ๋‹ค. t ๋ชจ๋“  ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ์™€ ํ•จ๊ป˜ ์ž‘๋™).

React๋Š” ํ˜„์žฌ ์š”์†Œ ์†์„ฑ์— ์ „๋‹ฌ๋œ ๋ชจ๋“  ๊ฐ’์„ ๋ฌธ์ž์—ด๋กœ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด React๊ฐ€ ์ด ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜์ง€ ์•Š์•˜๋‹ค๋ฉด (๋ฌธ์ž์—ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š”) frame-react ๊ฐ€

React๊ฐ€ ์ผ๋ฐ˜ JavaScript์—์„œ์™€ ๊ฐ™์ด ๋ฐ์ดํ„ฐ๋ฅผ ์š”์†Œ์— ์ „๋‹ฌํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์„ ํƒํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค€๋‹ค๋ฉด ๊ฐ€์žฅ ๋งŒ์กฑ์Šค๋Ÿฌ์šด ์‚ฌ์šฉ์ž๊ฐ€ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๐Ÿ˜Š

๋‹ค์‹œ ํ•œ ๋ฒˆ ๋ง์”€๋“œ๋ฆฌ์ง€๋งŒ ์ฃ„์†กํ•ฉ๋‹ˆ๋‹ค. ๋‹ค์Œ์— ํ•œ๋ฒˆ ๋” ์ƒ๊ฐํ•ด๋ด์•ผ๊ฒ ์Šต๋‹ˆ๋‹ค.

์ด์— ๋Œ€ํ•œ RFC PR์— ๋Œ€ํ•œ ์„ค๋ช… ์„ ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ์™€ ๊ทธ ์†์„ฑ์„ ์•ˆ์ •์ ์œผ๋กœ ์ถ”๋ก ํ•˜๊ธฐ ์œ„ํ•œ ๋” ๊ฐ„๋‹จํ•œ ๋ชจ๋ธ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ์ œ์•ˆ๋œ ๋‚ด์šฉ์„ ๋‹ค๋ฃจ๊ธฐ ๋•Œ๋ฌธ์— ๋…ผ์˜ํ•  ๊ฐ€์น˜๊ฐ€ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๋‹ค์‹œ ํ•˜์ด๋ธŒ๋ฆฌ๋“œ ์ ‘๊ทผ ๋ฐฉ์‹์œผ๋กœ ์ „ํ™˜ํ•˜์ง€๋งŒ ๋Œ€๋ถ€๋ถ„์˜ ์‚ฌ์šฉ ์‚ฌ๋ก€์— ๋Œ€ํ•ด ๊ตฌ์„ฑ์ด ํ•„์š” ์—†๋Š” ํ†ตํ•ฉ ๋ฐฉ์‹์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

์ด ๊ธฐ๋Šฅ์ด React์—์„œ ๊ตฌํ˜„๋˜๋Š” ๊ฒƒ์„ ๋ณด๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. React๋ฅผ ํ›Œ๋ฅญํ•˜๊ฒŒ ๋งŒ๋“œ๋Š” ๋…ธ๋ ฅ์— ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค.

์ด RFC์— ๋Œ€ํ•œ ์—…๋ฐ์ดํŠธ๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ?

์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์ •๋ง ์ข‹์•„์ง€๊ณ  ์žˆ์œผ๋ฉฐ ๋‚ด React ์•ฑ์—์„œ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. ์•„์ง ์†Œ์‹์ด ์—†๋‚˜์š”? ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ๋ฅผ ๋ž˜ํ•‘ํ•˜๊ณ  ๋‚˜์ค‘์— ๋‹ค์‹œ ๊ตฌ๋ฌธ ๋ถ„์„ํ•˜๊ธฐ ์œ„ํ•ด ํ•ด๋‹น ๋‚ด์šฉ์„ ๋ฌธ์ž์—ดํ™”ํ•˜๋Š” ๊ฒƒ์€ Vue ๋ฐ Angular๊ฐ€ ๊ธฐ๋ณธ์ ์œผ๋กœ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์‰ฝ๊ฒŒ ์ฒ˜๋ฆฌํ•œ๋‹ค๋Š” ์ ์„ ๊ณ ๋ คํ•  ๋•Œ ์ƒ๋‹นํžˆ ์‹คํ–‰ ๋ถˆ๊ฐ€๋Šฅํ•œ ์†”๋ฃจ์…˜์ž…๋‹ˆ๋‹ค.

์ด ๋ฌธ์ œ์— ๋Œ€ํ•œ ์—…๋ฐ์ดํŠธ๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ?

๋‚˜๋„ ํ•ดํ‚น์— ์˜์กดํ•˜์ง€ ์•Š๊ณ  ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. ์ด ๋ฌธ์ œ๊ฐ€ ํ•ด๊ฒฐ๋˜์—ˆ์œผ๋ฉด ํ•ฉ๋‹ˆ๋‹ค.

@mgolub2 React ํŒ€์€ ์›น ์ปค๋ฎค๋‹ˆํ‹ฐ๊ฐ€ ์›ํ•˜๋Š” ๊ฒƒ์ด ๋ฌด์—‡์ธ์ง€ ์‹ ๊ฒฝ ์“ฐ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์›น ๊ตฌ์„ฑ ์š”์†Œ๋Š” ์ด์ œ ๋„๋ฆฌ ์ง€์›๋˜๋Š” ํ‘œ์ค€์ด๋ฉฐ 2๋…„์ด ์ง€๋‚œ ํ›„์—๋„ ์ด ํ‘œ์ค€์„ ์ง€์›ํ•˜๋ผ๋Š” ํŒ€์˜ ์‹ ํ˜ธ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

์•ˆ๋…•ํ•˜์„ธ์š” ์—ฌ๋Ÿฌ๋ถ„, ์ €๋Š” ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ๋‹ค์Œ ๋‘ ์ค„์„ ๋ณ€๊ฒฝํ•˜์—ฌ ํ’€ ๋ฆฌํ€˜์ŠคํŠธ๋ฅผ ์‹œ์ž‘ํ–ˆ์Šต๋‹ˆ๋‹ค: https://github.com/facebook/react/pull/16899

์ด๋ฅผ ํ†ตํ•ด ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ ์ž‘์„ฑ์ž๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

class MyElement extends HTMLElement {
  setAttribute(name, value) {
    // default to existing behavior with strings
    if (typeof value === 'string')
      return super.setAttribute(name, value)

    // but now a custom element author can decide what to do with non-string values.
    if (value instanceof SomeCoolObject) { /*...*/ }
  }
}

ํ™•์žฅ๋œ setAttribute ๋ฉ”์„œ๋“œ์˜ ๋ชจ์–‘์—๋Š” ๋งŽ์€ ๋ณ€ํ˜•์ด ์žˆ์œผ๋ฉฐ ์ด๋Š” ํ•˜๋‚˜์˜ ์ž‘์€ ์˜ˆ์ผ ๋ฟ์ž…๋‹ˆ๋‹ค.

React ํŒ€, ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ ์ž‘์„ฑ์ž๋Š” ๊ฒฝ์šฐ์— ๋”ฐ๋ผ DOM์˜ ๊ธฐ๋ณธ ์†์„ฑ ์ฒ˜๋ฆฌ๋ฅผ ์šฐํšŒํ•˜๊ธฐ ๋•Œ๋ฌธ์—(๊ฐ’์ด ๋ฌธ์ž์—ด์ด ์•„๋‹Œ ๊ฒฝ์šฐ fe) ๊ทธ๋ ‡๊ฒŒ ํ•ด์„œ๋Š” ์•ˆ ๋œ๋‹ค๊ณ  ์ฃผ์žฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹น์‹ ์ด ๊ทธ ์˜๊ฒฌ์„ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค๊ณ  ํ•ด๋„ ๊ทธ๊ฒƒ์ด ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ ์ž‘์„ฑ์ž๊ฐ€ __ ์‚ฌ์šฉ์ž ์ •์˜ __ ์š”์†Œ๋กœ ํ•  ์ˆ˜ ์žˆ๋Š” ์ผ์„ ๋ฐฉํ•ดํ•ด์•ผ ํ•œ๋‹ค๋Š” ์˜๋ฏธ๋Š” ์•„๋‹™๋‹ˆ๋‹ค.

React๋Š” ๊ธฐ์กด DOM API๊ฐ€ ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉ๋˜๋Š”์ง€์— ๋Œ€ํ•ด ์˜๊ฒฌ์„ ์ œ์‹œํ•ด์„œ๋Š” ์•ˆ ๋ฉ๋‹ˆ๋‹ค. React๋Š” DOM์„ ์กฐ์ž‘ํ•˜๊ธฐ ์œ„ํ•œ ๋„๊ตฌ์ด๋ฉฐ DOM์— ๋Œ€ํ•ด ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ์ž‘์—…์— ๋Œ€ํ•ด ์˜๊ฒฌ์„ ์ œ์‹œํ•ด์„œ๋Š” ์•ˆ ๋ฉ๋‹ˆ๋‹ค. "๋ฐ์ดํ„ฐ๊ฐ€ DOM์œผ๋กœ ํ๋ฅด๋Š” ๋ฐฉ์‹"์ด๋ž€ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๊ณ  ๋ฐ์ดํ„ฐ๊ฐ€ ๊ฑฐ๊ธฐ์— ๋„๋‹ฌํ•˜๋Š” ๋ฐ ๊ฑธ๋ฆฌ๋Š” ๊ฒฝ๋กœ๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค(์ž‘์„ฑ์ž์˜ ๊ฐœ์ฒด๋ฅผ ๋ฌธ์ž์—ด๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๊ฒƒ์€ ์ž‘์„ฑ์ž์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค).

์ž‘์„ฑ์ž์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณ€๊ฒฝํ•˜๋ ค๋Š” ์ด์œ ๋Š” ๋ฌด์—‡์ž…๋‹ˆ๊นŒ? DOM์„ ์กฐ์ž‘ํ•˜๋ ค๋Š” ์‚ฌ๋žŒ์ด DOM์— ์ „๋‹ฌํ•  ๋ฐ์ดํ„ฐ๋ฅผ ์•Œ๊ณ  ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•  ์ˆ˜ ์—†๋Š” ์ด์œ ๋Š” ๋ฌด์—‡์ž…๋‹ˆ๊นŒ?

@trusktr ๋‚˜๋Š” ์ด๊ฒƒ์ด https://github.com/facebook/react/issues/10070 ์—์„œ ๋…ผ์˜๋˜์—ˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ ์ž‘์„ฑ์ž์—๊ฒŒ setAttribute ์™€ ๊ฐ™์€ ๋‚ด์žฅ ๋ฉ”์„œ๋“œ๋ฅผ ์žฌ์ •์˜ํ•˜๋ผ๊ณ  ๋งํ•˜๋Š” ๊ฒƒ์— ๋Œ€ํ•ด ์‚ฌ๋žŒ๋“ค์—๊ฒŒ ์ •๋ง ์ฃผ์˜๋ฅผ ์ฃผ๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๊ฐ€ ์›์ˆญ์ด ํŒจ์น˜๋ฅผ ํ•  ์˜๋„๊ฐ€ ์•„๋‹ˆ๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. cc @gaearon

์ด์™€ ๊ฐ™์€ ํ•˜์œ„ ํด๋ž˜์Šค์—์„œ setAttribute ๋ฅผ ์žฌ์ •์˜ํ•˜๋Š” ๊ฒƒ์€ ๋ฌดํ•ดํ•ฉ๋‹ˆ๋‹ค(์›์ˆญ์ด ํŒจ์น˜๊ฐ€ ์•„๋‹˜). ๊ทธ๋Ÿฌ๋‚˜ ๋‚ด๊ฐ€ ์–ธ๊ธ‰ํ–ˆ๋“ฏ์ด, ๊ทธ๊ฒƒ์ด ๋ฐ˜๋“œ์‹œ React ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ์ž‘์—…์ด ์•„๋‹Œ ๊ฒฝ์šฐ React๊ฐ€ ๊ทธ๊ฒƒ์— ๋Œ€ํ•ด ์ง€์‹œํ•ด์•ผ ํ•˜๋Š” ์ด์œ ๋Š” ๋ฌด์—‡์ž…๋‹ˆ๊นŒ? ์šฐ๋ฆฌ๋Š” (์žฅ์•  ์—†์ด) DOM์„ ์กฐ์ž‘ํ•˜๊ธฐ ์œ„ํ•ด React๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ๋ฅผ ์›ํ•ฉ๋‹ˆ๋‹ค.

์„ฑ๋Šฅ ํ–ฅ์ƒ์„ ์œ„ํ•ด ์ˆ˜๋™์œผ๋กœ el.setAttribute() ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ์—๋„ ๊ฐœ๋ฐœ ํ™˜๊ฒฝ์ด ์•…ํ™”๋ฉ๋‹ˆ๋‹ค.

React ํŒ€์ด setAttribute ๋กœ ์ „๋‹ฌ๋œ ๋ชจ๋“  ๊ฒƒ์„ ๋ฌธ์ž์—ด๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ ์—„์ฒญ๋‚œ ์œ„ํ—˜์—์„œ ๋งŽ์€ ์‚ฌ๋žŒ๋“ค์„ ๊ตฌํ•˜๊ณ  ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๋‹ค๋ฅธ ์†”๋ฃจ์…˜์ด ๋” ๋‚˜์„ ์ˆ˜ ์žˆ๋‹ค๋Š” ๋ฐ ๋™์˜ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด JSX ์‚ฌ์–‘์„ ์ƒˆ๋กœ์šด ๊ตฌ๋ฌธ์œผ๋กœ ์—…๋ฐ์ดํŠธํ•˜์ง€๋งŒ ์‹œ๊ฐ„์ด ์˜ค๋ž˜ ๊ฑธ๋ฆฌ๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

์ž๋™ ๋ฌธ์ž์—ด ๋ณ€ํ™˜์„ ์—†์• ๋ฉด ์ปค๋ฎค๋‹ˆํ‹ฐ๊ฐ€ ์žƒ๋Š” ๊ฒƒ์€ ๋ฌด์—‡์ž…๋‹ˆ๊นŒ? React ํŒ€์€ ๋ฌด์—‡์„ ์žƒ์Šต๋‹ˆ๊นŒ?

React ํŒ€์€ ๋‚˜์ค‘์— ๋” ๋‚˜์€ ์†”๋ฃจ์…˜์œผ๋กœ ์ƒํ™ฉ์„ ๊ฐœ์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ตœ์†Œํ•œ ๋‹จ์ˆœํžˆ ๋ฌธ์ž์—ดํ™”๋ฅผ ์šฐํšŒํ•  ์ˆ˜ ์žˆ๋Š” ์˜ต์…˜์„ ์ œ๊ณตํ•˜์ง€ ์•Š๋Š” ์ด์œ ๋Š” ๋ฌด์—‡์ž…๋‹ˆ๊นŒ? ๊ทธ๊ฒƒ์€ ๋‹น์‹ ์ด ๊ธฐ๊บผ์ด ๊ณ ๋ คํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ž…๋‹ˆ๊นŒ?

์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ ์ž‘์„ฑ์ž์—๊ฒŒ setAttribute ์™€ ๊ฐ™์€ ๋‚ด์žฅ ๋ฉ”์„œ๋“œ๋ฅผ ์žฌ์ •์˜ํ•˜๋ผ๊ณ  ๋งํ•˜๋Š” ๊ฒƒ์— ๋Œ€ํ•ด ์‚ฌ๋žŒ๋“ค์—๊ฒŒ ์ •๋ง ์ฃผ์˜๋ฅผ ์ฃผ๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค.

๊ทธ ์ด์œ ์— ๋Œ€ํ•ด ์ข‹์€ ์ด์œ ๋ฅผ ์ œ์‹œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

์ด๊ฒƒ์€ ์ฒญ์–ด์ฒ˜๋Ÿผ ๋ณด์ž…๋‹ˆ๋‹ค. "์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๋ชจ๋“  ์‚ฌ๋žŒ์ด ์ž์‹ ์˜ ์š”์†Œ์— ํŠน์ • ๋™์ž‘์ด ์žˆ๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ์ฒจ๋ถ€ํ•˜๋„๋ก ์„ค๋“"์€ DOM ์š”์†Œ์— ์†์„ฑ์„ ์„ค์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•œ ์ด ๋ฌธ์ œ์— ๋Œ€ํ•œ ํ•ด๊ฒฐ์ฑ…์ด ์•„๋‹™๋‹ˆ๋‹ค.

@trusktr

๊ทธ ์ด์œ ์— ๋Œ€ํ•ด ์ข‹์€ ์ด์œ ๋ฅผ ์ œ์‹œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

์›น ๊ตฌ์„ฑ ์š”์†Œ๋Š” ํ‘œ์ค€์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ํ‘œ์ค€์˜ ํŒŒ์ƒ๋ฌผ๋„ ํ‘œ์ค€์„ ์ค€์ˆ˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ setAttribute ์žฌ์ •์˜ํ•˜๋Š” ๊ฒƒ์€ ์ด ์กฐ๊ฑด์— ๋งž์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ ์›น ๊ตฌ์„ฑ ์š”์†Œ์™€ ํ•จ๊ป˜ ์ž‘๋™ํ•˜๋Š” ๋‹ค๋ฅธ ๋งŽ์€ ํ”„๋ ˆ์ž„์›Œํฌ๊ฐ€ ์žˆ์ง€๋งŒ React์— ๋Œ€ํ•ด์„œ๋งŒ ํ•ดํ‚น์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ React์™€ ์ „ํ˜€ ์ž‘๋™ํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ์—๋„ React ํ•ต์„ ์†Œ๋น„ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋‚˜๋Š” ๊ทธ๊ฒƒ์ด ์˜ฌ๋ฐ”๋ฅธ ํ•ด๊ฒฐ์ฑ…์ด๋ผ๊ณ  ์ƒ๊ฐํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

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

๊ฐœ์ธ์ ์œผ๋กœ, ์–ด๋–ค ์ข…๋ฅ˜์˜ React ๋ž˜ํผ๊ฐ€ ํ›จ์”ฌ ๋” ์œ ๋งํ•ด ๋ณด์ธ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

์—ฌ๋Ÿฌ๋ถ„, ๊ธฐ๋‹ค๋ฆฌ๋Š” ๋™์•ˆ React https://www.npmjs.com/package/reactify-wc ์—์„œ ์›น ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ๋ž˜ํ•‘ํ•˜๊ธฐ ์œ„ํ•œ shim์„ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค.

import React from "react";
import reactifyWc from "reactify-wc";

// Import your web component. This one defines a tag called 'vaadin-button'
import "@vaadin/vaadin-button";

const onClick = () => console.log('hello world');

const VaadinButton = reactifyWc("vaadin-button");

export const MyReactComponent = () => (
  <>
    <h1>Hello world</h1>
    <VaadinButton onClick={onClick}>
      Click me!
    </VaadinButton>
  </>
)

์ด๊ฒƒ์ด ๋„์›€์ด ๋˜๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค.

(์ด๊ฒƒ์€ ๋‚ด๊ฐ€ OSS์— ์ฒ˜์Œ์œผ๋กœ ์ง„์ถœํ•œ ๊ฒƒ์ด๊ณ , ์‚ฌ๋ฌด์‹ค ๋ฐ–์—์„œ ๋ฌด์–ธ๊ฐ€๋ฅผ ๊ณต๊ฐœํ•œ ์ตœ์ดˆ์˜ ๊ฒƒ ์ค‘ ํ•˜๋‚˜์ž…๋‹ˆ๋‹ค. ๊ฑด์„ค์ ์ธ ๋น„ํŒ์€ ๋”ํ•  ๋‚˜์œ„ ์—†์ด ํ™˜์˜์ž…๋‹ˆ๋‹ค ๐Ÿ˜„ )

์—ฌ๋Ÿฌ๋ถ„, ๊ธฐ๋‹ค๋ฆฌ๋Š” ๋™์•ˆ React https://www.npmjs.com/package/reactify-wc ์—์„œ ์›น ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ๋ž˜ํ•‘ํ•˜๊ธฐ ์œ„ํ•œ shim์„ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค.

import React from "react";
import reactifyWc from "reactify-wc";

// Import your web component. This one defines a tag called 'vaadin-button'
import "@vaadin/vaadin-button";

const onClick = () => console.log('hello world');

const VaadinButton = reactifyWc("vaadin-button");

export const MyReactComponent = () => (
  <>
    <h1>Hello world</h1>
    <VaadinButton onClick={onClick}>
      Click me!
    </VaadinButton>
  </>
)

์ด๊ฒƒ์ด ๋„์›€์ด ๋˜๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค.

(์ด๊ฒƒ์€ ๋‚ด๊ฐ€ OSS์— ์ฒ˜์Œ์œผ๋กœ ์ง„์ถœํ•œ ๊ฒƒ์ด๊ณ , ์‚ฌ๋ฌด์‹ค ๋ฐ–์—์„œ ๋ฌด์–ธ๊ฐ€๋ฅผ ๊ณต๊ฐœํ•œ ์ตœ์ดˆ์˜ ๊ฒƒ ์ค‘ ํ•˜๋‚˜์ž…๋‹ˆ๋‹ค. ๊ฑด์„ค์ ์ธ ๋น„ํŒ์€ ๋”ํ•  ๋‚˜์œ„ ์—†์ด ํ™˜์˜์ž…๋‹ˆ๋‹ค ๐Ÿ˜„ )

ํ›Œ๋ฅญํ•œ ๋ž˜ํผ :)

Stencil๋กœ ์›น ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ๋นŒ๋“œํ•˜๋ฉด React์—์„œ ์ด ๋ฌธ์ œ๊ฐ€ ํ•ด๊ฒฐ๋œ๋‹ค๋Š” ์ ๋„ ์–ธ๊ธ‰ํ•  ๊ฐ€์น˜๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. https://stenciljs.com/docs/faq#can -data-be-passed-to-web-components-

@matsgm Stencil์„ ์‚ฌ์šฉํ•œ ๋นŒ๋“œ๊ฐ€ ๋„์›€์ด ๋˜์–ด ๊ธฐ์ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์šฐ๋ฆฌ ๊ฒฝํ—˜์— ๋”ฐ๋ฅด๋ฉด Stencil์€ ๋‹ค๋ฅธ ์›น ๊ตฌ์„ฑ ์š”์†Œ ํ”„๋ ˆ์ž„์›Œํฌ, ํŠนํžˆ Polymer์—์„œ ์ œ๋Œ€๋กœ ์ž‘๋™ํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์œผ๋กœ ์ž…์ฆ๋˜์—ˆ์œผ๋ฉฐ ๋นŒ๋“œ ๋„๊ตฌ, ์ง€์› ๋ฐ ์ผ๋ฐ˜ ๊ธฐ๋Šฅ ์‚ฌ์ด์˜ 6๊ฐ€์ง€ ๋‹ค๋ฅธ ๋ฌธ์ œ๋กœ ์ธํ•ด ์งœ์ฆ์ด ๋‚ฌ์Šต๋‹ˆ๋‹ค. ๊ท€ํ•˜์˜ ๋งˆ์ผ๋ฆฌ์ง€๊ฐ€ ๋‹ค๋ฅผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค :)

์ด ์Šค๋ ˆ๋“œ๋กœ ์ตœ์‹  ์ •๋ณด๋ฅผ ์–ป์œผ๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ์ตœ์ข… ํ•ด๊ฒฐ์ฑ…์€ ๋ฌด์—‡์ž…๋‹ˆ๊นŒ?

์–ด๋–ค ๋ฉด์—์„œ ์ €๋Š” ๋งค์šฐ ํ˜ผ๋ž€์Šค๋Ÿฌ์šธ ์ˆ˜ ์žˆ๋Š” ๋งˆ์ˆ ์  ๋ฐœ๊ฒฌ๋ณด๋‹ค ์†์„ฑ, ์†Œํ’ˆ, ์ด๋ฒคํŠธ๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ ์ •์˜ํ•˜๋Š” ๊ฒƒ์„ ์ข‹์•„ํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด snabbdom ์€ ๋ช…์‹œ์ ์ธ ์ตœ์ƒ์œ„ ๋„ค์ž„์ŠคํŽ˜์ด์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ ๋ฌด์—‡์ด ์–ด๋””๋กœ ๊ฐ€๋Š”์ง€ ์‰ฝ๊ฒŒ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋” ๋น ๋ฅธ ์‹คํ–‰์„ ์œ„ํ•œ ๋ฌธ์ž์—ด ์กฐ์ž‘์€ ์—†์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด onClick => click ์—์„œ ์ ‘๋ฏธ์‚ฌ๋ฅผ ์ž๋ฅด๋Š” ๊ฒƒ์€ ์—ฌ์ „ํžˆ โ€‹โ€‹์„ฑ๋Šฅ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

<input attrs={{placeholder: `heyo`}} style={{color: `inherit`}} class={{hello: true, world: false}} on={{click: this.handleClick}} props={{value: `blah`}} />
attr = (attr, val) => elem.setAttribute(attr, val);
prop = (prop, val) => elem[prop] = val;
on  = (event, handler) => elem.addEventListener(event, handler)
style = (prop, val) => elem.style[prop] = val;
class = (name, isSet) => isSet ? elem.classList.add(name) : elem.classList.remove(val)
dataset = (key, val) => elem.dataset[key] = val;

JSX๊ฐ€ ์  ๊ตฌ๋ฌธ์œผ๋กœ ๋„ค์ž„์ŠคํŽ˜์ด์Šค๋ฅผ ์ง€์›ํ–ˆ์œผ๋ฉด ํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ props๊ฐ€ ๊ธฐ๋ณธ ๋„ค์ž„์ŠคํŽ˜์ด์Šค๊ฐ€ ๋˜๋ฉฐ ๊ฐ„๋‹จํžˆ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Œ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

<div tabIndex={-1} attr.title={"abcd"} on.click={handler} style.opacity={1} class.world={true} />`

์ฐธ๊ณ ๋กœ @sebmarkbage ^

const whatever = 'Whatever';
const obj = { a: 1, b: 2 };
const reactComponent = (props) => (
<div>
  ...
  <custom-element attr="{whatever}" someProp={obj} />
  { /* double quotes for attributes */ }
  { /* no quotes for properties */ }
</div>
);

์ด๊ฒƒ์€ React JSX Pragma ํŒŒ์„œ๋ฅผ ์ˆ˜์ •ํ•˜์—ฌ ๋‹ฌ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ถ”๊ฐ€ ์˜ต์…˜์€ propeties (๋˜๋Š” ๋ฐ˜์‘ ํŒฌ์˜ ๊ฒฝ์šฐ props )์„ ์ž์‚ฐ ์ „๋‹ฌ์— ๋Œ€ํ•œ ์ง€์ •๋œ ๋‹จ์–ด๋กœ ์œ ์ง€ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์˜ค๋Š˜ 17.0์ด ์ถœ์‹œ๋˜์—ˆ์œผ๋ฏ€๋กœ ์ด ๋ฌธ์ œ๊ฐ€ ์–ธ์ œ ํ•ด๊ฒฐ๋˜๋Š”์ง€ ์ƒํƒœ๋ฅผ ๋ฐ˜์˜ํ•˜๋„๋ก ์ด ๋ฌธ์ œ๋ฅผ ์—…๋ฐ์ดํŠธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

์‘. ์šฐ๋ฆฌ๋Š” ์›๋ž˜ React 17์„ ๋” ๋งŽ์€ ์ง€์› ์ค‘๋‹จ์ด ์ œ๊ฑฐ๋˜๊ณ  ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ์ด ํฌํ•จ๋œ ๋ฆด๋ฆฌ์Šค๋กœ ๊ณ„ํšํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์˜ค๋ž˜๋œ ์ฝ”๋“œ๋ฒ ์ด์Šค๊ฐ€ ๋ชจ๋“  ์ฝ”๋“œ๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๋Š” ๊ฒƒ์€ ๊ทธ๋‹ค์ง€ ํ˜„์‹ค์ ์ด์ง€ ์•Š์œผ๋ฉฐ, ์ด๊ฒƒ์ด ์šฐ๋ฆฌ๊ฐ€ ํ•˜๋‚˜์˜ ์ค‘์š”ํ•œ ์ฃผ์š” ๋ณ€๊ฒฝ ์‚ฌํ•ญ(์ด๋ฒคํŠธ๋Š” ๋ฌธ์„œ๊ฐ€ ์•„๋‹Œ ๋ฃจํŠธ ์š”์†Œ์— ์ฒจ๋ถ€๋จ)์—๋งŒ ์ดˆ์ ์„ ๋งž์ถ˜ React 17์„ ์ถœ์‹œํ•˜๊ธฐ๋กœ ๊ฒฐ์ •ํ•œ ์ด์œ ์ž…๋‹ˆ๋‹ค. ). ์ด๋Š” ์˜ค๋ž˜๋œ ์•ฑ์ด React 17์— ์˜์›ํžˆ ๋‚จ์•„ ์žˆ๊ณ  ๊ทธ ์ค‘ ์ผ๋ถ€๋งŒ 18+๋กœ ์—…๋ฐ์ดํŠธํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๊ธฐ ์œ„ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ด ํŠน์ • ๊ธฐ๋Šฅ์ด 17์— ๋“ค์–ด๊ฐˆ ๊ฒƒ์ด๋ผ๊ณ  ๋งํ•˜๋Š” ๊ฒƒ์ด ์‹ค๋ง์Šค๋Ÿฝ๋‹ค๋Š” ๊ฒƒ์„ ์••๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์›๋ž˜ 17์— ๋Œ€ํ•ด ๊ณ„ํšํ–ˆ๋˜ ๋ชจ๋“  ๊ธฐ๋Šฅ๋„ 18๋กœ ์˜ฎ๊ฒจ์กŒ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ฒŒ ๋˜์‹ค ๊ฒƒ์ž…๋‹ˆ๋‹ค. 17์€ ํŠน๋ณ„ํ•œ ๋””๋”ค๋Œ ๋ฐœ๋งค์ž…๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด 18์—์„œ ๋” ๊ณต๊ฒฉ์ ์ธ ์ฃผ์š” ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์•ž์œผ๋กœ ๋ช…ํ™•ํ•œ ๊ฒฝ๋กœ๊ฐ€ ์žˆ๋‹ค๋ฉด ์ด ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ํฌํ•จํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ ์˜ต์…˜ ์ค‘ ์–ด๋Š ๊ฒƒ์ด ๋” ๋ฐ”๋žŒ์งํ•œ์ง€์— ๋Œ€ํ•œ WC ์ปค๋ฎค๋‹ˆํ‹ฐ์˜ ์ตœ์‹  ํ•ฉ์˜๊ฐ€ ๋ฌด์—‡์ธ์ง€ ์ž˜ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์€ ๊ทธ๋“ค ๋ชจ๋‘๊ฐ€ (๊ทธ ์ผ์„ ์œ„ํ•ด @robdodson์— ํฐ ์†Œํ’ˆ) ์ƒ๊ฐ์„ ์ ์–ด์ด ๋งค์šฐ ๋„์›€์ด๋ฉ๋‹ˆ๋‹ค. ์ด ์Šค๋ ˆ๋“œ๊ฐ€ ์ž‘์„ฑ๋œ ์ดํ›„ ์ด๋Ÿฌํ•œ ์˜ต์…˜์— ๋Œ€ํ•œ ์‚ฌ๋žŒ๋“ค์˜ ์˜๊ฒฌ์ด ๋ฐœ์ „ํ–ˆ๋Š”์ง€, ๋ฐฉํ–ฅ์„ ์„ ํƒํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋  ์ˆ˜ ์žˆ๋Š” ์ƒˆ๋กœ์šด ์ •๋ณด๊ฐ€ ์žˆ๋Š”์ง€ ๊ถ๊ธˆํ•ฉ๋‹ˆ๋‹ค.

์ €๋Š” WC ์ปค๋ฎค๋‹ˆํ‹ฐ๊ฐ€ ์„ ํ˜ธํ•˜๋Š” ์˜ต์…˜์„ ๋ณ€๊ฒฝํ–ˆ๋‹ค๊ณ  ์ƒ๊ฐํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์—ฌ์ „ํžˆ ์˜ต์…˜ 3์ž…๋‹ˆ๋‹ค. @developit ์€ Preact๊ฐ€ ์‚ฌ์šฉ์ž ์ง€์ • ์š”์†Œ์™€ ์–ด๋–ป๊ฒŒ ํ˜ธํ™˜๋˜๋Š”์ง€์— ๋Œ€ํ•ด ๋” ๋งŽ์ด ๋งํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” React์—์„œ๋„ ํฅ๋ฏธ๋กœ์šธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ”„๋ ˆ์ž„์›Œํฌ๊ฐ€ ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ์— (๋ณต์žกํ•œ) ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๊ฒƒ๊ณผ ์–ด๋–ป๊ฒŒ ํ˜ธํ™˜๋˜๋Š”์ง€์— ๋Œ€ํ•œ ์ผ๋ฐ˜์ ์ธ ๊ฐœ์š”๋ฅผ ๋ณด๋ ค๋ฉด https://custom-elements-everywhere.com/ ์— ๋ชจ๋“  ์„ธ๋ถ€ ์ •๋ณด๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

https://github.com/vuejs/vue/issues/7582 ์—์„œ Vue๋Š” sigil์„ ์‚ฌ์šฉํ•˜๊ธฐ๋กœ ์„ ํƒํ–ˆ๊ณ  "."๋ฅผ ์„ ํƒํ–ˆ์Šต๋‹ˆ๋‹ค. ์ ‘๋‘์‚ฌ๋กœ (Glimmer์˜ "@"๊ฐ€ ์•„๋‹˜).

https://github.com/vuejs/vue/issues/7582#issuecomment -362943450์—์„œ @trusktr ์€ ๊ฐ€์žฅ ์ •ํ™•ํ•œ SSR ๊ตฌํ˜„์ด sigil'd ์†์„ฑ์„ SSR'd HTML์˜ ์†์„ฑ์œผ๋กœ ๋ Œ๋”๋งํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์ด๋ผ๊ณ  ์ œ์•ˆํ–ˆ์Šต๋‹ˆ๋‹ค. ๋Œ€์‹  ์ˆ˜ํ™” ์ค‘์— JS๋ฅผ ํ†ตํ•ด ์†์„ฑ์œผ๋กœ ์„ค์ •ํ•˜์‹ญ์‹œ์˜ค.

์ด ํŠน์ • ๊ธฐ๋Šฅ๋งŒ์„ ์œ„ํ•ด ์ƒˆ๋กœ์šด JSX ๊ตฌ๋ฌธ์„ ๋„์ž…ํ•  ๊ฐ€๋Šฅ์„ฑ์€ ๊ฑฐ์˜ ์—†๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

์˜ต์…˜(5)์˜ ๋ณด๋‹ค ์ผ๋ฐ˜์ ์ธ ๋ฒ„์ „์ด ํ…Œ์ด๋ธ”์— ์žˆ์„ ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ ์˜ต์…˜(3)์„ ์ˆ˜ํ–‰ํ•  ๊ฐ€์น˜๊ฐ€ ์žˆ๋Š”์ง€์— ๋Œ€ํ•œ ์งˆ๋ฌธ๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์ฆ‰, ์˜ต์…˜ (5)๋Š” ์‚ฌ์šฉ์ž ์ง€์ • ๋งˆ์šดํŠธ/์—…๋ฐ์ดํŠธ/๋งˆ์šดํŠธ ํ•ด์ œ/์ˆ˜ํ™” ๋™์ž‘์œผ๋กœ ์‚ฌ์šฉ์ž ์ง€์ • ์ €์ˆ˜์ค€ React ๋…ธ๋“œ๋ฅผ ์„ ์–ธํ•˜๋Š” ์ €์ˆ˜์ค€ ๋ฉ”์ปค๋‹ˆ์ฆ˜์ด ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ ์ž์ฒด์—๋งŒ ๊ตญํ•œ๋˜์ง€๋Š” ์•Š์Šต๋‹ˆ๋‹ค(์‚ฌ์šฉ ์‚ฌ๋ก€ ์ค‘ ํ•˜๋‚˜์ผ์ง€๋ผ๋„).

์ด ํŠน์ • ๊ธฐ๋Šฅ์— ๋Œ€ํ•ด ์™„์ „ํžˆ ์ƒˆ๋กœ์šด JSX ๊ตฌ๋ฌธ์„ ๋„์ž…ํ•˜๋Š” ๋Œ€์‹  ๋ณด๋‹ค ์ผ๋ฐ˜์ ์ธ JSX๋ฅผ ๋„์ž…ํ•˜๊ณ  ์ด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์‚ฌ์šฉ์ž ์ •์˜ ์†์„ฑ์„ ์ •์˜ํ•˜๋Š” ๊ฒƒ์€ ์–ด๋–ป์Šต๋‹ˆ๊นŒ?

๋‚˜๋Š” ์˜ค๋ž˜์ „์— JSX์— ECMAScript์˜ ๊ณ„์‚ฐ๋œ ์†์„ฑ ๊ตฌ๋ฌธ์„ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์„ ์ œ์•ˆํ–ˆ๊ณ (facebook/jsx#108) ์ผ๋ฐ˜์ ์œผ๋กœ ๊ตฌ๋ฌธ์— ์œ ์šฉํ•œ ์ถ”๊ฐ€๊ฐ€ ๋  ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

๊ณ„์‚ฐ๋œ ์†์„ฑ ๊ตฌ๋ฌธ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ ๊ณ„์‚ฐ๋œ ์†์„ฑ ๊ตฌ๋ฌธ๊ณผ ๊ธฐํ˜ธ ๋˜๋Š” ์ ‘๋‘์–ด๊ฐ€ ๋ถ™์€ ๋ฌธ์ž์—ด์„ ์‚ฌ์šฉํ•˜์—ฌ ์†์„ฑ์„ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ€๋Šฅ์„ฑ์ด ์—ด๋ ค ์žˆ์Šต๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด:

import {property} from 'react';
// ...
<custom-img [property('src')]="corgi.jpg" [property('hiResSrc')]="[email protected]" width="100%">

@dantman ์ด ์ œ์•ˆ์€ ์„œ๋ฒ„ ๋ Œ๋”๋ง ๋ฐ ์ˆ˜ํ™”๋ฅผ ์–ด๋–ป๊ฒŒ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๊นŒ?

WC ์ปค๋ฎค๋‹ˆํ‹ฐ์˜ ๋ˆ„๊ตฌ๋„ ์˜ต์…˜ 5๋ฅผ ์›ํ•˜์ง€ ์•Š๋Š”๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ์— ๋Œ€ํ•œ ์‚ฌ์šฉ์ž ์ •์˜ React ๋ž˜ํผ ์ž‘์„ฑ์„ ํŒจ์น˜ํ•˜๋Š” ํ˜„์žฌ ๊ด€ํ–‰๊ณผ ์‹ค์ œ๋กœ ๋‹ค๋ฅด์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด ์ ‘๊ทผ ๋ฐฉ์‹์˜ ํฐ ๋‹จ์ ์€ ๊ตฌ์„ฑ ์š”์†Œ ์ž‘์„ฑ์ž์—๊ฒŒ ํŠน๋ณ„ํ•œ ๊ฒฝ์šฐ์˜ React ๋˜๋Š” ๊ตฌ์„ฑ ์š”์†Œ ์†Œ๋น„์ž์—๊ฒŒ ํŠน๋ณ„ํ•œ ๊ฒฝ์šฐ์˜ ์‚ฌ์šฉ์ž ์ง€์ • ์š”์†Œ์— ๋Œ€ํ•œ ๋ถ€๋‹ด์„ ์ฃผ๋ฉฐ ๋‘˜ ๋‹ค ํ•„์š”ํ•˜์ง€ ์•Š์•„์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์„œ๋ฒ„ ๋ Œ๋”๋ง ๋ฐ ์ˆ˜ํ™”์— ๋Œ€ํ•ด ์–ด๋–ป๊ฒŒ ์ƒ๊ฐํ•˜์‹ญ๋‹ˆ๊นŒ? ๋ช…์‹œ์  ๊ตฌ์„ฑ์ด ์—†๋Š” ๊ฒฝ์šฐ ์–ด๋–ค ๊ฒฝํ—˜์  ๋ฐฉ๋ฒ•์ด ๋ฐ”๋žŒ์งํ•ฉ๋‹ˆ๊นŒ? WC ์ปค๋ฎค๋‹ˆํ‹ฐ์—์„œ ์ผ๋ฐ˜์ ์œผ๋กœ ์ˆ˜ํ–‰๋˜๋Š” ๋ฐฉ์‹์ด ํ†ตํ•ฉ๋˜์—ˆ์Šต๋‹ˆ๊นŒ? ์ด RFC๋ฅผ ๋‹ค์‹œ ์ฝ์—ˆ๋Š”๋ฐ ์ด ์ฃผ์ œ์— ๋Œ€ํ•œ ์„ธ๋ถ€ ์ •๋ณด๊ฐ€ ์—†๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ํŠนํžˆ React๊ฐ€ ์„œ๋ฒ„ ๋ Œ๋”๋ง์— ๋” ์ค‘์ ์„ ๋‘๋Š” ๋ฐฉํ–ฅ์œผ๋กœ ์ด๋™ํ•จ์— ๋”ฐ๋ผ ๋งค์šฐ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.

@gaearon ํ•„์š”ํ•œ ๊ฒƒ์ด ๋ฌด์—‡์ธ์ง€ ์•Œ๊ธฐ์— ์ถฉ๋ถ„ํ•œ ์ˆ˜ํ™” ๋ฐ ์‚ฌ์šฉ์ž ์ •์˜ ์†์„ฑ์„ ์•Œ์ง€ ๋ชปํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ์ฃผ๋กœ ๊ตฌ๋ฌธ ์ œ์•ˆ์ž…๋‹ˆ๋‹ค.

์ผ๋ฐ˜์ ์œผ๋กœ property(propertyName) ๋Š” ๊ตฌํ˜„ ๋ฐฉ๋ฒ•์— ๋”ฐ๋ผ ์ ‘๋‘์–ด๊ฐ€ ๋ถ™์€ ๋ฌธ์ž์—ด(์˜ˆ: '__REACT_INTERNAL_PROP__$' + propertyName )์„ ์ถœ๋ ฅํ•˜๊ฑฐ๋‚˜ Symbol์„ ์ƒ์„ฑํ•˜๊ณ  "symbol => propertyName" ์—ฐ๊ด€์„ ์ €์žฅํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ง€๋„.

๋‚˜์ค‘์— ํ•ด๋‹น ๋งต์„ ํด๋ผ์ด์–ธํŠธ์™€ ํ†ต์‹ ํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ ๋ฌธ์ œ๊ฐ€ ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

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

์›น ๊ตฌ์„ฑ ์š”์†Œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ž‘์„ฑ์ž๋กœ์„œ ์˜ต์…˜ 5๋Š” ํŽธ๋ฆฌํ•œ ์„ ํƒ์ด ์•„๋‹™๋‹ˆ๋‹ค. ๊ฐ ํ”„๋ ˆ์ž„์›Œํฌ ๋ฐ ๊ตฌ์„ฑ ์š”์†Œ์— ๋Œ€ํ•œ ์Šคํ‚ค๋งˆ๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ ์ •์˜ํ•˜์ง€ ์•Š๊ณ ๋„ ์‚ฌ์šฉ์ž ์ง€์ • ์š”์†Œ๋ฅผ ๋งŒ๋“ค๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋งŽ์€ ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ ์ž‘์„ฑ์ž๋Š” ์ด๊ฒƒ์„ ํ•˜์ง€ ์•Š์•„ React ๊ฐœ๋ฐœ์ž์—๊ฒŒ ๋ถ€๋‹ด์„ ์ค๋‹ˆ๋‹ค.

์˜ต์…˜ 5๋กœ ์Šน์ž๋Š” ์—†์Šต๋‹ˆ๋‹ค. ๐Ÿ˜•

@claviska ์„œ๋ฒ„ ๋ Œ๋”๋ง ๋ฐ ์ˆ˜ํ™” ์ž‘์—…์ด ๋ณด๋‹ค ์•”์‹œ์ ์ธ ์ ‘๊ทผ ๋ฐฉ์‹์œผ๋กœ ์ž‘๋™ํ•˜๋Š” ๋ฐฉ์‹์— ๋Œ€ํ•œ ์˜๊ฒฌ์ด ์žˆ์Šต๋‹ˆ๊นŒ?

@gaearon SSR์€ ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ๊ฐ€ SSR์„ ์ง€์›ํ•˜๋Š” ๊ฒฝ์šฐ์™€ ์ง€์›ํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ์˜ ๋‘ ๊ฐ€์ง€ ์ƒํ™ฉ์œผ๋กœ ์„ธ๋ถ„ํ™”๋ฉ๋‹ˆ๋‹ค.

SSR์„ ์ง€์›ํ•˜์ง€ ์•Š๋Š” ์š”์†Œ์˜ ๊ฒฝ์šฐ ์„œ๋ฒ„์˜ ์†์„ฑ ์„ค์ •์€ ์ค‘์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. id ๋ฐ className ์™€ ๊ฐ™์€ ๋‚ด์žฅ ๋ฐ˜์˜ ์†์„ฑ์„ ์ œ์™ธํ•˜๊ณ ๋Š” ์‚ญ์ œํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ํด๋ผ์ด์–ธํŠธ์—์„œ๋งŒ ์“ธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

SSR ์†์„ฑ์„ ์ง€์›ํ•˜๋Š” ์š”์†Œ์˜ ๊ฒฝ์šฐ ์ค‘์š”ํ•˜์ง€๋งŒ DOM์—์„œ ๋ฐœ์ƒํ•˜๋Š” ๊ฒฐ๊ณผ๋ฅผ ํŠธ๋ฆฌ๊ฑฐํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ์œ„ํ•ด์„œ๋Š” ์š”์†Œ ์ธ์Šคํ„ด์Šค ๋˜๋Š” ์ผ์ข…์˜ SSR ํ”„๋ก์‹œ/์Šคํƒ ๋“œ์ธ ๋ฐ SSR์˜ DOM ์ƒํƒœ๋ฅผ ์ „๋‹ฌํ•˜๊ธฐ ์œ„ํ•œ ์ผ๋ถ€ ํ”„๋กœํ† ์ฝœ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์•„์ง ์ด ํ”„๋กœ์„ธ์Šค์— ๋Œ€ํ•œ ๊ณตํ†ต ์„œ๋ฒ„ ์ธก ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ์—†์œผ๋ฏ€๋กœ ์ง€๊ธˆ์€ ์—ฌ๊ธฐ์„œ ์ˆ˜ํ–‰ํ•  ์ž‘์—…์ด ์—†์Šต๋‹ˆ๋‹ค. ์›น ๊ตฌ์„ฑ ์š”์†Œ ์ž‘์„ฑ์ž์™€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์œ ์ง€ ๊ด€๋ฆฌ์ž๋Š” React๊ฐ€ ๊ฑฐ๊ธฐ์— ๋‹ค๋ฆฌ๋ฅผ ๊ตฌ์ถ•ํ•˜๊ธฐ ์ „์— ๋ช‡ ๊ฐ€์ง€ ์‚ฌํ•ญ์„ ํŒŒ์•…ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

SSR ๋‚ด ํŒ€์˜ ์ž‘ํ’ˆ์—์„œ ์šฐ๋ฆฌ๋Š” ํŒจ์น˜์— ์˜ํ•ด ๋ฐ˜์ž‘์šฉ๊ณผ ํ†ตํ•ฉ ํ•œ createElement ํ•˜๊ณ  ์‚ฌ์šฉํ•˜์—ฌ dangerouslySetInnerHTML . ๋‚˜๋Š” ๊ทธ๊ฒƒ์ด ์šฐ๋ฆฌ๊ฐ€ ์ž ์‹œ ๋™์•ˆ ์žˆ์„ ํ†ตํ•ฉ/์‹คํ—˜์˜ ์ˆ˜์ค€์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์กฐ๋งŒ๊ฐ„ SSR ์‹œ์Šคํ…œ ๋‚ด์—์„œ ์ƒํ˜ธ ์šด์šฉ์„ฑ์„ ์œ„ํ•œ ์ผ๋ถ€ ์‚ฌ์šฉ์ž ์˜์—ญ ํ”„๋กœํ† ์ฝœ์— ์ˆ˜๋ ดํ•  ์ˆ˜ ์žˆ๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค. ๊ทธ๋•Œ๊นŒ์ง€๋Š” _deep_ SSR ์—†์ด ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ ์†์„ฑ ๋ฐ ์ด๋ฒคํŠธ ์ง€์›์„ ๊ฐ–๋Š” ๊ฒƒ์ด ์™„๋ฒฝํ•˜๊ฒŒ ์•ˆ์ „ํ•˜๊ณ  ์‹ ์ค‘ํ•ฉ๋‹ˆ๋‹ค. ์š”์†Œ์˜ ํƒœ๊ทธ๋Š” ์˜ค๋Š˜๋‚ ๊ณผ ๊ฐ™์ด ์—ฌ์ „ํžˆ React ๊ตฌ์„ฑ ์š”์†Œ์˜ ์ž์‹์œผ๋กœ SSR'๋ฉ๋‹ˆ๋‹ค.

id ๋ฐ className๊ณผ ๊ฐ™์€ ๋‚ด์žฅ ๋ฐ˜์˜ ์†์„ฑ์„ ์ œ์™ธํ•˜๊ณ ๋Š” ์‚ญ์ œํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ํด๋ผ์ด์–ธํŠธ์—์„œ๋งŒ ์“ธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๊ฒƒ์ด ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€ ์ดํ•ดํ•˜๋„๋ก ๋„์™€ ์ฃผ์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ? ์˜ˆ๋ฅผ ๋“ค์–ด <github-icon iconname="smiley" /> ๊ฐ€ ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค. SSR์ด HTML ์‘๋‹ต์— <github-icon /> ๋งŒ ํฌํ•จํ•˜๋ฉด React๊ฐ€ ์ˆ˜ํ™” ์ค‘์— domNode.iconname = ... ์„ค์ •ํ•œ๋‹ค๋Š” ๋œป์ธ๊ฐ€์š”? ์ด ๊ฒฝ์šฐ React ํ•˜์ด๋“œ๋ ˆ์ด์…˜์ด ๋ฐœ์ƒํ•˜๊ธฐ ์ „์— ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ ๊ตฌํ˜„์ด ๋กœ๋“œ๋˜๋ฉด ์–ด๋–ป๊ฒŒ ๋˜๋Š”์ง€ ์ž˜ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค. iconname ๊ฐ€ HTML์— ์—†๋Š” ๊ฒฝ์šฐ github-icon ๊ตฌํ˜„์—์„œ ๋ Œ๋”๋งํ•  ์•„์ด์ฝ˜์„ ์–ด๋–ป๊ฒŒ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

์•„์ง ์ด ํ”„๋กœ์„ธ์Šค์— ๋Œ€ํ•œ ๊ณตํ†ต ์„œ๋ฒ„ ์ธก ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ์—†์œผ๋ฏ€๋กœ ์ง€๊ธˆ์€ ์—ฌ๊ธฐ์„œ ์ˆ˜ํ–‰ํ•  ์ž‘์—…์ด ์—†์Šต๋‹ˆ๋‹ค. ์›น ๊ตฌ์„ฑ ์š”์†Œ ์ž‘์„ฑ์ž์™€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์œ ์ง€ ๊ด€๋ฆฌ์ž๋Š” React๊ฐ€ ๊ฑฐ๊ธฐ์— ๋‹ค๋ฆฌ๋ฅผ ๊ตฌ์ถ•ํ•˜๊ธฐ ์ „์— ๋ช‡ ๊ฐ€์ง€ ์‚ฌํ•ญ์„ ํŒŒ์•…ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์— ์ปค๋ฎค๋‹ˆํ‹ฐ๊ฐ€ ํ•ฉ์˜๋ฅผ ์ด๋ฃจ๊ธฐ ์œ„ํ•ด ํŠน๋ณ„ํžˆ ํ•ด์•ผ ํ•  ์ผ์ด ์žˆ๋Š”์ง€ ๊ถ๊ธˆํ•ฉ๋‹ˆ๋‹ค. ๋ฆฌ์•กํŠธ๊ฐ€ ๊ทธ๊ฒƒ์„ ๋ง‰๊ณ  ์žˆ์Šต๋‹ˆ๊นŒ? ์ด ๋ฌธ์ œ๊ฐ€ 2017๋…„๋ถ€ํ„ฐ ๊ณต๊ฐœ๋˜์–ด ๋‹ต๋‹ตํ•จ์„ ๋งŽ์ด ์ดํ•ดํ•ฉ๋‹ˆ๋‹ค. ํ•œํŽธ, 3๋…„์ด ์ง€๋‚ฌ๊ณ  ์•„์ง ์ด๋Ÿฌํ•œ ํ•ฉ์˜๊ฐ€ ์ด๋ฃจ์–ด์ง€์ง€ ์•Š์•˜๋‹ค๊ณ  ๋ง์”€ํ•˜์‹œ๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๋ฐœ์ƒํ•˜๊ธฐ ์œ„ํ•œ ์ „์ œ ์กฐ๊ฑด์€ ๋ฌด์—‡์ž…๋‹ˆ๊นŒ? ๋‹จ์ง€ ๋” ๋งŽ์€ ์‹คํ—˜์˜ ๋ฌธ์ œ์ž…๋‹ˆ๊นŒ?

@gaearon ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ ๊ตฌํ˜„์ด React ์ˆ˜ํ™” ์ „์— ๋กœ๋“œ๋˜๋ฉด iconname ์†์„ฑ์˜ ๊ธฐ๋ณธ ๊ฐ’์ด ๋ฌด์—‡์ด๋“  ํ• ๋‹นํ•ฉ๋‹ˆ๋‹ค. if _iconname_ does not exist in the HTML ์€(๋Š”) ๋ฌด์Šจ ๋œป์ธ๊ฐ€์š”? HTMLElement ์œ ํ˜•์— ์ •์˜๋œ ์†์„ฑ์ด ์—†์œผ๋ฉด ๋ฌด์‹œํ•ฉ๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ ์ •์˜๊ฐ€ ๋กœ๋“œ๋˜๋ฉด HTMLElement ์œ ํ˜•์„ ํ™•์žฅํ•˜๊ณ  iconname ์ •์˜ํ•˜๊ณ  ์ „๋‹ฌ๋˜๋Š” ์ƒˆ ๊ฐ’์— ๋ฐ˜์‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‚˜๋Š” ์ด๊ฒƒ์„ ์‚ฌ์šฉ์ž์˜ ๊ด€์ ์—์„œ ์ดํ•ดํ•˜๋ ค๊ณ  ๋…ธ๋ ฅํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์„œ๋ฒ„์—์„œ ํŽ˜์ด์ง€๋ฅผ ๋ Œ๋”๋งํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ํ…์ŠคํŠธ ์ค‘๊ฐ„์— ์•„์ด์ฝ˜์ด ์žˆ์Šต๋‹ˆ๋‹ค. ํ•ด๋‹น ์•„์ด์ฝ˜์€ ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ๋กœ ๊ตฌํ˜„๋ฉ๋‹ˆ๋‹ค. ์ตœ์ข… ์‚ฌ์šฉ์ž๊ฐ€ ๊ฒฝํ—˜ํ•ด์•ผ ํ•˜๋Š” ์ˆœ์„œ๋Š” ๋ฌด์—‡์ž…๋‹ˆ๊นŒ?

์ง€๊ธˆ๊นŒ์ง€ ๋‚ด ์ดํ•ด๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  1. ๊ทธ๋“ค์€ ์ดˆ๊ธฐ ๋ Œ๋”๋ง ๊ฒฐ๊ณผ๋ฅผ ๋ด…๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์—๋Š” ๋ชจ๋“  ์ผ๋ฐ˜ ๋งˆํฌ์—…์ด ํฌํ•จ๋˜์ง€๋งŒ <github-icon> ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ๋Š” ์ „ํ˜€ ํ‘œ์‹œ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์•„๋งˆ๋„ ๋นˆ div์™€ ๊ฐ™์€ ๊ตฌ๋ฉ์ด ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ œ๊ฐ€ ํ‹€๋ ธ๋‹ค๋ฉด ์ง€์ ํ•ด์ฃผ์„ธ์š”(?). ๊ตฌํ˜„์ด ์•„์ง ๋กœ๋“œ๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.

  2. <github-icon> ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ ๊ตฌํ˜„์ด ๋กœ๋“œ๋˜๊ณ  ๋“ฑ๋ก๋ฉ๋‹ˆ๋‹ค. ๋‚ด๊ฐ€ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ดํ•ดํ•˜๋ฉด ์ด๊ฒƒ์ด "์—…๊ทธ๋ ˆ์ด๋“œ"๋ผ๋Š” ํ”„๋กœ์„ธ์Šค์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ JS๊ฐ€ ์ค€๋น„๋˜์–ด ์žˆ์–ด๋„ HTML์— iconname ๋ฅผ ํฌํ•จํ•˜์ง€ ์•Š์•˜๊ธฐ ๋•Œ๋ฌธ์— ์—ฌ์ „ํžˆ ์•„๋ฌด๊ฒƒ๋„ ํ‘œ์‹œ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๋ Œ๋”๋งํ•  ์•„์ด์ฝ˜์— ๋Œ€ํ•œ ์ •๋ณด๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ์ด์ „์— "๋น„ ๋‚ด์žฅ ์†์„ฑ์€ HTML์—์„œ ์‚ญ์ œํ•  ์ˆ˜ ์žˆ๋‹ค"๊ณ  ๋งํ–ˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์‚ฌ์šฉ์ž๋Š” ์—ฌ์ „ํžˆ "๊ตฌ๋ฉ"์„ ๋ด…๋‹ˆ๋‹ค.

  3. React์™€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ฝ”๋“œ๊ฐ€ ๋กœ๋“œ๋ฉ๋‹ˆ๋‹ค. ์ˆ˜๋ถ„์ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ์ˆ˜ํ™”ํ•˜๋Š” ๋™์•ˆ React๋Š” ํœด๋ฆฌ์Šคํ‹ฑ์— ๋”ฐ๋ผ .iconname = ์†์„ฑ์„ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž๋Š” ์ด์ œ ์•„์ด์ฝ˜์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ JS ๊ตฌํ˜„์ด ๋จผ์ € ๋กœ๋“œ๋˜๋Š” ๊ฒฝ์šฐ์— ๋Œ€ํ•œ ์˜ฌ๋ฐ”๋ฅธ ๋ถ„์„์ž…๋‹ˆ๊นŒ? ์ด๊ฒƒ์ด WC ์ปค๋ฎค๋‹ˆํ‹ฐ์— ๋ฐ”๋žŒ์งํ•œ ํ–‰๋™์ž…๋‹ˆ๊นŒ?

@gaearon ๋„ต ์ด ์ƒํ™ฉ์—์„œ ์˜ˆ์ƒ๋˜๋Š” ์ผ์ž…๋‹ˆ๋‹ค.

ํ•œํŽธ 3๋…„์ด ์ง€๋‚ฌ๋Š”๋ฐ ์•„์ง ์ด๋Ÿฐ ๊ณต๊ฐ๋Œ€๊ฐ€ ํ˜•์„ฑ๋˜์ง€ ์•Š์•˜๋‹ค๋Š” ๋ง์”€์ด์‹  ๊ฒƒ ๊ฐ™์€๋ฐ์š”.

ํ•ฉ์˜๊ฐ€ ์ด๋ฃจ์–ด์ง€์ง€ ์•Š์•˜๋‹ค๋Š” ๋ง์€ ์•„๋‹™๋‹ˆ๋‹ค. ์ง€๊ธˆ ๋‹น์žฅ์€ _deep_ SSR์— ๋Œ€ํ•ด ๊ฑฑ์ •ํ•  ํ•„์š”๊ฐ€ ์—†์œผ๋ฉฐ ํ˜„์žฌ ๋‹ฌ์„ฑํ•  ์ˆ˜ ์žˆ๊ณ  ๋งค์šฐ ์œ ์šฉํ•œ ๊ฐ€์žฅ ๊ธฐ๋ณธ์ ์ธ ํด๋ผ์ด์–ธํŠธ ์ธก ์ƒํ˜ธ ์šด์šฉ์„ฑ์„ ๋ง‰๋Š” ๋ง‰์—ฐํ•œ ์šฐ๋ ค๋กœ ์ธํ•ด ๊ฑฑ์ •ํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

๋‚˜๋Š” ์ด ๊ตฌ๋ณ„(๊นŠ์€ ๊ฒƒ๊ณผ ์–•์€ ๊ฒƒ)์„ ๋ณธ ์ ์ด ์—†์œผ๋ฏ€๋กœ ๋‚ด๊ฐ€ ๋‹น์‹ ์„ ์ดํ•ดํ–ˆ๋Š”์ง€ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด ๋‹ค์‹œ ๋งํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

"๊นŠ์€" SSR์€ React ๊ตฌ์„ฑ ์š”์†Œ์—์„œ ์ž‘๋™ํ•˜๋Š” ๋ฐฉ์‹๊ณผ ์œ ์‚ฌํ•œ SSR์„ ์˜๋ฏธํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, CE๋ฅผ ๋ Œ๋”๋งํ•˜๋ฉด ํ•ด๋‹น CE์˜ ๋…ผ๋ฆฌ๊ฐ€ ๋กœ๋“œ๋˜๊ธฐ ์ „์— ํ‘œ์‹œ๋  ์ˆ˜ ์žˆ๋Š” ์ถœ๋ ฅ์ด ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ์šฐ๋ฆฌ๊ฐ€ ์ง€๊ธˆ ์ง€์›์— ๋Œ€ํ•ด ๊ฑฑ์ •ํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค๊ณ  ๋งํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์€ ๋‚˜์—๊ฒŒ ์˜๋ฏธ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

"๊นŠ์ง€ ์•Š์€" SSR์€ CE ํƒœ๊ทธ ์ž์ฒด๋ฅผ HTML์— ๋„ฃ์—ˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์ด ๋ฌด์—‡์„ ํ•ด๊ฒฐํ•˜๋Š”์ง€ ๊ฑฑ์ •ํ•˜์ง€ ์•Š๊ณ . ์ €์—๊ฒŒ๋„ ์˜๋ฏธ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‚ด ์งˆ๋ฌธ์€ _์ด_ ํ๋ฆ„์— ๊ด€ํ•œ ๊ฒƒ์ด์ง€๋งŒ "๊นŠ์€" SSR์— ๋Œ€ํ•œ ๊ฒƒ์ด ์•„๋‹™๋‹ˆ๋‹ค.

ํŠนํžˆ https://github.com/facebook/react/issues/11347#issuecomment -713230572 ๋Š” CE ๋กœ์ง์„ ๋‹ค์šด๋กœ๋“œํ•œ _์ด๋ฏธ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๊ฒฝ์šฐ์—๋„ ์ˆ˜ํ™”๋  ๋•Œ๊นŒ์ง€ ์‚ฌ์šฉ์ž์—๊ฒŒ ์•„๋ฌด ๊ฒƒ๋„ ํ‘œ์‹œํ•  ์ˆ˜ ์—†๋Š” ์ƒํ™ฉ์„ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค. ์ „์ฒด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ JS ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ๊ฐ€ ๋กœ๋“œ๋˜๊ณ  ์ˆ˜ํ™”๋  ๋•Œ๊นŒ์ง€ ์†์„ฑ์„ ์•Œ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด ์‹ค์ œ๋กœ ์›ํ•˜๋Š” ๋™์ž‘์ธ์ง€ ๋ฌป๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

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

@gaearon

https://github.com/facebook/react/issues/11347#issuecomment -713230572๊ฐ€ ์ด ๊ธฐ๋Šฅ์ด ํ•„์š”ํ•œ ๊ฐ€์žฅ ์ข‹์€ ์˜ˆ๊ฐ€ ์•„๋‹ ์ˆ˜๋„ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

์ ์–ด๋„ ๋‚ด ๊ฒฝํ—˜์— ๋”ฐ๋ฅด๋ฉด ์†์„ฑ๋ณด๋‹ค๋Š” ์†์„ฑ์„ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์ด ๋ฌธ์ž์—ด, ์ˆซ์ž ๋˜๋Š” ๋ถ€์šธ๊ณผ ๊ฐ™์€ ๋‹จ์ˆœํ•œ ์œ ํ˜•์— ํ•„์š”ํ•œ ์ „๋ถ€๋Š” ์•„๋‹™๋‹ˆ๋‹ค.

์„ค๋ช…ํ•˜๋Š” ๊ฒฝ์šฐ๋Š” iconname ๋ฅผ ์†์„ฑ์œผ๋กœ ์ง์ ‘ ์‚ฌ์šฉํ•˜์—ฌ ์‰ฝ๊ฒŒ ๋‹ฌ์„ฑํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ์ˆ˜ํ™”๋ฅผ ๊ธฐ๋‹ค๋ฆฌ์ง€ ์•Š๊ณ  ์—ฌ์ „ํžˆ ๊ฑฐ์˜ ๋™์ผํ•œ ์ตœ์ข… ๋ Œ๋”๋ง ๊ฒฐ๊ณผ์ž…๋‹ˆ๋‹ค.

NS์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ ๊ตฌํ˜„์ด ๋กœ๋“œ๋˜๊ณ  ๋“ฑ๋ก๋ฉ๋‹ˆ๋‹ค. ๋‚ด๊ฐ€ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ดํ•ดํ•˜๋ฉด ์ด๊ฒƒ์ด "์—…๊ทธ๋ ˆ์ด๋“œ"๋ผ๋Š” ํ”„๋กœ์„ธ์Šค์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ JS๊ฐ€ ์ค€๋น„๋˜์–ด ์žˆ์Œ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ  HTML์— iconname์„ ํฌํ•จํ•˜์ง€ ์•Š์•˜๊ธฐ ๋•Œ๋ฌธ์— ์—ฌ์ „ํžˆ ์•„๋ฌด๊ฒƒ๋„ ํ‘œ์‹œ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๋ Œ๋”๋งํ•  ์•„์ด์ฝ˜์— ๋Œ€ํ•œ ์ •๋ณด๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ์ด์ „์— "๋น„ ๋‚ด์žฅ ์†์„ฑ์€ HTML์—์„œ ์‚ญ์ œํ•  ์ˆ˜ ์žˆ๋‹ค"๊ณ  ๋งํ–ˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์‚ฌ์šฉ์ž๋Š” ์—ฌ์ „ํžˆ "๊ตฌ๋ฉ"์„ ๋ด…๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์„œ ์–ธ๊ธ‰ํ•œ ๋‚ด์šฉ์€ ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ๊ตฌํ˜„๋˜๋Š” ๋ฐฉ์‹์— ๋”ฐ๋ผ "๊ตฌ๋ฉ"์ด ํ‘œ์‹œ๋˜๋Š” ์ด ๋ฌธ์ œ๋ฅผ ํ”ผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ๊ฒฝ์šฐ ๊ธฐ๋ณธ ์„ค์ •์„ ๋‹จ์ˆœํ•˜๊ฒŒ ์„ค์ •ํ•˜๊ฑฐ๋‚˜ ์Šฌ๋กฏ์„ ํ†ตํ•ด ์ฝ˜ํ…์ธ ์˜ ์ผ๋ถ€ ๋˜๋Š” ๋Œ€๋ถ€๋ถ„์„ ์ˆ˜๋ฝํ•˜์—ฌ ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ์—…๊ทธ๋ ˆ์ด๋“œ๋˜๊ธฐ ์ „์—๋„ ์ฝ˜ํ…์ธ ๊ฐ€ ํ‘œ์‹œ๋˜๋„๋ก ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


์ด ๊ธฐ๋Šฅ์€ ๊ฐ์ฒด, ๋ฐฐ์—ด, ํ•จ์ˆ˜ ๋“ฑ์˜ ์†์„ฑ์ด ์žˆ๋Š” ๋” ๋ณต์žกํ•œ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐ ๊ฐ€์žฅ ์œ ์šฉํ•  ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

lit-virtualizer ๊ฐ€์ƒ ์Šคํฌ๋กค๋Ÿฌ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์˜ˆ๋กœ ๋“ค์–ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

์ด๊ฒƒ์ด ์ œ๋Œ€๋กœ ์ž‘๋™ํ•˜๋ ค๋ฉด items ๋ฐฐ์—ด๊ณผ renderItem ํ•จ์ˆ˜๊ฐ€ ํ•„์š”ํ•˜๋ฉฐ ์„ ํƒ์ ์œผ๋กœ scrollTarget ์š”์†Œ๋ฅผ ์„ค์ •ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๋ชจ๋“  ๊ฒƒ์€ refs๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ React์—์„œ๋งŒ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ง€๊ธˆ ๋ฐ”๋กœ.

์ด์™€ ๊ฐ™์€ ๊ฒฝ์šฐ์—๋Š” ์ผ์ข…์˜ ํŽ˜์ด์ง€ ๋งค๊น€ ๋˜๋Š” ์ง€์—ฐ ๋กœ๋”ฉ์œผ๋กœ ์ฝ˜ํ…์ธ ๋ฅผ ๋กœ๋“œํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ SSR ์ผ€์ด์Šค์˜ ์ˆ˜ํ™” ๋‹จ๊ณ„๊นŒ์ง€ ์ฝ˜ํ…์ธ ๊ฐ€ ์—†๋Š” ๊ฒƒ์ด ๋ฌธ์ œ๊ฐ€ ๋˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

@gaearon ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ๋Š” DOM ํ‘œ์ค€์ด๋ฏ€๋กœ ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ชจ๋“  ์‚ฌ๋žŒ์ด ๋™์ผํ•œ ๋ฐฉ์‹์œผ๋กœ ์‚ฌ์šฉํ•œ๋‹ค๋Š” ์˜๋ฏธ์—์„œ "WC ์ปค๋ฎค๋‹ˆํ‹ฐ" ์ž์ฒด๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ๋Š” ๋ณธ์งˆ์ ์œผ๋กœ ์‚ฌ๋žŒ๋“ค์ด ๊ตฌ์ถ•ํ•˜๋Š” ๋‚ฎ์€ ์ˆ˜์ค€์˜ ๊ธฐ๋ณธ ์š”์†Œ์ด๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ ๊ฐœ๋ฐœ์ž๋ฅผ ์œ„ํ•ด ๊ณ ์œ ํ•œ ๋ฐฉ์‹์œผ๋กœ ํ†ตํ•ฉ๋ฉ๋‹ˆ๋‹ค.

์ฆ‰, ์‹œ๊ฐ„์ด ์ง€๋‚จ์— ๋”ฐ๋ผ ์ˆ˜๋งŽ์€ ํŒจํ„ด์ด ๋“ฑ์žฅํ–ˆ์œผ๋ฉฐ ๋ชจ๋“  ์ธ๊ธฐ ์žˆ๋Š” ํ”„๋ ˆ์ž„์›Œํฌ(React ์ œ์™ธ)๋Š” ์ด DOM ํ‘œ์ค€์— ๋Œ€ํ•œ ํ˜ธํ™˜์„ฑ์„ ์ œ๊ณตํ•˜๊ธฐ ์œ„ํ•ด ๋ช‡ ๊ฐ€์ง€ ์†”๋ฃจ์…˜์„ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค. https://custom-elements-everywhere.com/ ์—์„œ ๋ณผ ์ˆ˜ ์žˆ๋“ฏ์ด ๋ชจ๋“  ํ”„๋ ˆ์ž„์›Œํฌ/๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ(React ์ œ์™ธ)๋Š” ๋‹ค๋ฅธ ์˜ต์…˜์„ ์„ ํƒํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฒˆ ํ˜ธ์—์„œ ์„ ํƒํ•œ ์˜ต์…˜์€ ์˜ต์…˜ 1, 2, 3์œผ๋กœ ๋‚˜์—ด๋ฉ๋‹ˆ๋‹ค. ํ˜„์žฌ ์˜ต์…˜ 4 ๋˜๋Š” 5๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ํ”„๋ ˆ์ž„์›Œํฌ/๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์—†์œผ๋ฉฐ ์ด๋Ÿฌํ•œ ์˜ต์…˜์„ ๊ตฌํ˜„ํ•˜๋Š” ๊ฒƒ์ด ๋ฐ”๋žŒ์งํ•˜์ง€ ์•Š๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ๋‚˜๋Š” React๊ฐ€ ๋‹ค๋ฅธ ํ”„๋ ˆ์ž„์›Œํฌ/๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๋”ฐ๋ฅด๊ณ  ์ž‘๋™์ด ์ž…์ฆ๋œ ์˜ต์…˜(์˜ˆ: ์˜ต์…˜ 1-3 ์ค‘์—์„œ ์„ ํƒ)์„ ์„ ํƒํ•  ๊ฒƒ์„ ์ œ์•ˆํ•ฉ๋‹ˆ๋‹ค. ๋‚˜๋Š” React๊ฐ€ ์—ฌ๊ธฐ์—์„œ ์˜ต์…˜ 4 ๋˜๋Š” 5๋ฅผ ์„ ํƒํ•˜์—ฌ ๋ฐ”ํ€ด๋ฅผ ์žฌ๋ฐœ๋ช…ํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ๊ฐ€ ์—†๋Š” React ๋˜๋Š” DOM ํ‘œ์ค€์„ ๊ธฐ๋ฐ˜์œผ๋กœ ๊ตฌ์ถ•๋œ ์†”๋ฃจ์…˜์— ๋Œ€ํ•ด ์žฅ๊ธฐ์ ์œผ๋กœ ์œ ์ง€ ๊ด€๋ฆฌ ๊ฐ€๋Šฅํ•œ ์†”๋ฃจ์…˜์ž…๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ์ œ๊ฑฐ ํ”„๋กœ์„ธ์Šค(์•„๋ž˜์— ๋งํฌ๋œ ์ฃผ์„ ํฌํ•จ)์— ์˜ํ•ด ์˜ต์…˜ 3์€ JSX์—์„œ ์ˆ˜ํ–‰๋˜์ง€ ์•Š์„ ๊ฒƒ์ด๊ณ  ์˜ต์…˜ 4์™€ 5๋Š” ์ด ์Šค๋ ˆ๋“œ์—์„œ WC ์‚ฌ๋žŒ๋“ค์— ์˜ํ•ด ๋ฐ”๋žŒ์งํ•˜์ง€ ์•Š์€ ๊ฒƒ์œผ๋กœ ํ‘œ์‹œ๋˜์—ˆ์œผ๋ฏ€๋กœ ์šฐ๋ฆฌ๋Š” 1 ๋˜๋Š” 2์— ๊ฐ‡ํ˜€ ์žˆ์Šต๋‹ˆ๋‹ค. .

๊ทธ๋ฆฌ๊ณ  1๋ฒˆ์€ ๋ฒ„ํ‹ธ ์ˆ˜ ์—†๋Š” ๋‹จ์ ์ด ์žˆ๋Š” ๊ฒƒ ๊ฐ™์•„์„œ ์˜ต์…˜ 2๋ฒˆ ์ด ํ•˜๋‚˜์ธ ๊ฒƒ ๊ฐ™์ฃ ? Preact๊ฐ€ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ๊ฐ€์‹ญ์‹œ์˜ค.


ํ˜„์žฌ ์˜ต์…˜ 4 ๋˜๋Š” 5๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ํ”„๋ ˆ์ž„์›Œํฌ/๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์—†์œผ๋ฉฐ ์ด๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๊ฒƒ์ด ๋ฐ”๋žŒ์งํ•˜์ง€ ์•Š๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

( https://github.com/facebook/react/issues/11347#issuecomment-713474037์˜ @TimvdLippe )

์ด ํŠน์ • ๊ธฐ๋Šฅ๋งŒ์„ ์œ„ํ•ด ์ƒˆ๋กœ์šด JSX ๊ตฌ๋ฌธ์„ ๋„์ž…ํ•  ๊ฐ€๋Šฅ์„ฑ์€ ๊ฑฐ์˜ ์—†๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

( https://github.com/facebook/react/issues/11347#issuecomment-713210204์˜ @gaearon )

๊ทธ๊ฒƒ์€ ๋‚˜์—๊ฒŒ ์ดํ•ด๊ฐ€ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์š”์•ฝ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค! ๐Ÿ˜„

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

๋‚˜๋Š” ์ž˜ ๋”ฐ๋ฅด์ง€ ์•Š๋Š”๋‹ค. ๋‚ด ๊ฐ€์ƒ ์‹œ๋‚˜๋ฆฌ์˜ค๋Š” https://github.com/facebook/react/issues/11347#issuecomment -713223628์— ๋Œ€ํ•œ ์‘๋‹ต์œผ๋กœ id ์ œ์™ธํ•˜๊ณ  ์„œ๋ฒ„ ์ƒ์„ฑ HTML์—์„œ ์†์„ฑ์„ ์ „ํ˜€ ๋‚ด๋ณด๋‚ด์ง€ ์•Š์•„์•ผ ํ•œ๋‹ค๋Š” ์ œ์•ˆ์ฒ˜๋Ÿผ ๋“ค๋ ธ์Šต๋‹ˆ๋‹ค.

  1. ๋‚ด๊ฐ€ ์„ค๋ช…ํ•œ ์‹œ๋‚˜๋ฆฌ์˜ค์—์„œ ์„œ๋ฒ„ ์ƒ์„ฑ HTML์—์„œ ์ •ํ™•ํžˆ ์ง๋ ฌํ™”๋˜๋Š” ๊ฒƒ์€ ๋ฌด์—‡์ž…๋‹ˆ๊นŒ?
    NS. <github-icon iconname="smiley" />
    NS. ๊ท€ํ•˜๊ฐ€ ์ œ๊ธฐํ•œ ๊ฒฝ์šฐ, ์˜ˆ: <github-icon icon={{ name: "smiley" }} />
  2. ๋‘ ๊ฒฝ์šฐ ๋ชจ๋‘ ์ˆ˜ํ™” ์ค‘์— ํด๋ผ์ด์–ธํŠธ์—์„œ ํ˜ธ์ถœ๋˜๋Š” DOM API

๊ฐ์‚ฌ ํ•ด์š”!

React.createElement() ๋ฅผ ๋‚ด๋ถ€์—์„œ ์†์„ฑ ๋งคํ•‘์„ ์ˆ˜ํ–‰ํ•˜๋Š” ์‚ฌ์šฉ์ž ์ •์˜ ๊ตฌํ˜„์œผ๋กœ ๋Œ€์ฒดํ•˜์—ฌ ์‹ฌ์„ ์ƒ์„ฑํ•˜๋Š” ์˜ต์…˜์œผ๋กœ ๊ฐ„์ฃผ๋˜์—ˆ์Šต๋‹ˆ๊นŒ?

์‚ฌ์šฉ ์˜ˆ:

/** <strong i="8">@jsx</strong> h */
import { h } from 'react-wc-jsx-shim';

function Demo({ items }) {
   return <my-custom-list items={items} />
}

์ดˆ์•ˆ ๊ตฌํ˜„:

export function h(element, props, children) {
   if(typeof element === 'string' && element.includes('-')) {
      return React.createElement(Wrapper, { props, customElementName: element }, children)
   }
   return React.createElement(element, props, children);

}

function Wrapper({customElementName, props}) {
   const ref = React.useRef();
   React.useEffect(() => {
      for(const prop in props) {
         ref.current[prop] = props[prop];
      }
   });
   return React.createElement(customElementName, { ref, ...props });
}

์ด๊ฒƒ์ด ๊ธฐ๋ณธ ์ œ๊ณต ๊ธฐ๋Šฅ์ด ์•„๋‹ˆ๋ผ๋Š” ๊ฒƒ์„ ์•Œ๊ณ  ์žˆ์ง€๋งŒ ๋งค์šฐ ๋‚ฎ์€ ์˜ค๋ฒ„ํ—ค๋“œ๋กœ ์‚ฌ์šฉ์ž ์ฐจ๋‹จ์„ ํ•ด์ œํ•ด์•ผ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

@just-boris๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ createElement ํŒจ์น˜ ๋˜๋Š” ๋ž˜ํผ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์•ฑ์ด๋‚˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ํ˜„์žฌ ์ˆ˜ํ–‰ํ•˜๋Š” ์ž‘์—…์ž…๋‹ˆ๋‹ค. ๋˜ํ•œ React์—์„œ ํŠน๋ณ„ํ•œ ๊ฒฝ์šฐ์˜ ์†์„ฑ ์ด๋ฆ„์„ ์ œ์™ธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋‚ด ๋ณด๋‚ธ ๋ชฉ๋ก์ด ์—†๋‹ค๊ณ  ์ƒ๊ฐํ•˜๋ฏ€๋กœ ['children', 'localName', 'ref', 'elementRef', 'style', 'className'] ์™€ ๊ฐ™์€ ๊ฑฐ๋ถ€ ๋ชฉ๋ก์„ ํ•˜๋“œ ์ฝ”๋”ฉํ•ฉ๋‹ˆ๋‹ค.

ref ๊ธฐ๋ฐ˜์ด๊ธฐ ๋•Œ๋ฌธ์— ์†์„ฑ์€ ์„œ๋ฒ„์—์„œ ์„ค์ •๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด ๋‚ด๊ฐ€ ์šฐ๋ ค๋ฅผ ๋ชจํ˜ธํ•˜๋‹ค๊ณ  ๋ถ€๋ฅด๋Š” ์ด์œ ์ž…๋‹ˆ๋‹ค. React์—์„œ๋Š” ์†์„ฑ์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด ์ „ํ˜€ ์—†์œผ๋ฏ€๋กœ ์ง€๊ธˆ์€ ๋ชจ๋‘ ๋ง๊ฐ€์กŒ์Šต๋‹ˆ๋‹ค. ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์€ ์ด๋ฏธ ํด๋ผ์ด์–ธํŠธ์—์„œ๋งŒ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ์„œ๋ฒ„๊ฐ€ ์•„๋‹Œ ํด๋ผ์ด์–ธํŠธ์—์„œ ์†์„ฑ์„ ์„ค์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ๋‚ด์žฅ๋˜์–ด ์žˆ์œผ๋ฉด SSR์ด ๊ฐ‘์ž๊ธฐ ์ˆ˜์ •๋˜๊ฑฐ๋‚˜ ์ค‘๋‹จ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์‚ฌ์‹ค ์ €๋Š” SSR๋ณด๋‹ค ์ด๋ฒคํŠธ์— ๋” ๊ด€์‹ฌ์ด ์žˆ์Šต๋‹ˆ๋‹ค. React๋Š” ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ์ถ”๊ฐ€ํ•  ๋ฐฉ๋ฒ•์ด ์—†์œผ๋ฉฐ, ์ด๋Š” ๊ธฐ๋ณธ DOM API์™€์˜ ์ƒํ˜ธ ์šด์šฉ์„ฑ์—์„œ ํฐ ๊ตฌ๋ฉ์ž…๋‹ˆ๋‹ค.

React.createElement()๋ฅผ ๋‚ด๋ถ€์—์„œ ์†์„ฑ ๋งคํ•‘์„ ์ˆ˜ํ–‰ํ•˜๋Š” ์‚ฌ์šฉ์ž ์ง€์ • ๊ตฌํ˜„์œผ๋กœ ๋Œ€์ฒดํ•˜์—ฌ shim์„ ๋งŒ๋“œ๋Š” ์˜ต์…˜์œผ๋กœ ๊ฐ„์ฃผ๋˜์—ˆ์Šต๋‹ˆ๊นŒ?

์›๋ž˜ ๋ฌธ์ œ์—์„œ Rob์ด ์–ธ๊ธ‰ํ–ˆ๋“ฏ์ด https://github.com/skatejs/val ์„ ํ†ตํ•ด ๊ณผ๊ฑฐ์— ์ด๊ฒƒ์„ ์‹คํ—˜ํ•œ ์ ์ด ์žˆ์œผ๋ฏ€๋กœ React.createElement ๋ฅผ ๋ž˜ํ•‘ํ•˜๋Š” ์‚ฌ์šฉ์ž ์ •์˜ JSX pragma๋ฅผ ๊ฐ–๋Š” ๊ฒƒ์ด ์‹คํ–‰ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค ๋‹จ๊ธฐ - ์†”๋ฃจ์…˜.

๋˜ํ•œ ํŠนํžˆ React์— ๋Œ€ํ•ด ๊นŠ๊ณ  ์–•์€ SSR์ด๋ผ๊ณ  ํ•˜๋Š” ๊ฒƒ์„ ๋ชจ๋‘ ๊ตฌํ˜„ํ•˜๋Š” Skate์˜ WIP ๋ถ„๊ธฐ ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ง€๊ธˆ๊นŒ์ง€ ์ด ์ž‘์—…์—์„œ ์–ป์€ ๊ตํ›ˆ์€ ๊ฐ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์ž์ฒด API ๋ฐ ์•Œ๊ณ ๋ฆฌ์ฆ˜์— ์˜์กดํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์‹ฌ์ธต SSR์„ ์ˆ˜ํ–‰ํ•˜๋ ค๋Š” ๊ฒฝ์šฐ ๋ชจ๋“  ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ๋Œ€ํ•ด ๋‹จ์ผ JSX ๋ž˜ํผ๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์—†๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. (์ปจํ…์ŠคํŠธ๋ฅผ ์œ„ํ•ด Skate๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ํ•ต์‹ฌ ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ ๋ถ€๋ถ„๊ณผ ์‹œ์žฅ์—์„œ ์ธ๊ธฐ ์žˆ๋Š” ๊ฐ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ํ†ตํ•ฉํ•˜์—ฌ ์ „๋ฐ˜์ ์œผ๋กœ ์†Œ๋น„ ๋ฐ ์‚ฌ์šฉ์„ ์ผ๊ด€๋˜๊ฒŒ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด ๊ตฌ์ถ•๋œ ์ž‘์€ ๋ ˆ์ด์–ด๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.)


๋‚˜๋Š” ๋” ์ด์ƒ ์˜คํ”ˆ ์†Œ์Šค์—์„œ ๋งŽ์€ ์ผ์„ ํ•˜์ง€ ์•Š์œผ๋ฉฐ ๋” ์ด์ƒ ํŠธ์œ„ํ„ฐ๋„ ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์˜ต์…˜ 1์€ ์˜ต์…˜ 2์— ๋Œ€ํ•œ ์•…๋งˆ์˜ ์˜นํ˜ธ์ž๋กœ ์กด์žฌํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋Š๊ปด์ง‘๋‹ˆ๋‹ค.

์˜ต์…˜ 2๋Š” ๊ฐˆ ๊ธธ์ฒ˜๋Ÿผ ๋Š๊ปด์ง‘๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ Preact๊ฐ€ ํ•œ ๊ฒƒ๊ณผ ๋น„์Šทํ•˜๋ฏ€๋กœ ์„ ๋ก€์™€ ์ปค๋ฎค๋‹ˆํ‹ฐ ํ‘œ์ค€์˜ ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ์Šต๋‹ˆ๋‹ค(์–ด์จŒ๋“  ํ•˜๋Š” ๊ฒƒ์ด ํ™˜์ƒ์ ์ผ ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. JSX๋Š” ์ด๊ฒƒ์ด ์ž‘๋™ํ•  ์ˆ˜ ์žˆ์Œ์„ ๋ณด์—ฌ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค). ๋˜ํ•œ ์—…๊ทธ๋ ˆ์ด๋“œํ•˜๊ธฐ ์‰ฝ๊ธฐ ๋•Œ๋ฌธ์— React์˜ ์‹ค์šฉ์ ์ธ ์›€์ง์ž„์ด๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค. (์˜ต์…˜ 1๊ณผ ๋ฐ˜๋Œ€).

์˜ต์…˜ 3์€ ๋ฌธ์„œ์ƒ์œผ๋กœ๋Š” ์ข‹์•„ ๋ณด์ด์ง€๋งŒ ์ธ์ง€ ์˜ค๋ฒ„ํ—ค๋“œ, ์–ธ๊ธ‰๋œ ์˜ค๋ฒ„ํ—ค๋“œ์— ๋Œ€ํ•œ ๋ฌธ์„œํ™” ๋ฐ SSR์— ๋Œ€ํ•œ ์•Œ๋ ค์ง€์ง€ ์•Š์€ ์‚ฌํ•ญ์œผ๋กœ ์ธํ•ด ๋…ผ๋ฆฌ์ ์œผ๋กœ ์˜ต์…˜ 2๋ณด๋‹ค ํ›จ์”ฌ ๋” ์–ด๋ ค์šธ ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

์–ธ๊ธ‰ํ–ˆ๋“ฏ์ด ์›๋ž˜ ์˜ต์…˜ 4๋ฅผ ์ œ์‹œํ–ˆ์ง€๋งŒ ๋ฐ˜์„ฑ ํ›„ ๋” ์ด์ƒ ๋งˆ์Œ์— ๋“ค์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋ช…์‹œ์ ์ธ props ๋ฐ events ( attrs ๋Œ€์‹ )๋ฅผ ์ง€์ •ํ•˜๋Š” ๋” ๋งŽ์€ ์„ ํƒ์œผ๋กœ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ์˜ต์…˜ 2๋Š” ๊ตฌํ˜„ ์„ธ๋ถ€ ์ •๋ณด์— ๋Œ€ํ•œ ์ง€์‹์ด ๋œ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ทธ๊ฒƒ์„ ์ฑ„ํƒํ•˜๊ธฐ ์œ„ํ•ด ๋ณ€๊ฒฝํ•ด์•ผ ํ•  ์‚ฌ๋žŒ์€ ์—†์Šต๋‹ˆ๋‹ค.

์˜ต์…˜ 5๋Š” ํ•ต์‹ฌ ๋ฌธ์ œ๋ฅผ ์™„์ „ํžˆ ๋ฌด์‹œํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋Š๊ปด์ง‘๋‹ˆ๋‹ค.


์ œ์ณ๋‘๊ณ , ๋‚˜๋Š” ์ด๊ฒƒ์— ๋Œ€ํ•œ ๊ด€์‹ฌ์„ ๋ณด๊ฒŒ๋˜์–ด ๋งค์šฐ ๊ธฐ์ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์—ฌ๋Ÿฌ๋ถ„ ๋ชจ๋‘๊ฐ€ ์ž˜ํ•˜๊ณ  ์žˆ๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค!

์‚ฌ์šฉ์ž ์˜์—ญ์— ๊ฐ€๋Šฅํ•œ ์†”๋ฃจ์…˜์ด ์žˆ๋‹ค๋ฉด ๋‹น๋ถ„๊ฐ„ ์ปค๋ฎค๋‹ˆํ‹ฐ์—์„œ ํ†ตํ•ฉ ๋ฐ ๊ถŒ์žฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

๊ธฐ๋Šฅ์ด ์ด๋ฏธ ์ธ๊ธฐ ์žˆ๊ณ  ์‹คํ–‰ ๊ฐ€๋Šฅํ•œ ํƒ€์‚ฌ ๋ชจ๋“ˆ๋กœ ์กด์žฌํ•œ๋‹ค๋ฉด React ํ•ต์‹ฌ ํŒ€์ด ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•˜๋„๋ก ์„ค๋“ํ•˜๋Š” ๊ฒƒ์ด ํ›จ์”ฌ ์‰ฌ์šธ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์‚ฌ์šฉ์ž ์˜์—ญ์— ๊ฐ€๋Šฅํ•œ ์†”๋ฃจ์…˜์ด ์žˆ๋‹ค๋ฉด ๋‹น๋ถ„๊ฐ„ ์ปค๋ฎค๋‹ˆํ‹ฐ์—์„œ ํ†ตํ•ฉ ๋ฐ ๊ถŒ์žฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

๋‚˜๋Š” ์ด๊ฒƒ์ด ์™ธ๋ถ€์—์„œ [๊น”๋”ํ•˜๊ฒŒ] ํŒจ์น˜๋  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด๋ผ๊ณ  ๋ฏฟ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋Œ€๋ถ€๋ถ„์˜ userland ์†”๋ฃจ์…˜์€ this ๋ฐ this ์™€ ๊ฐ™์€ ๋ž˜ํผ์ž…๋‹ˆ๋‹ค. React๋ฅผ ์ˆ˜์ •ํ•˜์ง€ ์•Š๊ณ ๋Š” ์ด ์ ‘๊ทผ ๋ฐฉ์‹์— ๋Œ€ํ•œ ํ•ฉ๋ฆฌ์ ์ธ ๋Œ€์•ˆ์„ ์ƒ๊ฐํ•  ์ˆ˜ ์—†์œผ๋ฉฐ ๋ž˜ํ•‘์€ ํ™•์‹คํžˆ ์ด์ƒ์ ์ธ ์†”๋ฃจ์…˜์ด ์•„๋‹™๋‹ˆ๋‹ค. ๐Ÿ˜•

vuejs/vue#7582์—์„œ Vue๋Š” sigil์„ ์‚ฌ์šฉํ•˜๊ธฐ๋กœ ์„ ํƒํ–ˆ๊ณ  "."๋ฅผ ์„ ํƒํ–ˆ์Šต๋‹ˆ๋‹ค. ์ ‘๋‘์‚ฌ๋กœ (Glimmer์˜ "@"๊ฐ€ ์•„๋‹˜).

์ด์— ๋Œ€ํ•œ ์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š” ์„ค๋ช…์— ๋Œ€ํ•œ ๋งํฌ๊ฐ€ ์—†์ง€๋งŒ(Vue์— ๋” ๊ฐ€๊นŒ์šด ์‚ฌ๋žŒ์ด ๋ช…์‹œ์ ์œผ๋กœ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Œ) Vue๊ฐ€ Vue 3.0๋ถ€ํ„ฐ Option 2๋กœ ์ด๋™ํ•œ ๊ฒƒ์œผ๋กœ ๋ณด์ž…๋‹ˆ๋‹ค. ์ฆ‰, Preact์™€ ์œ ์‚ฌํ•˜๊ฒŒ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค. (๋งฅ๋ฝ์€ ์ด ๋ฌธ์ œ ๋ฅผ ์ฐธ์กฐํ•˜์‹ญ์‹œ์˜ค.)

ref ๊ธฐ๋ฐ˜์ด๊ธฐ ๋•Œ๋ฌธ์— ์†์„ฑ์€ ์„œ๋ฒ„์—์„œ ์„ค์ •๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด ๋‚ด๊ฐ€ ์šฐ๋ ค๋ฅผ ๋ชจํ˜ธํ•˜๋‹ค๊ณ  ๋ถ€๋ฅด๋Š” ์ด์œ ์ž…๋‹ˆ๋‹ค. React์—์„œ๋Š” ์†์„ฑ์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด ์ „ํ˜€ ์—†์œผ๋ฏ€๋กœ ์ง€๊ธˆ์€ ๋ชจ๋‘ ๋ง๊ฐ€์กŒ์Šต๋‹ˆ๋‹ค. ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์€ ์ด๋ฏธ ํด๋ผ์ด์–ธํŠธ์—์„œ๋งŒ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ์„œ๋ฒ„๊ฐ€ ์•„๋‹Œ ํด๋ผ์ด์–ธํŠธ์—์„œ ์†์„ฑ์„ ์„ค์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ๋‚ด์žฅ๋˜์–ด ์žˆ์œผ๋ฉด SSR์ด ๊ฐ‘์ž๊ธฐ ์ˆ˜์ •๋˜๊ฑฐ๋‚˜ ์ค‘๋‹จ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

https://github.com/facebook/react/issues/11347#issuecomment -713514984์—์„œ ํŠน์ • ์งˆ๋ฌธ์— ๋‹ต๋ณ€ํ•ด ์ฃผ์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ? ์šฐ๋ฆฌ๊ฐ€ ์„œ๋กœ ๊ณผ๊ฑฐ๋ฅผ ์ด์•ผ๊ธฐํ•˜๋Š” ๊ฒƒ ๊ฐ™์€ ๋Š๋‚Œ์ด ๋“ญ๋‹ˆ๋‹ค. ๋‚˜๋Š” ๋‹จ์ง€ ์˜๋„๋œ ์ „์ฒด ๋™์ž‘์„ ํŠน์ •ํ•œ ๋ฐฉ์‹์œผ๋กœ ์ดํ•ดํ•˜๊ณ  ์‹ถ์„ ๋ฟ์ž…๋‹ˆ๋‹ค. ์–ธ์ œ ์„ค์ •๋˜๊ณ  ์–ด๋–ค ๊ฒฝ์šฐ ์ง๋ ฌํ™”๋˜๋Š”์ง€.

์—ฌ๊ธฐ์„œ ์šฐ์—ฐํžˆ ๋ฐœ๊ฒฌํ•œ ์ž„์˜์˜ Preact+WC ๊ฐœ๋ฐœ์ž๋กœ์„œ ์ €๋Š” "์˜ต์…˜ 2"๊ฐ€ _๋ธŒ๋ ˆ์ดํ‚น ์ฒด์ธ์ง€_์ผ ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ _๋ถˆ์™„์ „ํ•œ ์†”๋ฃจ์…˜_์ž„์„ ์ง€์ ํ•˜๊ณ  ์‹ถ์—ˆ์Šต๋‹ˆ๋‹ค(Preact๋Š” ์—ฌ์ „ํžˆ ์œ ํšจํ•œ ์›น ๊ตฌ์„ฑ ์š”์†Œ์˜ ํ•˜์œ„ ์ง‘ํ•ฉ๊ณผ ์„ ์–ธ์ ์œผ๋กœ๋งŒ ์ƒํ˜ธ ์ž‘์šฉํ•  ์ˆ˜ ์žˆ์Œ).

ํœด๋ฆฌ์Šคํ‹ฑ์„ ํ˜„์žฌ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋Š” ์‚ฌ๋žŒ์ด๋ผ๊ณ  ํ•ด๋„ ์žฅ๊ธฐ์ ์œผ๋กœ ๋ณด๊ธฐ์—๋Š” ๊ทธ๋‹ค์ง€ ๋ฐ”๋žŒ์งํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.


Preact์˜ ํœด๋ฆฌ์Šคํ‹ฑ("์˜ต์…˜ 2")์€ React(ํ‚ค, ์ž์‹ ๋“ฑ) ๋˜๋Š” Preact( on ์‹œ์ž‘ํ•˜๋Š” ๋ชจ๋“  ๊ฒƒ)์—์„œ ํŠน๋ณ„ํ•œ ์˜๋ฏธ๋ฅผ ๊ฐ–๋Š” ์†์„ฑ์„ ์„ค์ •ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

์ฆ‰, JSX ์•„๋ž˜์—์„œ ๋ Œ๋”๋งํ•œ ํ›„:

<web-component key={'key'} ongoing={true} children={[1, 2]} />

key , ongoing ๋ฐ children ์†์„ฑ์€ web-component ์˜ ์ƒ์„ฑ๋œ ์ธ์Šคํ„ด์Šค์—์„œ ๋ชจ๋‘ undefined (๋˜๋Š” ๊ธฐ๋ณธ๊ฐ’์ด ๋ฌด์—‡์ด๋“ )๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.

๋˜ํ•œ OP์™€ ๋‹ฌ๋ฆฌ ์ด ์˜ต์…˜๋„ ๋ธŒ๋ ˆ์ดํ‚น ์ฒด์ธ์ง€์ž…๋‹ˆ๋‹ค. ๋Œ€๋ถ€๋ถ„์˜ ์›น ๊ตฌ์„ฑ ์š”์†Œ(์˜ˆ: lit-element )๋Š” ์ˆœ์ˆ˜ HTML๊ณผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด ์†์„ฑ์„ ํ†ตํ•ด ์ง๋ ฌํ™”๋œ ํ’๋ถ€ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๊ตฌ์„ฑ ์š”์†Œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด React์—์„œ ๋ Œ๋”๋ง๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

<web-component richdata={JSON.stringify(something)} />

"์˜ต์…˜ 2"๋ฅผ ์„ ํƒํ•˜๋ฉด ์ค‘๋‹จ๋ฉ๋‹ˆ๋‹ค. ์›น ๊ตฌ์„ฑ ์š”์†Œ์˜ ์ด๋Ÿฌํ•œ ์‚ฌ์šฉ์ด React์—์„œ ์–ผ๋งˆ๋‚˜ ์ผ๋ฐ˜์ ์ธ์ง€ ํ™•์‹คํ•˜์ง€ ์•Š์ง€๋งŒ ๊ทธ๋ ‡๊ฒŒ ํ•˜๋Š” ์ผ๋ถ€ ์ฝ”๋“œ ๊ธฐ๋ฐ˜์ด ๋ถ„๋ช…ํžˆ ์žˆ์Šต๋‹ˆ๋‹ค. refs๋ณด๋‹ค ๋œ ํšจ์œจ์ ์ด์ง€๋งŒ ๊ฐ„๊ฒฐํ•ฉ๋‹ˆ๋‹ค.

๋งˆ์ง€๋ง‰์œผ๋กœ Web Component์˜ ์ž‘์„ฑ์ž๋Š” ๋™์ผํ•œ ์ด๋ฆ„์˜ ์†์„ฑ๊ณผ ์†์„ฑ์— ๋ฏธ๋ฌ˜ํ•˜๊ฒŒ ๋‹ค๋ฅธ ์˜๋ฏธ๋ฅผ ์ž์œ ๋กญ๊ฒŒ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๊ธฐ๋ณธ input ์š”์†Œ์˜ ๋™์ž‘์„ ๋ชจ๋ฐฉํ•˜๋Š” ์›น ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. value ์†์„ฑ์„ ์ดˆ๊ธฐ ๊ฐ’์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๊ณ  value ์†์„ฑ์˜ ๋ณ€๊ฒฝ ์‚ฌํ•ญ๋งŒ ๊ด€์ฐฐํ•ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๊ตฌ์„ฑ ์š”์†Œ๋Š” ๊ฒฝํ—˜์  ์ ‘๊ทผ ๋ฐฉ์‹์œผ๋กœ jsx๋ฅผ ํ†ตํ•ด ์™„์ „ํžˆ ์ƒํ˜ธ ์ž‘์šฉํ•  ์ˆ˜ ์—†์œผ๋ฉฐ ๋„์ž…๋œ ๊ฒฝ์šฐ ๋ฏธ๋ฌ˜ํ•œ ์†์ƒ์„ ๊ฒฝํ—˜ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ํŠน์ • ๊ธฐ๋Šฅ๋งŒ์„ ์œ„ํ•ด ์ƒˆ๋กœ์šด JSX ๊ตฌ๋ฌธ์„ ๋„์ž…ํ•  ๊ฐ€๋Šฅ์„ฑ์€ ๊ฑฐ์˜ ์—†๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

๋„ค์ž„์ŠคํŽ˜์ด์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ ์–ด๋–ป์Šต๋‹ˆ๊นŒ? https://github.com/facebook/jsx/issues/66 ์€ key ๋ฐ ref ์— ๋Œ€ํ•œ react ๋„ค์ž„์ŠคํŽ˜์ด์Šค ์ถ”๊ฐ€๋ฅผ ์ œ์•ˆํ•ฉ๋‹ˆ๋‹ค. ๊ฐ™์€ ๋งฅ๋ฝ์—์„œ react-dom ๊ฒƒ์ด DOM ์†์„ฑ์„ ์‹๋ณ„ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ดœ์ฐฎ์€ ๋„ค์ž„์ŠคํŽ˜์ด์Šค๊ฐ€ ๋ ๊นŒ์š”? OP์˜ ์˜ต์…˜ 3 ์˜ˆ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

<custom-img react-dom:src="corgi.jpg" react-dom:hiResSrc="[email protected]" width="100%">

๊ทธ๊ฒƒ์€ ๊ฐ€์žฅ ์ธ์ฒด ๊ณตํ•™์ ์ด์ง€ ์•Š์Šต๋‹ˆ๋‹ค. dom ์žˆ์œผ๋ฉด ๋” ์ข‹๊ฒ ์ง€๋งŒ React๊ฐ€ react ์‹œ์ž‘ํ•˜์ง€ ์•Š๋Š” ๋„ค์ž„์ŠคํŽ˜์ด์Šค๋ฅผ ๋งŒ๋“ค๊ณ  ์‹ถ์–ดํ•˜๋Š”์ง€ ํ™•์‹คํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ ์†์„ฑ์œผ๋กœ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์ด ๋œ ์ผ๋ฐ˜์ ์ธ ๊ฒฝ์šฐ๋ผ๋Š” ์•„์ด๋””์–ด๊ฐ€ ์žˆ๋‹ค๋ฉด ์ด๊ฒƒ์— ๋Œ€ํ•œ ์ž˜๋ชป๋œ ์ธ์ฒด ๊ณตํ•™์€ ์„ธ์ƒ์˜ ๋์ด ์•„๋‹™๋‹ˆ๋‹ค. SSR๊ณผ์˜ ํŒจ๋ฆฌํ‹ฐ๋ฅผ ์ œ๊ณตํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์†์„ฑ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋” ์ข‹์Šต๋‹ˆ๋‹ค. ์†์„ฑ์œผ๋กœ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์€ ์†์„ฑ์— ๋ฌธ์ œ๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ(์˜ˆ: ๊ฐœ์ฒด๋ฅผ ์ „๋‹ฌํ•˜๊ฑฐ๋‚˜ ์†์„ฑ์ด ์ง€์›ํ•˜์ง€ ์•Š๋Š” ์†์„ฑ์— ๋Œ€ํ•œ ๊ฒฝ์šฐ)์šฉ์ด๋ฉฐ, ์–ด์จŒ๋“  ์†์„ฑ์— SSR์„ ์ ์šฉํ•  ์ˆ˜ ์—†๊ณ  ์ˆ˜ํ™”ํ•ด์•ผ ํ•˜๋Š” ๋ฌธ์ œ๊ฐ€ ์žˆ๋Š” ์†์„ฑ์— ๋Œ€ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค. JS๋ฅผ ํ†ตํ•ด

_๋ถˆ์™„์ „ํ•œ ํ•ด๊ฒฐ์ฑ…_

(Preact๋Š” ์—ฌ์ „ํžˆ ์œ ํšจํ•œ ์›น ๊ตฌ์„ฑ ์š”์†Œ์˜ ํ•˜์œ„ ์ง‘ํ•ฉ๊ณผ ์„ ์–ธ์ ์œผ๋กœ๋งŒ ์ƒํ˜ธ ์ž‘์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.)

@brainlessbadger ์ด ํ•˜์œ„ ์ง‘ํ•ฉ์ด ์‹ค์ œ๋กœ ๋ฌด์—‡์ธ์ง€ ํฌํ•จํ•˜๋„๋ก ์œ„์˜ ์˜๊ฒฌ์„ ํŽธ์ง‘ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๊นŒ? ์˜ˆ. ์–ด๋–ค ์›น ๊ตฌ์„ฑ ์š”์†Œ/์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ๊ฐ€ ์˜ํ–ฅ์„ ๋ฐ›์Šต๋‹ˆ๊นŒ(์˜ˆ์ œ ํฌํ•จ)? ๊ทธ๋ฆฌ๊ณ  ์ •ํ™•ํžˆ ์–ด๋–ป๊ฒŒ ์˜ํ–ฅ์„ ๋ฐ›์Šต๋‹ˆ๊นŒ?

@karlhorky ์„ค๋ช…์„ ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค. ์“ธ๋ฐ์—†์ด ๋ชจํ˜ธํ•ด์„œ ์ฃ„์†กํ•ฉ๋‹ˆ๋‹ค.

์›น ๊ตฌ์„ฑ ์š”์†Œ ์ด๋ฒคํŠธ ๊ด€๋ จ. ์ด๋ฒคํŠธ ์ด๋ฆ„ ์ถฉ๋Œ๋กœ ์ธํ•ด ํ–ฅํ›„ ์ฐจ๋‹จ์„ ๋ฐฉ์ง€ํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•œ ํ•ฉ์˜๊ฐ€ ์•„์ง ์žˆ์Šต๋‹ˆ๊นŒ?

๋‹ค์Œ๊ณผ ๊ฐ™์ด HTMLElement์— ์ƒˆ ์†์„ฑ์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์†์„ฑ ๋ฐ ์†์„ฑ์—๋„ ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes ์ƒˆ๋กœ ์ถ”๊ฐ€๋œ ํ•ญ๋ชฉ๋„ ์žˆ์œผ๋ฏ€๋กœ ์—ฌ์ „ํžˆ ์ƒˆ๋กœ์šด ํ•ญ๋ชฉ์ด ์ถ”๊ฐ€๋˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

์—„๋ฐ€ํžˆ ๋งํ•˜๋ฉด ์‚ฌ์šฉ์ž ์ •์˜ ์†์„ฑ์ด๋‚˜ ์‚ฌ์šฉ์ž ์ •์˜ ์ด๋ฒคํŠธ์˜ ์ด๋ฆ„์— - ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

๋‹ค๋ฅธ ๋ชจ๋“  ๊ฒƒ์€ ํ•ด๋‹น ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ํ–ฅํ›„ ์‚ฌ์–‘์—์„œ ๋ฉ‹์ง„ ์ด๋ฆ„์„ ์‚ฌ์šฉํ•˜์ง€ ๋ชปํ•˜๋„๋ก ์ฐจ๋‹จํ•˜๋Š” ์œ„ํ—˜์„ ํ‰๊ฐ€ํ•˜๋Š” ์ ˆ์ถฉ์•ˆ์ž…๋‹ˆ๋‹ค.

์ด๋ฒคํŠธ๋Š” ํ•ด๋‹น ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ํ˜ธํ™˜๋˜์ง€ ์•Š๋Š” ๋™์ž‘์„ ํ•  ์œ„ํ—˜์ด ์—†๊ธฐ ๋•Œ๋ฌธ์— ์ €๋ฅผ ๋”์šฑ ๊ธด์žฅํ•˜๊ฒŒ ๋งŒ๋“ญ๋‹ˆ๋‹ค. ์ƒˆ ์ด๋ฒคํŠธ๊ฐ€ ๋ฒ„๋ธ”๋ง๋˜๋ฉด ํ•ด๋‹น ํŠธ๋ฆฌ ๊ฒฝ๋กœ์— ์žˆ๋Š” ๋ชจ๋“  ๊ธฐ์กด ์›น ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ํŠธ๋ฆฌ๊ฑฐ๋ฉ๋‹ˆ๋‹ค.

์‚ฌ์šฉ์ž ์ •์˜ ์†์„ฑ ๋ฐ ์ด๋ฒคํŠธ๊ฐ€ ์ด๋ฆ„์— - ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ ์‚ฌ์šฉํ•  ํ•ญ๋ชฉ์„ ๊ฒฐ์ •ํ•˜๊ธฐ ์œ„ํ•œ ๊ฒฝํ—˜์  ๋ฐฉ๋ฒ•์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ ๋‚ด์žฅ๋œ ํŠน์ˆ˜ํ•œ ๊ฒฝ์šฐ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด ์šฐ๋ฆฌ๊ฐ€ ์ฒ˜์Œ์— ์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ์ธ์ง€ ์—ฌ๋ถ€๋ฅผ ์ด๋ฏธ ์•„๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.

๊ทธ๋Ÿฐ ๋‹ค์Œ ์†์„ฑ์„ ํŽธ์˜๋กœ ์‚ฌ์šฉํ•˜์—ฌ ๋” ์ข‹์€ ์•ฝ์‹์„ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ ์–ด๋„ ๊ทธ๊ฒƒ๋“ค์€ ๋‚ด์žฅ ์†์„ฑ์„ ๊ฐ€๋ฆฌ๊ณ  ๋ฏธ๋ž˜ ์†์„ฑ๊ณผ ์ถฉ๋Œํ•˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์—„๋ฐ€ํžˆ ๋งํ•˜๋ฉด ์‚ฌ์šฉ์ž ์ •์˜ ์†์„ฑ์ด๋‚˜ ์‚ฌ์šฉ์ž ์ •์˜ ์ด๋ฒคํŠธ์˜ ์ด๋ฆ„์œผ๋กœ -๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

์‚ฌ์šฉ์ž ์ •์˜ ์š”์†Œ ์‚ฌ์–‘์—๋Š” ์ด๋Ÿฌํ•œ ์ œํ•œ ์‚ฌํ•ญ์ด ํฌํ•จ๋˜์–ด ์žˆ์ง€ ์•Š์œผ๋ฏ€๋กœ React์—์„œ ์ ์šฉํ•˜๋ฉด ์ƒํ˜ธ ์šด์šฉ์„ฑ์— ์ƒ๋‹นํ•œ ์˜ํ–ฅ์„ ๋ฏธ์นฉ๋‹ˆ๋‹ค.

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

์ด์ƒ์ ์œผ๋กœ๋Š” ํ”„๋ ˆ์ž„์›Œํฌ๊ฐ€ ํ‘œ์ค€์„ ์ˆ˜์šฉํ•˜๋„๋ก ์กฐ์ •๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋ฌผ๋ก . setAttribute() ๋ฐ dispatchEvent() ๋Š” ์ฒ˜์Œ๋ถ€ํ„ฐ ์ž„์˜์˜ ์ด๋ฆ„์„ ํ—ˆ์šฉํ•œ ์›น ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ์•„๋‹Œ ํŠน์ • API์ž…๋‹ˆ๋‹ค. ๋ชจ๋“  ์š”์†Œ๋Š” ๋ชจ๋“  ์†์„ฑ์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๊ณ  ๋ชจ๋“  ์ด๋ฒคํŠธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” DOM์˜ ๊ธฐ๋ณธ ์ •๋ณด์ผ ๋ฟ์ž…๋‹ˆ๋‹ค.

data- ๋„ค์ž„์ŠคํŽ˜์ด์Šค๊ฐ€ ์ถ”๊ฐ€๋œ ์ด์œ ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ธฐ์ˆ ์ ์œผ๋กœ ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ๊ณผ ๋ชจ๋ฒ” ์‚ฌ๋ก€ ์‚ฌ์ด์—๋Š” ์ฐจ์ด๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ธฐ์ˆ ์ ์œผ๋กœ ํ”„๋กœํ† ํƒ€์ž…์„ ํŒจ์น˜ํ•  ์ˆ˜๋„ ์žˆ์ง€๋งŒ ํฌํ•จ/ํฌํ•จ ์ƒํ™ฉ์ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

React๋งŒ์ด ์ด๊ฒƒ์„ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ์ปค๋ฎค๋‹ˆํ‹ฐ๊ฐ€ ๋ฏธ๋ž˜์˜ ๋„ค์ž„์ŠคํŽ˜์ด์Šค๋ฅผ ๋ณดํ˜ธํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋˜๋„๋ก ์ด ๊ทœ์น™์œผ๋กœ ์ „ํ™˜ํ•˜๋Š” ๊ฒƒ์„ ์ œ์•ˆํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋‹ค๋งŒ ์ด ๋ฌธ์ œ๊ฐ€ ์‹ฌ๊ฐํ•˜๊ฒŒ ๋ฐ›์•„๋“ค์—ฌ์ง€์ง€ ์•Š๋Š” ๊ฒƒ์ด ์•ˆํƒ€๊นŒ์šธ ๋ฟ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์•„๋งˆ๋„ ์›น์€ ์ƒˆ๋กœ์šด API์— ์–ด์ƒ‰ํ•œ ์ด๋ฆ„๋งŒ ์ถ”๊ฐ€ํ•  ์šด๋ช…์ž…๋‹ˆ๋‹ค.

๋‚˜๋Š” SSR์—์„œ ๋‚ด์žฅ๋˜์ง€ ์•Š์€ ๊ฒƒ์„ ์ œ์™ธํ•œ๋‹ค๋Š” ์•„์ด๋””์–ด๋ฅผ ์ข‹์•„ํ•˜๊ณ  ์„ ์–ธ์  ๊ทธ๋ฆผ์ž DOM์„ ์‚ฌ์šฉํ•˜๋ฉด ์‹ค์ œ ์ฝ˜ํ…์ธ ๊ฐ€ ๋‚ด๋ถ€์—์„œ ํ™•์žฅ๋  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ˆ˜ํ™” ์ค‘์— ์†์„ฑ์„ ์„ ํ˜ธํ•ฉ๋‹ˆ๋‹ค.

๊ตฌ์ฒด์ ์œผ๋กœ๋Š” ์†์„ฑ์„ ์‚ฌ์šฉํ•˜๊ณ  AMP ๋Ÿฐํƒ€์ž„์ด ์ด๋ฏธ ๋กœ๋“œ๋˜์—ˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์‚ฌ๋žŒ๋“ค์ด SSR + AMP์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๋Š” ํ˜„์žฌ ์ ‘๊ทผ ๋ฐฉ์‹์— ๋ฌธ์ œ๋ฅผ ์ผ์œผํ‚ฌ ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

์˜ต์…˜ 3์—์„œ ๋ฌธ์ด ๋‹ซํžˆ์ง€ ์•Š์•˜๋‹ค๊ณ  ๊ฐ€์ •ํ•˜๋ฉด ์œ„์˜ ๋‹จ์ ์— ๋‚˜์—ด๋˜์ง€ ์•Š์€ ์˜ต์…˜ 2์— ๋น„ํ•ด ์ƒ๋‹นํ•œ ์ด์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค. -- ์˜ต์…˜ 2์—์„œ ๋ฐœ๊ฒฌํ•œ ๋ฌธ์ œ๋Š” ์›น ๊ตฌ์„ฑ ์š”์†Œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ๋น„๋™๊ธฐ์‹ ์œผ๋กœ ๋กœ๋“œ๋˜๋Š” ๊ฒฝ์šฐ preact๊ฐ€ ๊ทธ๋ ‡์ง€ ์•Š์„ ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์•Œ ์ˆ˜ ์—†๋Š” ์š”์†Œ์˜ ๊ฒฝ์šฐ "์†์„ฑ"์ด ์†์„ฑ์ด ๋  ๊ฒƒ์ž„์„ ์•Œ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. unknown ์š”์†Œ์— ์žˆ๋Š” ์†์„ฑ์„ ์ฐพ์ง€ ๋ชปํ•˜๋ฏ€๋กœ ๊ธฐ๋ณธ์ ์œผ๋กœ ์†์„ฑ์ด ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์€ ์ข…์† ์›น ๊ตฌ์„ฑ ์š”์†Œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ๋กœ๋“œ๋  ๋•Œ๊นŒ์ง€ ํ•ด๋‹น ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ๋ Œ๋”๋งํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด๋Š” ๋งค์šฐ ์šฐ์•„ํ•˜์ง€ ์•Š๊ฑฐ๋‚˜ ์„ฑ๋Šฅ๋ฉด์—์„œ ์ด์ƒ์ ์ด์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์šฐ๋ฆฌ ๊ทธ๋ฃน์€ node.js๊ฐ€ ์•„๋‹Œ asp.net์„ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์‹ค์ œ๋กœ SSR์„ ํƒ์ƒ‰ํ•œ ์ ์ด ์—†์œผ๋ฏ€๋กœ ์•„๋ž˜ ๊ด€์ฐฐ์€ ์ถ”์ธก์ž…๋‹ˆ๋‹ค.

React ํŒ€์˜ ์ž…์žฅ์—์„œ๋Š” SSR๊นŒ์ง€ ๋‹ค๋ฅธ ํ”„๋ ˆ์ž„์›Œํฌ๊ฐ€ ์ง€์›ํ•˜๋Š” ๊ฒƒ ์ด์ƒ์œผ๋กœ ์ œ์•ˆํ•˜๋Š” ๊ฒƒ์€ ์ข‹์€ ์ œ์Šค์ฒ˜๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž๊ฐ€ ๋” ์ข‹์Šต๋‹ˆ๋‹ค.

๋ป”ํ•œ ๋ง์ธ์ง€ ์•„๋‹Œ์ง€๋Š” ๋ชจ๋ฅด๊ฒ ์ง€๋งŒ ์ผ๋ถ€ ์†์„ฑ์˜ ๊ฒฝ์šฐ JSON ๋ฌธ์ž์—ด์„ ํ†ตํ•ด ์†์„ฑ์˜ ์ดˆ๊ธฐ ๊ฐ’์„ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์ด ํŽธ๋ฆฌํ•˜๋‹ค๋Š” ์›น ๊ตฌ์„ฑ ์š”์†Œ์— ์•ฝ๊ฐ„์˜ ํ•ฉ์˜ ๊ฐ€ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐ ํ•ฉ๋‹ˆ๋‹ค . ์ž‘์€๋”ฐ์˜ดํ‘œ๋กœ ๋ฌถ์Šต๋‹ˆ๋‹ค.

AMP๋Š” ๋‹ค๋ฅธ ๊ทœ์น™์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. -- ์ด๋ฅผ ์ˆ˜ํ–‰ํ•˜๊ธฐ ์œ„ํ•ด ์Šคํฌ๋ฆฝํŠธ type=application.json ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ํ•ฉ๋ฆฌ์ ์ธ(๊ทธ๋Ÿฌ๋‚˜ ์žฅํ™ฉํ•œ) ๋Œ€์•ˆ์ž…๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ์†์„ฑ ์ ‘๊ทผ ๋ฐฉ์‹์„ ๊ณ ์ˆ˜ํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋Ÿฐ ๋‹ค์Œ ์›น ๊ตฌ์„ฑ ์š”์†Œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ์†์„ฑ์„ ๊ตฌ๋ฌธ ๋ถ„์„ํ•˜๊ฑฐ๋‚˜ ์†์„ฑ์„ ํ†ตํ•ด ๊ฐ’์„ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ์ˆ˜ํ™” ์ง€์—ฐ์„ ๋ฐฉ์ง€ํ•˜๋ ค๋ฉด ๋‹ค์Œ์„ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์ด ํŽธ๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

<github-icon icon='{"name":"smiley"}'></github-icon>

SSR ์ค‘. ๊ทธ๋Ÿฌ๋ฉด github-icon์€ ์ฆ‰์‹œ ๊ทธ ์ผ์„ ํ•  ์ˆ˜ ์žˆ๊ณ  ๋‚ด๋ถ€์ ์œผ๋กœ ์†์„ฑ์˜ JSON.parse๋ฅผ ์ˆ˜ํ–‰ํ•˜๊ณ  React๊ฐ€ (๋” ์™„์ „ํ•œ?) ๊ฐ์ฒด ๊ฐ’์„ ์ „๋‹ฌํ•  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆด ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

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

๋ฌผ๋ก  ์ผ๋ถ€ ์†์„ฑ์€ ๋ฌธ์ž์—ดํ™”/ํŒŒ์‹ฑ์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์—†๋Š” ๊ฐœ์ฒด์ด๋ฏ€๋กœ ์ด๋Š” ์ ์šฉ๋˜์ง€ ์•Š์œผ๋ฉฐ ํ•ด๋‹น ์†์„ฑ์€ ์ˆ˜ํ™”๊ฐ€ ์™„๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ ค์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋ชจ๋“  ์†์„ฑ๊ณผ ์†์„ฑ์ด React ํŒ€์ด ์„ ํ˜ธํ•˜๋Š” ๋ช…๋ช… ๊ทœ์น™(์•„๋งˆ๋„)์„ ๋”ฐ๋ž๋‹ค๋ฉด -- ๋ชจ๋“  ์†์„ฑ์— ๋Œ€์‹œ๊ฐ€ ์žˆ๊ณ  ๋ชจ๋“  ์†์„ฑ์ด camelCase๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ณตํ•ฉ ์ด๋ฆ„์ด์—ˆ๋‹ค๋ฉด ๋Œ€์‹œ๊ฐ€ ์žˆ์œผ๋ฉด ์†์„ฑ๊ณผ ์†์„ฑ์„ ๊ตฌ๋ณ„ํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

<github-icon my-icon={myStringifiedProperty} myIcon={myObjectProperty}></github-icon>

๋ฌธ์ œ๋Š” ์œ„์˜ ๊ตฌ๋ฌธ์—์„œ ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„์—์„œ ์ˆ˜ํ–‰ํ•  ์ž‘์—…์„ ๋‚˜ํƒ€๋‚ด์ง€ ์•Š์œผ๋ฉฐ ์ด์ƒ์ ์œผ๋กœ๋Š” ๋‘˜ ๋‹ค์— ๋Œ€ํ•ด ํ•˜๋‚˜์˜ ๋ฐ”์ธ๋”ฉ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ณ  React๋Š” ์–ด๋Š ๊ฒƒ์„ ์‚ฌ์šฉํ• ์ง€ ์•Œ์•„๋‚ผ ๋งŒํผ ์ถฉ๋ถ„ํžˆ ๋˜‘๋˜‘ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

React๋Š” ์†์„ฑ/์†์„ฑ ํ‚ค๊ฐ€ ์นด๋ฉœ ์ผ€์ด์Šค์ธ ๊ฒฝ์šฐ ํ•ญ์ƒ ํด๋ผ์ด์–ธํŠธ ์ธก์—์„œ ๊ฐ์ฒด๋กœ ์ „๋‹ฌํ•˜๊ณ  SSR ์ค‘์— ์„ค์ •๋œ ๊ฒฝ์šฐ ๊ฐ์ฒด์˜ JSON ๋ฌธ์ž์—ด ์ง๋ ฌํ™”๋ฅผ ์ „๋‹ฌํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ, ํ‚ค์˜ ๋Œ€์‹œ๋Š” (์•ˆ์ „ํ•˜๊ฒŒ, ์ œ ์ƒ๊ฐ์—) ๊ทธ๊ฒƒ์ด ์†์„ฑ์ด๋ผ๊ณ  ๊ฐ€์ •ํ•˜๊ณ  ๊ฐ’์˜ .toString()์„ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋‚˜๋Š” ์ด๊ฒƒ์ด ๋„ˆ๋ฌด ๋งŽ์€ ๊ฒƒ์„ ๊ฐ€์ •ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  HTMLElement๋ฅผ ํ™•์žฅํ•˜๋Š” ์›น ์ปดํฌ๋„ŒํŠธ์— ์†์„ฑ์„ ์ ์šฉํ•˜๋ฉด ์œ ํšจํ•œ HTML๋กœ ๊ฐ„์ฃผ๋˜๋Š” ๋‹จ์ผ ๋‹จ์–ด ์†์„ฑ ๋ฐ ์†์„ฑ์„ ์ง€์›ํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์€ ๋„ˆ๋ฌด ์ œํ•œ์ ์ž…๋‹ˆ๋‹ค. ๋‚˜๋Š” W3C๊ฐ€ ๋ฏธ๋ž˜์— ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” "์˜ˆ์•ฝ๋œ" ์†์„ฑ ์ด๋ฆ„ ๋ชฉ๋ก์„ ๋ฐœํ–‰ํ•˜๋Š” ๋ฐ ์ฐฌ์„ฑํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” JS์˜ ์˜ˆ์•ฝ๋œ ํ‚ค์›Œ๋“œ์™€ ์œ ์‚ฌํ•˜๋ฉฐ, ์˜ˆ์•ฝ๋œ ์†์„ฑ ์ด๋ฆ„์„ ๋ถ€์ ์ ˆํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ ๊ฐœ๋ฐœ์ž์—๊ฒŒ ๊ฒฝ๊ณ ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ฐพ๋Š” ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์ฐพ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ์˜ต์…˜ 3์ด ๊ฐ€์žฅ ์ข‹์€ ๋ฐฉ๋ฒ•์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋” ๋‚˜์€ ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์„ ์œ„ํ•ด @gaearon์ด ์ œ์•ˆํ•œ ๋Œ€๋กœ ํ–ฅ์ƒ๋  ์ˆ˜ ์žˆ๋‹ค๋ฉด ์ข‹์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋‚ด ์ œ์•ˆ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

<github-icon icon={myDynamicIcon}/>

์†์„ฑ(toString())์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

<github-icon icon:={myDynamicIcon}/>

์˜๋ฏธ -- SSR ๋™์•ˆ ๋ฌด์‹œํ•˜์ง€๋งŒ ํด๋ผ์ด์–ธํŠธ์—์„œ ๊ฐœ์ฒด ์†์„ฑ์— ๋ฐ”์ธ๋”ฉํ•ฉ๋‹ˆ๋‹ค(์ˆ˜ํ™” ํ›„).

์ด์ œ ์‹œ๋‚˜๋ฆฌ์˜ค(์ผ๋ถ€?)๋Š” ์–ด๋–ป์Šต๋‹ˆ๊นŒ? React ํŒ€์ด ํ•ด๊ฒฐํ•˜๋Š” ๋ฐ ๊ด€์‹ฌ์ด ์žˆ์Šต๋‹ˆ๊นŒ? ๋‚ด ์ฒซ ๋ฒˆ์งธ ์ƒ๊ฐ์€ ๋‘ ๊ฐœ์˜ ์ฝœ๋ก ๊ณผ ๊ฐ™์€ ๋‹ค๋ฅธ ๊ธฐํ˜ธ์˜€์Šต๋‹ˆ๋‹ค.

<github-icon icon::={myDynamicIcon}/> //Not my final suggestion!

์ฆ‰, SSR ๋™์•ˆ JSON.stringify ์†์„ฑ์„ ๋ Œ๋”๋ง๋œ HTML์—์„œ ์†์„ฑ์œผ๋กœ ์„ค์ •ํ•˜๊ณ  ์†์„ฑ์ด ์ˆ˜ํ™” ํ›„ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์— ๋ฐ”์ธ๋”ฉ๋  ๋•Œ ํด๋ผ์ด์–ธํŠธ์—์„œ ๊ฐœ์ฒด๋กœ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ ๋ณตํ•ฉ ์ด๋ฆ„์œผ๋กœ ๋ฌด์—‡์„ ํ•ด์•ผ ํ•˜๋Š”์ง€์— ๋Œ€ํ•œ ๊นŒ๋‹ค๋กœ์šด ์ƒํ™ฉ์„ ๋‚จ๊น๋‹ˆ๋‹ค. ์ฆ‰, ๋‹ค์Œ์„ ์„ค์ •ํ•˜๋ฉด:

<github-icon iconProps::={myDynamicIconProp}/>  //Not my final suggestion!

์†์„ฑ ์ด๋ฆ„ iconProps์— ๋Œ€ํ•œ ํ•ด๋‹น ์†์„ฑ์ด icon-props์—ฌ์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์€ ๊ณผ๊ฑฐ์— ๋…ผ๋ž€์˜ ์—ฌ์ง€๊ฐ€ ์—†์—ˆ์Šต๋‹ˆ๋‹ค.

์•„๋งˆ๋„ ์ด๋Ÿฌํ•œ ์›น ๊ตฌ์„ฑ ์š”์†Œ ์ค‘ ์ผ๋ถ€๊ฐ€ ๋ณ€๊ฒฝ ์—†์ด ํ”Œ๋žซํผ์— ๋‚ด์žฅ๋  ์ˆ˜ ์žˆ๋‹ค๋Š” ๋ง๋ น ๋•Œ๋ฌธ์— ์ด๊ฒƒ์€ ๋” ๋…ผ๋ž€์ด ๋˜์—ˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์†์„ฑ์—๋Š” ๋Œ€์‹œ๊ฐ€ ํฌํ•จ๋  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค(๊ทธ๋Ÿฌ๋‚˜ ์†์„ฑ์€ camelCase์ผ ์ˆ˜ ์žˆ์Œ). ๋‚ด๊ฐ€ ์•„๋Š” ํ•œ JSON ์—ญ์ง๋ ฌํ™”๋ฅผ ํ†ตํ•ด ๋ณต์žกํ•œ ๊ฐœ์ฒด๋ฅผ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋ณธ ์š”์†Œ๋Š” ์•„์ง ์—†์ง€๋งŒ ๋‚˜์ค‘์— ํ•„์š”ํ•  ๊ฒฝ์šฐ ๋†€๋ผ์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ ‡๋‹ค๋ฉด React๋Š” ๋Œ€์‹œ๋ฅผ ์–ธ์ œ ์‚ฝ์ž…ํ• ์ง€ ์—ฌ๋ถ€๋ฅผ ์–ด๋–ป๊ฒŒ ์•Œ ์ˆ˜ ์žˆ์„๊นŒ์š”?

๋‚ด๊ฐ€ ์ƒ๊ฐํ•ด๋‚ผ ์ˆ˜ ์žˆ๋Š” ์œ ์ผํ•œ (์ถ”ํ•œ?) ์ œ์•ˆ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

<github-icon icon-props:iconProps={myDynamicIconProp}/>

์ฆ‰, ์„œ๋ฒ„์—์„œ๋Š” ์ง๋ ฌํ™” ํ›„ ์†์„ฑ icon-props๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ํด๋ผ์ด์–ธํŠธ์—์„œ๋Š” ์†์„ฑ iconProps๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐœ์ฒด๋ฅผ ์ง์ ‘ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.

ํ•˜์ด๋ธŒ๋ฆฌ๋“œ ์†์„ฑ/์†์„ฑ ์Œ์„ ํ—ˆ์šฉํ•˜๋Š” ๋” ์ž์„ธํ•œ ํ‘œ๊ธฐ๋ฒ•์˜ ๋˜ ๋‹ค๋ฅธ ์ž ์žฌ์  ์ด์ ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. ํŠนํžˆ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฒฝ์šฐ ํ•ด๋‹น ์†์„ฑ๋ณด๋‹ค ๊ธฐ๋ณธ ์š”์†Œ์˜ ์†์„ฑ์„ ๋ฐ˜๋ณต์ ์œผ๋กœ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์ด ์กฐ๊ธˆ ๋” ๋น ๋ฅผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฌธ์ž์—ด์ด ์•„๋‹Œ ์†์„ฑ. ๊ทธ๋ ‡๋‹ค๋ฉด React๋Š” ํ˜„์žฌ ์„œ๋ฒ„์˜ ์†์„ฑ๊ณผ ํด๋ผ์ด์–ธํŠธ์˜ ์†์„ฑ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๊นŒ? ๊ทธ๋ ‡์ง€ ์•Š๋‹ค๋ฉด ์ด ํ‘œ๊ธฐ๋ฒ•์œผ๋กœ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋Š” ๋ช…๋ช… ๋ฒˆ์—ญ์˜ ์–ด๋ ค์›€๊ณผ ๊ฐ™์€ ๋ฌธ์ œ ๋•Œ๋ฌธ์ž…๋‹ˆ๊นŒ?

@bahrus ๋‹จ์ˆœํ™” ํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

<my-element attr='using-quotes' property={thisIsAnObject} />

๊ตฌ์ฒด์ ์ธ ์˜ˆ๋ฅผ ๋“ค์–ด ๋ฌธ์ œ๋ฅผ ์„ค๋ช…ํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€์žฅ ์ข‹์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

HTML Form ์š”์†Œ์—๋Š” ์—ฌ๋Ÿฌ ์†์„ฑ์ด ์žˆ์Šต๋‹ˆ๋‹ค. "๋ณตํ•ฉ ์ด๋ฆ„"์ด ์žˆ๋Š” ์ด๋ฆ„์€ ๋ชจ๋‘ ์ผ๊ด€๋œ ์ด๋ฆ„ ์ง€์ • ํŒจํ„ด์„ ๋”ฐ๋ฅด๋Š” ๊ฒƒ ๊ฐ™์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ผ๋ฐ˜์ ์œผ๋กœ ๋ชจ๋‘ ์†Œ๋ฌธ์ž๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ๊ตฌ๋ถ„ ๊ธฐํ˜ธ๊ฐ€ ์—†์ง€๋งŒ ๋Œ€์‹œ ๊ตฌ๋ถ„ ๊ธฐํ˜ธ๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ๋„ ์žˆ์Šต๋‹ˆ๋‹ค. - "๊ฐฑ์‹ ํ•˜๋‹ค".

ํ•ด๋‹น JS ์†์„ฑ ์ด๋ฆ„์€ acceptCharset, noValidate์™€ ๊ฐ™์€ ๋ฉ‹์ง„ ๋ฒ”์šฉ ํŒจํ„ด์—๋„ ๋งž์ง€ ์•Š์Šต๋‹ˆ๋‹ค. noValidate ์†์„ฑ/novalidate ์†์„ฑ์€ ๋ถ€์šธ์ด๋ฏ€๋กœ ํด๋ผ์ด์–ธํŠธ์—์„œ myForm.noValidate = true์™€ ๋ฐ˜๋Œ€๋กœ myForm.setAttribute('novalidate', '')๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ์€ ๋‚ญ๋น„(์ƒ์ƒ)์ž…๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ์„œ๋ฒ„์—์„œ myForm.noValidate = true๋กœ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์€ ์˜๋ฏธ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. DOM์˜ ๋ฌธ์ž์—ด ํ‘œํ˜„์„ ๋ณด๋‚ด๊ณ  ์‹ถ๊ธฐ ๋•Œ๋ฌธ์— ์†์„ฑ์„ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

<form novalidate={shouldNotValidate}>

์‚ฌ์‹ค, React/JSX๊ฐ€ boolean ์†์„ฑ์„ ์กฐ๊ฑด๋ถ€ ๋กœ ๊ณ ์ •๋œ ์ •์  ์กฐํšŒ ํ…Œ์ด๋ธ” ์— ์˜์กด

๊ฐœ๋ฐœ์ž๊ฐ€ ์„ฑ๋Šฅ์„ ํฌ์ƒํ•˜์ง€ ์•Š๊ณ  ์„œ๋ฒ„(์†์„ฑ์„ ํ†ตํ•ด)์™€ ํด๋ผ์ด์–ธํŠธ(์†์„ฑ์„ ํ†ตํ•ด)๋ฅผ ์™„์ „ํžˆ ์ œ์–ดํ•  ์ˆ˜ ์žˆ๋„๋ก ์ด๋Ÿฌํ•œ ๋ชจ๋“  ์‹œ๋‚˜๋ฆฌ์˜ค๋ฅผ ์–ด๋–ป๊ฒŒ ๋‚˜ํƒ€๋‚ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ? novalidate์™€ ๊ฐ™์€ ๋ถ€์šธ์˜ ๊ฒฝ์šฐ ๋‹ค์Œ์„ ์ œ์•ˆํ•ฉ๋‹ˆ๋‹ค.

<form novalidate:noValidate?={shouldNotValidate}/>

React๊ฐ€ DOM์„ ์™„๋ฒฝํ•˜๊ฒŒ ์ง€์›ํ•œ๋‹ค๋ฉด, ์ง€์ €๋ถ„ํ•˜์ง€๋งŒ ๊ฐ€๋Šฅํ•œ ํ•œ ์„ฑ๋Šฅ์ด ์ข‹์€ ๋ฐฉ์‹์œผ๋กœ, ๋„ค์ด๋ฐ ํŒจํ„ด์—์„œ ๊ทธ๋‹ค์ง€ ์ผ๊ด€์„ฑ์ด ์—†์„ ์ˆ˜๋„ ์žˆ๋Š” ์‚ฌ์šฉ์ž ์ง€์ • ์š”์†Œ๋ฅผ ์ง€์›ํ•˜๋Š” ๋ฐ ํฐ ๋„์›€์ด ๋  ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

์„œ๋ฒ„์—์„œ JSON.stringify๋ฅผ ํ†ตํ•ด ์†์„ฑ์— ๊ฐ์ฒด ์†์„ฑ์„ ์„ ํƒ์ ์œผ๋กœ ์ง๋ ฌํ™”ํ•˜๋Š” ์ง€์›์„ ์ถ”๊ฐ€ํ•˜๋ฉด React ๋ฐ ์›น ๊ตฌ์„ฑ ์š”์†Œ์— ์ถ”๊ฐ€์ ์ธ ํฐ ์œˆ-์œˆ์ด ๋  ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

์•„๋‹ˆ๋ฉด ๋‚ด๊ฐ€ ๋ญ”๊ฐ€๋ฅผ ๋†“์น˜๊ณ  ์žˆ์Šต๋‹ˆ๊นŒ? ( @eavichay , ๊ท€ํ•˜์˜ ์˜ˆ๋ฅผ ๋”ฐ๋ฅด์ง€ ์•Š๊ณ  ์ด๋Ÿฌํ•œ ์‹œ๋‚˜๋ฆฌ์˜ค๋ฅผ ๊ฐ€์žฅ ์ž˜ ํ‘œํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ œ์•ˆํ•˜์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ?)

์ด ํŽ˜์ด์ง€๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‚˜์š”?
0 / 5 - 0 ๋“ฑ๊ธ‰