안경잡이개발자

728x90
반응형

▶ 구글 파이어베이스 콘솔: https://console.firebase.google.com/


1. 프로젝트 생성하기




2. 데이터베이스 페이지 확인



3. 데이터베이스에 단어(Word) 데이터 구축


  (단, 원래는 ID 값으로 0, 1, 2와 같은 단순한 숫자를 넣지 않습니다. 이는 예시 데이터를 구성하기 위해 넣은 것이며, 실제 DB 연동 작업을 마쳤을 때에는 이러한 예시 데이터를 삭제해야 오류가 발생하지 않습니다.)



4. 규칙(Rule) 설정을 통한 외부 접속 허용



5. 단어(Word) API 호출 테스트



▶ ./src/components/Words.js


import React from 'react';
import Card from '@material-ui/core/Card';
import CardContent from '@material-ui/core/CardContent';
import Typography from '@material-ui/core/Typography';

const databaseURL = "https://react-example-55161.firebaseio.com/";

class Words extends React.Component {
constructor() {
super();
this.state = {
words: {}
};
}

_get() {
fetch(`${databaseURL}/words.json`).then(res => {
if(res.status != 200) {
throw new Error(res.statusText);
}
return res.json();
}).then(words => this.setState({words: words}));
}

shouldComponentUpdate(nextProps, nextState) {
return nextState.words != this.state.words
}

componentDidMount() {
this._get();
}

render() {
return (
<div>
{Object.keys(this.state.words).map(id => {
const word = this.state.words[id];
return (
<div key={id}>
<Card>
<CardContent>
<Typography color="textSecondary" gutterBottom>
가중치: {word.weight}
</Typography>
<Typography variant="h5" component="h2">
{word.word}
</Typography>
</CardContent>
</Card>
<br/>
</div>
);
})}
</div>

);
}
}

export default Words;


※ 실행 결과 ※


728x90
반응형

728x90
반응형

  가장 먼저 라우팅 기능을 위해 라이브러리를 설치합니다.



▶ ./src/components/Home.js


import React from 'react';
import Card from '@material-ui/core/Card';
import CardContent from '@material-ui/core/CardContent';

class Home extends React.Component {
render() {
return (
<Card>
<CardContent>
React 및 Firebase 기반의 워드 클라우드 프로젝트
</CardContent>
</Card>
);
}
}

export default Home;


▶ ./src/components/Texts.js


import React from 'react';
import Card from '@material-ui/core/Card';
import CardContent from '@material-ui/core/CardContent';

class Texts extends React.Component {
render() {
return (
<Card>
<CardContent>
Texts 페이지
</CardContent>
</Card>
);
}
}

export default Texts;


▶ ./src/components/Words.js


import React from 'react';
import Card from '@material-ui/core/Card';
import CardContent from '@material-ui/core/CardContent';

class Words extends React.Component {
render() {
return (
<Card>
<CardContent>
Words 페이지
</CardContent>
</Card>
);
}
}

export default Words;


▶ ./src/components/App.js


import React from 'react';
import { HashRouter as Router, Route } from 'react-router-dom';
import AppShell from './AppShell';
import Home from './Home';
import Texts from './Texts';
import Words from './Words';

class App extends React.Component {
render() {
return (
<Router>
<AppShell>
<div>
<Route exact path="/" component={Home}/>
<Route exact path="/texts" component={Texts}/>
<Route exact path="/words" component={Words}/>
</div>
</AppShell>
</Router>
);
}
}

export default App;


▶ ./src/components/AppShell.js


import React from 'react';
import { Link as RouterLink } from 'react-router-dom';
import Link from '@material-ui/core/Link';
import { withStyles } from '@material-ui/core/styles';
import AppBar from '@material-ui/core/AppBar';
import Drawer from '@material-ui/core/Drawer';
import MenuItem from '@material-ui/core/MenuItem';
import IconButton from '@material-ui/core/IconButton';
import MenuIcon from '@material-ui/icons/Menu';

const styles = {
root: {
flexGrow: 1,
},
menuButton: {
marginRight: 'auto'
},
};

