본문 바로가기
Frontend2026년 4월 15일5분 읽기

Web Components 2026 — 프레임워크 없이 재사용 UI 만드는 법 (Shadow DOM·Slot·Form Internals)

YS
김영삼
조회 284

핵심 요약

Web Components는 네이티브 브라우저 API 3종 세트다. React·Vue 없이도 재사용 UI 컴포넌트를 만들 수 있다. 디자인 시스템을 여러 프레임워크에 동시에 배포해야 할 때 가장 유리하다.

  • Custom Elements: 태그 정의
  • Shadow DOM: 스타일·DOM 캡슐화
  • Templates & Slots: 콘텐츠 투영

기본 컴포넌트

class UiButton extends HTMLElement {
  static formAssociated = true;

  constructor() {
    super();
    this.attachShadow({ mode: 'open' });
    this.shadowRoot.innerHTML = `
      <style>
        button { padding: 8px 16px; border-radius: 8px; }
        :host([variant="primary"]) button { background: #2563eb; color: white; }
      </style>
      <button><slot></slot></button>
    `;
  }

  connectedCallback() {
    this.shadowRoot.querySelector('button')
      .addEventListener('click', () => this.dispatchEvent(new CustomEvent('ui-click')));
  }
}
customElements.define('ui-button', UiButton);
<ui-button variant="primary">저장</ui-button>

Shadow DOM 스타일링

  • :host: 호스트 요소 자체 스타일
  • :host([attr]): 속성 조건부
  • ::slotted(selector): 슬롯된 콘텐츠
  • ::part(name): 외부에서 내부 요소 스타일링 허용
  • CSS 변수는 Shadow 경계를 넘어감 (테마링에 활용)

Form Internals (form-associated)

폼과 자연스럽게 통합되는 커스텀 입력을 만들 수 있다.

class UiInput extends HTMLElement {
  static formAssociated = true;
  #internals;
  constructor() {
    super();
    this.#internals = this.attachInternals();
    this.attachShadow({ mode: 'open' }).innerHTML = `<input>`;
    this.shadowRoot.querySelector('input')
      .addEventListener('input', (e) => {
        this.#internals.setFormValue(e.target.value);
      });
  }
  static get observedAttributes() { return ['required']; }
}
customElements.define('ui-input', UiInput);

이제 <form> 안에서 FormData로 값이 제출된다.

React와의 상호운용

  • React 19부터 custom element props·event가 기본 지원
  • 그 이전은 ref로 속성·이벤트 바인딩
  • Vue·Svelte·Angular 모두 호환

실전 디자인 시스템 전략

  • 디자인 토큰(CSS 변수) → 전역 테마
  • ::part 공개 범위를 문서에 명시 (API 안정성)
  • i18n은 slot으로 외부 주입
  • 번들: 런타임은 없음, 단일 .js 모듈로 배포

자주 묻는 질문

React에서 써도 성능 이점이 있나?

컴포넌트 단위 성능보다 프레임워크 중립성이 핵심 가치. 여러 플랫폼(Next.js, 레거시 jQuery, Vue)에 같은 UI를 공급할 때 유리.

SSR 지원은?

Declarative Shadow DOM으로 SSR 가능. Next·Lit SSR이 대표적.

댓글 0

아직 댓글이 없습니다.
Ctrl+Enter로 등록