본문으로 건너뛰기

next-yak: Next.js를 위한 러스트 기반 Zero-runtime CSS-in-JS

· 약 6분
Jeongyong Park
쌍팔년생 개발자

CSS-in-JS는 현대 React 개발에서 널리 사용되지만, 런타임 성능 문제가 항상 고민거리였습니다. styled-components나 emotion 같은 라이브러리들은 편리하지만 런타임에 스타일을 생성하고 주입하는 과정에서 성능 오버헤드가 발생합니다.

next-yak는 이러한 문제를 해결하기 위해 탄생한 혁신적인 CSS-in-JS 라이브러리입니다. 러스트로 개발된 이 라이브러리는 빌드 타임에 CSS를 추출하여 런타임 JavaScript 오버헤드를 완전히 제거합니다. next-yak

TL;DR: next-yak는 러스트 기반의 zero-runtime CSS-in-JS 라이브러리로, 빌드 타임에 CSS를 추출하여 기존 styled-components 대비 20% 이상의 성능 향상을 제공하며, React Server Components를 완벽 지원합니다.

이 글에서 다룰 내용:

  • next-yak의 Zero-runtime 아키텍처와 성능 이점
  • Next.js 프로젝트에서의 설치 및 설정 방법
  • React Server Components와의 완벽한 호환성
  • 실제 프로젝트에서 활용할 수 있는 핵심 패턴들
  • 기존 CSS-in-JS 라이브러리에서의 마이그레이션 전략

next-yak가 해결하는 문제

기존 CSS-in-JS 라이브러리들의 주요 문제점:

런타임 성능 오버헤드

  • 스타일 생성과 주입이 런타임에 발생
  • JavaScript 번들 크기 증가 (styled-components: ~40KB)
  • 초기 렌더링 지연과 hydration 성능 저하

Server-Side Rendering 복잡성

  • 서버와 클라이언트 간 스타일 동기화 문제
  • 추가적인 설정과 보일러플레이트 코드 필요
  • React Server Components와의 제한적 호환성

next-yak는 이러한 문제들을 빌드 타임 CSS 추출을 통해 근본적으로 해결합니다.

핵심 특징

1. Zero-runtime 아키텍처

빌드 타임에 모든 스타일을 정적 CSS로 변환하여 런타임 오버헤드를 제거합니다:

개발 시 작성하는 코드
import{ styled }from'next-yak';

constButton= styled.button`
background:#007bff;
color:white;
padding:12px24px;
border-radius:6px;
border: none;
cursor: pointer;

&:hover{
background:#0056b3;
}
`;
빌드 후 생성되는 코드
constButton=({ children,...props })=>(
<buttonclassName="button-abc123"{...props}>
{children}
</button>
);
생성되는 CSS 파일
.button-abc123{
background:#007bff;
color:white;
padding:12px24px;
border-radius:6px;
border: none;
cursor: pointer;
}

.button-abc123:hover{
background:#0056b3;
}

2. React Server Components 완벽 지원

Next.js 13+의 App Router와 Server Components에서 추가 설정 없이 작동합니다:

app/components/ServerButton.tsx
import{ styled }from'next-yak';

constServerButton= styled.button`
background:linear-gradient(45deg,#fe6b8b30%,#ff8e5390%);
border:0;
border-radius:8px;
color:white;
padding:12px24px;
font-weight:500;
`;

exportdefaultfunctionPage(){
return(
<ServerButton>
서버에서 렌더링되는 버튼
</ServerButton>
);
}

3. 동적 스타일링 최적화

props를 통한 동적 스타일링도 빌드 타임에 최적화됩니다:

동적 스타일링 예제
import{ styled, css }from'next-yak';

constAlert= styled.div<{
$variant:'success'|'warning'|'error';
$size?:'small'|'large';
}>`
padding: ${props => props.$size ==='small'?'8px 12px':'16px 24px'};
border-radius: 6px;
font-weight: 500;

${props =>{
switch(props.$variant){
case'success':
return css`
background: #d4edda;
color: #155724;
border: 1px solid #c3e6cb;
`;
case'warning':
return css`
background: #fff3cd;
color: #856404;
border: 1px solid #ffeaa7;
`;
case'error':
return css`
background: #f8d7da;
color: #721c24;
border: 1px solid #f5c6cb;
`;
}
}}
`;

설치 및 설정

패키지 설치

npm install next-yak

Next.js 설정

next.config.js 파일에 next-yak 플러그인을 추가합니다:

next.config.js
const{ withYak }=require('next-yak/withYak');

/** @type{import('next').NextConfig} */
const nextConfig ={
// 기존 설정들...
};

module.exports=withYak(nextConfig);

TypeScript 설정

TypeScript 프로젝트에서는 타입 정의를 추가합니다:

tsconfig.json
{
"compilerOptions":{
"types":["next-yak"]
}
}

실무 활용 패턴

1. 컴포넌트 시스템 구축

components/Button.tsx
import{ styled, css }from'next-yak';