class AppShell extends React.Component {
constructor(props) {
super(props);
this.state = {
toggle: false
};
}
handleDrawerToggle = () => this.setState({toggle: !this.state.toggle})
render() {
const { classes } = this.props;
return (
<div>
<div className={classes.root}>
<AppBar position="static">
<IconButton className={classes.menuButton} color="inherit" onClick={this.handleDrawerToggle}>
<MenuIcon/>
</IconButton>
</AppBar>
<Drawer open={this.state.toggle}>
<MenuItem onClick={this.handleDrawerToggle}>
<Link component={RouterLink} to="/">
Home
</Link>
</MenuItem>
<MenuItem onClick={this.handleDrawerToggle}>
<Link component={RouterLink} to="/texts">
Texts
</Link>
</MenuItem>
<MenuItem onClick={this.handleDrawerToggle}>
<Link component={RouterLink} to="/words">
Words
</Link>
</MenuItem>
</Drawer>
</div>
<div id="content" style={{margin: 'auto', marginTop: '20px'}}>
{React.cloneElement(this.props.children)}
</div>
</div>
);
}
}

export default withStyles(styles)(AppShell);


※ 실행 결과 ※





728x90
반응형

728x90
반응형

  가장 먼저 material-ui 라이브러리를 설치합니다.


  yarn add @material-ui/core

  yarn add @material-ui/icons


  이후에 내비게이션 바의 틀을 만들 수 있습니다.


▶ ./src/components/Appshell.js


import React from 'react';
import { withStyles } from '@material-ui/core/styles';
import AppBar from '@material-ui/core/AppBar';
import Drawer from '@material-ui/core/Drawer';
import MenuItem from '@material-ui/core/MenuItem';
import IconButton from '@material-ui/core/IconButton';
import MenuIcon from '@material-ui/icons/Menu';

const styles = {
root: {
flexGrow: 1,
},
menuButton: {
marginRight: 'auto'
},
};

class AppShell extends React.Component {
constructor(props) {
super(props);
this.state = {
toggle: false
};
}
handleDrawerToggle = () => this.setState({toggle: !this.state.toggle})
render() {
const { classes } = this.props;
return (
<div className={classes.root}>
<AppBar position="static">
<IconButton className={classes.menuButton} color="inherit" onClick={this.handleDrawerToggle}>
<MenuIcon/>
</IconButton>
</AppBar>
<Drawer open={this.state.toggle}>
<MenuItem onClick={this.handleDrawerToggle}>Home</MenuItem>
</Drawer>
</div>
);
}
}

export default withStyles(styles)(AppShell);


▶ ./src/components/App.js


import React from 'react';
import AppShell from './AppShell';

class App extends React.Component {
render() {
return (
<AppShell/>
);
}
}

export default App;


※ 실행 결과 ※


1. 내비게이션 바(Close)



2. 내비게이션 바(Open)



728x90
반응형

728x90
반응형

  이번 시간에는 고객(Customer) 정보를 삭제하는 기능을 구현하는 시간을 가져보도록 하겠습니다. 특정한 데이터의 삭제 기능을 구현하는 방법은 굉장히 다양합니다. 몇 가지 예제를 살펴보자면 ① 삭제를 수행했을 때 실제 테이블에서 데이터를 삭제하는 방식이 있으며 ② 삭제를 수행했을 때 삭제 체크만 한 뒤에 실제 데이터베이스에는 남겨 놓는 방식이 있습니다.


  우리는 두 번째 방식으로 구현하겠습니다. 따라서 Customer 테이블의 정보부터 수정하도록 하겠습니다.


USE management;

ALTER TABLE CUSTOMER ADD createdDate DATETIME;

ALTER TABLE CUSTOMER ADD isDeleted INT;


  또한 기본적으로 현재 들어있던 데이터에는 새로운 속성(Property)에 대한 데이터가 없으므로 이를 채워넣어줄 수 있도록 합니다.


USE management;

UPDATE CUSTOMER SET createdDate = now();

UPDATE CUSTOMER SET isDeleted = 0;


  위와 같이 MySQL 테이블 설정 명령어를 수행한 이후에 DESC 명령어로 테이블(Table) 정보를 확인해 보시면 다음과 같습니다.



  따라서 모든 데이터는 방금 생성이 된 것으로 처리 되었고, 현재 삭제 되지 않은 상태로 남아있게 되었습니다. 이제 새롭게 CustomerDelete.js를 생성해주도록 합니다.



