웹 개발에서 컴포넌트는 같은 틀을 가졌지만 필요에 따라 다른 모습을 표현할 수 있는 재사용 가능한 블록같은 것입니다. 출처: copilot

웹 컴포넌트는 HTML, CSS, 자바스크립트를 활용하여 재사용 가능하고 캡슐화된 웹 요소를 만드는 도구입니다. 웹 컴포넌트는 표준 웹 기술을 사용하여 구현하기 때문에 웹 프레임워크나 라이브러리에 의존하지 않고 개발할 수 있습니다. 덕분에 다양한 환경에서 사용될 수 있고, 개발자가 선택할 수 있는 유연성을 제공합니다.

웹 컴포넌트

웹 컴포넌트는 React나 Vue에서 말하는 컴포넌트와 같은 것을 가르킵니다. 즉 재사용이 가능한 코드를 의미합니다. 웹 컴포넌트를 사용하면 다른 컴포넌트를 사용하는 것과 똑같은 이점을 가질 수 있습니다. 웹 개발자들이 쉽게 코드를 재사용하여 생산성을 높이고 동일한 디자인 요소를 가진 코드를 컴포넌트로 만들어 일관된 사용자 인터페이스를 구현할 수 있게 하는 것이 바로 웹 컴포넌트 사용으로 얻어낼 수 있는 이점입니다.

주요 요소

웹 컴포넌트는 커스텀 요소와 Shadow Dom이라는 같은 두 가지 요소로 구성되어 있습니다.

커스텀 요소

커스텀 요소는 새로운 HTML 태그를 정의하여 웹 컴포넌트의 기본 구조를 만드는 기술입니다. HTML 문법을 확장하여 자신만의 태그를 만들고, 이를 재사용할 수 있습니다. 쉽게 말해 HTMLElement를 상속 받아 새로운 HTML 태그를 만들 수 있습니다.

class GreetingElement extends HTMLElement {
  constructor() {
    super();
  }

  connectedCallback() {
    const name = this.getAttribute("name") || "World";
    this.innerHTML = `<p>Hello, ${name}!</p>`;
  }
}
customElements.define("greeting-element", GreetingElement);

커스텀 요소를 정의하기 위한 간단한 코드 스니펫입니다. 해당 요소는 name이라는 속성을 받아 innerHTML로 표시하는 기능을 합니다. constructor에서 부모의 constructor를 상속받고 HTML에 처음 그려질 때 connectedCallback이 실행됩니다. 이렇게 만든 greeting-element라는 커스텀 요소는 customElements.define를 통해 등록되고 HTML파일에서 다른 태그들처럼 사용할 수 있습니다.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>

    <script src="./index.js" type="module"></script>
  </head>
  <body>
    <greeting-element name="curt poem"></greeting-element>
  </body>
</html>

greeting-element는 앞서 정의한 커스텀 태그이며 소문자로 시작하여 하이픈(-) 가 들어가 있는 케밥케이스를 사용하는 것이 일반적입니다. 이는 커스텀 요소와 기존 HTML 요소를 구분하기 위해서입니다. 하이픈이 없는 이름은 HTML 표준에 의해 정의된 요소로 간주될 수 있기 때문에 혼동을 피하기 위해서입니다. 위와 같이 작성된 HTML은 브라우저에서 다음과 같이 표시됩니다.

웹 컴포넌트를 사용해 만든 결과물

상태를 React나 Vue의 Props와 같은 역할로 사용하고 있습니다. 이렇게 재사용이 가능한 컴포넌트를 React나 Vue의 도움없이 정의하고 사용할 수 있습니다. 웹 컴포넌트는 라이브러리나 프레임워크에 종속되지 않기 때문에 React와 Vue에서도 웹 컴포넌트를 자유롭게 사용할 수 있습니다.

앞서 HTMLElement를 상속받을 때, connectedCallback은 해당 요소가 HTML에 그려질 때 실행된다고 하였습니다. 이 외에도 HTML이 DOM에서 제거될 때 실행되는 disconnectedCallback, 해당 태그의 속성이 변경될 때 실행되는 attributeChangedCallback, 컴포넌트가 다른 DOM으로 이동할 때 호출되는 adoptiveCallback 까지 미리 정해져 있는 콜백함수들이 존재합니다. 이 함수들은 컴포넌트의 생명주기와 관련되며, Vue의 Mounted와 같은 생명주기와 비슷한 역할을 합니다.

Shadow Dom

Shdow DOM은 DOM의 일부를 캡슐화하여 외부와 격리된 상태로 유지할 수 있게 해주는 기능입니다. Shadow DOM은 호스트 요소(Host Element) 내부에 독립적인 DOM 트리를 생성하게 됩니다. 이 캡슐화된 DOM 트리는 바깥의 스타일이 내부에 영향을 주지 않고 내부에 정의된 스타일이 바깥의 요소에 영향을 주지 않습니다. 다른 부분과 충돌하지 않기 때문에 CSS의 클래스 명이나 JS의 함수 이름을 간단하게 유지할 수 있습니다.

 

Shadow DOM은 다음과 같은 방법으로 만들 수 있습니다.

let shadow = elementRef.attachShadow({ mode: "open" });

모든 요소에 shadow root를 부착할 수 있기 때문에 elementRef는 어떤 HTML 요소도 될 수 있습니다. 다만 mode라는 옵션을 가진 매개변수가 필요할 뿐입니다. mode는 open 또는 closed라는 값을 가질 수 있으며, open 은 메인 페이지 맥락에서 작성된 JavaScript를 사용하여 shadow DOM에 접근할 수 있음을 의미합니다. closed는 외부로부터 shadow DOM에 접근할 수 없습니다.

let myShadowDom = myCustomElem.shadowRoot;

위의 코드는 해당 HTML 요소에 부착된 shadow DOM에 접근하는 메서드입니다. mode가 open일 경우 shadow root를 가져올 수 있지만 closed일 경우 null이 됩니다. 다만 웹컴포넌트에서 Shadow DOM을 만들 때 내부에 접근 할 수 있는 메서드를 만든다면 접근이 불가능하지는 않습니다.

결론

웹 컴포넌트는 웹 개발의 생산성을 향상시키고, 유지 관리를 용이하게 하며, 일관된 사용자 인터페이스 구현을 지원합니다. 재사용 가능한 코드를 통해 기능 개발을 간소화하고 코드 기반을 강화하는 데 도움을 줍니다. 웹 컴포넌트는 아직 초기 단계여서 작은 커뮤니티를 가지고 있고 개발을 하기 위해서 개발 환경을 하나부터 열까지 직접 설정해야 합니다. 하지만 React와 Vue와 같은 다른 라이브러리 및 프레임워크와 혼용하여 사용하는 것이 어렵지 않고 현재는 거의 모든 브라우저가 지원하는 기본 웹 API점에서 발전 가능성이 높다고 생각하는 기술입니다.

참고자료

MDN, 웹 컴포넌트
요즘 IT 웹 컴포넌트는 왜 등장했을까?
Open vs. Closed Shadow DOM

+ Recent posts