ํ ํฌ ๋ธ๋ก๊ทธ ๊ธฐํ
๊ธฐ์กด์ GIthub Pages๋ก ๋ฐฐํฌํ github.io ๋ธ๋ก๊ทธ๋ฅผ ๊ฐ์ง๊ณ ์๊ธด ํ์ง๋ง, ๊ธํ ๋ ํ ํ๋ฆฟ ๊ฐ์ง๊ณ ์์ ๊ณ ์ณ ์ด ๊ฒ ๋ค๋ผ ๋ ์ด์์์ ์ ์ฝ์ด ์ปค ์์ ์๋ก ์ ์ํ๊ธฐ๋ก ํ๋ค. ์ ์ํ๋ฉฐ ์ฌํ ์ ์จ๋ดค์ง๋ง, ์จ๋ด์ผ ํ ๊ฒ ๊ฐ์ ๊ธฐ์ ๋ค์ ๋ชฝ๋ ์ฒดํํด๋ณด๋ ๊ฒ์ด ๋ชฉํ.
์๋ก์ด ํ ํฌ ๋ธ๋ก๊ทธ์๋ ํฌํธํด๋ฆฌ์ค์ Reusme ๊ทธ๋ฆฌ๊ณ Blog ๊ธฐ๋ฅ๊น์ง ๋ฃ์ ๊ฑฐ๋ผ ๋์์ธ์ ์ต๋ํ ์ฌํํ๊ฒ ํ๊ธฐ๋ก ํ๋ค.
๊ณ์ ๋๊ณ ๋๊ณ ์ฐ๊ฒ ๋ ์น ์ฌ์ดํธ์ด๋ ๊ณํ๊ณผ ํ๋กํ ํ์ดํ์๋ ์ ๊ฒฝ์ ์ผ๊ณ , ์ด๋ค ๊ธฐ๋ฅ์ ์ต์ํ์ผ๋ก ๊ฐ์ถ์ง, ์ด๋ค ๋ถ๋ถ์ ์์ผ๋ก ์ถ๊ฐํด์ ์จ๋ ๊ด์ฐฎ์์ง ๋ฑ์ ๊ผผ๊ผผํ ์๊ฐํ๋ฉฐ ๋์์ธํ๋ค.
Figma Prototyping
์ด์จ๊ฑฐ๋ Resume ์ญํ ์ ํ๊ฒ ๋ ๋ธ๋ก๊ทธ์ด๋ ๋ชจ๋ฐ์ผ๋ก ๋ณผ ์ผ์ด ๋ ๋ง๊ฒ ๋ค ์ถ์ด ๋ชจ๋ฐ์ผ ์คํฌ๋ฆฐ ์ฌ์ด์ฆ์ ๋ง์ถฐ ๋จผ์ ๋์์ธ์ ํ๋ค.
๋ฐ์คํฌํ ํ๋ฉด์์๋ ์ด๋ฐ ๋๋์ผ๋ก ๋ง๋ค์๋ค.
Framework/Library ์ ํ๊ธฐ
Vue.js๋ก๋ ๊ฐ๋ฐํ ์ ์์์ง๋ง, ๊ตฌ์ง ์ฌ์ดํธ๋ฅผ ๋ณด๋ฉด ๋ณผ์๋ก ์๋์ ์ผ๋ก React.js ์ฐ๋ ํ์ฌ๊ฐ ๋ง๊ณ , Vue.js๋ก๋ง ๊ฐ๋ฐํ๋ ํ์ฌ๋ ์์ด์ ํ ๋ฒ์ ๊ณต๋ถํ๊ณ ๋์ด๊ฐ์ผ์ง ์ถ์ด React.js๋ฅผ ์จ๋ณด๊ธฐ๋ก ํ๋ค. ์๋ 1๋ ์ฌ ์ ์ ๋ง JavaScript ๊ณต๋ถ๋ฅผ ์์ํ ๋ React.js๋ฅผ ๋ง๋ณด๊ธฐ ์ ๋๋ก๋ง ํ๊ณ Vue.js๋ฅผ ๋ณธ๊ฒฉ์ ์ผ๋ก ๊ณต๋ถํ๊ธฐ ์์ํ๋ค. ๊ทธ๋ ๊ฒ ํ ๋ฒ ํ๋ ์์ํฌ๋ฅผ ๋ค๋ค๋ณด๊ณ ๋ค์ ๋ฆฌ์กํธ๋ฅผ ๋ณด๋ ๊ฒน์น๋ ๋ถ๋ถ์ด ๋ง์ ์คํ๋ ค React.js๋ง์ ์ปจ์ ์ ๋ ์ ์ดํดํ ์ ์์ ๊ฒ ๊ฐ์๋ค.
๊ทธ ๋ค์์ UI ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ญ ๋๋ฌ๋ณด๋ค๊ฐ ๋ฏธ๋ฆฌ ํ๋กํ ํ์ดํํ ๋์์ธ๊ณผ ์ด์ง๊ฐ ์์ด ์ ์ด์ธ๋ฆด ๊ฒ ๊ฐ์ ๋์์ธ์ ์ปดํฌ๋ํธ๊ฐ ๋ง์ Grommet UI๋ฅผ ์จ๋ณด๊ธฐ๋ก ํ๋ค. ์ฐจํธ ์ปดํฌ๋ํธ๊ฐ ๋ค์ํ ๊ฒ๋ ๋ฌด์ฒ ๋งค๋ ฅ์ด์๋ค.
๋ค๋ง ๋ค๋ฅธ ์ ๋ช ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค์ ๋นํด ์ ์ ์๋ ์กฐ๊ธ ์ ์ด์ ์ด์๊ฐ ์๊ธฐ๊ฑฐ๋ ์ ์ ํ๋ฆด ๋ ์ฐธ๊ณ ํ ๋งํ ๋ฌธ์๋ ๋ณ๋ก ์์ ๊ฒ ๊ฐ์ ๊ฑฑ์ ์ด๊ธด ํ๋ค.
AppBar ๋ง๋ค๊ธฐ
ํค๋๋ฅผ ๋จผ์ ๋ง๋ค์๋ค. ๋์์ธ ๋ฐ๋ผ์ ์ปดํฌ๋ํธ ์ฐธ๊ณ ํ๋ฉฐ ๋ง๋ค์๋ค. Sidebar์ header์ Nav ๋ถ๋ถ์๋ ์นดํ ๊ณ ๋ฆฌ๊ฐ ๊ฒน์น๋ categories ๋ณ์ ์์ ํ์ํ ๋ฐ์ดํฐ๋ค์ ๋จผ์ ์ ๋ฆฌํด ๋ฃ์ด์ฃผ์๋ค.
const categories = [
{title: 'About', isOnMain: true, href: '#'},
{title: 'Portfolio', isOnMain: true, href: '#' },
{title: 'Resume', isOnMain: false, href: '#' },
{title: 'Blog', isOnMain: true, href: '#' },
{title: 'Contact', isOnMain: true, href: '#' },
]
Resume๋ ๋๋ฉํ์ด์ง์ ์กด์ฌํ์ง ์๊ณ ๋งํฌ๋ก๋ง ๋์ด๊ฐ๊ฒ ํ ๊ฒ์ด๋ฏ๋ก isOnMain ์์ฑ๋ ๋ฐ๋ก ๋ง๋ค์ด์คฌ๋ค.
์คํฌ๋ฆฐ์ด ์ค์ด๋ค๋ฉด ์ด๋ ๊ฒ ํ๋ฒ๊ฑฐ ๋ฉ๋ด ์์ด์ฝ์ด ๋์ค๊ณ , Nav์ ์นดํ ๊ณ ๋ฆฌ๋ค์ Sidebar๋ก ์ด๋ฆฌ๋๋ก ํ๋ค. Grommet์ด ์ ๊ณตํ๋ Utility ์ค์ ResponsiveContext ์ปดํฌ๋ํธ๋ฅผ ์ฌ์ฉํด์ ๊ต์ฅํ ์ฝ๊ณ , ๋ ๊ฐ๋ ์ฑ ์ข๊ฒ ๋ฐ์ํ ๋์์ธ์ ํ ์ ์์๋ค.
์ ์ปดํฌ๋ํธ ๋ฐ๊ฒฌ์ ์ฌ์ค ๋ฆ๊ฒ ํด์ ์ด๊ณณ ์ฝ๋์๋๋ฐ์ค ๋งํฌ ์ฐธ๊ณ ํด ์์ React.js๋ก๋ ๋๋ฆ ๊ฐ๋จํ๊ฒ ์์ฑ ๊ฐ๋ฅํ๋ค.
React.createContext
const viewportContext = React.createContext({});
Context ๊ฐ์ฒด๋ฅผ ๋ง๋๋ createContext๋ผ๋ API๊ฐ ์๋๋ฐ, ์ด ๊ฐ์ฒด์ Provider๋ฅผ ํตํด ํ์ ์ปดํฌ๋ํธ๋ค(๊ณต์ ๋ฌธ์์์๋ ์ด๋ฅผ 'context'๋ฅผ ๊ตฌ๋ ํ๋ ์ปดํฌ๋ํธ๋ผ๊ณ ํํํ๋ค)์ prop์ ์ผ์ผ์ด ์ค๊ฐ ๋งค๊ฐ์๋ค์ ๊ฑฐ์น๋ฉฐ ์ ๋ฌํ๋ ๊ฒ์ด ์๋๋ผ ํธ๋ฆฌ ๊น์ด๊น์ง ๊ณจ๊ณ ๋ฃจ ๋ฟ๋ ค์ฃผ๋ ์ญํ ์ ํ๋ค.
๋๋ถ์ size์ ๋ฐ๋ผ ํน์ ์ปดํฌ๋ํธ๋ค์ ๋ ๋๋ง์ ์กฐ์ํ ์ ์๋ค.
sidebar๋ grommet์ <Sidebar> ์ปดํฌ๋ํธ๋ฅผ ์ฌ์ฉํ๊ณ , ํน์ดํ๊ฒ Sidebar ๋ด๋ถ์์๋ Header, Main, Footer๋ฅผ ๊ตฌ๋ถํด์ ๋ก๊ณ ๋ฅผ ์ํด Header๋ฅผ, navigation category๋ฅผ ์ํด Main์ ์ฌ์ฉํ๋ค. ์์ ์ฑ๋์ ์์ด์ฝ์ ํ๋จ์ ์์นํ ์์ ์ด๋ผ ๋๋๋ footer๋ฅผ ์จ์ฃผ๋ฉด ๋ ๊ฒ ๊ฐ๋ค. Sidebar๋ Header ์๋ฅผ ๋ฎ๊ธฐ ์ํด์ z-index ์์ฑ์ ์ถ๊ฐํด์ฃผ์๋ค.
{size === 'small' && (
<Collapsible
direction='horizontal'
open={this.state.showSidebar}>
<Sidebar
responsive={false}
width='medium'
background='orange'
header={<SidebarHeader />}
pad={{ left: 'small', right: 'medium', vertical: 'small' }}
elevation='small'
style={{
position: 'absolute',
top: '0px',
zIndex: '2'
}}
>
<MainNavigation />
</Sidebar>
</Collapsible>
)}
์คํฌ๋ฆฐ ์ฌ์ด์ฆ๊ฐ small์ผ ๊ฒฝ์ฐ์๋ง ๋ ๋๋ง๋๋๋ก ํ๋ ์ฝ๋. Collapse๋ ๋ ์ ๋๋ฉ์ด์ ์ด ๋ฐ์์ด ๋๋ฆฐ ๊ฒ ๊ฐ์์ ์์ ํ๊ณ ์ถ์๋ฐ, ์ผ๋จ์ ๋์ค์ ์๊ฐํ๊ธฐ๋ก ํ๋ค.
{size === 'small' && (
<Button
icon={<Menu />}
onClick={() => { this.setState({ showSidebar: !this.state.showSidebar})}}
style={{
display: 'block',
position: 'absolute',
top: '15px',
right: '5%',
zIndex: '5'
}}
/>
)}
์๋๋ ๋ฒํผ์๋ง size ์กฐ๊ฑด์ ์คฌ๋๋ฐ, ๋ฉ๋ด ๋ฒํผ์ ํด๋ฆญํ๊ณ ๋ธ๋ผ์ฐ์ ํ๋ฉด์ ์กฐ์ํ ๋ sidebar๊ฐ ์ฌ์ ํ ์ฌ๋ผ์ง์ง ์๊ณ ํผ์ณ์ง ์ํ๊ฐ ๋ผ์ ๋ ์ปดํฌ๋ํธ ๋ชจ๋์ size ์กฐ๊ฑด์ ์คฌ๋ค.
<Button> ์ปดํฌ๋ํธ๋ display๊ฐ inline-block์ด๋ block์ผ๋ก ๋ฐ๊ฟ์คฌ๋ค.
Component์์ useState ์ฐ๊ธฐ
App.js์์ ์ญ ์ญ ์ฝ๋๋ฅผ ์์ฑํ๋ค๊ฐ ๋๋ฌด ๊ธธ์ด์ ธ์ Header.js๋ก ์ปดํฌ๋ํธ๋ฅผ ๋ถ๋ฆฌํด์คฌ๋ค. src ํด๋ ๋ด components ํด๋๋ฅผ ์์ฑํ๊ณ , Header.js ๋ผ๋ ์ด๋ฆ์ผ๋ก ์๋ฐ์คํฌ๋ฆฝํธ ํ์ผ์ ๋ง๋ ๋ค.
import React, { Component } from 'react';
import { Menu } from 'grommet-icons'
import logo from '../logo.svg';
Component ์์ฑ์ ์ํด React ๋ค์์ Component๋ ์์ง ์๊ณ ๊ฐ์ ธ์จ๋ค.
๋ก๊ณ ๋ import ํด์ฃผ๊ณ , grommet์ด ์ ๊ณตํ๋ ์์ด์ฝ์ grommet-icons๋ก ๊ทธ๋ ๊ทธ๋ import ํด์ฃผ์ด์ผ ํ๋ค.
npm install grommet-icons
์์ด์ฝ์ ์ ๋งํฌ์์ ํ์ธํ ์ ์๋ค. ๋๋ ๊ฐ์ด๋์์ ์๋ดํ๋๋ก grommet ํจํค์ง ์ค์นํ ๋ ์๋ ๋ช ๋ น์ด๋ก ํ ๋ฒ์ ์ค์นํด์ฃผ์๋ค.
npm install grommet grommet-icons styled-components --save
๋ฆฌ์กํธ ์ปดํฌ๋ํธ๋ ๋๋ฌธ์๋ก ์์ํ๊ณ , ํด๋์ค๋ ๋ง์ฐฌ๊ฐ์ง๋ค. importํ Componet๋ฅผ ์์๋ฐ์ Header๋ผ๋ ํด๋์ค๋ฅผ ๋ง๋ ๋ค.
class Header extends Component {
constructor() {
super();
this.state = {
showSidebar: false
}
}
render() {
return (
// ..
)
}
}
export default Header;
ํน์ดํ ๊ฑด Class Component ๋ด์์๋ useState(), useEffect() ์ฌ์ฉ์ด ์กฐ๊ธ ๋ฌ๋ผ์ ธ์ ๊ฒ์ํด๋ดค๋๋ ์์ฒ๋ผ ์์ฑ์ ์์์ ์ด๊ธฐํ๋ฅผ ํด์ฃผ๋ ๋ฐฉ์์ ์ฌ์ฉํ๋ค๊ณ ํ๋ค.
Class/Functional Component ์์์ ์ ๋ ํ ์ ์๋ชป ์ฌ์ฉํ๋ฉด ์๋ ๊ฐ์ ์๋ฌ ๋ฉ์ธ์ง๋ฅผ ๋ผ ๊ฒ์ด๋ค.
React Hook "useState" cannot be called in a class component.
React Hooks must be called in a React function component or a custom React Hook functio
๊ทธ๋ฆฌ๊ณ render() ํจ์ ๋ด๋ถ์์๋ ์๋์ฒ๋ผ ์ฌ์ฉํ๋ฉด ๋๋ค.
<Button
icon={<Menu />}
onClick={() => { this.setState({ showSidebar: !this.state.showSidebar})}}
style={{
display: 'block',
position: 'absolute',
top: '15px',
right: '5%',
zIndex: '5'
}}
/>
์์ง useState๋ useEffect๊ฐ ์ด์ํ ๋ด๊ฒ๋ Vue์์ ํ๋ ๊ฒ๊ณผ ์ ์ฌํ ์ ๋ฐฉ์์ด ๋ ํธํ๊ฒ ์ธ ์ ์์๋ค.
Class Component๊ฐ ์๋ Functional Component์์๋ ์๋์ฒ๋ผ ์์ฑํ๋ ๊ฒ ์์น์ด๋ค. constructor()๋ this ํค์๋, render() function์ด ์๊ธฐ ๋๋ฌธ
const [state, setState] = useState({
args: 'initialValue'
})
console.log(state.args); // 'initialValue'
react๋ก๋ถํฐ useState๋ฅผ import ๋ฐ์ ๋ค์์๋ ์์ฒ๋ผ ์ ์ธํด์ฃผ๋ฉด ๋๋๋ฐ, useState๋ ์ด๊ธฐ๊ฐ ํ๋๋ฅผ ์ธ์๋ก ๋ฐ๋๋ค. ์ฌ์ฉํ ๋๋ Class Component์์์ ๋ง์ฐฌ๊ฐ์ง๋ก ์๋์ฒ๋ผ ์ด๋ค.
setState({ args: 'Use Like this' })
์ด๊ณณ ์ํฐํด์์ ๋ช ์พํ๊ฒ ์ค๋ช ์ด ์ ๋์ด ์์ด์ ์ข์ ์ฐธ๊ณ ๊ฐ ๋์๋ค. ๋ค๋ง ์ ์ด๋ ๊ฒ ๊ตฌ๋ถํด์ ์์ฑํ๋์ง์ ๋ํ ๊ทผ๊ฑฐ๋ ๊ณต์ ๋คํ๋จผํธ์์ ํ์ธํ ์ ์์๋ค. ์ต์์ ๋ ๋ฒจ์์๋ง Hook์ ํธ์ถํด ์ค๊ฐ์ Hook๋ค์ด ๊ผฌ์ด๋ ๊ฒ์ ๋ฐฉ์งํ๊ณ , ์ํ๋ค์ ๊น๋ํ๊ฒ ์ ์งํ๊ธฐ ์ํจ์ด์๋ค. ๋๋ create react app์ ํตํด ํ๋ก์ ํธ ์ ์ ์ ํด์ ์ด๋ฐ ๊ท์น์ ๊ฐ์ ํ๋ eslint-plugin-react-books๊ฐ ์ด๋ฏธ ์์๋ค.
์ฒ์ react.js๋ก ์ ๋๋ก ์์ฑํ๋ค๋ณด๋ Vue.js๋ฅผ ๊ฒฝํํ๊ณ ์์ ๊ทธ๋ฐ์ง ๋ฌ๋์ปค๋ธ๊ฐ ๋ฎ์ ๋ง์์ด ํธ์ํด์ง๋ ํจ๊ณผ๋ฅผ ๋๋ฆฌ๊ณ ์๋ค..๐ ์ฒ์ Vue.js ๊ณต๋ถํ ๋๋ Hook์ด ๋ญ๊ณ , ์ํ ๊ด๋ฆฌ๊ฐ ๋ญ๊ณ ๋๋ฌด ์ด๋ ค์ ๋๋ฐ ๋ง์ด๋ค...