CHAPTER 3. The wonderful land of Web Components

A brave new world

์ปดํฌ๋„ŒํŠธ๋Š” ๊ฐœ๋ฐœ์ธก๋ฉด์—์„œ ์˜ค๋ž˜๋œ ํ™˜์ƒ์ด์—ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ด๊ฒƒ์€ ์™„์ „ํžˆ ์ƒˆ๋กœ์šด๊ฒƒ์€ ์•„๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ๊ฝค ์˜ค๋žซ๋™์•ˆ ์›น ๊ฐœ๋ฐœ์—์„œ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์—ˆ์œผ๋‚˜ ์ปดํฌ๋„ŒํŠธ๋“ค์€ ๋‹น์‹ ์˜ ์•ฑ์—๋Š” ํ•„์š”ํ•˜์ง€ ์•Š๋”๋ผ๋„ jqeury, dojo, prototype, angularjs ๋“ฑ ๋ช‡๋ช‡์˜ ์ข…๋ฅ˜๋ฅผ ์š”๊ตฌํ•˜์˜€๋‹ค.

์›น ์ปดํฌ๋„ŒํŠธ๋Š” ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ณ ์ž ํ•œ๋‹ค. : ๊ทธ๋Ÿผ ์žฌ์‚ฌ์šฉ์ ์ด๊ณ  ์บก์Šํ™”๋œ ์ปดํฌ๋„ŒํŠธ๋“ค์„ ๊ฐ€์ ธ๋ณด๋„๋ก ํ•˜์ž.

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

์ƒˆ๋กœ์šด ํ‘œ์ค€์€ 4๊ฐ€์ง€ ๊ทœ๊ฒฉ์— ์ •์˜๋˜์–ด์žˆ๋‹ค.

  • Custom elemts

  • Shadow DOM

  • Template

  • HTML Imports

์•ž์œผ๋กœ์˜ ์ƒ˜ํ”Œ๋“ค์„ ๊ฐ€์žฅ ์ž˜ ๋™์ž‘ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์ตœ์‹  ๋ฒ„์ ผ์˜ ํฌ๋กฌ์ด๋‚˜ ํŒŒ์ด์–ดํญ์Šค๋ฅผ ์ด์šฉํ•˜๋ผ.

Custom elements

์ปค์Šคํ…€ ์ปดํฌ๋„ŒํŠธ๋Š” ๊ฐœ๋ฐœ์ž์—๊ฒŒ </ns-pony>์™€ ๊ฐ™์€ ์œ ์š”ํ•œ HTML ์—˜๋ฆฌ๋จผํŠธ ๊ฐ™์ด ๊ทธ๋“ค ์ž์‹ ์˜ DOM ์—˜๋ฆฌ๋จผํŠธ๋ฅผ ๋งŒ๋“ค์ˆ˜์žˆ๋„๋ก ํ—ˆ์šฉํ•œ๋‹ค. ์ด ์‚ฌ์–‘์€ ์ด์ „์— ์กด์žฌํ•˜๋Š” ์—˜๋ฆฌ๋จผํŠธ๋ฅผ ์–ด๋–ป๊ฒŒ ํ™•์žฅํ• ์ˆ˜ ์žˆ๋Š”์ง€๋ฅผ ์„ ์–ธํ•œ๋‹ค. ์ปค์Šคํ…€ ์—˜๋ฆฌ๋จผํŠธ๋ฅผ ์„ ์–ธํ•˜๋Š” ๊ฒƒ์€ "document.registerElement('ns-pony')" ์™€ ๊ฐ™์ด ์„ ์–ธํ•˜๋ฉด ๊ฐ„๋‹จํžˆ ์ •์˜๋˜์–ด ์ง„๋‹ค.

// new element
var PonyComponent = document.registerElement('ns-pony');
// insert in current body
document.body.appendChild(new PonyComponent());

