인사이트

인사이트리포트

디지털프렌스포메이션 최신 정보 및 트렌드를 제공합니다.

IT 트렌드

새로운 스타일링 시스템, StyleX

2024.06.21이윤석 프로
다운로드

들어가며

StyleX는 메타(Meta)에서 개발한 오픈 소스 CSS-in-JS 라이브러리로, 웹 앱 스타일링을 위한 간단하고 사용하기 쉬운 JavaScript 구문 및 컴파일러이다. 본 아티클에서는 StyleX의 특장점과 사용법에 대해 알아보겠다.

 

원 칙

단일 위치(co-location)

스타일을 작성하는 가장 좋고 읽기 쉬운 방법은 스타일을 마크업과 동일한 파일에 작성하는 것이다. StyleX는 로컬에서 스타일을 작성, 적용 및 추론하도록 설계되었다.

 

결정론적 해결(deterministic resolution)

기존에는 서로 다른 CSS 선택자(selector)가 충돌하지 않도록 BEM, OOCSS 등의 규율이 필요했다. StyleX는 스타일의 일관성, 예측 가능성, 표현력을 모두 향상시키는 것을 목표로 하고, 이를 빌드 도구를 통해 가능하다고 생각한다.

StyleX는 여러 파일에서 작동하는 완전히 예측 가능하고 결정론적인 스타일 지정 시스템을 제공한다. 이는 여러 선택자를 병합할 때뿐만 아니라 여러 약어 및 보통 속성을 병합할 때도 결정론적인 결과를 생성한다. (예) margin vs margin-top)

“마지막으로 적용된 스타일이 항상 승리한다.”

 

저비용 추상화

StyleX의 성능 비용과 관련하여 기본 원칙은 StyleX가 항상 특정 패턴을 달성하는 가장 빠른 방법이어야 한다는 것이다. 일반 패턴에는 런타임 비용이 없어야 하며 고급 패턴은 최대한 빨라야 한다. StyleX는 런타임 성능을 향상시키기 위해 빌드 타임에 더 많은 작업을 수행하는 것으로 절충한다.

 

작은 API

StyleX의 목표는 StyleX를 최대한 최소화하고 배우기 쉽게 만드는 것이다. 따라서 StyleX는 너무 많은 API를 개발하고 싶지 않다. 대신, 가능한 경우 일반적인 JavaScript 패턴을 활용하고 가능한 가장 작은 API를 제공할 수 있기를 원한다.

 

공유 가능한 상수

CSS 클래스 이름, CSS 변수, 기타 CSS 식별자는 전역 네임스페이스에 정의된다. 이러한 문자열을 JavaScript 상수에 대한 참조로 대체하는 API를 제공한다.

 

프레임워크에 구애 받지 않음(framework-agnostic)

StyleX는 현재 React와 가장 잘 작동하도록 맞춤화 되었지만 JavaScript에서 마크업 작성을 허용하는 모든 JavaScript 프레임워크와 함께 사용하도록 설계되었다. 여기에는 JSX, 템플릿 문자열 등을 사용하는 프레임워크가 포함된다.

 

 

기능

확장 가능

  • 아토믹(atomic) CSS로 CSS 아웃풋 최소화
  • 컴포넌트 수가 늘어나도 CSS 크기는 유지됨
  • 계속해서 커지는 소스 코드 내에서 스타일은 읽기 쉽고 유지 보수 가능함

 

예측 가능

  • 요소(element)의 클래스 이름은 동일한 요소에만 직접 스타일 지정 가능
  • 특이성(specificity) 문제 없음
  • “마지막으로 적용된 스타일이 항상 승리”

 

구성이 용이함

  • 조건부로 스타일 적용
  • 컴포넌트와 파일 경계를 넘어 임의의 스타일을 병합하고 구성
  • 스타일을 DRY(Don’t Repeat Yourself)로 유지하려면 지역 변수와 표현식을 사용

 

빠름

  • 런타임 스타일 주입 없음
  • 모든 스타일은 컴파일 타임에 정적 CSS 파일에 번들로 제공됨
  • 클래스 이름 병합을 위해 런타임이 최적화됨

 

타입 안정성

  • 타입이 안정한 API
  • 타입이 안정한 스타일
  • 타입이 안정한 테마

 

 

간단한 사용법

스타일 정의

스타일은 객체 구문과 create() API를 사용하여 정의된다. 추가적인 키 및 create() 호출을 사용하여 원하는 만큼의 규칙을 생성할 수 있다.

 

스타일 사용

스타일을 사용하려면 스타일을 props() 함수에 전달해야 한다. 스타일은 표준 JavaScript 표현식을 사용하여 조건부로 결합하고 적용할 수 있다.

 

 

스타일 정의

제약 사항

