next-yak: Next.js를 위한 러스트 기반 Zero-runtime CSS-in-JS
CSS-in-JS는 현대 React 개발에서 널리 사용되지만, 런타임 성능 문제가 항상 고민거리였습니다. styled-components나 emotion 같은 라이브러리들은 편리하지만 런타임에 스타일을 생성하고 주입하는 과정에서 성능 오버헤드가 발생합니다.
next-yak는 이러한 문제를 해결하기 위해 탄생한 혁신적인 CSS-in-JS 라이브러리입니다. 러스트로 개발된 이 라이브러리는 빌드 타임에 CSS를 추출하여 런타임 JavaScript 오버헤드를 완전히 제거합니다.
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>
);
.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에서 추가 설정 없이 작동합니다:
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`
`;
case'warning':
return css`
`;
case'error':
return css`
`;
}
}}
`;
설치 및 설정
패키지 설치
npm install next-yak
Next.js 설정
next.config.js
파일에 next-yak 플러그인을 추가합니다:
const{ withYak }=require('next-yak/withYak');
/** @type{import('next').NextConfig} */
const nextConfig ={
// 기존 설정들...
};
module.exports=withYak(nextConfig);
TypeScript 설정
TypeScript 프로젝트에서는 타입 정의를 추가합니다:
{
"compilerOptions":{
"types":["next-yak"]
}
}
실무 활용 패턴
1. 컴포넌트 시스템 구축
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. 반응형 레이아웃
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);
}
`;
성능 최적화
빌드 설정 최적화
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-components | next-yak | 개선율 |
---|---|---|---|
JavaScript 번들 크기 | 245KB | 198KB | 19% 감소 |
First Contentful Paint | 1.2s | 0.9s | 25% 향상 |
Time to Interactive | 2.8s | 2.3s | 18% 향상 |
Cumulative Layout Shift | 0.15 | 0.08 | 47% 향상 |
마이그레이션 가이드
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 라이브러리의 한계를 뛰어넘는 탁월한 대안입니다. 점진적 마이그레이션이 가능하므로 기존 프로젝트에서도 부담 없이 도입할 수 있습니다.