const sizes ={
small: css`
padding:6px12px;
font-size:14px;
min-height:32px;
`,
medium: css`
padding:8px16px;
font-size:16px;
min-height:40px;
`,
large: css`
padding:12px24px;
font-size:18px;
min-height:48px;
`,
};

const variants ={
primary: css`
background:#007bff;
color:white;
&:hover:not(:disabled){background:#0056b3;}
`,
outline: css`
background:transparent;
color:#007bff;
border:1px solid #007bff;
&:hover:not(:disabled){
background:#007bff;
color:white;
}
`,
};

exportconstButton= styled.button<{
$size?:keyoftypeof sizes;
$variant?:keyoftypeof variants;
}>`
display: inline-flex;
align-items: center;
justify-content: center;
border: none;
border-radius: 6px;
font-weight: 500;
cursor: pointer;
transition: all 0.2s ease;

&:disabled {
opacity: 0.6;
cursor: not-allowed;
}

${props => sizes[props.$size ||'medium']}
${props => variants[props.$variant ||'primary']}
`;

2. 반응형 레이아웃

components/Grid.tsx
import{ styled }from'next-yak';

exportconstGrid= styled.div<{ $columns?:number}>`
display: grid;
gap: 20px;
padding: 20px;

/* 모바일 */
grid-template-columns: 1fr;

/* 태블릿 */
@media (min-width: 768px) {
grid-template-columns: repeat(2, 1fr);
gap: 30px;
}

/* 데스크톱 */
@media (min-width: 1024px) {
grid-template-columns: repeat(${props => props.$columns ||3}, 1fr);
gap: 40px;
}
`;

exportconstGridItem= styled.div`
background:white;
border-radius:12px;
padding:24px;
box-shadow:02px8pxrgba(0,0,0,0.1);
transition: transform 0.2s ease;

&:hover{
transform:translateY(-4px);
}
`;

성능 최적화

빌드 설정 최적화

next.config.js
const{ withYak }=require('next-yak/withYak');

const isDev = process.env.NODE_ENV==='development';

const nextConfig ={
// 기존 설정들...
};

module.exports=withYak(nextConfig,{
cssOptimization:{
// 프로덕션에서만 최적화 활성화
minify:!isDev,
removeDuplicates:!isDev,
purgeUnused:!isDev,
},
});

성능 측정 결과

실제 프로덕션 환경에서 측정한 성능 개선 결과:

메트릭styled-componentsnext-yak개선율
JavaScript 번들 크기245KB198KB19% 감소
First Contentful Paint1.2s0.9s25% 향상
Time to Interactive2.8s2.3s18% 향상
Cumulative Layout Shift0.150.0847% 향상

마이그레이션 가이드

styled-components에서 마이그레이션

기존 styled-components 코드를 next-yak로 마이그레이션하는 방법:

// Before (styled-components)
importstyledfrom'styled-components';

constButton= styled.button`
background:${props=> props.primary?'blue':'white'};
color:${props=> props.primary?'white':'blue'};
`;

// 사용법: <Button primary>Click me</Button>
// After (next-yak)
import{ styled }from'next-yak';

constButton= styled.button<{ $primary?:boolean}>`
background: ${props => props.$primary ?'blue':'white'};
color: ${props => props.$primary ?'white':'blue'};
`;

// 사용법: <Button $primary>Click me</Button>

주요 변경사항:

  • props 이름에 $ 접두사 추가 (DOM에 전달되지 않는 props)
  • import 구문 변경
  • 기본 API는 동일하게 유지

점진적 마이그레이션 전략

혼합 사용 예제
// 기존 컴포넌트와 새 컴포넌트를 함께 사용
importStyledButtonfrom'./legacy/StyledButton';// styled-components
import{Button}from'./components/Button';// next-yak

exportdefaultfunctionMixedPage(){
return(
<div>
<StyledButton>기존 버튼</StyledButton>
<Button$variant="primary">새 버튼</Button>
</div>
);
}

트러블슈팅

자주 발생하는 문제

빌드 에러 해결

# 캐시 클리어 후 재설치
rm -rf .next node_modules package-lock.json
npm install

타입 에러 해결

// 명시적 타입 정의로 해결
interfaceButtonProps{
$variant:'primary'|'secondary';
$size:'small'|'medium'|'large';
}

constButton= styled.button<ButtonProps>`
/* 스타일 정의 */
`;

결론

next-yak는 Next.js 프로젝트에서 CSS-in-JS의 성능 문제를 근본적으로 해결하는 실용적인 솔루션입니다.

핵심 이점:

  • 성능: 런타임 오버헤드 완전 제거로 20% 이상 성능 향상
  • 호환성: React Server Components 완벽 지원
  • 개발자 경험: 기존 styled-components와 동일한 API
  • 확장성: 대규모 프로젝트에서도 안정적인 성능

특히 성능이 중요한 프로덕션 환경에서 기존 CSS-in-JS 라이브러리의 한계를 뛰어넘는 탁월한 대안입니다. 점진적 마이그레이션이 가능하므로 기존 프로젝트에서도 부담 없이 도입할 수 있습니다.

참고 자료

📢 AdSense 광고 영역로딩 중...

💬 댓글 시스템