๋ง๊ทธ๋๋ก style์ด ์๋ component์ด๋ค.
Sass์ ๊ฐ์ css ์ ์ฒ๋ฆฌ๊ธฐ (์์ ๋ง์ ํน๋ณํ syntax๋ฅผ ๊ฐ์ง๊ณ css๋ฅผ ์์ฑํ๋๋ก ํ๋ ํ๋ก๊ทธ๋จ)์ด ๋ฑ์ฅํ์์๋ ๋ถ๊ตฌํ๊ณ ์๋ฐ์คํฌ๋ฆฝํธ์ ์ํ ๊ฐ์ ๊ณต์ ํ ์ ์์ด์ ๋์ ์ผ๋ก ์คํ์ผ๋ง ํ๊ธฐ ์ํด์๋ ์ธ๋ผ์ธ ์คํ์ผ์ ์ด์ฉํ๊ฑฐ๋ css ํด๋์ค๋ช ์ผ๋ก ์กฐ๊ฑด๋ถ ์คํ์ผ๋ง์ ์ด์ฉํ๋ ๋ฐฉ์์ผ๋ก ์ฌ์ฉํ๋ค.
ํ์ง๋ง ์ธ๋ผ์ธ ์คํ์ผ์ ์ ์ธํ๋ฉด ์คํ์ผ ์ ์ฉ ์์๊ฐ ๋์์ง๋ฉฐ ์คํ์ผ์ ์ฌ์ฌ์ฉ ํ ์ ์๋ ๋ฌธ์ ๊ฐ ์์๊ณ , ํด๋์ค ์ด๋ฆ์ ์ฌ์ฉํ์ ๋๋ css ํด๋์ค ์ฆ๊ฐ์ ๋ฐ๋ฅธ ํด๋์ค ์ด๋ฆ์ ๋ํ ๊ณ ๋ฏผ์ด ์์๋ค.
์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ๋ฑ์ฅํ ํจ๋ฌ๋ค์์ด CSS-in-JS์ด๋ค.
CSS-in-JS๋ js ํ์ผ ์์์ css ์ฝ๋๋ฅผ ์์ฑํ๊ธฐ ๋๋ฌธ์ css์ ๋ณ์์ ํจ์๋ฅผ ๊ทธ๋๋ก ์ฌ์ฉํ ์ ์๋ค. ๊ทธ๋ฆฌ๊ณ css ํด๋์ค๋ช ์ ํด์ ๊ฐ์ผ๋ก ์๋ ์์ฑํ์ฌ ํด๋์ค ์ด๋ฆ ์๋ช ์ ๋ํ ๊ณ ๋ฏผ์ ์๊ณ ๊ฐ ๋ํ๋ค. ๋ํ ๋ชจ๋ํ(์ ๋๋ณ๋ก ๋๋์ด ์ฌ์กฐ๋ฆฝํ๋ ๋ฐฉ์)์๋ ์ ์ฉํ๋ค.
npm install styled-components
์คํ์ผ๋ ์ปดํฌ๋ํธ๋ ์คํ์ผ๋ง์ ํ ๋ ES6์ Tagged Templeate Literal ๋ฌธ๋ฒ์ ์ด์ฉํ์ฌ jsํ์ผ ์์์ ์ ์ธํด์ ์ฌ์ฉํ ์ ์๋ค.
// App.js
import React from 'react';
import Styled from 'styled-components'; // 1
const App = () => {
return <Title>styled-components!!</Title>; //2
};
const Title = styled.h1`
font-size: 32px;
text-align: center;
color: purple;
`
export default App; //3
ex) <LogoImage src ="/images/logo.png" alt="๋ก๊ณ " />
(ํ๊ทธ์ฒ๋ผ ์ฌ์ฉํ์ง๋ง, PascalCase๋ก ์ปดํฌ๋ํธ ์ด๋ฆ์ ์์ฑํด์ฃผ์ด์ผ ํ๋ค.)
3. ์๋์ ๊ฐ์ด styled ๊ฐ์ฒด์ Tagged Templete ๋ฌธ๋ฒ์ ํ์ฉํด์ css ์์ฑ์ ์ ์ํ๋ค.
const [์ปดํฌ๋ํธ๋ช
] = styled.[htmlํ๊ทธ]`
[๋ถ์ฌํ๊ณ ์ ํ๋ css์์ฑ]
`;
๋์ ์ผ๋ก ์คํ์ผ์ ์ ์ฉํ๊ธฐ ์ํด์ ๊ฐ์ฅ ๋ง์ด ์ฌ์ฉ๋๋ ํ์ฉ ๋ฐฉ๋ฒ์ด๋ค. ๋ถ๋ชจ์์ ์์์ปดํฌ๋ํธ์ ๊ฐ์ ๋๊ฒจ์ค ๋ props๋ฅผ ์ฌ์ฉํ ๊ฒ์ฒ๋ผ, ์ด๋ฅผ ํ์ฉํ์ฌ ์กฐ๊ฑด์ ๋ฐ๋ฅธ ์คํ์ผ๋ง์ ํ ์ ์๋ค. <์ปดํฌ๋ํธ ์์ฑ๋ช =๊ฐ /> ์ ํํ๋ก ์ ์ธํด์ค๋ค. ๊ทธ๋ฌ๋ฉด, ${(props) => props.์์ฑ๋ช } ์ผ๋ก ๊ฐ์ ์ ๋์ ์ผ๋ก ์ฌ์ฉํ ์ ์๋ค.
ex) <Button color="red" /> --> props.color = red
// App.js
import React, { useState } from 'react';
import styled, { css } from 'styled-components';
const App = () => {
const [changeColor, setChangeColor] = useState(false);
const handleChangeColor = () => {
setChangeColor(!changeColor);
};
return (
<>
<Button onClick={handleChangeColor} primary={changeColor}>
Button
</Button>
</>
);
}
const Button = styled.button`
padding: 20px;
margin: 10px;
border: none;
background-color: ${(props) => (props.primary ? "purple" : "pink")}; //1
`;
export default App;
์คํ์ผ๋ ์ปดํฌ๋ํธ์ ์์ ๊ธฐ๋ฅ์ ์ด์ฉํ๋ค๋ฉด, ์ด๋ฏธ ์ ์ธ๋ ์คํ์ผ๋ ์ปดํฌ๋ํธ๋ฅผ ํ์ฉํด์ ์๋ก์ด ์คํ์ผ๋ ์ปดํฌ๋ํธ๋ฅผ ๋ง๋ค ์๋ ์๋ค.
const [์๋ก์ด ์ปดํฌ๋ํธ๋ช
] = styled(๊ธฐ์กด ์ปดํฌ๋ํธ๋ช
)`
[๋ถ์ฌํ๊ณ ์ ํ๋ css์์ฑ]
`;
Button ์ปดํฌ๋ํธ๋ฅผ ํ์ฉํ์ฌ NewButton ์ปดํฌ๋ํธ ๊ตฌ์ฑํ๋ ์์
// App.js
const App = () => {
return (
<>
<Button>Button</Button>
<NewButton>New Button</NewButton>
</>
);
};
const Button = styled.button`
margin: 20px;
padding: 20px;
border: none;
background-color: yellow;
font-size: 20px;
`;
const NewButton = styled(Button)`
color: white;
background-color: purple;
`;
export default App;
ํฐํธ ์ปฌ๋ฌ์ ๋ฐฑ๊ทธ๋ผ์ด๋ ์ปฌ๋ฌ๋ง ๋ค๋ฅธ ๋ ๊ฐ์ง์ ๋ฒํผ์ ๋ง๋ ๋ค๊ณ ๊ฐ์ ํ์ ๋ Button ์ปดํฌ๋ํธ์ ๊ธฐ๋ณธ์ ์ธ ์คํ์ผ์ ์ ์ฉ์ํค๊ธฐ ์ํด์
const NewButton = styled(Button)` [์คํ์ผ]`;
์ ๊ฐ์ด ์์ํ์ฌ ์ ์ฉํ๋ค. NewButton ์ปดํฌ๋ํธ์๋ Button ์ปดํฌ๋ํธ์ ์ ์ฉํ ์คํ์ผ์ด ๊ทธ๋๋ก ์์๋์ด NewButton์ปดํฌ๋ํธ์์ ์ถ๊ฐ๋ก ์ ์ฉํ ํฐํธ ์ปฌ๋ฌ, ๋ฐฑ๊ทธ๋ผ์ด๋ ์ปฌ๋ฌ ์ด์ธ์๋ ๊ฐ์ ์คํ์ผ์ด ์ ์ฉ๋๋ค.
๊ฐ๋ฐ์ ๋๊ตฌ์ Elements ํญ์ ํ์ธํด๋ณด๋ฉด, ์๋์ ๊ฐ์ด ์คํ์ผ์ด ๋ถ์ฌ๋๋ค.
// Elements
<button class="sc-bczRLJ jgCBVB">Button</button> // 1
<button class="sc-bczRLJ sc-gsnTZi jgCBVB hXQPTY">New Button</button> //2
์์ ์์์ฒ๋ผ ๊ฐ์ ํ์ผ์์ ์ ์ธํ ์คํ์ผ๋ ์ปดํฌ๋ํธ๋ฟ ์๋๋ผ, Link, ์์ด์ฝ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ฑ ์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์ปดํฌ๋ํธ๋ import ํ๋ฉด ์๋์ ์์์ฒ๋ผ ์คํ์ผ์ ํ์ฅํด์ ์ฌ์ฉํ ์ ์๋ค.
// App.js
import { Link } from 'react-router-dom';
import styled from 'styled-components';
const App = () => {
return <CartLink to="/cart">์ฅ๋ฐ๊ตฌ๋</CartLink>;
};
const CartLink = styled(Link)`
color: red;
`;
export default App;
// Elements
<a class="sc-eCYdqJ gubPie" href="/cart">์ฅ๋ฐ๊ตฌ๋</a>
์คํ์ผ๋ ์ปดํฌ๋ํธ์์๋ ์๋์ ๊ฐ์ด ๋ค์คํ ํด์ ์คํ์ผ์ ์ ์ฉํ ์ ์๋ค. ํ์ง๋ง ์คํ์ผ ์ปดํฌ๋ํธ๋ ์ปดํฌ๋ํธ๋ฅผ ๋ถ๋ฆฌํด์ ๋ชจ๋ํํ๊ธฐ ์ํด ์ต์ ํ๋์ด์๊ธฐ ๋๋ฌธ์, ๋ค์คํ ์ ์ ์ฉํด์ ์ฌ์ฉํ๋ ๊ฒ๋ณด๋ค ํ๋์ ์ปดํฌ๋ํธ๋ก ๋ถ๋ฆฌํด์ ์ฌ์ฉํ๋ ๊ฒ์ด ๋ ์ข๋ค.
import React from 'react';
import styled from 'styled-components';
const Main = () => {
return (
<List>
<li>
๋ฉ๋ด<a href="http://list">ํด๋ฆญ</a>
</li>
</List>
);
};
const List = styled.ul`
padding: 0;
li {
padding: 10px 0;
color: red;
font-size: 30px;
a {
color: green;
}
}
`;
export default Main;
ํ์ง๋ง ์คํ์ผ๋ ์ปดํฌ๋ํธ๋ฅผ ์ฌ์ฉํ๋ค ๋ณด๋ฉด ๋ค์คํ ์ ์ฌ์ฉํด์ผ ํ๋ ๋๋ ์๋ค. react-slick๊ณผ ๊ฐ์ ์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ์ฌ ์ด๋ฏธ ์ ํด์ง ์คํ์ผ์ ๋ณ๊ฒฝํด์ผ ํ ๋๋ ๋ค์คํ ์ ์ด์ฉํด์ ์คํ์ผ๋ง์ ํด์ผํ๋ค.
import React from 'react';
import styled from 'styled-components';
import Slider from 'react-slick';
import 'slick-carousel/slick/slick.css';
import 'slick-carousel/slick/slick-theme.css';
const Main = () => {
return (
<Carousel>
// slick ์ฝ๋
</Carousel>
);
};
const Carousel = styled(Slider)`
.slick-slide {
// slick ์ปค์คํ
์คํ์ผ
}
`;
export default Main;
์ปดํฌ๋ํธ ๊ฐ๊ฐ์ ์ ์ฉํด์ฃผ๋ฉด ์ข์ css ์คํ์ผ์ด ์์ง๋ง common.css, common.scss ์ฒ๋ผ ์ ์ญ์ ๊ณตํต์ผ๋ก css ์คํ์ผ์ ์ ์ฉํด์ฃผ๋ ๋๋ ์๋ค. ์คํ์ผ๋ ์ปดํฌ๋ํธ์์๋ createGlobalStyle ํจ์๋ฅผ ํตํด ์ ์ญ์ ์ ์ฉํ๊ธฐ ์ํ ์คํ์ผ ์ปดํฌ๋ํธ๋ฅผ ์์ฑํ ์ ์๋ค.
// src/styles/GlobalStyle.js
import React from 'react'
import { createGlobalStyle } from 'styled-components'
const GlobalStyle = createGlobalStyle`
* {
box-sizing: border-box;
font-family: 'Noto Sans KR', sans-serif;
}
`
export default GlobalStyle;
๋ํ, ์๋์ ์์์ฒ๋ผ createGlobalStyle ํจ์๋ก ์์ฑํ GlobalStyle ์ปดํฌ๋ํธ๋ฅผ ์ ์ญ์คํ์ผ์ ์ ์ฉํด์ฃผ๊ณ ์ถ์ ์ปดํฌ๋ํธ ์์์ ์ ์ฉํด์ฃผ๋ฉด GlobalStyle ์ปดํฌ๋ํธ ํ์์ ์ปดํฌ๋ํธ์๋ ์ ์ญ์คํ์ผ์ด ์ ์ฉ๋๋ค.
// index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import { ThemeProvider } from 'styled-components';
import Router from './Router';
import GlobalStyle from './styles/GlobalStyle';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<ThemeProvider>
<GlobalStyle />
<Router />
</ThemeProvider>
);
๋ธ๋ผ์ฐ์ ๋ง๋ค ์ค์ ๋์ด์๋ css ๊ธฐ๋ณธ ์คํ์ผ์ ์ด๊ธฐํํด์ฃผ๊ธฐ ์ํด reset.css, reset.scss ํ์ผ์ ์์ฑํด์ import ํด์ฃผ์ด ์ฌ์ฉํ๋ค. css ๊ธฐ๋ณธ ์คํ์ผ์ ์ด๊ธฐํํด์ฃผ๋ ์์ ์ ์คํ์ผ๋ ์ปดํฌ๋ํธ์์๋ styled-reset ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ค์นํ ํ GlobalStyle.js ํ์ผ์ ์ ์ธํ์ฌ ์ ์ญ์ ์ ์ฉํ ์ ์๋ค.
npm insall styled-reset
// src/styles/GlobalStyle.js
import React from 'react';
import { createGlobalStyle } from 'styled-components';
import reset from 'styled-reset';
const GlobalStyle = createGlobalStyle`
${reset}
* {
box-sizing: border-box;
font-family: 'Do Hyeon', sans-serif;
}
`;
export default GlobalStyle;
sass์์๋ ๋ณ์์ mixin ๋ฑ ๊ณตํต์ผ๋ก ์ฌ์ฉํ ์คํ์ผ์ ๋ํด์ ํ์ผ์ ๋ง๋ค๊ณ , ์ฌ์ฉํ๊ณ ์ ํ๋ scssํ์ผ์ import๋ฅผ ํด์ ์ ์ฉ์ ์์ผฐ๋ค. ํ์ง๋ง ๋งค๋ฒ import๋ฅผ ํด์ฃผ๊ณ , ์ฐธ์กฐํด์ผ ํ๋ css ํ์ผ์ด ๋ง์์ง๋ฉด ์์กด์ฑ์ ๊ด๋ฆฌํ๊ธฐ๋ ํ๋ค์ด์ง๋ค. ์ด๋ฐ ๋ฌธ์ ๋ค์ ํด๊ฒฐํ๊ธฐ ์ํด์ ์คํ์ผ๋ ์ปดํฌ๋ํธ์์๋ ThemeProvider๋ฅผ ํตํด ์ ์ญ์ผ๋ก ํ ๋ง, JS๋ณ์ ๋ฑ์ ๊ณต์ ํ์ฌ ์ฌ์ฉํ๋ค. ThemeProvider๋ ํ์ ํ๊ทธ์๋ themeํ์ผ์ ์ฐพ์ ์ ์๋๋ก ์ ๋ฌํด์ฃผ๋ ์ญํ ์ ํ๋ค.
// index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import { ThemeProvider } from 'styled-components';
import GlobalStyle from './styles/GlobalStyle';
import theme from './styles/theme';
import Router from './Router';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<ThemeProvider theme={theme}>
<GlobalStyle />
<Router />
</ThemeProvider>
);
ThemeProvider๋ ์์ ์์์ ๊ฐ์ด ํ๋ก์ ํธ์ ์ํธ๋ฆฌ ํฌ์ธํธ์ธ index.js์ ์ต์ด๋ก ๋ ๋๋ง ๋๋ ์ปดํฌ๋ํธ๋ฅผ ๊ฐ์ธ์ฃผ์ด์ ๋ชจ๋ ์ปดํฌ๋ํธ์ prop์ theme์ ๋ถ์ฌํ์ฌ ์ ์ฉํ ์ ์์ต๋๋ค.
color, fontSize๋ฑ ๊ณตํต๋ ํ ๋ง๋ theme.js์์ ์ ์ธํ์ฌ ๊ฐ ์ปดํฌ๋ํธ์์ props๋ก ๋ฐ์ ์คํ์ผ์ ์ ์ฉํ ์ ์๋ค. ThemeProvider์ ์์ฑ์ผ๋ก ๋๊ฒจ์ฃผ๋ฉด ์ ์ญ์์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
// theme.js
const theme = {
black: '#000000',
white: '#FFFFFF',
lightGray: '#B0B0B0',
middleGray: '#717171',
deepGray: '#222222',
hoverGray: '#DBDBDB',
};
export default theme;
// App.js
import { Link } from 'react-router-dom';
import styled 'styled-components';
const App = () => {
return <Container>title</Container>;
};
const Container = styled.div`
background-color: ${props => props.theme.lightGray}
`;
์ ์ญ์ ์ผ๋ก ์ฌ์ฉํ๊ธฐ ์ํ theme.js ํ์ผ์ ๋ง๋ค๊ณ , ํด๋น ํ์ผ์ index.js์์ ThemeProvider๋ฅผ ํตํด ์ค์ ํด์ฃผ๋ฉด, ์์ ์์์ฒ๋ผ props๋ก ๋ฐ์์์ ์ฌ์ฉํ ์ ์๋๋ฐ ์ด๋ค ํํ๋ก ๋ค์ด์ค๋์ง console.log๋ก ํ์ธํ๋ฉด props๋ ๋ค์๊ณผ ๊ฐ์ ๊ฐ์ฒด ํํ๋ก ๋ฐ์ดํฐ๊ฐ ๋ค์ด์จ๋ค. ๊ทธ๋์ props.theme.lightgray๋ก ๊ฐ์ ์ฌ์ฉํ ์ ์๋ค.
// App.js
const Container = styled.div`
background-color: ${props => console.log(props)}
`;
// console.log(props)์ ๊ฒฐ๊ณผ
props: {
children: 'title',
theme: {
black: '#000000',
white: '#FFFFFF',
lightGray: '#B0B0B0',
middleGray: '#717171',
deepGray: '#222222',
hoverGray: '#DBDBDB',
},
},
์์ฃผ ์ฌ์ฉํ๋ css ์คํ์ผ์ ๋ํด์๋ variables.js ํ์ผ์ ๋ณ๋๋ก ์์ฑํ์ฌ ์ฌ์ฉํ๋ ๊ฒ ์ข๋ค. variables.js ํ์ผ์ theme๊ณผ variables๋ฅผ Theme Provider์ ๊ฐ์ด prop์ผ๋ก ํฉ์ณ์ ์ ์ญ์์ ์ฌ์ฉํ๊ฑฐ๋, ์ฌ์ฉํ๊ณ ์ ํ๋ ํ์ผ์์๋ง import ํด์ mixin์ ์ฌ์ฉํ ์ ์๋ค. ์๋์ ๊ฐ์ variables.js ํ์ผ์ ์์ฑํ์ ๋ ์ด๋ค ๋ฐฉ์์ผ๋ก ์ ์ฉํ ์ ์๋์ง ํ์ธํด๋ณด์.
// variables.js
import { css } from 'styled-components';
const variables = {
flex: (direction = 'row', justify = 'center', align = 'center') => `
display: flex;
flex-direction: ${direction};
justify-content: ${justify};
align-items: ${align};
`,
absoluteCenter: css`
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
`,
};
export default variables;
// index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import { ThemeProvider } from './styles/GlobalStyle';
import GlobalStyle from './styles/GlobalStyle';
import theme from './styles/theme';
import variables from './styles/variables';
import Router from './Router';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<ThemeProvider theme={{ style: theme, variables }}>
<GlobalStyle />
<Router />
</ThemeProvider>
);
์ฌ์ฉํ ๋์๋ ๋ค์๊ณผ ๊ฐ์ด ์ ์ฉํ ์ ์๋ค.
// App.js
const App = () => {
return (
<Container>
<Button>์ฒซ๋ฒ์งธ ๋ฒํผ</Button>
<Button>๋๋ฒ์งธ ๋ฒํผ</Button>
</Container>
);
};
const Container = styled.div`
${(props) => props.theme.variables.flex()}
`; // a
const Button = styled.button`
background-color: ${(props) => props.theme.style.lightGray};
`;
export default App;
variables.js ํ์ผ์์ ๊ธฐ๋ณธ์ผ๋ก ์ค์ ํ ๊ฐ์ ์ฌ์ฉํ ๋์๋ flex()๋ฅผ ์จ์ฃผ๊ณ , ๋ค๋ฅธ ์ธ์๋ฅผ ๋๊ฒจ์ค๋๋
${(props) => props.theme.variables.flex('', 'space-between', 'center')}
์ฒ๋ผ ์ ์ฉํ๊ณ ์ถ์ ์ธ์๋ฅผ ๋๊ฒจ์ค ์ ์๋ค.
// App.js
import styled from 'styled-components';
import variables from './styles/variables';
const App = () => {
return (
<Wrapper>
<Button primary="pink">Pink Button</Button>
<Button primary="yellow">Yellow Button</Button>
</Wrapper>
);
};
const Wrapper = styled.div`
${variables.flex()}
`;
const Button = styled.button`
margin: 20px;
padding: 20px;
border: none;
background-color: ${(props) => props.primary};
font-size: 20px;
`;
export default App;
์ ์ญ์์ ์ฌ์ฉํ๊ธธ ์ํ๋ฉด GlobalStyle.js์ body์์ font-family๋ฅผ ์น ํฐํธ ๋ช ์ผ๋ก ์ง์ ํด์ฃผ์ด์ผ ํ๋ค. ๊ทธ๋ฆฌ๊ณ ์น ํฐํธ๋ฅผ ์ฌ์ฉํ ๊ฒ์ธ์ง, ํฐํธ ํ์ผ์ ์ฌ์ฉํ ๊ฒ์ธ์ง์ ๋ํด์ ์ค์ ๋ฐฉ๋ฒ์ด ๋ฌ๋ผ์ง๋ค.
// GlobalStyle.js
import { createGlobalStyle } from 'styled-components';
import reset from 'styled-reset';
const GlobalStyle = createGlobalStyle`
${reset}
body{
font-family: 'Do Hyeon', sans-serif;
}
`;
export default GlobalStyle;
์น ํฐํธ ์ฌ์ฉํ ๋๋ ์น ํฐํธ ์ฌ์ดํธ์์ ์ ๊ณตํ๋ embedding(์๋ฒ ๋) ์ฝ๋๋ฅผ ๋ณต์ฌํ์ฌ html ํ์ผ์ ์ฝ๋๋ฅผ ์ถ๊ฐํด์ผ ํ๋ค. index.html์ head์์ link ํ๊ทธ๋ฅผ ์ด์ฉํด์ ๊ธ๋ก๋ฒ ํฐํธ๋ก ์ง์ ํด์ ์ฌ์ฉํ ์ ์๋ค.
// index.html
<head>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Do+Hyeon&display=swap"
rel="stylesheet"
/>
</head>
src
โโโ styles
โโโ fonts
โ โโโ DoHyeon-Regular.ttf
โโโ GlobalFont.js
โโโ GlobalStyle.js
โโโ theme.js
// src/styles/GlobalFont.js
import { createGlobalStyle } from 'styled-components';
import DoHyon from './fonts/DoHyeon-Regualr.ttf';
const GlobalFont = createGlobalStyle`
@font-face {
font-family: 'Do Hyeon';
src: url(${DoHyeon}) format('woff');
}
`;
export default GlobalFont;
// index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import { ThemeProvider } from 'styled-componenets';
import GlobalStyle from './styles/GlobalStyle';
import GlobalFont from './styles/GlobalFont';
import color from './styles/theme';
import Router from './Router';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<ThemeProvider theme={theme}>
<GlobalStyle />
<GlobalFont />
<Router />
</ThemeProvider>
)