zerovoids.dev
zerovoids.dev

Ø NEWS

스타일링 · 대규모 마이그레이션

라이너, 스타일드-컴포넌트를 버리고 메타의 스타일X로 완전히 갈아탔다

라이너가 리액트 앱을 스타일드-컴포넌트에서 메타의 스타일X로 옮기며 1,000개 넘는 풀 리퀘스트를 냈다. 런타임 스타일 비용을 없애는 동시에, 컴포넌트를 밖에서 함부로 다시 칠하지 못하게 만드는 쪽을 택했다.

키워드reactcssperformance

리액트 컴포넌트를 styled(Button)으로 감싸면, 그 스타일은 컴포넌트 밖 어디서든 다시 칠할 수 있었다. 프로젝트 관리 도구 라이너는 이 구멍을 없애려고 리액트 앱 전체를 스타일드-컴포넌트에서 메타의 스타일X(StyleX)로 옮겼다. 엔지니어 케네스 스코우후스에 따르면 이 작업에 들어간 풀 리퀘스트는 1,000개가 넘는다.

스코우후스가 개인 블로그에 진행률을 58%로 남긴 뒤, 팀은 2026년 8월 초 5개월 만에 작업을 끝냈다.

왜 버렸나

이유는 두 가지다. 하나는 성능이다. 런타임 CSS-in-JS는 스타일 생성과 규칙 주입을 클라이언트가 렌더링하는 동안 처리하는데, 라이너가 리액트 18의 동시성 렌더링으로 올라간 뒤 이 비용이 두드러지게 느껴졌다. 비슷한 시기에 스타일드-컴포넌트도 유지보수 모드로 들어갔다. 세니티의 코디 올슨은 리액트 18의 useInsertionEffect를 쓴 최적화 포크를 내놨고, 이를 "최후의 수단"이라 부르면서도 라이너의 렌더링 시간을 40% 줄였다.

다른 이유는 캡슐화다. styled(Button) 같은 패턴은 컴포넌트를 밖에서 재스타일링하기 너무 쉽게 만들었고, 코딩 에이전트가 코드를 더 많이 건드리는 지금 팀은 그걸 일부러 어렵게 만들고 싶어했다.

야후에서 비슷한 아토믹 스타일 시스템을 운영했던 스태프 엔지니어 리드 버크는 큰 API 표면을 고르는 함정을 조심하라고 경고했다. 스타일드-컴포넌트의 열려 있고 튜링-완전한 API가 바로 자동화를 어렵게 만든 원인이라는 것이다.

스타일X는 무엇을 바꾸나

스타일X는 스타일 생성을 빌드 타임으로 옮기고, 충돌 없는 아토믹 클래스를 내보낸다.

import * as stylex from '@stylexjs/stylex';
const styles = stylex.create({
  box: { padding: 16, color: 'blue' },
});

라이너는 리액트 스타일링 옵션을 대부분 검토했고, 바닐라-익스트랙트가 가장 근접한 대안이었지만 API가 파편화돼 있고 스타일 파일을 따로 둬야 해서 접었다. 손으로 옮기는 대신 스코우후스는 결정적 코드모드를 만들었는데, 지금은 500개 넘는 PR과 약 10만 줄 분량을 처리했고 온라인 플레이그라운드도 딸려 있다. 같은 전환을 하려는 팀은 스타일X 공식 문서에서 시작해 커스텀 규칙엔 옥스린트를 쓰고, 전역 셀렉터가 필요한 자리엔 CSS 모듈을 탈출구로 남겨 두면 된다 — 라이너도 그렇게 했다.

라이너에 따르면, 뷰가 많은 페이지에서 메인 스레드 작업이 20~35% 줄고, 중급 사양 기기에서 내비게이션이 약 30% 빨라졌으며, 페이지를 옮기는 동안 주입되는 CSS 규칙은 0건이 됐다.

라이너만의 얘기는 아니다

뉴스레터 디스 위크 인 리액트는 커서가 테일윈드에서 넘어오고 메타가 디자인 시스템 아스트릭스를 오픈소스로 푼 뒤, 스타일X가 X(트위터)에서 화제가 됐다고 전했다. 팟캐스트 신택스에서 스콧 톨린스키와 웨스 보스는 다들 왜 스타일X로 옮기는지 물었고, 사람에게는 그 엄격함이 별로 재미없지만 에이전트는 그걸 반긴다는 결론을 냈다.

스타일X 자체에 대한 불만도 있다. 깃허브의 한 논의 스레드 제목은 "스타일X는 훌륭하지만 가이드라인이 너무 엄격하다"이며, 부모에 의존하는 셀렉터와 전역 셀렉터에 걸린 제약이 가장 흔한 불평으로 꼽힌다.