웹 컴포넌트
웹 컴포넌트(Web Components)는 React·Vue·Angular 같은 프레임워크 없이 순수 HTML·CSS·JavaScript 웹 표준만으로 재사용 가능하고 캡슐화된 커스텀 컴포넌트를 만들 수 있는 기술이다. 프레임워크 환경이 아닌 전통적 웹에서도 컴포넌트 기반 개발의 이점을 얻을 수 있다.
핵심은 `HTMLElement`를 상속받은 클래스를 정의하고 `customElements.define('custom-name', CustomClass)`로 등록하는 것이다. 생명주기 훅으로 `connectedCallback()`(DOM 추가), `disconnectedCallback()`(제거), `attributeChangedCallback(name, oldValue, newValue)`(속성 변경) 등이 제공된다. Shadow DOM을 `this.attachShadow({ mode: 'open' })`로 연결하면 컴포넌트의 구조·스타일·동작이 외부 스타일에 영향받지 않고 캡슐화된다. 내부 이벤트를 외부로 전달하려면 `CustomEvent`를 `bubbles: true, composed: true`로 dispatch해 Shadow DOM 경계를 넘긴다.
스타일링의 어려움은 Shadow DOM이 외부로부터 격리되어 반복 선언이 필요하다는 점이다. 이를 해결하는 세 가지 기법:
- `::part` 의사 선택자: 내부 요소에 `part="label"` 속성을 붙이면 외부에서 `custom-button::part(label)`로 스타일 가능
- CSS 변수(Custom Properties): `var(--button-bg-color, #4CAF50)`처럼 선언해 외부에서 토큰으로 동적 조정
- `::slotted` 의사 요소: `
`에 삽입된 요소의 스타일을 내부에서 지정
핵심 내용
- 웹 컴포넌트: HTMLElement 상속 + `customElements.define` 등록
- 생명주기 훅: connectedCallback / disconnectedCallback / attributeChangedCallback
- Shadow DOM: 구조·스타일·동작 캡슐화
- 외부 이벤트 전달: `CustomEvent` + `composed: true`
- 스타일 공유: ::part, CSS 변수, ::slotted 세 가지 전략
- 웹 표준 기반 → 장기 호환성·프레임워크 비종속
- 단점: 상태 관리 복잡, 생태계 미성숙
관련 개념
- React TypeScript 패턴 — 프레임워크 기반 컴포넌트 패턴과의 비교
- 디자인 시스템 — 프레임워크 비종속 공용 컴포넌트 배포 수단
- SCSS 모듈 시스템 — 스타일 캡슐화의 또 다른 접근
출처
- JavaScript 웹 컴포넌트로 재사용 가능한 UI 구축하기 — bareum.park, UX Engineer 이야기