์ด๋ฆ„์—๋Š” dash๊ฐ€ ํฌํ•จ๋˜์–ด์•ผ ํ•œ๋‹ค๋Š”๊ฒƒ์„ ์ฃผ์˜ํ•ด๋ผ. ๊ทธ๋ž˜์•ผ์ง€ ๋ธŒ๋ผ์šฐ์ ธ๊ฐ€ ์ปค์Šคํ„ฐ ์—˜๋ฆฌ๋จผํŠธ๋ผ๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค. ๋ฌผ๋ก , ๋‹น์‹ ์˜ ์ปค์Šคํ…€ ์—˜๋ฆฌ๋จผํŠธ๋Š” ์†์„ฑ๋„ ์žˆ์„๊ฒƒ์ด๊ณ  ํ•จ์ˆ˜๋„ ์žˆ์„๊ฒƒ์ด๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ทธ๊ฒƒ์€ ์ง€์›Œ์ง€๊ฑฐ๋‚˜ ์ƒ์„ฑ๋˜๊ฑฐ๋‚˜ ์†์„ฑ์ด ๋ณ€๊ฒฝ๋  ๊ฒฝ์›จ ๋ฐœ์ƒํ•˜๋Š” ๋ผ์ดํ”„ ์‚ฌ์ดํด ์ฝœ๋ฐฑ๋„ ์žˆ์„๊ฒƒ์ด๋‹ค. ์ด๊ฒƒ์€ ์ž์‹ ์˜ ํ…œํ”Œ๋ฆฟ์„ ๊ฐ€์ง„๋‹ค. ์•„๋งˆ๋„ ns-pone๋Š” ๊ทธ๊ฒƒ์˜ ์ด๋ฆ„์ด๋‚˜ ์ด๋ฏธ์ง€๋ฅผ ๋ณด์—ฌ์ค„๊ฒƒ์ด๋‹ค.

// let's extend HTMLElement
var PonyComponentProto = Object.create(HTMLElement.prototype);
// and add some template using a lifecycle
PonyComponentProto.createdCallback = function() {
  this.innerHTML = '<h1>General Soda</h1>';
};
// new element
var PonyComponent = document.registerElement('ns-pony', {prototype: PonyComponentProto});
// insert in current body
document.body.appendChild(new PonyComponent());

๋งŒ์•ฝ ๋‹น์‹ ์ด dom ๊ฐ์ฒด๋ฅผ ํ™•์ธํ•œ๋‹ค๋ฉด, ๋‹น์‹ ์€ General Soda</ns-pony> ๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ์ด๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ด๊ฒƒ์€ ๋‹น์‹ ์˜ ์•ฑ์˜ CSS๋‚˜ javascript ๋กœ์ง์ด ์ปค์Šคํ…€ ์ปดํฌ๋„ŒํŠธ์— ์š”๊ตฌํ•˜์ง€ ์•Š๋Š” ํšจ๊ณผ๋ฅผ ์ค„์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•œ๋‹ค. ๊ทธ๋ž˜์„œ ์ฃผ๋กœ ํ…œํ”Œ๋ฆฟ์€ ๊ทธ๋ฆผ์ž DOM์ด๋ผ๋Š” ๊ฒƒ์œผ๋กœ ์บก์Šํ™”๋˜์–ด์ง€๊ณ  ์ˆจ๊ฒจ์ง€๋ฉฐ, ๋งŒ์•ฝ ๋‹น์‹ ์ด DOM ๊ฐ์ฒด์—์„œ ๊ฐ์ง€ํ•˜์—ฌ ๋ธŒ๋ผ์šฐ์ ธ์— pony์˜ ์ด๋ฆ„์ด ๋ณด์—ฌ์งˆ์ง€๋ผ๋„ ๋‹น์‹ ์€ ์˜ค์ง </ns-pony>๋ฅผ ๋ณผ๊ฒƒ์ด๋‹ค.

Shadow DOM

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

์ด์ „ ์•ฑ์œผ๋กœ ๋Œ์•„๊ฐ€๋ณด์ž.

var PonyComponentProto = Object.create(HTMLElement.prototype);
// add some template in the Shadow DOM
PonyComponentProto.createdCallback = function() {
  var shadow = this.createShadowRoot();
  shadow.innerHTML = '<h1>General Soda</h1>';
};
var PonyComponent = document.registerElement('ns-pony', {prototype: PonyComponentProto});
document.body.appendChild(new PonyComponent());

๋งŒ์•ฝ ๋‹น์‹ ์ด ํ™•์ธํ•ด๋ณด์•˜๋‹ค๋ฉด ์ด๋Ÿฌํ•œ ์ฝ”๋“œ๋ฅผ ํ™•์ธํ–ˆ์„ ๊ฒƒ์ด๋‹ค.

<ns-pony>
  #shadow-root (open)
   <h1>General Soda</h1>
</ns-pony>

์ด์ œ ๋‹น์‹ ์ด h1 ์—˜๋ฆฌ๋จผํŠธ์— ์•ฝ๊ฐ„์˜ ์Šคํƒ€์ผ์„ ์ถ”๊ฐ€ํ•˜์˜€์„์ง€๋ผ๋„, ์ปดํฌ๋„ŒํŠธ์˜ ๋ณด์ด๋Š” ๊ด€์ ์—์„œ๋Š” ์–ด๋– ํ•œ ๋ณ€ํ™”๋„ ์—†์„ ๊ฒƒ์ด๋‹ค. ๊ทธ๋ฆผ์ž DOM์ด ๋ฐฉ์–ด๋ฒฝ๊ณผ ๊ฐ™์€ ์—ญํ™œ์„ ํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

