🌐 웹개발

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를 노출하세요. 프레임워크 래퍼를 제공하면 사용성이 좋아집니다.

🔗 관련 용어

📚 더 배우기