๐จ Next.js App Router์์ CSS-in-JS ์ฌ์ฉํ๊ธฐ
๐จ Next.js App Router์์ CSS-in-JS ์ฌ์ฉํ๊ธฐ
Next.js App Router๋ ๋ค์ํ CSS-in-JS ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ง์ํ์ฌ, ์คํ์ผ์ ์ปดํฌ๋ํธ ๋ด๋ถ์์ ์ ์ธํ๊ณ ๊ด๋ฆฌํ ์ ์๋ ์ฅ์ ์ ์ ๊ณตํฉ๋๋ค.
์ด ๊ฐ์ด๋์์๋ Next.js์์ ์ฌ์ฉ ๊ฐ๋ฅํ ์ฃผ์ CSS-in-JS ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๊ฐ๊ฐ์ ์ค์ ๋ฐฉ๋ฒ์ ์๊ฐํฉ๋๋ค.
โ 1. CSS-in-JS์ ์ฅ์
- ๋ชจ๋ํ: ์ปดํฌ๋ํธ ๋จ์๋ก ์คํ์ผ์ ๊ด๋ฆฌํ์ฌ ์ถฉ๋ ๋ฐฉ์ง
- ๋์ ์คํ์ผ: ์ํ ๊ธฐ๋ฐ์ผ๋ก ์คํ์ผ์ ๋ณ๊ฒฝํ ์ ์์
- ์์ฒด ํธ์คํ : Google Fonts ๋ฑ์ ์ง์ ํธ์คํ ๊ฐ๋ฅ
- ์๋ฒ ์ฌ์ด๋ ๋ ๋๋ง(SSR): Next.js์ ์ ๋ง์ SEO ์ฑ๋ฅ ํฅ์
โ 2. Styled Components ์ฌ์ฉํ๊ธฐ
์ค์น
npm install styled-components
npm install -D @types/styled-components
์ค์ ํ์ผ ์ถ๊ฐ
// app/layout.tsx
'use client';
import { ThemeProvider } from 'styled-components';
const theme = {
colors: {
primary: '#0070f3',
},
};
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="ko">
<body>
<ThemeProvider theme={theme}>{children}</ThemeProvider>
</body>
</html>
);
}
์ฌ์ฉ๋ฒ
// app/page.tsx
'use client';
import styled from 'styled-components';
const Title = styled.h1`
font-size: 2rem;
color: ${(props) => props.theme.colors.primary};
`;
export default function HomePage() {
return <Title>Styled Components ์ ์ฉ ์๋ฃ</Title>;
}
โ 3. Emotion ์ฌ์ฉํ๊ธฐ
์ค์น
npm install @emotion/react @emotion/styled
npm install -D @emotion/babel-plugin
์ค์ ํ์ผ (babel.config.js)
module.exports = {
presets: ['next/babel'],
plugins: ['@emotion/babel-plugin'],
};
์ฌ์ฉ๋ฒ
// app/page.tsx
'use client';
import styled from '@emotion/styled';
const Title = styled.h1`
font-size: 2rem;
color: hotpink;
`;
export default function HomePage() {
return <Title>Emotion์ผ๋ก ์คํ์ผ๋ง!</Title>;
}
โ 4. Stitches ์ฌ์ฉํ๊ธฐ
์ค์น
npm install @stitches/react
์ฌ์ฉ๋ฒ
// app/page.tsx
'use client';
import { createStitches } from '@stitches/react';
const { styled } = createStitches({
theme: {
colors: {
primary: 'blue',
},
},
});
const Title = styled('h1', {
fontSize: '2rem',
color: '$primary',
});
export default function HomePage() {
return <Title>Stitches ์คํ์ผ ์ ์ฉ</Title>;
}
โ 5. Vanilla Extract ์ฌ์ฉํ๊ธฐ
์ค์น
npm install @vanilla-extract/css
npm install -D @vanilla-extract/babel-plugin
์ค์ ํ์ผ (babel.config.js)
module.exports = {
presets: ['next/babel'],
plugins: ['@vanilla-extract/babel-plugin'],
};
์ฌ์ฉ๋ฒ
// styles.css.ts
import { style } from '@vanilla-extract/css';
export const title = style({
fontSize: '2rem',
color: 'green',
});
// app/page.tsx
'use client';
import { title } from './styles.css';
export default function HomePage() {
return <h1 className={title}>Vanilla Extract ์คํ์ผ ์ ์ฉ</h1>;
}
โ 6. Linaria ์ฌ์ฉํ๊ธฐ
์ค์น
npm install @linaria/react @linaria/babel-preset
์ค์ ํ์ผ (babel.config.js)
module.exports = {
presets: ['next/babel', '@linaria'],
};
์ฌ์ฉ๋ฒ
// app/page.tsx
'use client';
import { css } from '@linaria/core';
const title = css`
font-size: 2rem;
color: darkorange;
`;
export default function HomePage() {
return <h1 className={title}>Linaria ์คํ์ผ ์ ์ฉ</h1>;
}
โ ์ฃผ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋น๊ต
๋ผ์ด๋ธ๋ฌ๋ฆฌ ํน์ง SSR ์ง์ ์ฌ๋ถ ์ฃผ์ ์ฅ์
Styled Components | ๊ฐ์ฅ ๋๋ฆฌ ์ฌ์ฉ, ์คํ์ผ ๋ชจ๋ํ | O | ๊ฐ๋จํ ์ค์ ๊ณผ ์ปดํฌ๋ํธ ๊ธฐ๋ฐ ์คํ์ผ |
Emotion | ์ฑ๋ฅ ์ฐ์, ์ ์ฐ์ฑ ๋์ ์คํ์ผ๋ง | O | ๋์ ์คํ์ผ ์ ์ฉ์ ์ ๋ฆฌ |
Stitches | ๋น ๋ฅธ ์ฑ๋ฅ, ๊ฒฝ๋ | O | ๋์์ธ ์์คํ ๊ตฌ์ถ์ ์ ํฉ |
Vanilla Extract | ํ์ ์์ CSS | X | ์ปดํ์ผ ํ์ ์คํ์ผ ์ ์ฉ |
Linaria | Zero-runtime CSS-in-JS | X | ์ฑ๋ฅ ์ต์ ํ์ ๊ฐ๋จํ ์ฌ์ฉ๋ฒ |
โ ์์ฝ
Next.js App Router์์๋ ๋ค์ํ CSS-in-JS ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ ์ ์์ผ๋ฉฐ, ํ๋ก์ ํธ ์๊ตฌ์ฌํญ์ ๋ฐ๋ผ ์ ํฉํ ๋๊ตฌ๋ฅผ ์ ํํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค.
SSR ์ง์ ์ฌ๋ถ์ ์ฑ๋ฅ, ์ฌ์ฉ์ฑ์ ๊ณ ๋ คํ์ฌ ์ ํํ๋ ๊ฒ์ด ๊ถ์ฅ๋ฉ๋๋ค.
Next.js, CSS-in-JS, Styled Components, Emotion, Stitches, Vanilla Extract, Linaria, ์คํ์ผ๋ง, SSR ์ง์, ์ฑ๋ฅ ์ต์ ํ