StyleX는 사전 컴파일에 의존하므로 모든 스타일을 정적으로 분석할 수 있는 것이 중요하다. 즉, 모든 “로(raw) 스타일 객체”에는 다음만 포함되어야 한다.

  • 일반 객체 리터럴
  • 문자열 리터럴
  • 숫자 리터럴
  • 배열 리터럴
  • null 또는 undefined
  • 위의 어느 하나로 분석되는 상수, 단순 표현식, 내장 함수(예) .toString())
  • 동적 스타일을 위한 화살표 함수

다음은 허용되지 않는다.

  • 함수 호출(StyleX 함수 제외)
  • 다른 모듈에서 가져온 값(.stylex.js 파일에서 StyleX를 사용하여 생성된 CSS 변수 제외)

 

스타일 생성

스타일은 stylex.create() 함수를 사용하여 생성해야 한다. 하나 이상의 네임스페이스 또는 스타일 객체를 정의할 수 있다. 다음의 예제에는 2개의 네임스페이스가 있는데 하나는 base이고 다른 하나는 highlighted이다.

 

의사(pseudo) 클래스

의사 클래스는 요소(element)의 다양한 상태를 나타낸다. StyleX에서 의사 클래스에 대한 선언은 속성 내에서 중첩된다.

다양한 상태에 대한 배경색을 변경하기 위해 의사 클래스를 추가하려면, 기존의 lightblue 값을 가진 문자열 리터럴을 의사 상태를 지닌 객체로 변경한다.

 

의사 요소

의사 요소는 사용자 에이전트가 제공하는 네이티브 HTML 요소 내에 포함된 shadow DOM 요소를 대상으로 지정하는 방법이다. 예를 들어 ::placeholder는 input 또는 textarea 요소 내에 placeholder 텍스트가 포함된 요소를 참조한다. StyleX에서 의사 요소를 대상으로 하려면 해당 요소를 네임스페이스 내의 최상위 키로 정의해야 한다.

 

미디어 쿼리

미디어 쿼리는 의사 클래스 선언 방식과 유사하다.

 

조건 결합

미디어 쿼리와 의사 선택자를 결합해야 하는 경우 스타일 값을 한 수준 이상 깊이로 중첩할 수 있다.

default 케이스에 스타일을 적용하지 않으려면 null을 값으로 사용할 수 있다.

 

대체(fallback) 스타일

특정 새 스타일 속성을 지원하는 않는 브라우저에 대한 대체 스타일이 필요한 상황이 있다.

CSS는 다음과 같이 할 수 있다.

JavaScript 객체를 사용할 때는 이러한 종류의 구문을 사용할 수 없다. 따라서 stylex.firstThatWorks() 함수를 사용하여 동일한 결과를 얻을 수 있다.

 

키프레임 애니메이션

stylex.keyframes() 함수를 사용하여 키프레임 애니메이션을 정의할 수 있다.

 

동적 스타일

동적 스타일은 드물게 사용해야 한다. 대부분의 사용 사례에서는 조건부 스타일이면 충분하다.

StyleX에서는 컴파일 타임에 모든 스타일을 생성한다. 즉 모든 스타일을 미리 알아야 한다는 의미이다. 그러나 때로는 런타임까지 무엇이 필요한지 알지 못하는 경우도 있다.

이러한 상황에서 스타일을 객체 대신 함수로 정의하고 필요한 스타일의 동적 구성 요소를 매개 변수로 전달할 수 있다.

스타일 사용

스타일이 정의되면 stylex.props() 함수를 사용하여 HTML 요소에 퍼질 수 있는 props로 변환할 수 있다. stylex.props() 함수는 HTML 요소에 적절한 className prop를 설정하고, 동적 스타일을 사용하는 경우 style prop을 설정한다.

SolidJS, Svelte, Qwik, Vue.js 등의 className 대신 class가 필요한 프레임워크의 경우 stylex.attrs()를 사용하면 된다.

 

스타일 병합

stylex.props() 함수는 스타일 목록을 가져와서 “항상 마지막으로 적용된 스타일이 우선”하는 결정론적 방식으로 병합할 수 있다.

다음과 같이 스타일 객체가 정의되어 있을 때,

결과 HTML 요소에는 rebeccapurple 텍스트가 표시된다. 해당 스타일이 마지막으로 적용되었기 때문이다.

대신에 아래와 같이 스타일 순서가 바뀌면 grey으로 표시된다.

 

조건부 스타일

스타일은 삼항 표현식 및 && 연산자와 같은 일반적인 JavaScript 패턴을 사용하여 런타임 시 조건부로 적용할 수 있다. styleX.props()는 null, undefined, false와 같은 값을 무시한다.

 

스타일 변형

