๐Ÿ‘ฉ‍๐Ÿ’ป/React

[React.js๋กœ ๋งŒ๋“œ๋Š” Tech Blog] #1 Figma ํ”„๋กœํ† ํƒ€์ดํ•‘/๊ฐœ๋ฐœํ™˜๊ฒฝ ์„ธํŒ…/Grommet UI Library/useState/Responsive Header ๋งŒ๋“ค๊ธฐ

ํ•œ๋‚˜ 2021. 2. 9. 03:44

ํ…Œํฌ ๋ธ”๋กœ๊ทธ ๊ธฐํš

๊ธฐ์กด์— GIthub Pages๋กœ ๋ฐฐํฌํ•œ github.io ๋ธ”๋กœ๊ทธ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๊ธด ํ–ˆ์ง€๋งŒ, ๊ธ‰ํ•  ๋•Œ ํ…œํ”Œ๋ฆฟ ๊ฐ€์ง€๊ณ  ์™€์„œ ๊ณ ์ณ ์“ด ๊ฒŒ ๋‹ค๋ผ ๋ ˆ์ด์•„์›ƒ์— ์ œ์•ฝ์ด ์ปค ์•„์˜ˆ ์ƒˆ๋กœ ์ œ์ž‘ํ•˜๊ธฐ๋กœ ํ–ˆ๋‹ค. ์ œ์ž‘ํ•˜๋ฉฐ ์—ฌํƒœ ์•ˆ ์จ๋ดค์ง€๋งŒ, ์จ๋ด์•ผ ํ•  ๊ฒƒ ๊ฐ™์€ ๊ธฐ์ˆ ๋“ค์„ ๋ชฝ๋•… ์ฒดํ—˜ํ•ด๋ณด๋Š” ๊ฒƒ์ด ๋ชฉํ‘œ.

์ƒˆ๋กœ์šด ํ…Œํฌ ๋ธ”๋กœ๊ทธ์—๋Š” ํฌํŠธํด๋ฆฌ์˜ค์™€ Reusme ๊ทธ๋ฆฌ๊ณ  Blog ๊ธฐ๋Šฅ๊นŒ์ง€ ๋„ฃ์„ ๊ฑฐ๋ผ ๋””์ž์ธ์€ ์ตœ๋Œ€ํ•œ ์‹ฌํ”Œํ•˜๊ฒŒ ํ•˜๊ธฐ๋กœ ํ–ˆ๋‹ค.

 

๊ณ„์† ๋‘๊ณ  ๋‘๊ณ  ์“ฐ๊ฒŒ ๋  ์›น ์‚ฌ์ดํŠธ์ด๋‹ˆ ๊ณ„ํš๊ณผ ํ”„๋กœํ† ํƒ€์ดํ•‘์—๋„ ์‹ ๊ฒฝ์„ ์ผ๊ณ , ์–ด๋–ค ๊ธฐ๋Šฅ์„ ์ตœ์†Œํ•œ์œผ๋กœ ๊ฐ–์ถœ์ง€, ์–ด๋–ค ๋ถ€๋ถ„์€ ์•ž์œผ๋กœ ์ถ”๊ฐ€ํ•ด์„œ ์จ๋„ ๊ดœ์ฐฎ์„์ง€ ๋“ฑ์„ ๊ผผ๊ผผํžˆ ์ƒ๊ฐํ•˜๋ฉฐ ๋””์ž์ธํ–ˆ๋‹ค.

 

Figma Prototyping

 

 

Figma๋กœ ๋””์ž์ธํ•œ ํ”„๋กœํ† ํƒ€์ž… ์ผ๋ถ€

 

์–ด์จŒ๊ฑฐ๋‚˜ Resume ์—ญํ• ์„ ํ•˜๊ฒŒ ๋  ๋ธ”๋กœ๊ทธ์ด๋‹ˆ ๋ชจ๋ฐ”์ผ๋กœ ๋ณผ ์ผ์ด ๋” ๋งŽ๊ฒ ๋‹ค ์‹ถ์–ด ๋ชจ๋ฐ”์ผ ์Šคํฌ๋ฆฐ ์‚ฌ์ด์ฆˆ์— ๋งž์ถฐ ๋จผ์ € ๋””์ž์ธ์„ ํ–ˆ๋‹ค.

 

Figma prototyping ์ผ๋ถ€

๋ฐ์Šคํฌํƒ‘ ํ™”๋ฉด์—์„œ๋Š” ์ด๋Ÿฐ ๋Š๋‚Œ์œผ๋กœ ๋งŒ๋“ค์—ˆ๋‹ค.

 

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 ํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค.

 

icons.grommet.io//

 

Grommet Icons

 

icons.grommet.io

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์ด ๋ญ๊ณ , ์ƒํƒœ ๊ด€๋ฆฌ๊ฐ€ ๋ญ๊ณ  ๋„ˆ๋ฌด ์–ด๋ ค์› ๋Š”๋ฐ ๋ง์ด๋‹ค...