안경잡이개발자

728x90
반응형

  이번 시간에는 안정적인 UI/UX를 위해 AppBar을 적용하는 시간을 가져보도록 하겠습니다. AppBar는 검색 바, 내비게이션 바 등의 목적으로 사용됩니다. 따라서 가장 먼저 client 폴더로 이동해서 다음과 같은 명령어를 입력해서 icons 라이브러리를 받으면 됩니다.


  ▶ Material UI icons 다운로드 명령어: npm i @material-ui/icons


  이제 코딩을 진행해보도록 하겠습니다. 우리가 적용할 AppBar는 React.js의 Material UI 공식 사이트에서 제공하고 있는 기본 예제입니다. 말 그대로 기본 예제라는 점에서 한글 웹 폰트(Web Font) 등은 적용되어 있지 않습니다. 따라서 우리가 직접 웹 폰트 등을 적용해야 합니다.


  ▶ Material UI AppBar 예제: https://material-ui.com/demos/app-bar/


  우리는 아래에 보이는 App Bar with search field 예제를 넣어보도록 하겠습니다.



※ AppBar 적용하기 ※


▶ App.js


import React, { Component } from 'react';
import Customer from './components/Customer'
import './App.css';
import Paper from '@material-ui/core/Paper';
import Table from '@material-ui/core/Table';
import TableHead from '@material-ui/core/TableHead';
import TableBody from '@material-ui/core/TableBody';
import TableRow from '@material-ui/core/TableRow';
import TableCell from '@material-ui/core/TableCell';
import CircularProgress from '@material-ui/core/CircularProgress';
import { withStyles } from '@material-ui/core/styles';
import CustomerAdd from './components/CustomerAdd';
import MenuIcon from '@material-ui/icons/Menu';
import SearchIcon from '@material-ui/icons/Search';
import InputBase from '@material-ui/core/InputBase';
import { fade } from '@material-ui/core/styles/colorManipulator';
import Typography from '@material-ui/core/Typography';
import AppBar from '@material-ui/core/AppBar';
import Toolbar from '@material-ui/core/Toolbar';
import IconButton from '@material-ui/core/IconButton';

const styles = theme => ({
root: {
width: "100%",
minWidth: 1080
},
menu: {
marginTop: 15,
marginBottom: 15,
display: 'flex',
justifyContent: 'center'
},
paper: {
marginLeft: 18,
marginRight: 18
},
progress: {
margin: theme.spacing.unit * 2
},
grow: {
flexGrow: 1,
},
tableHead: {
fontSize: '1.0rem'
},
menuButton: {
marginLeft: -12,
marginRight: 20,
},
title: {
display: 'none',
[theme.breakpoints.up('sm')]: {
display: 'block',
},
},
search: {
position: 'relative',
borderRadius: theme.shape.borderRadius,
backgroundColor: fade(theme.palette.common.white, 0.15),
'&:hover': {
backgroundColor: fade(theme.palette.common.white, 0.25),
},
marginLeft: 0,
width: '100%',
[theme.breakpoints.up('sm')]: {
marginLeft: theme.spacing.unit,
width: 'auto',
},
},
searchIcon: {
width: theme.spacing.unit * 9,
height: '100%',
position: 'absolute',
pointerEvents: 'none',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
},
inputRoot: {
color: 'inherit',
width: '100%',
},
inputInput: {
paddingTop: theme.spacing.unit,
paddingRight: theme.spacing.unit,
paddingBottom: theme.spacing.unit,
paddingLeft: theme.spacing.unit * 10,
transition: theme.transitions.create('width'),
width: '100%',
[theme.breakpoints.up('sm')]: {
width: 120,
'&:focus': {
width: 200,
},
},
}
});