▶ CustomerDelete.js


import React from 'react';

class CustomerDelete extends React.Component {

deleteCustomer(id){
const url = '/api/customers/' + id;
fetch(url, {
method: 'DELETE'
});
this.props.stateRefresh();
}

render() {
return (
<button onClick={(e) => {this.deleteCustomer(this.props.id)}}>삭제</button>
)
}
}

export default CustomerDelete;


▶ Customer.js


  이제 위에서 만든 Customer Delete 뷰(View)를 한 명의 고객 정보를 출력할 때 함께 보여줄 수 있도록 처리하면 됩니다.


import React from 'react';
import TableRow from '@material-ui/core/TableRow';
import TableCell from '@material-ui/core/TableCell';
import CustomerDelete from './CustomerDelete'

class Customer extends React.Component {
render() {
return (
<TableRow>
<TableCell>{this.props.id}</TableCell>
<TableCell><img src={this.props.image} alt="profile"/></TableCell>
<TableCell>{this.props.name}</TableCell>
<TableCell>{this.props.birthday}</TableCell>
<TableCell>{this.props.gender}</TableCell>
<TableCell>{this.props.job}</TableCell>
<TableCell><CustomerDelete stateRefresh={this.props.stateRefresh} id={this.props.id}/></TableCell>
</TableRow>
)
}
}

export default Customer;


▶ App.js


  이후에 다음과 같이 App.js에서 각 고객 컴포넌트에게 stateRefresh 함수를 넘겨 줄 수 있도록 합니다.


<div>
<Paper className={classes.root}>
<Table className={classes.table}>
<TableHead>
<TableRow>
<TableCell>번호</TableCell>
<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 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>
<CustomerAdd stateRefresh={this.stateRefresh} />
</div>


▶ server.js


  이제 실제로 Express 서버에 고객 데이터 삭제 모듈을 만들어주면 됩니다. 이 때 기존에 존재하던 고객 정보 삽입 모듈과 고객 목록 불러오기 모듈도 조금씩 바꾸어주시면 됩니다.


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 multer = require('multer');
const upload = multer({dest: './upload'})

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 WHERE isDeleted = 0',
(err, rows, fields) => {
res.send(rows);
}
)
});

app.use('/image', express.static('./upload'));

app.post('/api/customers', upload.single('image'), (req, res) => {
let sql = 'INSERT INTO CUSTOMER VALUES (null, ?, ?, ?, ?, ?, now(), 0)';
let image = '/image/' + req.file.filename;
let name = req.body.name;
let birthday = req.body.birthday;
let gender = req.body.gender;
let job = req.body.job;
let params = [image, name, birthday, gender, job];
connection.query(sql, params,
(err, rows, fields) => {
res.send(rows);
}
)
});

app.delete('/api/customers/:id', (req, res) => {
let sql = 'UPDATE CUSTOMER SET isDeleted = 1 WHERE id = ?';
let params = [req.params.id];
connection.query(sql, params,
(err, rows, fields) => {
res.send(rows);
}
)
});

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


  실행 결과는 다음과 같습니다. 다음과 같이 가장 오른쪽에 [삭제] 버튼이 추가된 것을 확인할 수 있습니다.



  그래서 결과적으로 다음과 같이 삭제 요청(Request)이 전송되는 것을 확인할 수 있습니다. REST API의 성격에 맞게 DELETE 메소드(Method)로 삭제 요청이 보내졌으며 성공적으로 삭제가 완료된 것입니다.



  결과적으로 다음과 같이 고객 목록이 갱신된 것을 확인할 수 있습니다.




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를 활용하여 REST API를 구축하는 방법에 대해서 알아보도록 하겠습니다. REST API는 최근 상당수의 웹 서버 프레임워크에서 기본적으로 지원하는 기능으로 서버와 클라이언트가 웹 프로토콜을 기반으로 하여 효과적으로 데이터를 주고 받을 수 있도록 해줍니다. 이를 실습하기 위해 가장 먼저 기존의 서버 모듈에 전체 고객 목록을 불러오는 API를 구현해보도록 합시다.


