웹 구성요소 방향

웹 구성요소는 커스텀 요소, Shadow DOM, HTML 템플릿입니다. 이는 문서에서 마크업과 스타일이 캡슐화된 재사용 가능하고 프레임워크에 구애받지 않는 구성요소를 위한 플랫폼 기본 요소입니다. 디자인 시스템, 삽입 가능한 위젯, 독립형 UI에 사용하세요.

아래 규칙은 여러 영역에 걸쳐 적용됩니다. 당면한 작업에 대한 구체적인 가이드를 검색합니다. 각 가이드는 필요한 컨텍스트를 다시 설명하고 해당 작업에 고유한 API와 함정을 문서화합니다.

커스텀 요소가 필요한지 결정하기

태그에 캡슐화된 동작, 수명 주기 또는 재사용 가능한 JS 지원 API가 필요한 경우에만 맞춤 요소를 사용하세요. 다음과 같은 경우에는 빌드하지 마세요.

  • CSS가 포함된 일반 HTML 요소로도 충분합니다. 스타일이 지정된 <button> 또는 <details>는 재구현보다 접근성이 높고 비용이 저렴합니다.
  • 이 요소는 동작이 없는 순수한 프레젠테이션 요소입니다. 네이티브 요소의 클래스는 성능이 더 우수하며 @layer 또는 @scope로 범위를 지정할 수 있습니다.
  • 상호작용 없이 서버에서 스타일 범위 지정만 필요합니다. 범위가 지정된 스타일시트 또는 선언적 섀도우 DOM (업그레이드 없음)으로 충분할 수 있습니다.

네이티브 시맨틱스 (포커스, 활성화, ARIA를 다시 만드는 맞춤 <my-button>)를 다시 빌드하는 것은 가장 일반적인 오용입니다. 네이티브 요소를 재사용하는 경우에만 플랫폼의 접근성을 무료로 상속받을 수 있습니다. <my-button> 스타일 래퍼가 필요한 경우(보통 공유 스타일 지정 후크, 추가 마크업 또는 네이티브 요소가 표현할 수 없는 동작의 경우) 실제 <button>를 다시 구현하는 대신 래핑합니다(스타일을 내부 네이티브 요소로 전달하는 방법은 웹 구성요소 스타일 지정 참고).

테스트는 단순히 다른 모양이 아니라 캡슐화된 상태, 스크립트 가능한 API 또는 네이티브 요소가 표현할 수 없는 동작이 필요한지 여부입니다. 좋아요/즐겨찾기 전환은 적합합니다. 래치된 도메인 상태를 전달하고, 해당 상태를 주변 페이지의 스타일 지정 후크로 노출하고, 자체 change 이벤트를 전달합니다. 스타일이 지정된 <button>는 이러한 기능을 제공하지 않습니다. 눌렀을 때 색상만 변경되는 버튼은 <button> + CSS를 사용하지 않습니다. 빌드할 때는 적절한 맞춤 상태 또는 속성을 사용하여 상태를 모델링합니다(맞춤 요소 참고).

코드베이스에 도구 일치시키기

