[๋ฆฌ์กํธ๋ฅผ ๋ค๋ฃจ๋ ๊ธฐ์ ] 2์ฅ - JSX
์ด ๊ธ์ ๊น๋ฏผ์ค(velopert)๋์ ๋ฆฌ์กํธ๋ฅผ ๋ค๋ฃจ๋ ๊ธฐ์ ์์ฐธ์กฐํ์ฌ ์์ฑํ ๊ธ์ ๋๋ค.
#
ํ๋ก์ ํธ ์์ฑ๊ฐ๋ฐ ํ๊ฒฝ ์ค์ ์ ์ด์์ฒด์ ์ ๋ง๊ฒ ์ ์ค์นํ ์ดํ ์๋์ ์ฝ๋๋ก ๋ฆฌ์กํธ ํ๋ก์ ํธ๋ฅผ์์ฑํ ์ ์๋ค.
yarn create react-app hello-react
# yarn์ ์ฌ์ฉํ์ง ์๋๋ค๋ฉดnpm init react-app hello-react
ํ๋ก์ ํธ๊ฐ ์ฑ๊ณต์ ์ผ๋ก ์์ฑ๋๋ฉด ํ๋ก์ ํธ ๋๋ ํ ๋ฆฌ๋ก ์ด๋ํ ์ดํ ๋ฆฌ์กํธ ์๋ฒ๋ฅผ ๊ตฌ๋ํ ์ ์๋ค.
cd hello-reactyarn start # ๋๋ npm start
ํฐ๋ฏธ๋์ ์ด๋ฌํ ๊ฒฐ๊ณผ๊ฐ ๋์ค๋ฉด ์ฑ๊ณต์ ์ผ๋ก ์๋ฒ๊ฐ ๊ตฌ๋๋ ๊ฒ์ด๋ค.
ํฐ๋ฏธ๋์ ๋์์๋ ๋๋ก ๋ธ๋ผ์ฐ์ ์์ http://localhost:3000์ ์ ์ํ๋ฉด ๋ฆฌ์กํธ ํ์ด์ง๋ฅผ ๋ณผ์์๋ค
๋งฅ์ ๊ฒฝ์ฐ ํฐ๋ฏธ๋์์ ^ + C
๋ก ์๋ฒ๋ฅผ ์ข
๋ฃํ ์ ์๋ค.
#
์ฝ๋ ์ดํดํ๊ธฐsrc/App.js
import React from 'react';import logo from './logo.svg';import './App.css';
function App() { return ( <div className="App"> <header className="App-header"> <img src={logo} className="App-logo" alt="logo" /> <p> Edit <code>src/App.js</code> and save to reload. </p> <a className="App-link" href="https://reactjs.org" target="_blank" rel="noopener noreferrer" > Learn React </a> </header> </div> );}
export default App;
create-react-app์ผ๋ก ํ๋ก์ ํธ๋ฅผ ์์ฑํ ํ src/App.js
๋ฅผ ์ด์ด๋ณด๋ฉด ๋ค์์ ์ฝ๋๊ฐ์์ฑ๋์ด ์๋ค.
import React from 'react';
์ด ์ฝ๋๋ ๋ฆฌ์กํธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๋ถ๋ฌ์์ ์ฌ์ฉํ ์ ์๊ฒ ํด์ฃผ๋ ์ฝ๋์ด๋ค. ๋ฆฌ์กํธ ํ๋ก์ ํธ๋ฅผ ๋ง๋ค๋ฉด node_modules
๋๋ ํ ๋ฆฌ๊ฐ ํจ๊ป ์์ฑ๋๋๋ฐ, ์ด ๋๋ ํ ๋ฆฌ๋ npm(Node Package Manager)์ผ๋ก ์ค์นํ ์ธ๋ถ ํจํค์ง๋ค์ด ์ ์ฅ๋๋ ๊ณณ์ด๋ค. ์ด ๋๋ ํ ๋ฆฌ์ ์๋ ๋ฆฌ์กํธ ๋ชจ๋์ ๊ฐ์ ธ์์ ์ฌ์ฉํ๋ ๊ฒ์ด๋ค.
import logo from './logo.svg';
, import './App.css';
์ด ์ฝ๋๋ฅผ ๋ณด๋ฉด ๋ฆฌ์กํธ๋ฟ๋ง ์๋๋ผ css, svg ๋ํ ๋ชจ๋๋ก ๊ฐ์ ธ์ค๋ ๊ฒ์ ํ์ธํ ์ ์๋ค. ์ด์ฒ๋ผ js, ์คํ์ผ์ํธ, ์ด๋ฏธ์ง ๋ฑ ๋ชจ๋ ๊ฒ์ ๋ชจ๋๋ก ๋ก๋ฉํด์ ์ฌ์ฉํ๋๋ก ํ ์ ์๋ค. ์ด๋ ๊ฒ ๋ชจ๋ ์์คํ
์ ์ฌ์ฉํ๋ฉด, ํ์ผ ๋จ์๋ก ๊ด๋ฆฌํ ์ ์์ด์ ํ๋ก์ ํธ์ ๊ท๋ชจ๊ฐ ์ปค์ง ๋ ๊ด๋ฆฌํ๊ธฐ์ฉ์ดํด์ง๋ค.
๊ทธ๋ฐ๋ฐ ์ด๋ ๊ฒ ๋ชจ๋์ ๋ถ๋ฌ์ ์ฌ์ฉํ๋ ๊ฒ์ ์๋ ๋ธ๋ผ์ฐ์ ์๋ ์๋ ๊ธฐ๋ฅ์ด๊ณ , Node.js์์ ์ง์ํ๋ ๊ธฐ๋ฅ์ด๋ค. ์ด๋ฌํ ๊ธฐ๋ฅ์ ๋ธ๋ผ์ฐ์ ์์ ์ฌ์ฉํ๊ธฐ ์ํด ๋ฒ๋ค๋ฌ (bundler)๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด๋ค. ๋ฆฌ์กํธ์์ ์ฃผ๋ก ์ฌ์ฉํ๋ ๋ฒ๋ค๋ฌ๊ฐ ๋ฐ๋ก ์นํฉ (Webpack)์ด๋ค. ์ด ๋ฒ๋ค๋ฌ ๋๊ตฌ๋ฅผ ์ฌ์ฉํ๋ฉด ๋ถ๋ฌ์จ ์ฌ๋ฌ ๊ฐ์ ๋ชจ๋์ ๋ชจ๋ ํฉ์ณ์ ํ๋์ ํ์ผ์ ์์ฑํ ์ ์๊ธฐ ๋๋ฌธ์ ๋ชจ๋ ๋ธ๋ผ์ฐ์ ์์ ์ฌ์ฉํ ์ ์๋ค.
์๋ ์นํฉ์ ์ฌ์ฉํ๊ธฐ ์ํด์ ์ง์ ์ค์นํ๊ณ ์ค์ ํ๋ ๊ณผ์ ์ ๊ฑฐ์ณ์ผ ํ์ง๋ง create-react-app์ ์ด ๋ฒ๊ฑฐ๋ก์ด ์์ ์ ๋ชจ๋ ๋์ ํด์ฃผ๊ธฐ ๋๋ฌธ์ ํธ๋ฆฌํ๋ค. (ํ์ง๋ง์ง์ ์ค์นํ๊ณ ์ค์ ํ๋ ๊ณผ์ ์ ๊ฒฝํํด๋ณผ ํ์๊ฐ ์๋ค.)
์ด ์นํฉ์ ์์ธํ ์๋ฆฌ์ ์๋ ๋ฐฉ๋ฒ์ ์๋์ ๊ฐ์ด ์ฝ๊ธฐ๋ฅผ ์ฝ์ด๋ณด์.
๊ทธ ๋ค์ ์ฝ๋๋ฅผ ๋ณด์.
function App() { return ( <div className="App"> <header className="App-header"> <img src={logo} className="App-logo" alt="logo" /> <p> Edit <code>src/App.js</code> and save to reload. </p> <a className="App-link" href="https://reactjs.org" target="_blank" rel="noopener noreferrer" > Learn React </a> </header> </div> );}
์ด ์ฝ๋๋ App์ด๋ผ๋ ์ปดํฌ๋ํธ๋ฅผ ๋ง๋๋๋ฐ, function
ํค์๋๋ฅผ ์ฌ์ฉํ์ฌ ๋ง๋ค๊ณ ์๋ค. ์ด๋ฅผ ํจ์ํ ์ปดํฌ๋ํธ๋ผ๊ณ ํ๋ค. ํ๋ก์ ํธ์์ ์ปดํฌ๋ํธ๋ฅผ ๋ ๋๋งํ๋ฉด ํจ์์์๋ฐํํ๊ณ ์๋ ๋ด์ฉ์ ๋ํ๋ธ๋ค. ๋ฐํํ๋ ๋ด์ฉ์ ๋ง์น HTML ์ฝ๋์ฒ๋ผ ๋ณด์ธ๋ค. ํ์ง๋ง์ด๋ JSX๋ผ๋ ๋ฌธ๋ฒ์ด๋ค. UI๊ฐ ์ด๋ป๊ฒ ๋ณด์ฌ์ผ ํ๋์ง ์ ์ํ๋ ์ฝ๋ ์กฐ๊ฐ์ด๋ผ๊ณ ํ ์์๋ค.
#
JSX๋?JSX๋ JavaScript XML์ ์ฝ์๋ก ์๋ฐ์คํฌ๋ฆฝํธ์ ํ์ฅ ๋ฌธ๋ฒ์ด๋ฉฐ XML๊ณผ ๋งค์ฐ ๋น์ทํ๊ฒ์๊ฒผ๋ค. JSX ์ฝ๋๋ ๋ธ๋ผ์ฐ์ ์์ ์คํ๋๊ธฐ ์ ์ ๋ฐ๋ฒจ(Babel)์ ์ฌ์ฉํ์ฌ ์ผ๋ฐ ์๋ฐ์คํฌ๋ฆฝํธ ํํ์ ์ฝ๋๋ก ๋ณํ๋๋ค.
function App() { return ( <div> Hello <b>react</b> </div> );}
์์ ์ฝ๋๋ ์๋์ ๊ฐ์ด ๋ณํ๋๋ค.
function App() { return React.createElement( 'div', null, 'Hello ', React.createElement('b', null, 'react'), );}
์๋์ฒ๋ผ ์์ฑํ๋ ๊ฒ์ ๋งค์ฐ ๋ถํธํ ์ผ์ด๋ค. JSX๋ฅผ ์ฌ์ฉํ๋ฉด ๋งค์ฐ ํธํ๊ฒ UI๋ฅผ ๋ ๋๋งํ ์ ์๋ค.
JSX๋ ๊ณต์์ ์๋ฐ์คํฌ๋ฆฝํธ ๋ฌธ๋ฒ์ด ์๋๋ค.
#
JSX์ ์ฅ์ #
๋ณด๊ธฐ ์ฝ๊ณ ์ต์ํ๋ค.JSX๋ HTML ์ฝ๋์ ๋น์ทํด ๊ฐ๋ ์ฑ์ด ๋๊ณ ์์ฑํ๊ธฐ๋ ์ฝ๋ค.
#
๋์ ํ์ฉ๋HTML ํ๊ทธ ๋ฟ๋ง ์๋๋ผ ๋ฆฌ์กํธ ์ปดํฌ๋ํธ๋ฅผ JSX ์์์ ์์ฑํ ์ ์๋ค. App.js
์์๋ง๋ App ์ปดํฌ๋ํธ๋ฅผ src/index.js
์์๋ ๋ง์น HTML ํ๊ทธ ์ฐ๋ฏ์ด ์์ฑํ๋ค.
ReactDOM.render(<App />, document.getElementById('root'));
index.js
์ ์ด ์ฝ๋๋ App ์ปดํฌ๋ํธ๋ฅผpublic/index.html
ํ์ผ์ ์์ฑ๋id="root"
์ธ ์์ ์์ ๋ ๋๋งํ๋ ์ญํ ์ ํ๋ค.
#
JSX ๋ฌธ๋ฒJSX๋ HTML๊ณผ ์ ์ฌํ ํธ๋ฆฌํ ๋ฌธ๋ฒ์ด์ง๋ง ๋ช๊ฐ์ง ๊ท์น์ ์ง์ผ์ผ ํ๋ค.
#
๊ฐ์ธ์ธ ์์์ปดํฌ๋ํธ์ ์ฌ๋ฌ ์์๊ฐ ์๋ค๋ฉด ๋ฐ๋์ ๋ถ๋ชจ ์์ ํ๋๋ก ๊ฐ์ธ์ผ ํ๋ค. ์๋์ ์ฝ๋๋์๋ํ์ง ์๋๋ค.
src/App.js
import React from 'react';
function App() { return ( <h1>Hello World!</h1> <h2>Hello React!</h2> );}
export default App;
Virtual DOM์์ ์ปดํฌ๋ํธ ๋ณํ๋ฅผ ๊ฐ์งํ ๋ ํจ์จ์ ์ผ๋ก ๋น๊ตํ๊ธฐ ์ํด ์ปดํฌ๋ํธ ๋ด๋ถ๋ ํ๋์ DOM ํธ๋ฆฌ ๊ตฌ์กฐ๋ก ์ด๋ฃจ์ด์ ธ์ผ ํ๋ค๋ ๊ท์น์ด ์๊ธฐ ๋๋ฌธ์ด๋ค. ์๋์ฒ๋ผ <div>
์์๋ก ๊ฐ์ธ๋ ๊ฒ์ผ๋ก ํด๊ฒฐํ ์ ์๋ค.
src/App.js
import React from 'react';
function App() { return ( <div> <h1>Hello World!</h1> <h2>Hello React!</h2> </div> );}
export default App;
ํ์ง๋ง ์ด๋ ๊ฒ ํ์ ๋ ๋ถํ์ํ๊ฒ ์์์ <div>
์์๊ฐ ์ถ๊ฐ๋๋ค.
์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ๋ฆฌ์กํธ์ Fragment ๊ธฐ๋ฅ์ ์ฌ์ฉํ ์ ์๋ค.
src/App.js
import React, {Fragment} from 'react';
function App() { return ( <Fragment> <h1>Hello World!</h1> <h2>Hello React!</h2> </Fragment> );}
export default App;
Fragment๋ฅผ ์ด๋ ๊ฒ๋ ํํํ ์ ์๋ค.
src/App.js
import React from 'react';
function App() { return ( <> <h1>Hello World!</h1> <h2>Hello React!</h2> </> );}
export default App;
์ด๋ ๊ฒ ๋ถํ์ํ <div>
์์ ์ถ๊ฐ๋ฅผ ๋ง์ ์ ์๋ค.
#
์๋ฐ์คํฌ๋ฆฝํธ ํํJSX ์์์๋ JS ํํ์์ ์ธ ์ ์๋ค. JSX ๋ด๋ถ์ ์ฝ๋๋ฅผ {}
๋ก ๊ฐ์ธ๋ฉด ๋๋ค.
src/App.js
import React from 'react';
function App() { const name = 'React'; return ( <> <h1>Hello World!</h1> <h2>Hello {name}!</h2> </> );}
export default App;
#
์กฐ๊ฑด๋ถ ์ฐ์ฐ์(์ผํญ ์ฐ์ฐ์)JSX ๋ฐ์์ if ๋ฌธ์ ์ฌ์ฉํ ์ ์์ง๋ง, JSX ๋ด๋ถ์์๋ ์กฐ๊ฑด๋ถ ์ฐ์ฐ์ ์ฆ ์ผํญ ์ฐ์ฐ์๋ฅผ ์ฌ์ฉํด์ผ ํ๋ค.
์ผํญ ์ฐ์ฐ์ : condition ? exprIfTrue : exprIfFalse
src/App.js
import React from 'react';
function App() { const name = 'React'; return ( <div> {name === 'React' ? <h1>Hello React!</h1> : <h1>Who are you?</h1>} </div> );}
export default App;
#
AND ์ฐ์ฐ์(&&)ํน์ ์กฐ๊ฑด์ ๋ง์กฑํ ๋ ๋ด์ฉ์ ๋ณด์ฌ์ฃผ๊ณ ๊ทธ๋ ์ง ์์ ๋ ์๋ฌด๊ฒ๋ ๋ ๋๋งํ์ง ์์์ผํ๋ ์ํฉ.
src/App.js
import React from 'react';
function App() { const name = 'Reaaaact'; return <div>{name === 'React' ? <h1>Hello React!</h1> : null}</div>;}
export default App;
์ด์ฒ๋ผ ์กฐ๊ฑด์ด false๋ผ๋ฉด null์ ๋ ๋๋งํ๊ฒ ํ๋ฏ๋ก ์กฐ๊ฑด๋ถ ๋ ๋๋ง์ ํ ์ ์๋๋ฐ, &&๋ฅผ ์ฌ์ฉํ๋ฉด ๋ ์งง์ ์ฝ๋๊ฐ ๊ฐ๋ฅํ๋ค.
<div> {name === 'React' ? <h1>Hello React!</h1>}</div>
๋ฆฌ์กํธ์์ false๋ฅผ ๋ ๋๋งํ ๋๋ null๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก ์๋ฌด๊ฒ๋ ๋ํ๋์ง ์๊ธฐ ๋๋ฌธ์ด๋ค.
์ฃผ์ํ ์ ์ falsyํ ๊ฐ์ธ 0์ ์์ธ์ ์ผ๋ก ํ๋ฉด์ ๋ํ๋๋ค๋ ๊ฒ์ด๋ค.
const number = 0;return number && <div>๋ด์ฉ</div>;
์ด ์ฝ๋๋ ํ๋ฉด์ ์ซ์ 0์ด ๋ ๋๋ง๋๋ค.
#
undefined๋ฅผ ๋ ๋๋งํ์ง ์๊ธฐ๋ฆฌ์กํธ ์ปดํฌ๋ํธ์์๋ ํจ์์์ undefined๋ง ๋ฐํํ์ฌ ๋ ๋๋งํ๋ ์ํฉ์ ๋ง๋ค๋ฉด ์๋๋ค.
src/App.js
import React from 'react';import './App.css';
function App() { const name = undefined; return name;}
export default App;
์ด ์ฝ๋๋ ์๋ฌ๊ฐ ๋ฐ์ํ๋ค.
์ด๋ค ๊ฐ์ด undefined์ผ ์ ์๋ ์ํฉ์ OR(||) ์ฐ์ฐ์๋ฅผ ์ฌ์ฉํด ๋ง์ ์ ์๋ค.
return name || '๊ฐ์ด undefined์
๋๋ค.';
JSX ๋ด๋ถ์์ undefined๋ฅผ ๋ ๋๋ง ํ๋ ๊ฒ์ ๊ด์ฐฎ๋ค.
return <div>{name}</div>;
#
์ธ๋ผ์ธ ์คํ์ผ๋ง๋ฆฌ์กํธ์์ DOM ์์์ ์คํ์ผ์ ์ ์ฉํ ๋๋ ๋ฌธ์์ด ํํ๊ฐ ์๋๋ผ ๊ฐ์ฒด ํํ๋ก ๋ฃ์ด์ฃผ์ด์ผ ํ๋ค. ๋ํ ์คํ์ผ ์ด๋ฆ์ ์นด๋ฉ ํ๊ธฐ๋ฒ(camelCase)๋ก ์์ฑํด์ผ ํ๋ค. (background-color๋ backgroundColor๋ก)
#
class ๋์ classNameHTML์์ ์ฌ์ฉํ๋ class ์์ฑ ๋์ JSX์์๋ className์ผ๋ก ์ฌ์ฉํ๋ค. JSX์์ class๋ก ์์ฑํด๋ ์ ์ฉ๋๊ธฐ๋ ํ์ง๋ง console ์ฐฝ์ ๊ฒฝ๊ณ ๊ฐ ๋ํ๋๋ค.
#
๊ผญ ๋ซ์์ผ ํ๋ ํ๊ทธHTML ์ฝ๋์์๋ ๊ฐ๋ ํ๊ทธ๋ฅผ ๋ซ์ง ์์ ์ํ๋ก ์์ฑํ๊ธฐ๋ ํ๋๋ฐ, JSX์์๋ ํ๊ทธ๋ฅผ๋ซ์ง ์์ผ๋ฉด ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ค. ํ๊ทธ ์ฌ์ด์ ๋ณ๋์ ๋ด์ฉ์ด ์๋ค๋ฉด self-closing ํ๊ทธ๋ก ์์ฑํ ์ ์๋ค.
#
์ฃผ์JSX ๋ด๋ถ ์ฃผ์์ {/* ... */}
๋ก ์์ฑํ๋ค. ํ๊ทธ ๋ด๋ถ์์๋ // ...
์ ํํ๋ ๊ฐ๋ฅํ๋ค.
#
ESLint์ Prettier#
ESLintESLint๋ ๋ฌธ๋ฒ ๊ฒ์ฌ ๋๊ตฌ๋ก, ์ฝ๋ ์์ฑ์ ์ค๋ฅ๊ฐ ์์ ๋ ์๋ฌ ํน์ ๊ฒฝ๊ณ ๋ฉ์์ง๋ฅผ VS Code์์ ๋ฐ๋ก ํ์ธํ ์ ์๋ค.
#
PrettierPrettier๋ฅผ ์ฌ์ฉํ๋ฉด ์ฝ๋๋ฅผ ์๋ ์ ๋ฆฌ ํ ์ ์๋ค. ํนํ ์คํ์ผ์ ์ปค์คํฐ๋ง์ด์งํ ์์๋ ์ฅ์ ์ด ์๋ค. ๋ฃจํธ ๋๋ ํฐ๋ฆฌ์ .prettierrc
๋ผ๋ ํ์ผ์ ์์ฑํ๊ณ ๋ค์์ฒ๋ผ ์
๋ ฅํ๋ค.
.prettierrc
{ "singleQuote": true, "semi": true, "useTabs": false, "tabWidth": 2}
์ค์ ์ด ์ดํดํ๊ธฐ ์ฝ๊ฒ ๋์ด์๋ค. ์์๋๋ก ์์ ๋ฐ์ดํ, ์ธ๋ฏธ์ฝ๋ก , ํญ ์ฌ์ฉ, ํญ ๊ธธ์ด์ ๋ํ ์ค์ ์ด๋ค.
๋ํ VS Code ์ค์ ์์ Format On Save ๊ธฐ๋ฅ์ ํ์ฑํํ๋ฉด ์ ์ฅ์ ํธ๋ฆฌ๊ฑฐ๋ก ์ฝ๋๊ฐ ์๋ ์ ๋ฆฌ๋๋ค.
#
๊ฐ์ด ์ฝ๊ธฐReact ๊ฐ๋ฐ ํ๊ฒฝ์ ๊ตฌ์ถํ๋ฉด์ ๋ฐฐ์ฐ๋ ์นํฉ(Webpack) ๊ธฐ์ด
SPA(single page app)์์ webpack์ ์ฌ์ฉํ๋ ์ด์
Webpack ๊ฐ์ ๋ชจ๋ ๋ฒ๋ค๋ฌ๋ฅผ ๋ง๋ค์ด ๋ณด์ - LINE ENGINEERING