홈으로 돌아가기

Symbiote.js: virtual DOM 없이 web components 구성 | 가이드

Symbiote.js를 사용한 web components 생성 기술 가이드. 탭 구현, 공유 컨텍스트 메커니즘 및 low-code 접근 이점 분석. 중/시니어 개발자 적합.

Symbiote.js: HTML 통해 인터페이스를 생성자처럼 조립하는 법
Advertisement 728x90

Symbiote.js: 가상 DOM 없이 Web Components의 고급 구성

Symbiote.js는 HTML 마크업을 통한 고급 구성에 초점을 맞춘 web components 생성을 위한 경량(~6 KB Brotli) 라이브러리입니다. 가상 DOM 의존성을 없애고 데이터 컨텍스트 작업을 위한 유연한 메커니즘을 제공함으로써 인터페이스의 구조적 조직 문제를 해결합니다. 전통적인 프레임워크와 달리 Symbiote.js는 DOM API를 직접 사용해 보일러플레이트를 최소화하고 선언적 마크업으로 컴포넌트를 조합할 수 있게 합니다.

구조적 구성의 기본

인터페이스 개발은 논리적 모델(컴포넌트, 데이터)과 구조적 구성(컴포넌트 연결, 데이터 흐름)의 두 측면으로 이루어집니다. Symbiote.js는 후자에 독특한 접근 방식을 제시하며, HTML을 의존성 정의의 핵심 도구로 활용합니다. 주요 원칙:

  • 컴포넌트 템플릿은 독립적인 HTML 문자열
  • 외부 마크업이 구조적 연결을 정의
  • JS 런타임에 바인딩되지 않음
  • 하이브리드 접근 지원(서버/클라이언트 렌더링)

이렇게 하면 미리 생성된 마크업을 활성화하거나 로직 없는 '멍청한' 컴포넌트를 만들거나 컨텍스트 제공자를 사용할 수 있습니다. 예를 들어 두 개의 연결된 컴포넌트로 탭을 구현할 수 있습니다:

Google AdInline article slot
import Symbiote, { css } from '@symbiotejs/symbiote';

class SuperTabs extends Symbiote {
  init$ = {
    '*currentTabName': 'first',
  };

  renderCallback() {
    this.tabEls = [...this.querySelectorAll('[tab]')];
    this.tabEls.forEach((/** @type {HTMLElement} */ el) => {
      let tab = el.getAttribute('tab');
      if (el.hasAttribute('current')) {
        this.$['*currentTabName'] = tab;
      }
      el.onclick = () => {
        this.$['*currentTabName'] = tab;
      };
    });
    this.sub('*currentTabName', (val) => {
      this.tabEls.forEach((/** @type {HTMLElement} */ el) => {
        if (el.getAttribute('tab') === val) {
          el.setAttribute('current', '');
        } else {
          el.removeAttribute('current');
        }
      });
    });
  }
}

SuperTabs.rootStyles = css`
super-tabs {
  display: inline-flex;
  gap: 2px;
  [tab] {
    cursor: pointer;
    &[current] {
      background-color: transparent;
      pointer-events: none;
    }
  }
}
`;

SuperTabs.reg('super-tabs');

두 번째 컴포넌트는 콘텐츠 표시를 처리합니다:

class SuperTabsView extends Symbiote {
  renderCallback() {
    this.tabCtxEls = [...this.querySelectorAll('[tab-ctx]')];
    this.sub('*currentTabName', (val) => {
      this.tabCtxEls.forEach((/** @type {HTMLElement} */ el) => {
        if (el.getAttribute('tab-ctx') === val) {
          el.setAttribute('active', '');
        } else {
          el.removeAttribute('active');
        }
      });
    });
  }
}

SuperTabsView.rootStyles = css`
super-tabs-view {
  display: block;
  [tab-ctx] {
    display: none;
    &[active] {
      display: contents;
    }
  }
}
`;

SuperTabsView.reg('super-tabs-view');

주요 기술적 특징

이 예시는 다섯 가지 핵심 메커니즘을 보여줍니다:

  • rootStyles — 부모 요소의 Shadow DOM 유무와 관계없이 스타일이 올바르게 적용됩니다. Tailwind, Bootstrap, 글로벌 스타일과의 호환성을 보장합니다.
  • renderCallback — 자식 노드에 접근할 수 있는 라이프사이클(표준 connectedCallback과 다름).
  • init$ — 기본값으로 반응형 속성 초기화.
  • sub() — 가상 DOM 없이 Pub/Sub를 통한 속성 변경 구독.
  • *별표()를 통한 속성** — 공유 컨텍스트 선언(input[type=radio]의 name 속성과 유사).

아키텍처의 특징은 추상화 없이 DOM API를 직접 사용하는 것입니다. 이는 안티패턴이 아니라 의도된 선택으로 가상 표현의 오버헤드를 제거합니다. 동시에 타이핑, 반응성, 런타임 디버깅을 지원합니다.

Google AdInline article slot

저코드 패러다임 실전

Symbiote.js의 장점은 JavaScript 없이 HTML 속성으로 인터페이스를 조립하는 시나리오에서 빛납니다. 현재 탭을 표시하는 컴포넌트를 고려해보세요:

class SuperCurrent extends Symbiote {}

SuperCurrent.rootStyles = css`
super-current {
  display: block;
  h2 {
    text-transform: capitalize;
  }
}
`;

SuperCurrent.template = html`<h2>{{*currentTabName}}</h2>`;

SuperCurrent.reg('super-current');

사용 예:

<super-current ctx="section-select"></super-current>

이 접근 방식은 다음 가능성을 열어줍니다:

Google AdInline article slot
  • 디자이너: HTML에서 직접 인터페이스 프로토타이핑
  • 콘텐츠 관리자: 코드 없이 속성으로 표시 커스터마이징
  • 임베디드 솔루션: 마크업으로 위젯 구성
  • AI 시스템: 예측 가능한 마크업과 동작 연결로 인터페이스 생성

라이브러리의 컴포넌트가 많을수록 HTML로 복잡한 인터페이스를 쉽게 조립할 수 있습니다. 각 컴포넌트 그룹은 ctx 속성으로 격리되어 페이지에 여러 독립 인스턴스를 배치할 수 있습니다.

중요한 점

  • 번들러 의존성 제로: Webpack/Vite 없이 작동
  • DOM을 통한 컨텍스트: 마크업 구조로 컴포넌트 간 연결 정의
  • 6 KB 크기: 성능에 미미한 영향
  • 모든 스택 호환: 기존 프로젝트에 마이그레이션 없이 통합
  • 기본 내장 타입: 추가 설정 없이 TypeScript 지원

Symbiote.js는 프레임워크를 대체하지 않고 구조적 구성 영역을 보완합니다. 논리적 작업에는 미니멀한 API를 제공하며, 다른 솔루션에서 서드파티 라이브러리로 구현하는 부분(상태 관리, 라우팅)에 집중합니다. 이는 특히 다양한 멤버로 구성된 팀에서 인터페이스 설계 시 인지 부하를 줄여줍니다.

— Editorial Team

Advertisement 728x90

다음 읽기