
- 매 컴포넌트가 증가함에 따라 스타일 코드의 일관성이 떨어진다. => 유지보수 비용의 증가
- 스타일 속성값들이 중구난방이라 어떤 속성을 갖고있는지 코드로 확인이 어렵다 => 협업에서의 문제
- 스타일마다 다른 속성을 갖고 있어서 재사용이 불가능하다 => 비효율성 증가
이런 문제점을 styled-components를 사용한다면 ContextAPI를 통해 한 번에 해결할 수 있는데, 그 방법이 바로 ThemeProvider이다.
styled-components는ThemeProvider를 통해서 강력한theming전략을 제공한다.
위에서 내가 문제점을 해결하기 위해서는 ContextAPI를 사용한다고 했는데, 이 ThemeProvider가 바로 context를 사용해서 모든 리액트 컴포넌트에게 theme 속성을 전달하는 역할을 수행한다.
어떤 컴포넌트가 몇 단계를 거쳐서 depth를 갖더라도 루트에 ThemeProvider가 자리잡고 있다면 모든 렌더 트리의 자식에는 다 theme 속성을 갖게 된다.
ContextAPI를 사용하듯이, 컴포넌트 트리의 루트에 갖다놓으면 모든 컴포넌트에서 theme을 사용 가능하다.
GlobalStyle 적용은 index.js 참고ThemeProvider를 감싼 코드는App.js 참고ThemeProvider의 theme attribute에 들어갈 theme은 theme.js 참고theme 데이터를 props로 사용한 예시 코드는 StyleTest.js 참고import React from "react";
import ReactDOM from "react-dom/client";
import { BrowserRouter } from "react-router-dom";
import "./index.css";
import App from "./App";
import { GlobalStyle } from "./styles/theme";
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<>
<BrowserRouter>
<GlobalStyle />
<App />
</BrowserRouter>
</>
);
import { ThemeProvider } from "styled-components";
import { theme } from "./styles/theme";
import Home from "./pages/Home";
import NotFound from "./pages/NotFound";
import { Routes, Route } from "react-router-dom";
function App() {
return (
<ThemeProvider theme={theme}>
<Routes>
<Route path="/" element={<Home />} />
<Route path="*" element={<NotFound />} />
</Routes>
</ThemeProvider>
);
}
export default App;
import { createGlobalStyle } from "styled-components";
export const GlobalStyle = createGlobalStyle`
@font-face {
font-family: 'Nanum Gothic';
src: url(//themes.googleusercontent.com/static/fonts/earlyaccess/nanumgothic/v3/NanumGothic-Bold.eot);
src: url(//themes.googleusercontent.com/static/fonts/earlyaccess/nanumgothic/v3/NanumGothic-Bold.eot?#iefix) format('embedded-opentype'),
url(//themes.googleusercontent.com/static/fonts/earlyaccess/nanumgothic/v3/NanumGothic-Bold.woff2) format('woff2'),
url(//themes.googleusercontent.com/static/fonts/earlyaccess/nanumgothic/v3/NanumGothic-Bold.woff) format('woff'),
url(//themes.googleusercontent.com/static/fonts/earlyaccess/nanumgothic/v3/NanumGothic-Bold.ttf) format('truetype');
font-display: swap;
}
@font-face {
font-family: 'Nanum Gothic';
/* font-style: normal;
font-weight: 800; */
src: url(//themes.googleusercontent.com/static/fonts/earlyaccess/nanumgothic/v3/NanumGothic-ExtraBold.eot);
src: url(//themes.googleusercontent.com/static/fonts/earlyaccess/nanumgothic/v3/NanumGothic-ExtraBold.eot?#iefix) format('embedded-opentype'),
url(//themes.googleusercontent.com/static/fonts/earlyaccess/nanumgothic/v3/NanumGothic-ExtraBold.woff2) format('woff2'),
url(//themes.googleusercontent.com/static/fonts/earlyaccess/nanumgothic/v3/NanumGothic-ExtraBold.woff) format('woff'),
url(//themes.googleusercontent.com/static/fonts/earlyaccess/nanumgothic/v3/NanumGothic-ExtraBold.ttf) format('truetype');
font-display: swap;
}
@font-face {
font-family: 'Nanum Gothic';
/* font-style: normal;
font-weight: 800; */
src: url(//themes.googleusercontent.com/static/fonts/earlyaccess/nanumgothic/v3/NanumGothic-Regular.eot);
src: url(//themes.googleusercontent.com/static/fonts/earlyaccess/nanumgothic/v3/NanumGothic-Regular.eot?#iefix) format('embedded-opentype'),
url(//themes.googleusercontent.com/static/fonts/earlyaccess/nanumgothic/v3/NanumGothic-Regular.woff2) format('woff2'),
url(//themes.googleusercontent.com/static/fonts/earlyaccess/nanumgothic/v3/NanumGothic-Regular.woff) format('woff'),
url(//themes.googleusercontent.com/static/fonts/earlyaccess/nanumgothic/v3/NanumGothic-Regular.ttf) format('truetype');
font-display: swap;
}
body {
margin: 0;
padding: 0;
font-family: 'Nanum Gothic', sans-serif;
font-weight: 400;
font-size: 16px;
line-height: 1.5;
color: #000000;
}
`;
export const theme = {
typography: {
header0: {
fontFamily: "Nanum Gothic",
fontWeight: "extraBold",
fontSize: "65px",
letterSpacing: "0px",
},
header1: {
fontFamily: "Nanum Gothic",
fontWeight: "bold",
fontSize: "48px",
letterSpacing: "0px",
},
subtitle1: {
fontFamily: "Nanum Gothic",
fontWeight: "bold",
fontSize: "25px",
letterSpacing: "0px",
},
subtitle1Regular: {
fontFamily: "Nanum Gothic",
fontWeight: "normal",
fontSize: "25px",
letterSpacing: "0px",
},
body1Bold: {
fontFamily: "Nanum Gothic",
fontWeight: "bold",
fontSize: "20px",
letterSpacing: "0px",
},
body1Regular: {
fontFamily: "Nanum Gothic",
fontWeight: "normal",
fontSize: "20px",
letterSpacing: "0px",
},
body2: {
fontFamily: "Nanum Gothic",
fontWeight: "bold",
fontSize: "14px",
letterSpacing: "0px",
},
button1: {
fontFamily: "Nanum Gothic",
fontWeight: "bold",
fontSize: "24px",
letterSpacing: "0px",
},
},
colors: {
backgroundWhite: "#FFFFFF",
black: "#000000",
},
};
import React from "react";
import styled from "styled-components";
function StyleTest() {
return (
<>
<Header1>헤더 0 스타일 적용 예시</Header1>
<h1>미적용한거</h1>
</>
);
}
export default StyleTest;
const Header1 = styled.h1`
font-family: ${({ theme }) => theme.typography.header1.fontFamily};
font-weight: ${({ theme }) => theme.typography.header1.fontWeight};
font-size: ${({ theme }) => theme.typography.header1.fontSize};
letter-spacing: ${({ theme }) => theme.typography.header1.letterSpacing};
color: ${({ theme }) => theme.colors.black};
`;