🌐 웹개발

Web Components

웹 컴포넌트

재사용 가능한 커스텀 HTML 요소. 프레임워크 독립적.

📖 상세 설명

Web Components는 재사용 가능한 커스텀 HTML 요소를 만들기 위한 웹 표준 기술입니다. Custom Elements, Shadow DOM, HTML Templates 세 가지 핵심 기술로 구성되며, React나 Vue 같은 프레임워크 없이도 캡슐화된 컴포넌트를 만들 수 있습니다.

Custom Elements는 새로운 HTML 태그를 정의합니다. class로 요소의 동작을 정의하고 customElements.define()으로 등록하면 <my-component>처럼 사용할 수 있습니다. Shadow DOM은 스타일과 마크업을 캡슐화하여 외부 CSS가 내부에 영향을 주지 않게 합니다.

Web Components의 가장 큰 장점은 프레임워크 독립성입니다. 한 번 만든 컴포넌트를 React, Vue, Angular, 순수 HTML 어디서나 사용할 수 있습니다. 디자인 시스템, 위젯, 마이크로프론트엔드에서 프레임워크 간 공유 컴포넌트로 활용됩니다.

실무에서는 Lit, Stencil, Fast 같은 라이브러리가 Web Components 개발을 더 쉽게 해줍니다. YouTube, GitHub, Salesforce Lightning 등 대형 서비스에서 Web Components를 적극 활용합니다. 단, IE11 지원이 필요하면 폴리필이 필요합니다.

💻 코드 예제

// Custom Element 정의
class MyCounter extends HTMLElement {
  constructor() {
    super();
    // Shadow DOM 생성 (캡슐화)
    this.attachShadow({ mode: 'open' });
    this.count = 0;
  }

  connectedCallback() {
    // DOM에 추가될 때 호출
    this.render();
    this.shadowRoot.querySelector('button')
      .addEventListener('click', () => this.increment());
  }

  increment() {
    this.count++;
    this.render();
    // 커스텀 이벤트 발생
    this.dispatchEvent(new CustomEvent('count-changed', {
      detail: { count: this.count }
    }));
  }

  render() {
    this.shadowRoot.innerHTML = `
      <style>
        /* Shadow DOM 내부에만 적용 */
        button { padding: 8px 16px; cursor: pointer; }
        span { font-size: 1.5rem; margin: 0 10px; }
      </style>
      <button>+</button>
      <span>${this.count}</span>
    `;
  }
}

// 커스텀 요소 등록
customElements.define('my-counter', MyCounter);

// HTML에서 사용
// <my-counter></my-counter>

// React에서 사용
function App() {
  const handleCount = (e) => console.log(e.detail.count);
  return <my-counter onCount-changed={handleCount} />;
}

🗣️ 실무에서 이렇게 말하세요

💬 아키텍처 논의에서
"마이크로프론트엔드에서 팀별로 다른 프레임워크를 쓴다면, 공통 컴포넌트는 Web Components로 만드는 게 좋아요. React 팀이든 Vue 팀이든 동일한 디자인 시스템 컴포넌트를 사용할 수 있습니다."
💬 면접에서
"Web Components는 Custom Elements, Shadow DOM, HTML Templates로 구성됩니다. Shadow DOM으로 스타일 캡슐화가 되어서 외부 CSS 충돌 걱정이 없고, 프레임워크와 무관하게 동작합니다. Lit 라이브러리를 사용하면 더 선언적으로 작성할 수 있습니다."
💬 코드 리뷰에서
"Shadow DOM을 쓰면 외부 스타일이 침투하지 않지만, 의도적으로 테마 변수를 받으려면 CSS Custom Properties(--변수)를 사용해야 해요. ::part() 의사 요소로 특정 부분만 스타일링 허용할 수도 있습니다."

⚠️ 흔한 실수 & 주의사항

SSR과의 호환성 문제

Web Components는 클라이언트 JavaScript가 필요합니다. SSR 환경에서는 Declarative Shadow DOM이나 hydration 전략이 필요합니다.

React와의 이벤트 처리 차이

React는 커스텀 이벤트를 자동으로 처리하지 않습니다. ref를 사용하거나 래퍼 컴포넌트를 만들어 이벤트 리스너를 직접 연결해야 합니다.

올바른 활용

Lit 같은 라이브러리로 개발 경험을 개선하고, 테마 지원을 위해 CSS Custom Properties를 노출하세요. 프레임워크 래퍼를 제공하면 사용성이 좋아집니다.

🔗 관련 용어

📚 더 배우기