디자인 시스템 및 구성요소 라이브러리에서 맞춤 속성을 사용하는 이점
저는 Nordhealth의 선임 프런트엔드 개발자인 데이브입니다. 구성요소 라이브러리의 웹 구성요소 빌드를 포함하여 디자인 시스템 Nord의 설계 및 개발을 담당하고 있습니다. CSS 맞춤 속성을 사용하여 Web Components 스타일 지정과 관련된 문제를 해결한 방법과 디자인 시스템 및 구성요소 라이브러리에서 맞춤 속성을 사용하는 다른 이점을 공유하고자 합니다.
웹 구성요소 빌드 방법
웹 구성요소를 빌드하려면 상태, 범위 지정된 스타일, 템플릿 등 많은 템플릿 코드를 제공하는 라이브러리인 Lit을 사용합니다. Lit는 가볍고 네이티브 JavaScript API를 기반으로 빌드되므로 브라우저에 이미 있는 기능을 활용하는 간결한 코드 번들을 제공할 수 있습니다.
하지만 웹 구성요소의 가장 매력적인 점은 거의 모든 기존 JavaScript 프레임워크와 호환되며 프레임워크가 전혀 없어도 작동한다는 것입니다. 기본 JavaScript 패키지가 페이지에서 참조되면 웹 구성요소를 사용하는 것은 네이티브 HTML 요소를 사용하는 것과 매우 유사합니다. 네이티브 HTML 요소가 아님을 보여주는 유일한 신호는 태그 내의 일관된 하이픈입니다. 이는 브라우저에 웹 구성요소임을 알리는 표준입니다.
Shadow DOM 스타일 캡슐화
네이티브 HTML 요소에 Shadow DOM이 있는 것과 마찬가지로 Web Components에도 Shadow DOM이 있습니다. Shadow DOM은 요소 내의 숨겨진 노드 트리입니다. 이를 시각화하는 가장 좋은 방법은 웹 인스펙터를 열고 '섀도우 DOM 트리 표시' 옵션을 사용 설정하는 것입니다. 이렇게 하면 검사기에서 네이티브 입력 요소를 살펴볼 수 있습니다. 이제 입력을 열고 그 안에 있는 모든 요소를 볼 수 있습니다. 웹 구성요소 중 하나를 사용하여 이 작업을 시도해 볼 수도 있습니다. 맞춤 입력 구성요소를 검사하여 Shadow DOM을 확인해 보세요.
Shadow DOM의 장점 (또는 관점에 따라 단점) 중 하나는 스타일 캡슐화입니다. 웹 구성요소 내에서 CSS를 작성하면 이러한 스타일이 유출되어 기본 페이지나 다른 요소에 영향을 줄 수 없습니다. 구성요소 내에 완전히 포함되어 있기 때문입니다. 또한 기본 페이지 또는 상위 웹 구성요소용으로 작성된 CSS는 웹 구성요소로 유출될 수 없습니다.
이러한 스타일 캡슐화는 구성요소 라이브러리의 이점입니다. 이렇게 하면 사용자가 구성요소 중 하나를 사용할 때 상위 페이지에 적용된 스타일과 관계없이 의도한 대로 표시될 가능성이 높아집니다. 확실히 하기 위해 모든 웹 구성요소의 루트 또는 '호스트'에 all: unset;
를 추가합니다.
하지만 웹 구성요소를 사용하는 사용자가 특정 스타일을 변경해야 할 타당한 이유가 있는 경우는 어떻게 해야 하나요? 맥락에 따라 대비가 더 필요한 텍스트가 있거나 테두리가 더 두꺼워야 할 수도 있습니다. 구성요소에 스타일을 적용할 수 없는 경우 이러한 스타일 지정 옵션을 사용 설정하려면 어떻게 해야 하나요?
이때 CSS 맞춤 속성이 유용합니다.
CSS 맞춤 속성
맞춤 속성은 이름이 매우 적절합니다. 맞춤 속성은 CSS 속성으로, 개발자가 직접 이름을 지정하고 필요한 값을 적용할 수 있습니다. 유일한 요구사항은 접두어에 하이픈 두 개를 추가해야 한다는 것입니다. 커스텀 속성을 선언한 후에는 var()
함수를 사용하여 CSS에서 값을 사용할 수 있습니다.
상속의 경우 모든 맞춤 속성이 상속되며 이는 일반 CSS 속성 및 값의 일반적인 동작을 따릅니다. 상위 요소 또는 요소 자체에 적용된 맞춤 속성은 다른 속성의 값으로 사용할 수 있습니다. 디자인 토큰의 경우 CSS 프레임워크를 통해 루트 요소에 적용하여 맞춤 속성을 많이 사용합니다. 즉, 웹 구성요소, CSS 도우미 클래스 또는 토큰 목록에서 값을 가져오려는 개발자 등 페이지의 모든 요소에서 이러한 토큰 값을 사용할 수 있습니다.
var()
함수를 사용하여 맞춤 속성을 상속하는 이 기능을 통해 Web Components의 Shadow DOM을 관통하고 개발자가 구성요소의 스타일을 지정할 때 더 세부적으로 제어할 수 있습니다.
Nord 웹 구성요소의 맞춤 속성
디자인 시스템의 구성요소를 개발할 때마다 CSS에 대해 신중하게 접근합니다. 간결하지만 유지보수가 쉬운 코드를 목표로 합니다. 디자인 토큰은 루트 요소의 기본 CSS 프레임워크 내에서 맞춤 속성으로 정의됩니다.
그러면 이러한 토큰 값이 구성요소 내에서 참조됩니다. 경우에 따라 CSS 속성에 값을 직접 적용하기도 하지만, 새로운 문맥식 맞춤 속성을 정의하고 값을 적용하기도 합니다.
또한 구성요소에만 해당하지만 토큰에는 없는 일부 값을 추상화하여 문맥 맞춤 속성으로 변환합니다. 구성요소와 관련된 맞춤 속성은 두 가지 주요 이점을 제공합니다. 첫째, 이 값은 구성요소 내의 여러 속성에 적용할 수 있으므로 CSS를 더 '건조하게' 사용할 수 있습니다.
두 번째로, 구성요소 상태와 변형 변경사항을 매우 깔끔하게 만듭니다. 예를 들어 마우스 오버 또는 활성 상태 또는 이 경우 변형에 스타일을 지정할 때 이러한 모든 속성을 업데이트하려면 맞춤 속성만 변경하면 됩니다.
하지만 가장 큰 이점은 구성요소에서 이러한 문맥식 맞춤 속성을 정의할 때 각 구성요소에 맞춤 CSS API를 만들 수 있다는 점입니다. 이 API는 해당 구성요소의 사용자가 활용할 수 있습니다.
위 예에서는 선택기를 통해 변경된 문맥 맞춤 속성이 있는 웹 구성요소 중 하나를 보여줍니다. 이 전체 접근 방식의 결과는 사용자에게 충분한 스타일 지정 유연성을 제공하면서도 대부분의 실제 스타일을 계속 유지하는 구성요소입니다. 또한 구성요소 개발자는 사용자가 적용한 이러한 스타일을 가로챌 수 있습니다. 이러한 속성 중 하나를 조정하거나 확장하려는 경우 사용자가 코드를 변경할 필요 없이 할 수 있습니다.
Google은 이 접근 방식이 디자인 시스템 구성요소의 제작자뿐만 아니라 Google 제품에서 이러한 구성요소를 사용하는 개발팀에도 매우 강력하다고 생각합니다.
맞춤 속성 심화
이 글을 작성하는 시점에서는 문서에 이러한 문맥 기반 맞춤 속성이 실제로 표시되지 않습니다. 하지만 더 많은 개발팀에서 이러한 속성을 이해하고 활용할 수 있도록 표시할 계획입니다. Google 구성요소는 npm에 매니페스트 파일과 함께 패키징되며, 이 파일에는 구성요소에 관한 모든 정보가 포함되어 있습니다. 그런 다음 문서 사이트가 배포될 때 매니페스트 파일을 데이터로 사용합니다. 이는 Eleventy 및 전체 데이터 기능을 사용하여 수행됩니다. 이러한 문맥 맞춤 속성을 이 매니페스트 데이터 파일에 포함할 계획입니다.
이러한 문맥 맞춤 속성이 값을 상속받는 방식도 개선하고자 합니다. 예를 들어 현재 두 개의 구분자 구성요소의 색상을 조정하려면 두 구성요소를 모두 선택기로 타겟팅하거나 스타일 속성을 사용하여 요소에 맞춤 속성을 직접 적용해야 합니다. 이 방법은 괜찮아 보이지만 개발자가 이러한 스타일을 포함 요소 또는 루트 수준에서 정의할 수 있으면 더 좋습니다.
구성요소에서 직접 맞춤 속성 값을 설정해야 하는 이유는 구성요소 호스트 선택기를 통해 동일한 요소에서 정의하기 때문입니다. 구성요소에서 직접 사용하는 전역 디자인 토큰은 이 문제의 영향을 받지 않고 바로 전달되며 상위 요소에서 가로챌 수도 있습니다. 두 가지 방법의 장점을 모두 누릴 수 있는 방법이 있을까요?
비공개 및 공개 맞춤 속성
비공개 맞춤 속성은 Lea Verou가 만든 속성으로, 구성요소 자체의 문맥 '비공개' 맞춤 속성이지만 대체 항목이 있는 '공개' 맞춤 속성으로 설정됩니다.
이러한 방식으로 문맥 맞춤 속성을 정의하면 전역 토큰 값을 상속하고 구성요소 코드 전체에서 값을 재사용하는 등 이전에 하던 모든 작업을 계속할 수 있습니다. 하지만 구성요소는 자체 또는 상위 요소에서 해당 속성의 새 정의를 원활하게 상속합니다.
이 방법이 실제로 '비공개'가 아니라고 주장할 수도 있지만, 우려했던 문제에 대한 매우 우아한 해결 방법이라고 생각합니다. 기회가 되면 Google은 개발팀이 구성요소 사용을 더 효과적으로 제어하면서도 기존 가드레일의 이점을 누릴 수 있도록 구성요소에서 이 문제를 해결할 것입니다.
CSS 맞춤 속성으로 Web Components를 사용하는 방법에 관한 이 정보가 도움이 되었기를 바랍니다. 의견을 보내주세요. 이러한 방법을 자신의 작업에 사용하기로 결정한 경우 트위터 @DavidDarnes에서 문의해 주세요. 트위터에서 Nordhealth @NordhealthHQ를 비롯해 이 디자인 시스템을 통합하고 이 도움말에 언급된 기능을 구현하기 위해 노력한 팀원인 @Viljamis, @WickyNilliams, @eric_habich도 만나보세요.
Dan Cristian Pădureț의 히어로 이미지