커스텀 요소로 해야 하는지 여부는 프로젝트에서 이미 사용 중인 항목에 따라 다릅니다. 에이전트는 지나치게 추상화하고 새로운 요소를 너무 적극적으로 찾는 경향이 있습니다. 의심스러운 경우 더 가벼운 옵션 (네이티브 요소, CSS, 서버 템플릿)이 일반적으로 적합하며, 재사용이나 동작이 실제로 필요한 경우 나중에 맞춤 요소로 승격할 수 있습니다. 휴리스틱(대략적인 우선순위):

  • 코드베이스에 이미 구성요소 모델 (React, Vue, Svelte 등)이 있습니다. 인앱 UI의 경우 해당 프레임워크의 구성요소를 기본값으로 사용합니다. 앱 또는 프레임워크 간에 공유되는 디자인 시스템 프리미티브, 프레임워크가 제어하지 않는 마크업에 삽입된 위젯, 일반 HTML (이메일, CMS, SSR 프래그먼트)로 작동해야 하는 출력과 같이 프레임워크를 이스케이프하거나 프레임워크보다 오래 지속되어야 하는 경우에만 맞춤 요소를 사용하세요. 일반 인앱 뷰에 병렬 구성요소 시스템을 설정하지 마세요.
  • 도구가 없고 대부분 정적 마크업입니다. 일반 HTML + CSS 또는 서버 템플릿/부분을 사용하는 것이 좋습니다. 커스텀 요소는 태그에 동작, 수명 주기 또는 JS 지원 API가 실제로 필요한 경우에만 가치가 있습니다. 단순히 마크업을 공유하기 위한 것이 아닙니다. 서버 포함 또는 <template>는 JS를 제공하지 않고도 마크업을 공유할 수 있습니다.
  • 상호작용 아일랜드가 있는 정적 사이트 생성기 마크업을 정적으로 렌더링하고 대화형 부분에 커스텀 요소를 예약합니다. '많은 마크업, 약간의 상호작용'의 경우 JS에서 모든 항목을 다시 렌더링하는 대신 Light DOM (또는 선언적 섀도우 DOM)에 마크업을 유지하고 작은 맞춤 요소가 점진적으로 개선하도록 합니다.
  • 대신 기본 제공 요소를 더 활용할 수 있습니다. 네이티브 요소를 최대한 활용하는 것 (CSS, 몇 가지 리스너, 가끔 사용하는 의사 요소)은 일반적으로 맞춤 요소보다 선호됩니다. 플랫폼의 접근성과 동작을 무료로 유지할 수 있기 때문입니다. 해결 방법을 더 이상 유지할 수 없는 경우, 즉 요소의 기본 제공 동작과 충돌하거나 작성 환경이 깔끔한 구성요소 API보다 나빠지는 경우 맞춤 요소로 전환하세요. 기본 제공 요소에 약간의 JS가 필요하다고 해서 그 자체로 요소를 대체할 이유는 되지 않습니다.

교차 규칙

이러한 원칙은 아래의 모든 가이드에 적용됩니다.

  • 필수: 태그 이름은 하나 이상의 하이픈이 있는 케밥 케이스여야 합니다 (예: my-element). 이는 맞춤 요소를 현재 및 향후 기본 제공 요소와 구분하는 요소입니다.
  • 필수: this를 터치하기 전에 생성자에서 super()를 먼저 호출합니다. this를 읽거나 쓰는 문 다음에 호출하면 예외가 발생합니다.
  • 필수: 그림자 템플릿 내에서 시맨틱 요소 (<button>, <nav>, <ul>)를 사용합니다. 섀도 트리의 대부분의 접근성 실패는 비시맨틱 마크업에서 발생합니다. 슬롯은 투사하는 역할의 역할을 변경하지 않습니다.
  • 필수: ARIA id 참조 (aria-labelledby, aria-describedby, aria-controls)는 그림자 경계를 넘을 수 없습니다. 참조 요소와 이 요소가 가리키는 id는 동일한 트리에 있어야 합니다.
  • 개발 도구, 페이지 스크립트, 서버 하이드레이션이 element.shadowRoot에 도달할 수 있도록 attachShadow({ mode: 'open' })를 사용하는 것이 좋습니다. 페이지 스크립트에서 내부 구조를 숨겨야 하는 경우에만 'closed'를 사용하세요.
  • 맞춤설정된 기본 제공 요소 (extends HTMLButtonElement 및 is="…")를 사용하지 마세요. Safari는 이를 영구적으로 지원하지 않습니다.

사용 사례 가이드 매트릭스

작업을 식별하고 가이드를 가져옵니다.

다음과 같은 경우… 검색
동작 및 수명 주기로 새 시맨틱 태그 정의 맞춤 요소
스타일 및 마크업의 범위를 구성요소로 지정하고 소비자 콘텐츠를 구성요소에 투사합니다. 섀도우 DOM, 템플릿, 슬롯
스타일이 지정되지 않은 콘텐츠가 깜박이지 않도록 서버 (SSR)에서 구성요소의 섀도 트리를 렌더링합니다. 커스텀 요소 사전 렌더링
섀도우 경계 전반의 스타일 (테마 설정, ::part, 맞춤 속성) 웹 구성요소 스타일 지정
주변 <form>에 맞춤 컨트롤 값 제출 양식 연결 맞춤 요소
맞춤 요소에 접근성 부여 (역할, 포커스, shadow root 전반의 ARIA) 접근성 웹 구성요소