class App extends Component {

constructor(props) {
super(props);
this.state = {
customers: '',
completed: 0
}
this.stateRefresh = this.stateRefresh.bind(this);
}

stateRefresh() {
this.setState({
customers: '',
completed: 0
});
this.callApi()
.then(res => this.setState({customers: res}))
.catch(err => console.log(err));
}

componentDidMount() {
this.timer = setInterval(this.progress, 20);
this.callApi()
.then(res => this.setState({customers: res}))
.catch(err => console.log(err));
}

componentWillUnmount() {
clearInterval(this.timer);
}

callApi = async () => {
const response = await fetch('/api/customers');
const body = await response.json();
return body;
}

progress = () => {
const { completed } = this.state;
this.setState({ completed: completed >= 100 ? 0 : completed + 1 });
};

render() {
const { classes } = this.props;
const cellList = ["번호", "프로필 이미지", "이름", "생년월일", "성별", "직업", "설정"]
return (
<div className={classes.root}>
<AppBar position="static">
<Toolbar>
<IconButton className={classes.menuButton} color="inherit" aria-label="Open drawer">
<MenuIcon />
</IconButton>
<Typography className={classes.title} variant="h6" color="inherit" noWrap>
고객 관리 시스템
</Typography>
<div className={classes.grow} />
<div className={classes.search}>
<div className={classes.searchIcon}>
<SearchIcon />
</div>
<InputBase
placeholder="검색하기"
classes={{
root: classes.inputRoot,
input: classes.inputInput,
}}
/>
</div>
</Toolbar>
</AppBar>
<div className={classes.menu}>
<CustomerAdd stateRefresh={this.stateRefresh} />
</div>
<Paper className={classes.paper}>
<Table>
<TableHead>
<TableRow>
{cellList.map(c => {
return <TableCell className={classes.tableHead}>{c}</TableCell>
})}
</TableRow>
</TableHead>
<TableBody>
{this.state.customers ?
this.state.customers.map(c => {
return <Customer stateRefresh={this.stateRefresh} key={c.id} id={c.id} image={c.image} name={c.name} birthday={c.birthday} gender={c.gender} job={c.job} />
}) :
<TableRow>
<TableCell colSpan="6" align="center">
<CircularProgress className={classes.progress} variant="determinate" value={this.state.completed} />
</TableCell>
</TableRow>
}
</TableBody>
</Table>
</Paper>
</div>
);
}
}

export default withStyles(styles)(App);


▶ index.css


  index.css에서는 Note Sans KR 글씨체를 웹 폰트 형태로 불러오게 됩니다.


