홈으로 돌아가기

Web Components: Custom Elements에 대한 미스와 진실

이 기사는 web components에 대한 미스를 폭로: property 전달, Shadow DOM, hooks. 코드 솔루션을 제공하고 복잡한 대시보드와 위젯의 강점을 강조.

개발자를 위한 web components에 대한 미스 폭로
Advertisement 728x90

웹 컴포넌트: 오해를 풀고 진짜 능력 살펴보기

웹 컴포넌트는 종종 속성을 통해서만 문자열 속성 전달이 가능하다는 이유로 비판받습니다. 이 오해는 attributeChangedCallback 메커니즘에 대한 잘못된 이해에서 비롯됩니다. HTML 속성은 마크업의 정적인 부분이며, JS 런타임과 직접 연결되지 않습니다. 객체, 배열 또는 기본형을 전달하려면 컴포넌트 클래스의 게터/세터를 사용하세요. 브라우저는 DOM API나 프록시를 통해 모든 유형의 속성을 직접 설정할 수 있습니다.

class MyElement extends HTMLElement {
  set data(value) {
    this._data = value;
    this.render();
  }
}

섀도우 DOM은 스타일과 DOM 격리를 제공하여 외부 충돌로부터 보호합니다. 격리를 단점으로 비판하는 것은 선택을 무시하는 것입니다: 커스텀 엘리먼트는 섀도우 DOM 없이도 작동합니다. 커스터마이징을 위해서는 CSS 변수와 ::part()를 사용하세요:

my-component::part(button) {
  background: var(--accent-color);
}

스타일 중복에 대한 오해: Adopted Style Sheets를 사용하면 모든 섀도우 DOM 인스턴스에 공유 스타일을 적용할 수 있습니다.

Google AdInline article slot

라이프사이클은 DOM에 연결될 때가 아닌 생성자에서 시작됩니다. 컴포넌트는 메모리에 생성되며, 렌더링 없이 가상화를 위해 DocumentFragment를 통해 조작됩니다.

반은 진실: 레지스트리와 라이프사이클 훅

전역 커스텀 엘리먼트 레지스트리는 고유한 이름을 요구합니다. 해결책은 접두사(예: app-button)와 등록 시 try/catch입니다:

try {
  customElements.define('app-button', ButtonElement);
} catch (e) {
  console.warn('이름 충돌:', e);
}

충돌은 테스트에서 발견됩니다. 평면 네임스페이스는 JS, DNS, HTML에서 표준 패턴입니다.

Google AdInline article slot

connectedCallback/disconnectedCallback 훅은 DOM 내 이동 시 트리거됩니다. 해결책은 초기화 플래그입니다:

connectedCallback() {
  if (this._initialized) return;
  this._initialized = true;
  this.init();
}

등록 해제는 불가능하지만, 이는 장점입니다: 브라우저는 오버헤드 없이 생성자를 캐시합니다.

실제 세부 사항과 해결책

HTML 파싱은 콘텐츠 처리 전에 여는 태그에서 connectedCallback을 트리거합니다. DOM API는 사용할 수 없습니다. 지연 초기화를 위해 defer 또는 type="module"을 사용하세요. 대안은 customElements.whenDefined()입니다:

Google AdInline article slot
const button = document.querySelector('app-button');
await customElements.whenDefined('app-button');
button.method();

자식 엘리먼트에 대한 접근을 보장하려면 renderCallback 또는 유사한 훅을 사용하세요.

웹 컴포넌트의 강점

웹 컴포넌트는 기본적으로 HTML 마크업과 JS를 연결합니다. 커스텀 태그는 벤더 종속 없이 서버나 클라이언트에서 통합을 위한 마커 역할을 합니다.

원자적 라이프사이클 관리: 브라우저는 프레임워크와 독립적으로 연결/해제에 대해 알립니다.

Lit, Symbiote.js, 마이크로 프론트엔드를 위한 기초 모델입니다. React, Vue, Angular, SPA, SSR과 함께 작동합니다.

  • 오버헤드 없는 격리: 섀도우 DOM은 선택 사항입니다.
  • 네이티브 반응성: 속성 + 프록시.
  • 다용도성: 위젯부터 WebSocket과 그래픽을 사용한 대시보드까지.
  • 가상화: 10만 개 이상의 엘리먼트 목록을 위한 DocumentFragment.
  • 스타일링: CSS 변수, ::part(), Adopted Style Sheets.

핵심 요약

  • 모든 유형의 속성은 게터/세터를 통해 전달됩니다; 속성은 문자열만을 위한 것입니다.
  • 섀도우 DOM은 격리하지만 필요 시 비활성화할 수 있습니다; 변수와 ::part를 통한 스타일.
  • 전역 레지스트리는 접두사와 테스트로 해결됩니다; 충돌은 드뭅니다.
  • connected/disconnected 훅과 플래그로 중복 초기화를 방지합니다.
  • 파싱 비동기성은 defer/module 또는 whenDefined로 해결됩니다.

— Editorial Team

Advertisement 728x90

다음 읽기