직관에 반하는 해결책: 더 많은 CSS를 보내라
GitHub은 최근 중요한 성과를 보고했습니다. 특정 대상 페이지에서 서버 렌더링 시간이 최대 22% 단축되었습니다. 이러한 성능 향상은 직관에 반하는 결정, 즉 더 많은 CSS를 전송하는 것에서 비롯되었습니다. GitHub은 스타일을 즉석에서 동적으로 생성하는 대신, 빌드 시점에 스타일링 작업을 컴파일하여 요청 처리 시 발생하는 CPU 집약적인 작업을 덜어내는 방식을 선택했습니다.
이 결과는 많은 웹 개발자에게는 거꾸로 된 것처럼 들립니다. 통념상 성능을 위해서는 경로별로 최적화된 가벼운 CSS가 이상적이라고 여겨집니다. 그러나 특히 서버 사이드 렌더링 CSS-in-JS 라이브러리를 사용하여 이러한 맞춤형 CSS를 동적으로 생성하면, 사용자 요청마다 상당한 서버 CPU 자원을 소모할 수 있습니다. "필요한" CSS만 보낸다는 체감상의 이점이 서버 측 병목 현상으로 변하는 것입니다.
중요한 점은 이 개선이 서버 사이드 렌더링에만 초점을 맞추고 있다는 것입니다. 22%라는 수치는 서버가 초기 HTML 응답을 준비하는 데 절약된 시간을 의미합니다. 전체 클라이언트 측 페이지 로드 시간이 동일한 폭으로 감소했거나 전체 애플리케이션이 22% 더 빨라졌다는 것을 의미하지는 않습니다. 이는 서버의 작업 부하를 위한 표적 최적화로, 스타일링 로직의 상당 부분을 런타임 실행에서 정적 자산 컴파일로 전환한 것입니다.
런타임 스타일링에 숨겨진 CPU 비용
GitHub의 초기 아키텍처는 서버 렌더링 CSS-in-JS에 크게 의존했습니다. 이는 요청마다 스타일링 로직이 실행되는 기술입니다. 이 방식은 JavaScript를 활용하여 프롭(prop)에 의존하는 스타일을 평가하고, 고유한 클래스 이름을 생성하며, 서버가 HTML을 렌더링하는 동안 필요한 CSS를 수집합니다. 효율적으로 보이지만, 이 동적 프로세스에는 숨겨진 계산 비용이 따릅니다.
컴포넌트가 많은 페이지에서는 이 비용이 급격히 증가합니다. 각 컴포넌트의 스타일 해석 및 삽입은 이미 바쁜 렌더링 경로에 CPU 작업을 추가합니다. 수백 개의 컴포넌트가 있는 페이지를 상상해 보십시오. 각 컴포넌트가 잠재적으로 자체 스타일 평가를 트리거하며, 그 누적 효과는 빠르게 심각한 서버 병목 현상으로 이어집니다.
런타임 스타일링은 특정 페이지 상태에 필요한 정확한 스타일만 방출하여 클라이언트 측 CSS 페이로드를 최소화한다는 강력한 이점을 제공합니다. 그러나 이러한 선택성에는 대가가 따릅니다. 서버는 모든 들어오는 요청에 대해 동일한 스타일 계산과 문자열 조작을 반복적으로 수행하며 CPU 자원을 소모하게 됩니다.
이러한 절충안은 GitHub에게 명확해졌습니다. 가벼운 클라이언트 번들에 대한 약속은 증가된 서버 렌더링 시간에 가려졌고, 그들은 성능 저하가 동적이고 컴포넌트 중심적인 스타일링의 체감 이점만큼 가치가 있는지 재평가해야 했습니다.
CSS Modules, 작업을 요청 이전으로 옮기다
GitHub의 CSS Modules 전환은 계산 작업이 어디에서 발생하는지에 대한 근본적인 변화를 보여줍니다. 스타일을 요청 시 생성하는 대신, CSS Modules는 빌드 시점에 스타일을 정적 .css 파일로 컴파일합니다. 이는 서버가 미리 정의된 클래스 이름이 포함된 정적 HTML만 렌더링하게 하여, 요청-응답 주기에서 스타일 생성 작업을 완전히 제거함을 의미합니다.
이는 작업을 없애는 것이 아니라 그 비용을 이동시키는 것입니다. 더 많은 CSS를 전송하면 클라이언트의 초기 페이로드가 약간 커질 수 있지만, 이러한 정적 파일은 캐싱 효율이 매우 높으며 서버의 CPU는 런타임 스타일 평가라는 집약적인 작업에서 해방됩니다. 이 절충안은 서버 성능과 더 빠른 초기 렌더링 시간을 우선시합니다.
특정 GitHub 페이지에서 보고된 22%의 서버 렌더링 시간 개선은 설득력 있는 결과이지만, 이를 전체 플랫폼에 걸친 보편적인 이득으로 혼동해서는 안 됩니다. 6,400개 이상의 동적 props를 폐기하는 과정을 포함한 GitHub의 광범위한 Primer 마이그레이션은 핵심 컴포넌트 제품군 전반에서 서버 사이드 렌더링 시간을 55%, 컴포넌트 초기화 시간을 25% 단축하는 결과를 가져왔습니다.
페이지별 개선 폭은 1%에서 22%까지 다양했으며, 이는 애플리케이션의 복잡성과 규모를 반영합니다. 이러한 미묘한 결과는 작업을 빌드 타임으로 옮기는 원칙은 타당하지만, 정확한 성능 이점은 애플리케이션의 고유한 아키텍처와 컴포넌트 사용 방식에 크게 의존한다는 점을 강조합니다. 이 아키텍처 전환에 대한 자세한 내용은 Improving site performance by shipping more CSS - The GitHub Blog를 참조하십시오.
이 글이 마음에 드셨나요? 매일 아침 이런 글을 메일로 받아보세요.
하루 한 통 · 두 번의 클릭으로 구독 취소 · 제3자 추적 없음
스타일링 이데올로기가 아닌 페이지를 측정하라
GitHub의 발견은 중요한 교훈을 줍니다. 스타일링 이데올로기가 아닌 페이지를 측정하십시오. 팀은 서버 렌더링 시간과 함께 CSS 바이트, 캐시 동작, 그리고 대표적인 경로에서의 Time to First Byte (TTFB) 및 Largest Contentful Paint (LCP)와 같은 사용자 중심의 핵심 지표를 평가해야 합니다. 이러한 전체적인 관점만이 사용자 경험에 미치는 진정한 영향을 드러냅니다.
단 하나의 절대적인 스타일링 솔루션은 없습니다. CSS Modules, Tailwind CSS, Chakra UI, 그리고 zero-runtime 도구들은 각각 작성 경험, 네트워크 페이로드, 아키텍처 오버헤드 측면에서 뚜렷한 장단점을 가지고 있습니다. 선택은 보편적인 규정이 아니라 애플리케이션의 구체적인 요구 사항과 성능 병목 현상에 전적으로 달려 있습니다.
전체 사용자 여정을 벤치마킹하는 것이 무엇보다 중요합니다. GitHub가 더 많은 CSS를 전송함으로써 서버 렌더링 시간을 최대 22% 단축했지만, 이것만으로 전체 페이지 로드 속도가 빨라진다고 보장할 수는 없습니다. 서버는 체인의 한 부분일 뿐이며, 더 무거운 클라이언트 사이드 페이로드나 느린 네트워크 환경은 이러한 서버 사이드 이점을 상쇄할 수 있습니다.
궁극적인 목표는 최종 사용자에게 더 빠르고 반응성이 뛰어난 애플리케이션을 제공하는 것입니다. 이는 포괄적인 지표 세트를 기준으로 스타일링 모델을 엄격하게 테스트하고 비교해야 함을 의미합니다. 애플리케이션 아키텍처에 가장 적합하고 풀 스택 전반에서 입증 가능한 개선을 제공하는 접근 방식을 선택하십시오.
자주 묻는 질문 (FAQ)
GitHub는 어떻게 서버 렌더링 시간을 22% 단축했나요?
특정 대상 페이지에서 GitHub는 런타임 CSS-in-JS에서 빌드 타임 CSS Modules로 전환하여 서버 사이드 스타일링 작업을 줄였습니다.
서버 렌더링이 22% 빨라지면 페이지도 22% 빨라지나요?
아니요. 이는 서버 렌더링 시간을 의미하며 총 로드 시간을 의미하지 않습니다. 네트워크 전송, CSS 파싱, 렌더링 또한 사용자가 경험하는 속도에 영향을 미칩니다.
런타임 CSS-in-JS가 서버 렌더링을 느리게 만드는 이유는 무엇인가요?
서버는 각 요청을 렌더링할 때 동적 스타일을 평가하고, 클래스 이름을 생성하며, CSS를 수집하거나 삽입해야 할 수 있기 때문입니다.
팀은 언제 CSS Modules를 고려해야 하나요?
서버 사이드 스타일 생성 비용이 높고 팀이 스코프가 지정된 스타일을 중요하게 생각할 때 좋은 선택이 될 수 있지만, CSS 페이로드는 측정해야 합니다.