์ง€๊ธˆ๊นŒ์ง€๋„, ์šฐ๋ฆฌ๋Š” Component์˜ ํ…œํ”Œ๋ฆฟ์œผ๋กœ ๋ฌธ์ž์—ด์„ ์‚ฌ์šฉํ•˜์˜€๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ด๊ฒƒ์€ ์ผ๋ฐ˜์ ์ธ ๋ฐฉ๋ฒ•์ด ์•„๋‹ˆ๋‹ค. ๋Œ€์‹ , ์š”์†Œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€์žฅ ์ข‹๋‹ค.

Template

ํ…œํ”Œ๋ฆฟ์€ ๋ธŒ๋ผ์šฐ์ ธ์—๋Š” ํ‘œ์‹œ๋˜์ง€ ์•Š๋Š” ์•ˆ์— ๋ช…์‹œ๋˜์–ด์ง„๋‹ค. ์ฃผ๋œ ๋ชฉ์ ์€ ํŠน์ • ์‹œ์ ์—์„œ ์š”์†Œ์— ๋ณต์ œ๋˜๋Š” ๊ฒƒ์ด๋‹ค. ํ…œํ”Œ๋ฆฟ์€ getElementById() ์™€ ๊ฐ™์€ ์ผ๋ฐ˜์ ์ธ ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋‚˜๋จธ์ง€ ํŽ˜์ด์ง€์—์„œ ์ฟผ๋ฆฌ ํ•  ์ˆ˜ ์—†์œผ๋ฉฐ ํŽ˜์ด์ง€์˜ ์•„๋ฌด ๊ณณ์—๋‚˜ ์•ˆ์ „ํ•˜๊ฒŒ ๋ฐฐ์น˜๋  ์ˆ˜ ์žˆ๋‹ค.

ํ…œํ”Œ๋ฆฟ์„ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ๋ณต์ œํ•ด์•ผํ•œ๋‹ค.

<template id="pony-tpl">
  <style>
   h1 { color: orange; }
  </style>
  <h1>General Soda</h1>
</template>
var PonyComponentProto = Object.create(HTMLElement.prototype);
// add some template using the template tag
PonyComponentProto.createdCallback = function() {
  var template = document.querySelector('#pony-tpl');
  var clone = document.importNode(template.content, true);
  this.createShadowRoot().appendChild(clone);
};
var PonyComponent = document.registerElement('ns-pony', {prototype: PonyComponentProto});
document.body.appendChild(new PonyComponent());

์•„๋งˆ ์šฐ๋ฆฌ๋Š” ํ•œ ํŒŒ์ผ์•ˆ์—์„œ ์„ ์–ธ์„ ํ• ์ˆ˜ ์žˆ๊ณ , ์šฐ๋ฆฌ๋Š” ์™„๋ฒฝํ•˜๊ฒŒ ์บก์Šํ™”๋œ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ฐ€์ง„๊ฒƒ์ด๋‹ค.

HTML Imports

์ด๊ฒƒ์€ ๋งˆ์ง€๋ง‰ ์‚ฌ์–‘์ด๋‹ค. HTML import๋Š” HTML ์•ˆ์— HTML์„ ๊ฐ€์ ธ์˜ค๋Š”๊ฒƒ์„ ํ—ˆ์šฉํ•œ๋‹ค.

์™€ ๊ฐ™์€ ํ˜•ํƒœ์ด๋‹ค. ns-pony.html ํŒŒ์ผ์€ ํ•„์š”ํ•œ ๋ชจ๋“ ๊ฒƒ์„ ๋‹ด์„ ์ˆ˜ ์žˆ๋‹ค.

๋งŒ์•ฝ ๋ˆ„๊ตฐ๊ฐ€ ์šฐ๋ฆฌ์˜ ํ›Œ๋ฅญํ•œ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๊ธธ ์›ํ•œ๋‹ค๋ฉด ๊ทธ๋“ค์€ ๋‹จ์ง€ HTML import ํ•ด์„œ ์‚ฌ์šฉํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ๋œ๋‹ค.

Polymer and X-tag

์›น ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ชจ๋“  ๋ธŒ๋ผ์šฐ์ ธ์—์„œ ์ง€์›ํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— polyfill์„ ๋‹น์‹ ์˜ ์•ฑ์— ํฌํ•จํ•˜๋ฉด ์ •์ƒ์ ์œผ๋กœ ๋™์ž‘ํ•  ๊ฒƒ์ด๋‹ค. polyfill์€ web-component.js๋กœ ๋ถˆ๋ฆฌ์–ด์ ธ ์žˆ๊ณ  google, mozila, microsoft๋“ฑ ๊ณต๋™์œผ๋กœ ๋…ธ๋ ฅํ•˜๊ณ  ์žˆ๋Š” ๊ฒฐ๊ณผ๋ฌผ์ด๋ผ๋Š” ์ ์€ ์ฃผ๋ชฉํ•  ๋งŒํ•œ ๊ฐ€์น˜๊ฐ€ ์žˆ๋‹ค.