“variants”라는 일반적인 스타일 패턴을 사용하면 variant라는 이름의 prop의 값을 기반으로 가능한 스타일 목록 중 하나를 적용할 수 있다.

각 변형은 스타일 객체에 적절한 변형 이름을 사용하여 정의할 수 있다. 그런 다음 variant prop을 스타일 객체의 키로 사용하여 적절한 스타일을 적용할 수 있다.

 

props로서의 스타일

StyleX는 스타일 단일 위치(co-locating)를 권장하지만 컴포넌트 경계를 넘어 스타일을 전달하고 사용할 수 있다.

 

컴포넌트에 style props 전달하기

조건부 스타일을 포함한 여러 스타일 객체는 배열 리터럴을 사용하여 전달할 수 있다.

사용자 정의 스타일을 적용하는 것은 다른 prop을 적용하는 것만큼 간단하다. 로컬 스타일 다음에 props로 전달된 스타일을 적용하는 것이 관용적이다. 이러한 규칙을 통해 디자인 시스템 구성 요소를 예측 가능하게 만들고 쉽게 사용자 정의할 수 있다.

 

설정 해제” 스타일

스타일을 적용하는 대신에 제거해야 하는 경우도 있다. CSS는 initial, inherit, unset, revert와 같은 값을 제공하지만 StyleX에서 이를 수행하는 가장 간단한 방법은 값을 null로 설정하는 것이다.

스타일 속성을 null로 설정하면 이전에 StyleX에서 적용한 스타일 모두 제거된다.

 

테 마

StyleX에는 CSS 사용자 정의 속성(CSS 변수)을 정의하기 위한 API도 있다.

 

변수 정의

변수 그룹은 stylex.defineVars() 함수를 사용하여 정의한다.

이 함수 역시 컴파일 타임에 처리되며 CSS 변수 이름이 자동으로 생성된다. 이는 HTML 문서의 :root에 변수를 정의한다. 상수로 가져와서 stylex.create() 호출 내에서 사용할 수 있다.

 

미디어 쿼리 사용

변수 값은 미디어 쿼리에 기반할 수 있다.

변수 정의 규칙

변수는 stylex.create() 호출 내에서 사용할 수 있는 유일한 유형의 비지역 값이다. 이는 다음의 몇 가지 규칙을 적용함으로써 가능하다.

 

1. 변수는 .stylex.js 파일에 정의되어야 한다.

변수는 다음 확장자 중 하나를 가진 파일에 있어야 한다.

  • .stylex.js
  • .stylex.mjs
  • .stylex.cjs
  • .stylex.ts
  • .stylex.tsx
  • .stylex.jsx

 

2. 변수는 named exports를 해야 한다.

모든 stylex.defineVars() 호출은 named exports해야 한다.

3. 파일 내 다른 exports는 허용되지 않는다.

.stylex.js 파일은 CSS 변수 정의에만 사용된다.

 

 

변수 사용

변수가 정의되면 stylex.create()를 사용하여 스타일을 선언하는 데 가져와 사용할 수 있다.

tokens.stylex.js라는 파일에 다음 변수가 정의되어 있다고 가정한다.

이러한 스타일을 다음과 같이 가져와서 사용할 수 있다.

테마 생성

모든 변수 그룹을 가져와서 다음과 같은 테마를 만들 수 있다.

테마 적용

“테마”는 stylex.create()로 생성된 것과 유사한 스타일 객체이다. stylex.props()를 사용하여 요소에 적용하여 해당 요소와 모든 하위 요소에 대한 변수를 재정의할 수 있다.

 

마치며

지금까지 StyleX의 특징과 사용법에 대해 간략히 알아보았다. StyleX는 공개된 지 얼마 되지 않았지만 메타에서 Facebook을 다시 구축할 때 수년간의 사용 경험을 통해 설계가 입증된 장점이 많은 라이브러리이다. StyleX의 철학과 장점에 공감한다면 프론트엔드 개발 시 적용해 보는 것을 권하는 바이다.

 

# References

- https://stylexjs.com

이윤석 프로

이윤석 프로

소프트웨어사업부 플랫폼사업팀

에스코어에서 프론트엔드 개발을 하고 있습니다

연관 아티클

  • 웹 애플리케이션 클립보드 활용 사례
    IT 트렌드2024.04.25

    웹 애플리케이션 클립보드 활용 사례

    자세히 보기
  • AI 시대, 디자이너가 알아야 할 가독성을 높이는 데이터 시각화 방법
    데이터 관리2024.03.15

    AI 시대, 디자이너가 알아야 할 가독성을 높이는 데이터 시각화 방법

    자세히 보기
  • RBAC을 활용한 클라우드 접근제어 강화
    디지털 혁신2023.12.19

    RBAC을 활용한 클라우드 접근제어 강화

    자세히 보기