@import url(http://fonts.googleapis.com/earlyaccess/notosanskr.css);

body {
margin: 0;
padding: 0;
font-family: "Noto Sans KR", -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
"Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}

code {
font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
monospace;
}


▶ index.js


  이제 index.js에서는 Material UI의 테마 폰트로 "Note Sans KR"을 적용주면 됩니다. 이렇게 해주지 않으면 곳곳에 사용된 Material UI에 전체적인 폰트 적용이 안 될 수도 있습니다.


import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
import { MuiThemeProvider, createMuiTheme } from '@material-ui/core/styles';

const theme = createMuiTheme({
typography: {
fontFamily: '"Noto Sans KR", serif',
},
});

ReactDOM.render(<MuiThemeProvider theme={theme}><App /></MuiThemeProvider>, document.getElementById('root'));

serviceWorker.unregister();


※ 실행 결과 ※


  결과적으로 다음과 같이 전체적인 UI가 Material한 형태로 업데이트 되었습니다.



728x90
반응형

728x90
반응형

  React에서 Form을 처리하기 위해서는 이벤트 처리(Event Handling)를 수행해야 합니다. 이번 시간에는 그러한 이벤트 처리 방법에 대해서 이해하고, 결과적으로 서버로 고객 데이터를 전송하여 데이터베이스에 신규 고객 정보를 등록하는 방법까지 알아보도록 하겠습니다. 따라서 가장 먼저 React 클라이언트의 components 폴더에 CustomerAdd.js를 만들어 보도록 하겠습니다.



  이제 디자인을 입히지 않은 상태로 하나의 <form> 태그를 작업하는 시간을 가져보도록 하겠습니다. 이를 위해 가장 먼저 서버와의 통신 목적의 라이브러리인 axios를 설치해주도록 하겠습니다. client 폴더로 이동하여 npm install --save axios 명령어를 입력하시면 됩니다. 이제 CustomerAdd.js 컴포넌트를 작업해 줍니다.


▶ CustomerAdd.js


import React from 'react'

import { post } from 'axios';


class CustomerAdd extends React.Component {


constructor(props) {

super(props);

this.state = {

file: null,

userName: '',

birthday: '',

gender: '',

job: '',

fileName: ''

}

this.handleFormSubmit = this.handleFormSubmit.bind(this)

this.handleFileChange = this.handleFileChange.bind(this)

this.handleValueChange = this.handleValueChange.bind(this)

this.addCustomer = this.addCustomer.bind(this)

}


handleFormSubmit(e) {

e.preventDefault()

this.addCustomer()

.then((response) => {

console.log(response.data);

})

}


handleFileChange(e) {

this.setState({

file: e.target.files[0],

fileName: e.target.value

});

}

handleValueChange(e) {

let nextState = {};

nextState[e.target.name] = e.target.value;

this.setState(nextState);

}


addCustomer(){

const url = '/api/customers';

const formData = new FormData();

formData.append('image', this.state.file)

formData.append('name', this.state.userName)

formData.append('birthday', this.state.birthday)

formData.append('gender', this.state.gender)

formData.append('job', this.state.job)

const config = {

headers: {

'content-type': 'multipart/form-data'

}

}

return post(url, formData, config)

}


render() {

return (

<form onSubmit={this.handleFormSubmit}>

<h1>고객 추가</h1>

프로필 이미지: <input type="file" name="file" file={this.state.file} value={this.state.fileName} onChange={this.handleFileChange} /><br/>

이름: <input type="text" name="userName" value={this.state.userName} onChange={this.handleValueChange} /><br/>

생년월일: <input type="text" name="birthday" value={this.state.birthday} onChange={this.handleValueChange} /><br/>

성별: <input type="text" name="gender" value={this.state.gender} onChange={this.handleValueChange} /><br/>

직업: <input type="text" name="job" value={this.state.job} onChange={this.handleValueChange} /><br/>

<button type="submit">추가하기</button>

</form>

)

}

}


export default CustomerAdd


▶ App.js


  이제 작업한 CustomerAdd 컴포넌트를 화면에 출력해 보도록 하겠습니다. 따라서 App.js를 수정해 봅시다.


import CustomerAdd from './components/CustomerAdd';


  위와 같이 CustomerAdd 컴포넌트를 추가해주신 이후에 다음과 같이 렌더링 되는 부분을 수정합니다.


<div>

<Paper className={classes.root}>

<Table className={classes.table}>

<TableHead>

<TableRow>

<TableCell>번호</TableCell>

<TableCell>이미지</TableCell>

<TableCell>이름</TableCell>

<TableCell>생년월일</TableCell>

<TableCell>성별</TableCell>

<TableCell>직업</TableCell>

</TableRow>

</TableHead>

<TableBody>

{this.state.customers ?

this.state.customers.map(c => {

return <Customer key={c.id} id={c.id} image={c.image} name={c.name} birthday={c.birthday} gender={c.gender} job={c.job} />

}) :

<TableRow>

<TableCell colSpan="6" align="center">

<CircularProgress className={classes.progress} variant="determinate" value={this.state.completed} />

</TableCell>

</TableRow>

}

</TableBody>

</Table>

</Paper>

<CustomerAdd/>

</div>


  실제로 이를 브라우저의 개발자 도구에서 테스트를 해보시면 서버로 데이터를 전송하는 것을 알 수 있습니다.



  아래쪽에 고객 추가 양식이 존재하며 여기에 데이터를 입력하여 실제로 고객을 추가할 수 있습니다.



  데이터를 입력해 [추가하기] 버튼을 누른 결과 다음과 같이 서버로 데이터가 전송되는 것을 알 수 있습니다. 실제로 이미지 파일은 바이너리 코드 형태로 서버로 전달됩니다. 따라서 다음 시간에 이러한 사용자의 요청 데이터를 적절히 처리하여 데이터베이스에 등록한 뒤에 그에 맞는 응답을 보내주는 작업을 수행해야 하빈다.





728x90
반응형

728x90
반응형

  지난 시간에는 AWS RDS 서비스를 이용해서 우리 고객 관리 시스템 프로젝트의 데이터베이스를 구축하는 시간을 가졌습니다. 이번 시간에는 실제로 우리가 지난 시간에 만든 MySQL 데이터베이스에 고객(Customer) 테이블을 구축한 뒤에 데이터를 삽입하는 시간을 가져보도록 하겠습니다.


※ 데이터베이스 테이블 구축하기 ※


  데이터베이스 이름을 management로 설정했으므로 여기에 들어가서 고객 테이블을 구축하여 데이터를 넣도록 소스를 작성해보겠습니다.


USE management;


CREATE TABLE CUSTOMER (

id INT PRIMARY KEY AUTO_INCREMENT,

image VARCHAR(1024),

name VARCHAR(64),

birthday VARCHAR(64),

gender VARCHAR(64),

job VARCHAR(64)

) DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;


INSERT INTO CUSTOMER VALUES (1, 'https://placeimg.com/64/64/1', '홍길동', '960508', '남자', '대학생');

INSERT INTO CUSTOMER VALUES (2, 'https://placeimg.com/64/64/2', '나동빈', '961222', '남자', '프로그래머');

INSERT INTO CUSTOMER VALUES (3, 'https://placeimg.com/64/64/3', '이순신', '961127', '남자', '디자이너');


SELECT * FROM CUSTOMER;



※ .gitignore ※


  이제 데이터베이스와 연동하는 작업을 처리하도록 하겠습니다. 기본적으로 데이터베이스 관련 정보는 Git Ignore 처리를 해서 깃 허브(Git Hub)에 올라가지 않도록 처리해야 합니다. 따라서 서버 프로그램의 .gitignore 파일을 다음과 같이 수정합니다.


# database

/database.json


  이후에 database.json에서 데이터베이스 정보를 설정하시면 됩니다.


{

    "host": 데이터베이스 주소,

    "user": 데이터베이스 사용자,

    "password": 데이터베이스 비밀번호,

    "port": "3306",

    "database": 데이터베이스 이름

}



  그러면 위와 같이 프로젝트가 구성됩니다.


※ Node.js와 MySQL 연동하기 ※


  이제 Node.js와 MySQL을 연동해 봅시다. 가장 먼저 NPM을 이용하여 MySQL 라이브러리를 설치하셔야 합니다.


▶ npm install -S mysql


  이후에 설치된 mysql 라이브러리를 활용하여 node.js와 MySQL을 연동할 수 있습니다.


const fs = require('fs');

const express = require('express');

const bodyParser = require('body-parser');

const app = express();

const port = process.env.PORT || 5000;

app.use(bodyParser.json());

app.use(bodyParser.urlencoded({ extended: true }));


const data = fs.readFileSync('./database.json');

const conf = JSON.parse(data);

const mysql = require('mysql');


const connection = mysql.createConnection({

host: conf.host,

user: conf.user,

password: conf.password,

port: conf.port,

database: conf.database

});

connection.connect();


app.get('/api/customers', (req, res) => {

connection.query(

'SELECT * FROM CUSTOMER',

(err, rows, fields) => {

res.send(rows);

}

)

});


app.listen(port, () => console.log(`Listening on port ${port}`));


  결과적으로 다음과 같이 서버 API가 정상적으로 동작하는 것을 확인할 수 있습니다.



  이후에 깃 허브(Git Hub)에 소스코드를 반영하면 다음과 같습니다.



  데이터베이스 설정 파일인 database.json 파일은 깃 허브에 올라가지 않는 것을 확인할 수 있습니다.


728x90
반응형

728x90
반응형

  이번 시간에는 Node.js Express리액트(React) 클라이언트 서비스와 연동하는 방법에 대해서 알아보도록 하겠습니다. 우리는 이미 클라이언트(Client) 파트를 구축하여 개발하고 있는 상태이므로 이어서 서버(Server) 모듈을 개발하여 클라이언트와 연동시키면 됩니다. 다시 말해 Node.js Express를 이용해 서버 API를 개발해서 고객 관리 시스템의 백 엔드를 구축할 수 있는 것입니다.


  따라서 가장 먼저 우리의 프로젝트 루트 폴더에서 client라는 이름의 폴더를 생성합니다. 그리고 기존에 존재했던 모든 소스코드를 이 client 폴더 안으로 넣으시면 됩니다. 그러면 다음과 같이 루트 폴더와 client 폴더가 구성됩니다.




  이후에 Node.js Express 서버를 개발하기 전에 환경 설정을 진행해주도록 하겠습니다. 이를 위해 루트 폴더에 package.json을 생성합니다. package.json 파일에서는 client 폴더에서 클라이언트 모듈을 실행하고, 루트 폴더에서는 서버 모듈을 실행하도록 명시해주도록 하겠습니다.


▶ package.json


{
"name": "management",
"version": "1.0.0",
"scripts": {
"client": "cd client && yarn start",
"server": "nodemon server.js",
"dev": "concurrently --kill-others-on-fail \"yarn server\" \"yarn client\""
},
"dependencies": {
"body-parser": "^1.18.3",
"express": "^4.16.4"
},
"devDependencies": {
"concurrently": "^4.0.1"
}
}


  이제 루트 폴더에 클라이언트와 동일한 형태의 .gitignore 파일을 위치시킵니다. 이 .gitignore 파일이 없으면 우리가 설치한 노드 모듈 또한 모두 깃 허브(Git Hub)에 올라가기 때문에 비효율적입니다. 이후에 루트 폴더를 기준으로 nodemon을 설치합니다.


▶ npm install -g nodemon

▶ yarn


  이제 서버 모듈 개발을 위해 루트 폴더에 server.js 파일을 생성합니다.


▶ server.js


const express = require('express');
const bodyParser = require('body-parser');
const app = express();
const port = process.env.PORT || 5000;
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

app.get('/api/hello', (req, res) => {
res.send({ message: 'Hello Express!' });
});

app.listen(port, () => console.log(`Listening on port ${port}`));


  이후에 node server.js 명령어로 서버를 구동시킬 수 있습니다.



※ GET 방식의 API 테스트하기 ※



728x90
반응형

728x90
반응형

  이번 시간에는 고객 컴포넌트(Customer Component)를 만들어 보는 시간을 가져보도록 하겠습니다. 말 그대로 한 명의 고객에 대한 정보를 보여주기(View) 위한 기능입니다. 기본적으로 React는 HTML 웹 문서를 효과적으로 보여주기 위한 라이브러입니다. 그래서 컴포넌트란 말 그대로 웹 문서에서 어떠한 내용을 보여주기 위한 기본적인 단위라고 이해하시면 됩니다.


※ Customer 컴포넌트 ※


  Customer 컴포넌트를 만들어 주도록 하겠습니다. 지금부터 만들 컴포넌트(Component)들은 하나의 공간에 모아 놓으려고 해요. 그래서 src 폴더에서 [New Folder]를 눌러 새로운 폴더를 만들어 주도록 하겠습니다. 이름은 components에요.


 


  이후에 다음과 같이 components 폴더에서 [New File]을 눌러서 Customer.js 컴포넌트를 생성해주도록 합시다.



  이후에 소스코드를 작성해주시면 됩니다.


  ▶ import: 특정한 라이브러리를 불러오기 할 때 사용

  ▶ export: 특정한 라이브러리를 내보내기 할 때 사용


  말 그대로 React Component 라이브러리를 사용하기 위해서 import 구문이 먼저 나와야 합니다. 그리고 나중에 다른 컴포넌트에서 지금 우리가 만든 컴포넌트를 사용하기 위해서는 export를 해주셔야 하는 거예요.



import React from 'react';

class Customer extends React.Component {
render() {
return (
<div>
<h2>홍길동</h2>
<p>961222</p>
<p>남자</p>
<p>대학생</p>
</div>
)
}
}

export default Customer;


※ App.js ※


  이제 App.js에서 방금 우리가 만든 Customer 컴포넌트를 사용하도록 해볼게요.


import React, { Component } from 'react';
import Customer from './components/Customer'
import './App.css';

class App extends Component {
render() {
return (
<Customer/>
);
}
}

export default App;


  이제 웹 브라우저를 확인해 보시면 다음과 같이 한 명의 고객에 대한 정보가 출력되는 것을 확인할 수 있어요.



※ Props를 이용해 구조화하기 ※


  이제 Props를 이용해서 App.js에서 데이터(Data)를 가진 상태에서 고객에 대한 정보를 출력하도록 구조화하도록 하겠습니다.


▶ App.js


import React, { Component } from 'react';
import Customer from './components/Customer'
import './App.css';

const customer = {
'name': '홍길동',
'birthday': '961222',
'gender': '남자',
'job': '대학생'
}

class App extends Component {
render() {
return (
<Customer
name={customer.name}
birthday={customer.birthday}
gender={customer.gender}
job={customer.job}
/>
);
}
}

export default App;


▶ Customer.js


import React from 'react';

class Customer extends React.Component {
render() {
return (
<div>
<h2>{this.props.name}</h2>
<p>{this.props.birthday}</p>
<p>{this.props.gender}</p>
<p>{this.props.job}</p>
</div>
)
}
}

export default Customer;


  실행 결과는 동일합니다. 기존에 객체 지향 프로그래밍을 해보신 분들이라면 현재의 소스코드가 그러한 객체 지향 프로그래밍의 구조를 정확히 잘 따르고 있다는 사실을 확인할 수 있을 거예요.

728x90
반응형

728x90
반응형

  리액트(React) 개발에 있어서 가장 효과적인 통합 개발 환경(IDE) 중 하나는 바로 비주얼 스튜디오 코드(Visual Studio Code)입니다. 일단 지난 시간에 만들었던 리액트 프로젝트를 실행(Start) 시켜주세요. 기본적으로 서버가 구동 중인 상태에서 소스코드를 수정하면 알아서, 수정된 내역에 맞게 다시 컴파일이 이루어지면서 실제 웹 서비스에 반영된다는 특징이 있습니다.



  이제 이 상태에서 비주얼 스튜디오 코드를 설치해서 프로젝트 소스코드를 비주얼 스튜디오로 열어 보도록 하겠습니다. 혹시 비주얼 스튜디오 코드가 설치되어 있지 않으신 분은 다음의 사이트에서 설치를 진행하시면 됩니다.


  ▶ 비주얼 스튜디오 코드(Visual Studio Code) 사이트: https://code.visualstudio.com/


  접속 이후에는 자신의 운영체제에 맞는 응용 프로그램으로 설치를 진행할 수 있습니다. 설치를 하실 때에는 기본 설정으로 설치를 진행해주셔도 별다른 어려움 없이 따라오실 수 있습니다.



  설치 이후에는 비주얼 스튜디오 코드를 실행해주세요. 이후에 [File] - [Open Folder] 자신의 리액트 프로젝트를 열어주세요.



  기본적으로 리액트(React)는 App.js라는 이름으로 메인 자바스크립트를 관리할 수 있습니다. 실제로 HTML 문서에서 <body> 태그에 해당하는 내용은 이 App.js가 채우게 됩니다. 따라서 한 번 이 App.js를 수정해 봅시다.



  저는 다음과 같이 내용을 대략 아무렇게나 바꾸어 보도록 하겠습니다.



  이후에 저장(Ctrl + S)을 해주시면 자동으로 소스코드가 컴파일 되어 다음과 같이 웹 사이트에서 수정 내역을 확인할 수 있습니다.



728x90
반응형

728x90
반응형

  React와 Node.js로 만드는 고객 관리 시스템 개발 강좌의 첫 번째 시간입니다. 이번 시간에는 Create React App을 이용해 리액트 프로젝트를 시작하는 방법에 대해서 소개하고자 합니다. CRA(Create React App)을 이용하면 별다른 환경 설정을 수행하지 않아도 매우 빠르고 간단하게 리액트 프로젝트를 생성할 수 있습니다. 이번 시간에는 빠르게 Create React App을 이용해 프로젝트를 구축해보도록 하겠습니다.


  기본적으로 리액트(React) 개발환경을 위해서는 node.js가 설치되어 있어야 합니다.


  ▶node.js 사이트: https://nodejs.org/


  저는 최신 버전의 노드인 11.6.0 버전을 설치했습니다.



  기본적인 설정으로 설치를 진행하시면 됩니다.



  설치 이후에는 node -v 명령어로 설치된 노드의 버전을 확인할 수 있습니다.



  node.js를 설치하면 패키지 매니저 도구 NPM이 자동으로 설치됩니다. 이를 이용해서 create-react-app를 설치하시면 됩니다.



  이제 특정한 폴더로 이동해서 React 프로젝트를 생성해주겠습니다. 명령어는 create-react-app {프로젝트 이름}입니다.


  리액트 앱을 만든 이후에는 해당 프로젝트 폴더로 이동하여 yarn start 명령어로 실행할 수 있습니다.



  실행 이후에는 다음과 같이 개발 서버가 구동 중인 것을 확인할 수 있습니다.



  기본 포트 번호는 3000번이므로 브라우저에서 localhost:3000으로 접속하시면 다음과 같이 리액트 앱의 내용이 출력됩니다.


728x90
반응형