웹 구성 요소를 사용하여 프레임워크에 구애받지 않는 UI를 구축하는 방법 | Alexander T. Williams


웹 컴포넌트를 활용한 프레임워크 독립적 UI 구축

웹 개발의 균형점

웹 개발은 유연성과 유지보수성 사이의 균형을 맞추는 작업이다. 프레임워크는 빠른 생산성을 약속하지만 락인(lock-in) 문제가 존재한다. React, Vue, Angular에 깊이 의존하면 탈출하기가 비행 중 비행기를 재배선하는 것과 같다.

웹 컴포넌트는 이 방정식을 뒤집는다. 프레임워크 정치와 버전 변동에 면역인 독립적인 UI 요소 구축 방법을 제공한다. 2025년 현재, 네이티브 브라우저 지원이 그 어느 때보다 우수하며, 더 이상 흥미로운 실험이 아닌 메인 이벤트가 되었다.

웹 컴포넌트의 부상 이유

성숙한 생태계

  • 브라우저 지원이 성숙함
  • 폴리필이 거의 필요 없음
  • 개발자들이 장기적 이득을 확인

웹 표준 기반

  • 커스텀 엘리먼트
  • Shadow DOM
  • HTML 템플릿
  • HTML이 작동하는 모든 곳에서 작동

미래 보장성

  • 프레임워크 마이그레이션 생존
  • 레거시 앱에 투입 가능
  • 그린필드 프로젝트에서 활용 가능
  • 네이티브 API 실행으로 프레임워크 렌더링 레이어 의존 없음

웹 컴포넌트의 구조

세 가지 핵심 요소

  1. 커스텀 엘리먼트: customElements.define으로 커스텀 HTML 태그 정의
  2. Shadow DOM: 스타일과 DOM 구조 캡슐화
  3. HTML 템플릿: 재사용 가능한 HTML 템플릿으로 구조화

기본 구현 예제

class FancyButton extends HTMLElement {
  constructor() {
    super();
    const shadow = this.attachShadow({ mode: 'open' });
    shadow.innerHTML = `
      <style>
        button {
          background: #6200ea;
          color: white;
          border: none;
          padding: 10px 20px;
          border-radius: 5px;
          cursor: pointer;
          font-weight: bold;
          transition: background 0.3s ease;
        }
        button:hover {
          background: #4b00b5;
        }
      </style>
      <button><slot></slot></button>
    `;
  }
}

customElements.define('fancy-button', FancyButton);

<fancy-button>은 Angular, 정적 사이트 생성기, 일반 HTML 등 어떤 HTML 페이지에도 사용 가능하다. 의존성 없음, 빌드 도구 불필요.

Shadow DOM: 격리 없는 캡슐화

주요 특징

  • DOM 요소와 스타일의 스코프된 서브트리 생성
  • 전역 CSS에 의한 누출이나 덮어쓰기 없음
  • 여러 프로젝트에서 일관된 모습과 동작을 유지하는 디자인 시스템에 적합

CSS 변수를 통한 커스터마이징

button {
  background: var(--primary-color, #6200ea);
}
  • 내부 안정성을 희생하지 않고 테마 설정 가능
  • 외부 스타일시트가 컴포넌트를 깨뜨리지 않음
  • 다양한 제품을 위한 브랜딩과 커스터마이징 유연성 유지

HTML 템플릿과 재사용성

템플릿 요소의 장점

<template id="card-template">
  <style>
    .card {
      border: 1px solid #ccc;
      padding: 10px;
      border-radius: 8px;
      background: white;
      box-shadow: 0 2px 4px rgba(0,0,0,0.1);
    }
  </style>
  <div class="card">
    <slot name="title"></slot>
    <slot name="content"></slot>
  </div>
</template>
  • JavaScript에서 반복적인 HTML 문자열 회피
  • 템플릿 변경 시 모든 새 인스턴스 업데이트
  • 코드 중복 감소
  • 전체 애플리케이션 생태계에서 일관된 UI 구조 강제

프레임워크와의 통합

React에서의 사용

function App() {
  return <fancy-button>Click Me</fancy-button>;
}
  • 라이프사이클 훅 불필요
  • 프롭 타입 정의 불필요
  • 네이티브 태그처럼 간단하게 사용

멀티 스택 환경의 이점

  • 다양한 기술 스택으로 구축된 제품군 통합
  • 각 제품 팀이 동일한 UI 라이브러리 사용
  • 일관된 디자인 보장
  • 중복 작업 감소

성능 최적화

기본 최적화 전략

  • 생성자에서 비싼 작업 회피
  • DOM 조작 최소화
  • JavaScript 애니메이션보다 CSS 트랜지션 선호

레이지 로딩 구현

if ('IntersectionObserver' in window) {
  const observer = new IntersectionObserver(entries => {
    entries.forEach(entry => {
      if (entry.isIntersecting) {
        import('./fancy-button.js');
        observer.unobserve(entry.target);
      }
    });
  });

  document.querySelectorAll('fancy-button').forEach(el => observer.observe(el));
}
  • 초기 로드 시간 감소
  • Core Web Vitals 점수 개선
  • 더 빠른 첫 인터랙션 제공

보안과 유지보수성

보안 강점

  • Shadow DOM 격리로 스타일 기반 공격 가능성 감소
  • 외부 소스로부터 DOM 조작 제한
  • 내부 DOM 구조 제어로 XSS 취약점 표면적 감소
  • 사용자 생성 콘텐츠는 여전히 sanitization 필요

유지보수 장점

  • 안정적인 웹 표준 기반
  • 벤더 로드맵 의존 없음
  • npm을 통한 배포 가능
  • 독립적 버전 관리
  • 모든 빌드 프로세스에 통합 가능
  • 프레임워크 업그레이드 시 재작업 감소

실제 도입 사례

프로덕션 사용 기업

  • GitHub: <details-menu> 컴포넌트
  • Salesforce: Lightning Web Components
  • Adobe: 프로덕션 환경 활용

도입 효과

  • 기술 스택 부풀림 없이 기능성 향상
  • 대규모 고성능 환경에서의 잠재력 입증
  • 유연성 유지하며 확장 가능
  • 다양한 기술 스택 유지 조직에서 프론트엔드 개발의 통합력 제공

전략적 가치

프레임워크는 계속 진화하고 인기가 오르락내리락하지만, 웹 컴포넌트는 그 변동 위에 위치한다.

핵심 이점

  • 락인에 대한 보험 정책
  • 진정으로 재사용 가능한 UI를 위한 티켓
  • 다양한 기술 스택 간의 다리

한 번 구축하고 어디든 배포할 수 있는 능력은 단순한 편의성이 아닌 전략적 결정이다. 웹은 마침내 유니버설 컴포넌트의 약속을 따라잡았고, 가장 현명한 팀들은 이미 기울어지고 있다.

문제는 더 이상 사용 여부가 아니라 얼마나 빨리 시작할 수 있는가이다.

1개의 좋아요