▶ 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/customers', (req, res) => {
res.send([
{
'id': 1,
'image': 'https://placeimg.com/64/64/1',
'name': '홍길동',
'birthday': '961222',
'gender': '남자',
'job': '대학생'
},
{
'id': 2,
'image': 'https://placeimg.com/64/64/2',
'name': '나동빈',
'birthday': '960508',
'gender': '남자',
'job': '프로그래머'
},
{
'id': 3,
'image': 'https://placeimg.com/64/64/3',
'name': '이순신',
'birthday': '961127',
'gender': '남자',
'job': '디자이너'
}
]);
});

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


  우리가 만든 /api/customers 경로에 들어가 보면 다음과 같이 고객 목록이 출력됩니다.



  고객 목록 데이터가 정상인지 확인하기 위하여 JSON 검증 서비스를 이용해보도록 합시다.


▶ JSON 검증 서비스: https://jsonlint.com/


  그대로 결과 JSON 문서를 붙여넣기 해보면 다음과 같이 정상적인 데이터라는 것을 확인할 수 있습니다.



  이후에 클라이언트(Client)에서 해당 API에 접근하여 고객 목록을 비동기적으로 가져오도록 만들면 됩니다. 가장 먼저 5000번 포트를 API 서버로 이용하기 위해서 클라이언트(Client)의 package.json 파일에 다음의 문구를 추가하시면 됩니다.


  "proxy": "http://localhost:5000/"


  이제 app.js 파일을 작성하여 실제로 API 서버에 접근할 수 있도록 처리하시면 됩니다.


▶ app.js


  비동기적으로 API 요청 기능을 수행하기 위해서 async - await 구문을 사용했습니다. 서버로부터 JSON 데이터를 받아올 때까지는 테이블에 내용을 출력하지 않다가 데이터를 모두 받아왔을 때 비로소 테이블에 내용을 채우게 됩니다.


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 { withStyles } from '@material-ui/core/styles';

const styles = theme => ({
root: {
width: "100%",
marginTop: theme.spacing.unit * 3,
overflowX: "auto"
},
table: {
minWidth: 1080
}
});

class App extends Component {

state = {
customers: ''
}

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

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

render() {
const { classes } = this.props;
return (
<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} />
}) : ''}
</TableBody>
</Table>
</Paper>
);
}
}

export default withStyles(styles)(App);


  이후에 yarn dev 명령어를 이용해 서버를 구동시킬 수 있습니다.



728x90
반응형

728x90
반응형

  지난 시간까지 해서 리액트(React) 프로젝트를 생성하고 비주얼 스튜디오 코드(VSC)를 이용해서 개발 환경을 구축하는 시간을 가졌습니다. 이번 시간에는 깃(Git)을 이용해서 소스코드를 관리하는 방법에 대해서 알아보도록 하겠습니다. 우리는 향후 프로젝트의 효과적인 관리를 위해서 Git 저장소(Repository)를 생성한 뒤에 해당 저장소에 소스코드를 올리게 될 것입니다.


  일단 깃에 소스코드를 올리기 전에 전체 소스코드의 윤곽을 잡고 나서 올리는 것이 좋습니다.


  따라서 간단히 소스코드를 수정하며 프로젝트의 윤곽을 이해하는 시간을 가져보도록 하겠습니다.


※ App.js ※


  App.js는 실질적인 웹 사이트 화면에 대한 내용 출력을 담당하는 부분입니다.



import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';

class App extends Component {
render() {
return (
<div className="gray-background">
<img src={logo} alt="logo" />
<h2>Let's develop management system!</h2>
</div>
);
}
}

export default App;


※ App.css ※


  App.css 파일은 App.js와 연동되어 웹 사이트의 메인 부분에 해당하는 내용의 디자인(Design)을 담당합니다. 저는 간단히 기존의 내용을 지운 뒤에 .gray-background라는 이름의 클래스(Class)를 만들어 보았습니다. 클래스는 웹 문서 내 각 요소의 디자인을 구분하기 위한 문법입니다.



.gray-background {
background: darkgray;
}