์ฃผ๋ชฉํ•  ๋งŒํ•œ ๊ธฐ๋Šฅ์„ ํ™•์ธํ•ด๋ณด๋„๋ก ํ•˜์ž.

  • Polymerfrom google

  • X-tagfrom Mozilla and Microsoft

๋””ํ…Œ์ผํ•˜๊ฒŒ๋Š” ์„ค๋ช…ํ•˜์ง€ ์•Š์„๊ฒƒ์ด๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋‹น์‹ ์€ ์ด๋ฏธ polymer component๋ฅผ ์‰ฝ๊ฒŒ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์„๊ฒƒ์ด๋‹ค. ๋‹น์‹ ์˜ ์•ฑ์•ˆ์— ์žˆ๋Š” ๊ตฌ๊ธ€ ๋งต์„ ์‚ดํŽด๋ณด๋„๋ก ํ•˜์ž.

<!-- Polyfill Web Components support for older browsers -->
<script src="webcomponents.js"></script>
<!-- Import element -->
<link rel="import" href="google-map.html">
<!-- Use element -->
<body>
  <google-map latitude="45.780" longitude="4.842"></google-map>
</body>

polymer์•ˆ์—๋Š” ๋งค์šฐ ๋‹ค์–‘ํ•œ ๊ตฌ์„ฑ์š”์†Œ๊ฐ€ ์žˆ๋‹ค. https://customelements.io ํ•ด๋‹น ์‚ฌ์ดํŠธ์—์„œ ์‚ดํŽด๋ณผ ์ˆ˜ ์žˆ๋‹ค. polymer๋Š” ์ปค์Šคํ…€ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋นŒ๋“œํ•˜๋Š”๋ฐ์—๋„ ๋„์›€์„ ์ค€๋‹ค.

<dom-module id="ns-pony">
  <template>
   <h1>[[name]]</h1>
  </template>
  <script>
   Polymer({
   is: 'ns-pony',
   properties: {
   name: String
   }
   });
  </script>
</dom-module>
<!-- Polyfill Web Components support for older browsers -->
<script src="webcomponents.js"></script>
<!-- Polymer -->
<link rel="import" href="polymer.html">
<!-- Import element -->
<link rel="import" href="ns-pony.html">
<!-- Use element -->
<body>
  <ns-pony name="General Soda"></ns-pony>
</body>

๋‹น์‹ ์€ Polymer๋ฅผ ๊ฐ€์ง€๊ณ  ๊ต‰์žฅํ•œ ๊ฒƒ๋“ค์„ ๋งŽ์ด ํ• ์ˆ˜ ์žˆ๋‹ค. (์–‘๋ฐฉํ–ฅ ๋ฐ”์ธ๋”ฉ, ๊ธฐ๋ณธ ์†์„ฑ ์„ค์ •, ์ปค์Šคํ…€ ์ด๋ฒคํŠธ, ์†์„ฑ๋ณ€๊ฒฝ์‹œ ๋ฐœ์ƒํ•˜๋Š” ์ด๋ฒคํŠธ ๋“ฑ)

์ง€๊ธˆ๊นŒ์ง€ ๋‹น์‹ ์—๊ฒŒ ๋งํ•œ ์›น ์ปดํฌ๋„ŒํŠธ์— ๋Œ€ํ•œ ์„ค๋ช…์€ ๋งค์šฐ ์งง๊ฒŒ ์š”์•ฝํ•œ ๊ฒƒ์ด๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์›น ์ปดํฌ๋„ŒํŠธ์— ๋Œ€ํ•œ ์ปจ์…‰์€ ๋ช…ํ™•ํ•˜๊ฒŒ ์„ค๋ช…ํ•˜์˜€๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ตฌ๊ธ€ ํŒ€์€ Angular 2 ์ปดํฌ๋„ŒํŠธ์— ๋”ฐ๋ผ์„œ ์›น ์ปดํฌ๋„ŒํŠธ ์‚ฌ์šฉ์„ ๋งค์šฐ ์‰ฝ๊ฒŒ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด Angular 2๋ฅผ ๋””์ž์ธ ํ–ˆ๋‹ค๋Š” ๊ฒƒ์„ ์ดํ•ดํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ์ด๋‹ค.

Reference URL

Last updated