이 글은 next.js 15와 styled-components를 사용한 프로젝트에 대해 다룹니다.
이 글의 테마는 MUI의 디자인 시스템 컬러를 참고하였습니다.
0. 코드 템플릿
1. 테마 타입 정의
src/types/styled.d.ts
import "styled-components";
declare module "styled-components" {
export interface DefaultTheme {
colors: {
primary: {
light: string;
main: string;
dark: string;
};
secondary: {
light: string;
main: string;
dark: string;
};
info: {
light: string;
main: string;
dark: string;
};
success: {
light: string;
main: string;
dark: string;
};
warning: {
light: string;
main: string;
dark: string;
};
error: {
light: string;
main: string;
dark: string;
};
};
}
}
2. 테마 생성
src/styles/theme.ts
import { DefaultTheme } from "styled-components";
export const theme: DefaultTheme = {
colors: {
primary: {
light: "#42A5F5",
main: "#2196F3",
dark: "#1E88E5",
},
secondary: {
main: "#BA68C8",
light: "#9C27B0",
dark: "#7B1FA2",
},
info: {
main: "#01579B",
light: "#0288D1",
dark: "#03A9F4",
},
success: {
main: "#4CAF50",
light: "#2E7D32",
dark: "#1B5E20",
},
warning: {
main: "#FF9800",
light: "#E65100",
dark: "#EF6C00",
},
error: {
main: "#EF5350",
light: "#D32F2F",
dark: "#C62828",
},
},
};
3. 테마 프로바이더 생성
src/components/ThemeProviderWrapper.tsx
"use client";
import { ThemeProvider } from "styled-components";
import { theme } from "@/styles/theme";
const ThemeProviderWrapper = ({ children }: { children: React.ReactNode }) => {
return <ThemeProvider theme={theme}>{children}</ThemeProvider>;
};
export default ThemeProviderWrapper;
4. 테마 프로바이더 적용
src/app/layout.tsx
import Sidebar from "@/components/ui/sidebar/Sidebar";
import SidebarButton from "@/components/ui/sidebar/SidebarButton";
import ThemeProviderWrapper from "@/components/ThemeProviderWrapper"; // 수정 부분✨
import type { Metadata } from "next";
export const metadata: Metadata = {
title: "데브카드(DevCard) | 개발자 면접 준비를 위한 면접질문 카드",
description: "데브카드는 개발자 면접 준비를 위한 면접질문 카드를 제공합니다.",
};
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="ko">
<body>
// 수정 부분✨
<ThemeProviderWrapper>
<Sidebar />
<SidebarButton />
{children}
</ThemeProviderWrapper>
// 수정 부분✨
</body>
</html>
);
}
5. 타입스크립트 설정
tsconfig.json
{
"compilerOptions": {
...기존 코드,
"types": ["styled-components"]
},
}
6. 서버 재시작
$ npm run dev
Q1. 왜 테마 프로바이더에 MUI 테마를 삽입한 후 styled.div에서 테마를 사용할 수 없는 이유에 대해 아주 자세히 설명해봐
A1.
문제 상황
MUI의 ThemeProvider로 테마를 설정했음에도 불구하고, styled-components에서 MUI 테마에 접근할 수 없는 이유는 두 라이브러리의 테마 시스템이 독립적이기 때문입니다.
---
1. MUI와 styled-components의 테마 시스템 차이
MUI의 테마 시스템
MUI는 자체적으로 React Context를 사용해 테마를 관리합니다.
@mui/material/styles의 ThemeProvider가 MUI 컴포넌트에서 테마 값을 공유합니다.
MUI 컴포넌트(Button, Typography 등)에서는 내부적으로 이 테마를 참조해서 스타일이 적용됩니다.
import { ThemeProvider, createTheme } from '@mui/material/styles';
const theme = createTheme({
palette: {
primary: {
main: '#1976d2',
},
},
});
중요 포인트
MUI 컴포넌트 내부에서는 이 테마에 자동으로 접근 가능.
하지만 styled-components는 이 컨텍스트에 접근할 방법이 없습니다.
---
styled-components의 테마 시스템
styled-components도 자체적으로 React Context를 사용해 테마를 관리합니다.
ThemeProvider로 테마를 주입하고, 이 값을 props.theme로 전달합니다.
import { ThemeProvider } from 'styled-components';
const theme = {
colors: {
primary: '#1976d2',
},
};
중요 포인트
styled-components는 오직 자체 컨텍스트에서 전달된 테마만 사용합니다.
MUI의 테마 컨텍스트에 접근할 수 없습니다.
---
2. 왜 MUI 테마가 styled-components에 전달되지 않을까?
독립된 컨텍스트 사용:
MUI와 styled-components는 서로 다른 Context API 인스턴스를 사용합니다.
→ 따라서 MUI의 테마는 styled-components 컴포넌트에 자동으로 전달되지 않습니다.
자동 전달이 안 됨:
두 라이브러리가 서로 다른 테마 객체 구조를 사용하기 때문에, React는 MUI의 테마를 styled-components의 theme prop에 자동으로 전달하지 않습니다.
---
3. 해결 방법: 두 테마 시스템 통합하기
방법 1️⃣ MUI 테마를 styled-components에도 전달
MUI ThemeProvider와 styled-components ThemeProvider를 중첩해서 MUI 테마를 두 곳 모두에 전달해야 합니다.
import { ThemeProvider as MuiThemeProvider, createTheme } from '@mui/material/styles';
import { ThemeProvider as StyledThemeProvider } from 'styled-components';
const theme = createTheme({
palette: {
primary: {
main: '#1976d2',
},
},
});
function App() {
return (
<MuiThemeProvider theme={theme}>
<StyledThemeProvider theme={theme}>
<MyComponent />
</StyledThemeProvider>
</MuiThemeProvider>
);
}
이렇게 하면:
MUI 컴포넌트는 MUI의 ThemeProvider에서 테마 값을 받습니다.
styled-components는 StyledThemeProvider를 통해 동일한 테마 값을 받습니다.
> ✅ 결과: 두 테마 시스템이 동일한 테마 값을 공유하게 됩니다.
---
방법 2️⃣ useTheme 훅을 사용해 수동으로 전달
MUI의 useTheme() 훅을 사용해 테마를 가져와 직접 넘겨줄 수도 있습니다.
import styled from 'styled-components';
import { useTheme } from '@mui/material/styles';
const StyledDiv = styled.div`
background-color: ${({ theme }) => theme.palette.primary.main};
`;
const MyComponent = () => {
const muiTheme = useTheme();
return <StyledDiv theme={muiTheme}>테마 적용</StyledDiv>;
};
이렇게 하면:
MUI의 테마를 직접 props로 전달해 styled-components가 이를 사용할 수 있습니다.
다만, 매번 테마를 직접 전달해야 하기 때문에 코드가 반복될 수 있습니다.
---
4. 정리
핵심 이유:
MUI와 styled-components는 서로 다른 Context 시스템을 사용하기 때문에, MUI 테마가 자동으로 styled-components에 전달되지 않습니다. 이를 해결하기 위해서는 두 테마 시스템을 명시적으로 연결해야 합니다.
Q2. 아 그럼 styled()로 선언하는 컴포넌트는 MUI 문법이야?
A2. 네, 맞습니다. styled() 함수는 MUI에서 제공하는 스타일링 유틸리티입니다.
MUI의 styled()는 @mui/system에서 제공되며, MUI 테마와 깊게 통합되어 있어 styled-components와는 다른 방식으로 동작합니다.
---
🔍 차이점: MUI의 styled() vs. styled-components
---
✅ MUI의 styled() 사용 예시
import { styled } from '@mui/system';
const MyStyledDiv = styled('div')(({ theme }) => ({
backgroundColor: theme.palette.primary.main,
color: theme.palette.secondary.contrastText,
padding: theme.spacing(2),
borderRadius: '8px',
}));
const MyComponent = () => {
return <MyStyledDiv> MUI 테마가 적용된 div </MyStyledDiv>;
};
특징:
theme 객체가 자동으로 주입됨 (별도로 전달 필요 없음)
MUI 테마에 맞춰 스타일이 동적으로 적용됨
MUI 컴포넌트와 호환성이 뛰어남
---
✅ styled-components의 styled() 사용 예시
import styled from 'styled-components';
const MyStyledDiv = styled.div`
background-color: ${({ theme }) => theme.colors.primary};
color: ${({ theme }) => theme.colors.secondary};
padding: 16px;
border-radius: 8px;
`;
특징:
테마 값을 사용하려면 별도로 **ThemeProvider**로 테마 주입이 필요
MUI 테마와의 통합이 자동으로 이루어지지 않음
더 범용적으로 사용 가능 (MUI에 종속되지 않음)
---
🎯 언제 MUI의 styled()를 사용해야 할까?
프로젝트에서 MUI 컴포넌트를 주로 사용하는 경우
MUI 테마 설정에 맞춰 스타일링을 일관되게 유지하고 싶은 경우
MUI의 시스템 속성(예: spacing, palette)을 그대로 활용하고 싶을 때
🎯 언제 styled-components를 사용해야 할까?
MUI 외에 다른 스타일링 접근법이 필요한 경우
MUI와 무관한 커스텀 스타일링이 필요한 경우
라이브러리 종속성이 적은 범용적인 스타일을 작성할 때
---
🔥 정리
styled() → MUI 문법
styled-components의 styled와 유사하지만, MUI 테마와 자동으로 통합
MUI 컴포넌트 스타일링 시에는 @mui/system의 styled()를 사용하는 것이 더 효율적
'라이브러리' 카테고리의 다른 글
OpenAI API(GPT) 사용법 (0) | 2025.03.30 |
---|---|
[react-swiper] 스와이퍼 범위가 무한히 늘어나는 버그 | 스크롤바가 무한히 늘어나는 원인 및 해결방법 (0) | 2025.02.23 |
[react-dnd] 드래그앤드랍 시 최신 state를 가져오지 못하는 버그 (0) | 2025.02.09 |
[Swiper] 리액트 스와이퍼 자동 재생 특정 횟수에서 멈추기 (0) | 2025.01.14 |
[Notistack] 알림 스택 라이브러리 notistack 사용방법 (0) | 2025.01.06 |
이 글은 next.js 15와 styled-components를 사용한 프로젝트에 대해 다룹니다.
이 글의 테마는 MUI의 디자인 시스템 컬러를 참고하였습니다.
0. 코드 템플릿
1. 테마 타입 정의
src/types/styled.d.ts
import "styled-components";
declare module "styled-components" {
export interface DefaultTheme {
colors: {
primary: {
light: string;
main: string;
dark: string;
};
secondary: {
light: string;
main: string;
dark: string;
};
info: {
light: string;
main: string;
dark: string;
};
success: {
light: string;
main: string;
dark: string;
};
warning: {
light: string;
main: string;
dark: string;
};
error: {
light: string;
main: string;
dark: string;
};
};
}
}
2. 테마 생성
src/styles/theme.ts
import { DefaultTheme } from "styled-components";
export const theme: DefaultTheme = {
colors: {
primary: {
light: "#42A5F5",
main: "#2196F3",
dark: "#1E88E5",
},
secondary: {
main: "#BA68C8",
light: "#9C27B0",
dark: "#7B1FA2",
},
info: {
main: "#01579B",
light: "#0288D1",
dark: "#03A9F4",
},
success: {
main: "#4CAF50",
light: "#2E7D32",
dark: "#1B5E20",
},
warning: {
main: "#FF9800",
light: "#E65100",
dark: "#EF6C00",
},
error: {
main: "#EF5350",
light: "#D32F2F",
dark: "#C62828",
},
},
};
3. 테마 프로바이더 생성
src/components/ThemeProviderWrapper.tsx
"use client";
import { ThemeProvider } from "styled-components";
import { theme } from "@/styles/theme";
const ThemeProviderWrapper = ({ children }: { children: React.ReactNode }) => {
return <ThemeProvider theme={theme}>{children}</ThemeProvider>;
};
export default ThemeProviderWrapper;
4. 테마 프로바이더 적용
src/app/layout.tsx
import Sidebar from "@/components/ui/sidebar/Sidebar";
import SidebarButton from "@/components/ui/sidebar/SidebarButton";
import ThemeProviderWrapper from "@/components/ThemeProviderWrapper"; // 수정 부분✨
import type { Metadata } from "next";
export const metadata: Metadata = {
title: "데브카드(DevCard) | 개발자 면접 준비를 위한 면접질문 카드",
description: "데브카드는 개발자 면접 준비를 위한 면접질문 카드를 제공합니다.",
};
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="ko">
<body>
// 수정 부분✨
<ThemeProviderWrapper>
<Sidebar />
<SidebarButton />
{children}
</ThemeProviderWrapper>
// 수정 부분✨
</body>
</html>
);
}
5. 타입스크립트 설정
tsconfig.json
{
"compilerOptions": {
...기존 코드,
"types": ["styled-components"]
},
}
6. 서버 재시작
$ npm run dev
Q1. 왜 테마 프로바이더에 MUI 테마를 삽입한 후 styled.div에서 테마를 사용할 수 없는 이유에 대해 아주 자세히 설명해봐
A1.
문제 상황
MUI의 ThemeProvider로 테마를 설정했음에도 불구하고, styled-components에서 MUI 테마에 접근할 수 없는 이유는 두 라이브러리의 테마 시스템이 독립적이기 때문입니다.
---
1. MUI와 styled-components의 테마 시스템 차이
MUI의 테마 시스템
MUI는 자체적으로 React Context를 사용해 테마를 관리합니다.
@mui/material/styles의 ThemeProvider가 MUI 컴포넌트에서 테마 값을 공유합니다.
MUI 컴포넌트(Button, Typography 등)에서는 내부적으로 이 테마를 참조해서 스타일이 적용됩니다.
import { ThemeProvider, createTheme } from '@mui/material/styles';
const theme = createTheme({
palette: {
primary: {
main: '#1976d2',
},
},
});
중요 포인트
MUI 컴포넌트 내부에서는 이 테마에 자동으로 접근 가능.
하지만 styled-components는 이 컨텍스트에 접근할 방법이 없습니다.
---
styled-components의 테마 시스템
styled-components도 자체적으로 React Context를 사용해 테마를 관리합니다.
ThemeProvider로 테마를 주입하고, 이 값을 props.theme로 전달합니다.
import { ThemeProvider } from 'styled-components';
const theme = {
colors: {
primary: '#1976d2',
},
};
중요 포인트
styled-components는 오직 자체 컨텍스트에서 전달된 테마만 사용합니다.
MUI의 테마 컨텍스트에 접근할 수 없습니다.
---
2. 왜 MUI 테마가 styled-components에 전달되지 않을까?
독립된 컨텍스트 사용:
MUI와 styled-components는 서로 다른 Context API 인스턴스를 사용합니다.
→ 따라서 MUI의 테마는 styled-components 컴포넌트에 자동으로 전달되지 않습니다.
자동 전달이 안 됨:
두 라이브러리가 서로 다른 테마 객체 구조를 사용하기 때문에, React는 MUI의 테마를 styled-components의 theme prop에 자동으로 전달하지 않습니다.
---
3. 해결 방법: 두 테마 시스템 통합하기
방법 1️⃣ MUI 테마를 styled-components에도 전달
MUI ThemeProvider와 styled-components ThemeProvider를 중첩해서 MUI 테마를 두 곳 모두에 전달해야 합니다.
import { ThemeProvider as MuiThemeProvider, createTheme } from '@mui/material/styles';
import { ThemeProvider as StyledThemeProvider } from 'styled-components';
const theme = createTheme({
palette: {
primary: {
main: '#1976d2',
},
},
});
function App() {
return (
<MuiThemeProvider theme={theme}>
<StyledThemeProvider theme={theme}>
<MyComponent />
</StyledThemeProvider>
</MuiThemeProvider>
);
}
이렇게 하면:
MUI 컴포넌트는 MUI의 ThemeProvider에서 테마 값을 받습니다.
styled-components는 StyledThemeProvider를 통해 동일한 테마 값을 받습니다.
> ✅ 결과: 두 테마 시스템이 동일한 테마 값을 공유하게 됩니다.
---
방법 2️⃣ useTheme 훅을 사용해 수동으로 전달
MUI의 useTheme() 훅을 사용해 테마를 가져와 직접 넘겨줄 수도 있습니다.
import styled from 'styled-components';
import { useTheme } from '@mui/material/styles';
const StyledDiv = styled.div`
background-color: ${({ theme }) => theme.palette.primary.main};
`;
const MyComponent = () => {
const muiTheme = useTheme();
return <StyledDiv theme={muiTheme}>테마 적용</StyledDiv>;
};
이렇게 하면:
MUI의 테마를 직접 props로 전달해 styled-components가 이를 사용할 수 있습니다.
다만, 매번 테마를 직접 전달해야 하기 때문에 코드가 반복될 수 있습니다.
---
4. 정리
핵심 이유:
MUI와 styled-components는 서로 다른 Context 시스템을 사용하기 때문에, MUI 테마가 자동으로 styled-components에 전달되지 않습니다. 이를 해결하기 위해서는 두 테마 시스템을 명시적으로 연결해야 합니다.
Q2. 아 그럼 styled()로 선언하는 컴포넌트는 MUI 문법이야?
A2. 네, 맞습니다. styled() 함수는 MUI에서 제공하는 스타일링 유틸리티입니다.
MUI의 styled()는 @mui/system에서 제공되며, MUI 테마와 깊게 통합되어 있어 styled-components와는 다른 방식으로 동작합니다.
---
🔍 차이점: MUI의 styled() vs. styled-components
---
✅ MUI의 styled() 사용 예시
import { styled } from '@mui/system';
const MyStyledDiv = styled('div')(({ theme }) => ({
backgroundColor: theme.palette.primary.main,
color: theme.palette.secondary.contrastText,
padding: theme.spacing(2),
borderRadius: '8px',
}));
const MyComponent = () => {
return <MyStyledDiv> MUI 테마가 적용된 div </MyStyledDiv>;
};
특징:
theme 객체가 자동으로 주입됨 (별도로 전달 필요 없음)
MUI 테마에 맞춰 스타일이 동적으로 적용됨
MUI 컴포넌트와 호환성이 뛰어남
---
✅ styled-components의 styled() 사용 예시
import styled from 'styled-components';
const MyStyledDiv = styled.div`
background-color: ${({ theme }) => theme.colors.primary};
color: ${({ theme }) => theme.colors.secondary};
padding: 16px;
border-radius: 8px;
`;
특징:
테마 값을 사용하려면 별도로 **ThemeProvider**로 테마 주입이 필요
MUI 테마와의 통합이 자동으로 이루어지지 않음
더 범용적으로 사용 가능 (MUI에 종속되지 않음)
---
🎯 언제 MUI의 styled()를 사용해야 할까?
프로젝트에서 MUI 컴포넌트를 주로 사용하는 경우
MUI 테마 설정에 맞춰 스타일링을 일관되게 유지하고 싶은 경우
MUI의 시스템 속성(예: spacing, palette)을 그대로 활용하고 싶을 때
🎯 언제 styled-components를 사용해야 할까?
MUI 외에 다른 스타일링 접근법이 필요한 경우
MUI와 무관한 커스텀 스타일링이 필요한 경우
라이브러리 종속성이 적은 범용적인 스타일을 작성할 때
---
🔥 정리
styled() → MUI 문법
styled-components의 styled와 유사하지만, MUI 테마와 자동으로 통합
MUI 컴포넌트 스타일링 시에는 @mui/system의 styled()를 사용하는 것이 더 효율적
'라이브러리' 카테고리의 다른 글
OpenAI API(GPT) 사용법 (0) | 2025.03.30 |
---|---|
[react-swiper] 스와이퍼 범위가 무한히 늘어나는 버그 | 스크롤바가 무한히 늘어나는 원인 및 해결방법 (0) | 2025.02.23 |
[react-dnd] 드래그앤드랍 시 최신 state를 가져오지 못하는 버그 (0) | 2025.02.09 |
[Swiper] 리액트 스와이퍼 자동 재생 특정 횟수에서 멈추기 (0) | 2025.01.14 |
[Notistack] 알림 스택 라이브러리 notistack 사용방법 (0) | 2025.01.06 |