※ index.html ※


  이후에 index.html을 수정합니다. 기존의 index.html 파일은 온갖 주석으로 가득 차 있었을 거예요. 그러한 주석을 모두 지워주시면 됩니다. 참고로 index.html 소스코드 내에는 <div id="root"></div>라는 부분이 있는데, 이 root 영역에 실제로 App.js의 내용이 출력됩니다.


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico" />
<meta
name="viewport"
content="width=device-width, initial-scale=1, shrink-to-fit=no"
/>
<meta name="theme-color" content="#000000" />
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<title>React App</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
</body>
</html>


※ README.md ※


  이어서 README.md 파일을 수정합니다. 이것은 깃 허브(Git Hub)에 올라가 출력될 내용입니다. 프로젝트의 소개, 설치 방법, 레퍼런스 등의 문구가 들어가는 공간이라고 이해하시면 돼요.



## Management System

본 프로젝트는 React 강의 목적으로 만들어진 고객 관리 시스템(Management System)입니다.


  모든 소스코드를 저장해주신 뒤에 웹 사이트를 새로고침(F5) 해보시면 정상적으로 적용된 것을 확인할 수 있습니다.



※ 깃으로 프로젝트 관리하기 ※


  이제 깃 허브에 저장소를 생성하여 우리 프로젝트를 관리해 봅시다.


  ▶ 깃 허브(Git Hub) 주소: https://github.com/


  깃 허브에 회원가입 및 로그인을 해주신 뒤에 [Create Repository]를 진행해주시면 됩니다. 말 그대로 소스코드가 올라갈 수 있는 하나의 저장 공간을 만들어 준다고 이해하시면 됩니다.



  위와 같이 프로젝트의 이름만 지어 주신 뒤에 생성 버튼을 눌러주시면 다음과 같이 저장소가 생성됩니다.



  이후에 저장소의 주소를 복사해서 가지고 있어주세요. 이제 VSC로 돌아와서 깃(Git) 탭으로 가보시면 우리가 수정한 소스코드의 내용이 모두 왼쪽 화면에 드러나는 것을 확인할 수 있습니다.



  먼저 우리가 수정한 소스코드의 내역을 우리 컴퓨터의 로컬 저장소에 반영하기 위해서는 커밋(Commit)을 해주시면 됩니다. 따라서 커밋을 하고자 하는 소스코드를 먼저 추가해주세요.



  그리고 커밋을 진행하시면 됩니다. 저는 커밋 메시지로 'Create React Project'라고 지어주었어요.



  이후에 우리가 만든 깃 허브(Git Hub)의 저장소로 푸시(Push)하기 위해서 터미널을 열어줍시다.



  이제 아까 복사했던 저장소의 주소를 원격지 주소로 설정한 뒤에 푸시(Push)를 진행해주시면, 소스코드가 깃 허브에 업로드 됩니다.


  ▶ 깃 허브 원격지 설정: git remote add origin https://github.com/ndb796/React-Management-System.git

  ▶ 깃 허브 원격지로 푸시: git push --set-upstream origin master



  푸시 이후에 깃 허브 저장소를 새로고침 해보시면 다음과 같이 소스코드가 모두 업로드 되어 있는 것을 확인할 수 있습니다.


728x90
반응형

728x90
반응형

  리액트(React)UI를 효과적으로 구축하기 위해 사용하는 자바스크립트(JavaScript) 기반의 라이브러리입니다. 그러므로 HTML과 자바스크립트를 할 수 있다면 리액트도 어렵지 않게 사용할 수 있습니다. 또한 리액트는 라이브러리라는 점에서 다른 라이브러리들과 함께 사용할 수 있어 효율적입니다. 무엇보다 리액트는 오픈소스 커뮤니티가 매우 방대하다는 장점이 있습니다.


  다시 말해서 리액트(React)를 배우기 전의 선행 과정은 JavaScript입니다. 또한 추가적으로 jQuery와 같은 다른 라이브러리를 사용해 본 경험이 있다면 리액트의 장점 및 필요성에 대해서 보다 쉽게 이해할 수 있을 것이라고 생각합니다.


  이 강좌는 초반부에는 리액트의 개요 및 사용 방법에 대해서 다루기 때문에 조금 지루할 수 있습니다. 다만 1시간 가량만 실습을 하더라도 기본적인 사용 방법에 대해서 알 수 있으며, 이후에는 바로 실습을 진행하며 공부하게 되므로 재미있게 학습하실 수 있습니다.


  ▶ 리액트 오픈소스: https://github.com/facebook/react



  리액트(React) 오픈소스는 별점이 10만 개가 넘는 유명한 프로젝트입니다. (그래서 리액트를 제대로 다룰 줄 모르는 저는 마치 저만 쓸 줄 모르는 것 같은 소외감을 느끼곤 했습니다.) 또한 MIT 라이센스를 따른다는 점에서 상당히 자유롭게 사용할 수 있는 편입니다.


※ 리액트의 특징 ※


  - 선언적(Declarative): 리액트는 대화형 UI를 작성하기에 유리합니다. 데이터가 변경되었을 때 효율적으로 렌더링을 수행할 수 있도록 합니다.


  - 컴포넌트 기반(Component-Based): 캡슐화된(Encapsulated) 컴포넌트가 상태를 관리하고 UI를 효과적으로 구성할 수 있습니다.


  - 한 번 배워서 어디에서나 사용하기(Learn Once, Write Anywhere): 기존의 소스코드를 불필요하게 다시 작성하지 않고 새로운 기능을 개발할 수 있습니다.


  이러한 리액트는 공식 문서를 읽으면서 바로 공부를 시작해 볼 수 있습니다.


  ▶ 리액트 학습 사이트: https://reactjs.org/docs/getting-started.html



  또한 기본적으로 리액트는 단순히 웹 환경에서 돌릴 수 있다는 점에서 굳이 우리 로컬(Local) 컴퓨터에 개발 환경을 구축하지 않아도 충분히 온라인 상에서 소스코드를 테스트 해 볼 수 있습니다.


  ▶ 리액트 사용해보기: https://reactjs.org/redirect-to-codepen/hello-world




※ 리액트의 장점과 단점 ※


  리액트는 뛰어난 성능을 가지고 있으며 클라이언트 렌더링 뿐만 아니라 서버 사이드 렌더링도 지원합니다. 그래서 Ajax 등과 같은 비동기 방식과 비교했을 때 검색 엔진 최적화(SEO) 등에 있어서 유리한 형태로 소스코드를 작성할 수 있습니다. 이러한 검색 엔진 최적화 문제는 상당수 SPA 프로젝트가 가지는 문제입니다.


  또한 리액트는 이미 많은 웹 서비스가 채택한 기술이라는 점에서 그에 따라서 오는 부가적인 장점이 있습니다.


  ▶ 리액트를 사용한 서비스들: https://github.com/facebook/react/wiki/Sites-Using-React


  확인을 해보시면 페이스북(Facebook), 인스타그램(Instagram) 등 유명한 서비스가 포함되어 있습니다.


  (+ 추가)


  또한, 리액트를 시작하기 전에 자바(Java), C++ 등을 해 본 사람을 위해서 이것이 무슨 라이브러리인지 쉽게 설명해드리겠습니다. 기존에 웹 사이트를 만들 때에는 보통 프론트 엔드 부분을 객체 지향적으로 작성하지는 않았어요. 백 엔드에서나 객체 지향 기법을 적절히 따르면서 개발했죠. 하지만 리액트는 프론트 엔드 또한 매우 객체 지향적으로 작성하도록 해주는 라이브러리라고 보시면 됩니다.


  그리고 기존에 JavaScript 및 jQuery까지 사용해보신 분들이라면 리액트(React) 과정은 하루에서 이틀 정도 잡으시고 빠르게 끝내시는 것을 추천드립니다. 어렵게 생각하지 마시고 단순한 라이브러리 따위 하루만에 정복하겠다는 거만한(?) 마인드로 공부하시면 좋아요.

728x90
반응형

'리액트(React)' 카테고리의 다른 글

React의 LifeCycle과 API 호출  (3) 2019.01.04
React의 State  (0) 2018.12.25
React의 Component와 Props  (0) 2018.12.25
React에서 JSX란?  (0) 2018.12.25
코드펜(Codepen)을 이용한 React 개발환경 구축하기  (0) 2018.12.25