안경잡이개발자

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
반응형

  이번 시간에는 AWS RDS 서비스를 이용하여 MySQL DB를 구축해보는 시간을 가져보도록 하겠습니다. 실제로 고객에 대한 정보를 저장하기 위해서는 MySQL과 같은 데이터베이스 시스템이 필요합니다. 따라서 이번 시간에는 AWS(Amazon Web Service)를 이용해서 데이터베이스를 구축하도록 하겠습니다. 일반적으로 AWS RDS를 이용하면 MySQL과 같은 관계형 데이터베이스 시스템을 쉽고 빠르게 구축할 수 있어요. 


  심지어 프리티어(Free-Tier) 서비스를 이용하면 무료로 이용할 수 있다는 점에서 매우 효과적이랍니다.


※ AWS RDS로 데이터베이스 만들기 ※


  AWS RDS 서비스를 검색하여 관계형 데이터베이스를 관리할 수 있습니다.



  이후에 [데이터베이스 생성]란에 들어가서 데이터베이스를 만들어 주시면 됩니다.



  저는 MySQL 서비스를 이용하도록 하겠습니다. 이 때 [RDS 프리 티어에 적용되는 옵션만 사용] 란에 체크해주시면 됩니다.



  이후에 DB 세부 정보를 지정할 수 있습니다. 저는 MySQL 5.6 버전을 이용하도록 하겠습니다.



  이후에 기본 스토리지 크기인 20GiB를 사용하시면 됩니다. 그리고 이후에 데이터베이스에 접속하기 위한 계정 정보를 넣어주세요.



  이제 [고급 설정 구성]을 진행하시면 됩니다. 일반적으로 DB 보안 관리를 꼭 해주셔야 하지만 저는 강의를 위해서 일단 외부에서 쉽게 접속할 수 있도록 [퍼블릭 액세스 가능성]을 예(Yes)로 설정하겠습니다.



  포트(Port) 번호 또한 기본 포트인 3306번 포트를 사용하시면 됩니다. DB 이름도 설정하시면 돼요.



  이후에 다음과 같이 [데이터베이스 생성]을 진행할 수 있습니다.



  인스턴스를 생성한 이후에는 [DB 인스턴스 세부 정보 보기]를 눌러서 세부 정보를 확인할 수 있습니다.



  기본적으로 MySQL은 영어로 설정되어 있으므로 한글을 넣고자 한다면 UTF-8으로 인코딩 설정을 해야 합니다. 따라서 [파라미터 그룹] 탭으로 이동해서 [파라미터 그룹 생성]을 진행하시면 됩니다.



  저는 다음과 같이 utf8-parameter라는 이름으로 파라미터 그룹을 생성해보았습니다.



  가장 먼저 char를 검색해서 나오는 모든 속성에 대해서 값으로 UTF-8 설정을 해주세요.



  이후에 collation을 검색하여 값으로 utf8_general_ci를 설정하시면 됩니다.




  이제 이렇게 만들어진 파라미터 그룹을 우리의 데이터베이스에 적용해보도록 하겠습니다.



  해당 데이터베이스에서 [수정] 탭으로 들어가 적용해주시면 됩니다.




  결과적으로 [변경 중] 표시가 뜨면서 약간의 시간이 흐른 뒤에 파라미터 그룹이 적용됩니다.



  혹여 파라미터 그룹 설정이 적용이 되지 않는 경우에는 데이터베이스를 재시작하시면 됩니다.


※ HeidiSQL을 이용해 데이터베이스에 접속하기 ※


  이제 HeidiSQL을 이용해서 데이터베이스에 접속하는 방법에 대해서 알아보도록 하겠습니다.


  ▶ HeidiSQL 설치 경로: https://www.heidisql.com/download.php


  위 경로에 접속하여 HeidiSQL을 설치할 수 있습니다.



  기본적인 설치 프로그램으로 설치를 진행하시면 됩니다. 이후에 해당 프로그램을 실행해 주시면 됩니다.



  저는 위와 같이 신규 세션(Session)을 만들어 주었습니다. MySQL 접속 경로는 AWS RDS 관리 페이지에서 확인할 수 있습니다.



  이전에 자신이 설정했던 계정 정보로 그대로 로그인을 해주시면 됩니다.



  로그인 이후에는 다음과 같이 데이터베이스가 구성되어 있는 것을 확인할 수 있습니다. 왼쪽 탭에서는 데이터베이스 정보가 출력됩니다. 아까 전에 우리가 만들었던 management라는 이름의 데이터베이스가 존재합니다.



  간단히 쿼리(Query) 탭으로 이동하여 select version(); 명령어를 실행해 MySQL 버전을 확인할 수 있습니다.



※ 데이터베이스 접속이 안 되는 경우 ※


  혹시 데이터베이스 접속이 안 되는 경우 데이터베이스의 [보안 그룹]을 확인하시는 것이 중요합니다.



  보안 그룹의 [인바운드] 규칙을 확인했을 때 다음과 같이 접속하고자 하는 소스(Source)가 0.0.0.0(위치 무관)으로 설정되어 있어야 언제 어디서든 해당 데이터베이스에 접근할 수 있습니다.



728x90
반응형

728x90
반응형

  흔히 소프트웨어에서는 프로그레스 바(Progress Bar)를 구현하여 API 로딩 메시지를 웹 사이트 상에 출력할 수 있습니다. 이번 시간에는 고객 목록을 불러오는 API를 요청했을 때 서버에서 응답을 늦게 하는 경우 로딩 메시지를 화면에 띄워주는 방법에 대해서 알아보도록 하겠습니다. 프로그레스 바 UI 또한 Material UI에 이미 구현이 되어 있습니다. 따라서 이를 단순히 사용해주면 됩니다.


  ▶ Material UI 프로그레스 바: https://material-ui.com/demos/progress/


  우리는 이 예제 중에서 [Determinate]을 선택해 구현해 보도록 하겠습니다.



※ React의 라이프 사이클(Life Cycle) ※


  기본적으로 리액트 라이브러리가 처음 컴포넌트를 실행할 때는 다음의 순서를 따릅니다.


1) constructor()

2) componentWillMount()

3) render()

4) componentDidMount()


  그리고 컴포넌트의 props 혹은 state가 변경될 때는 shouldComponentUpdate() 함수 등이 사용되어 실질적으로 다시 render() 함수를 불러와 뷰(View)를 갱신하게 됩니다. 또한 컴포넌트가 삭제될 때는 componentWillUnmount() 함수가 실행된다는 특징이 있습니다.


  따라서 일반적으로 API를 불러와서 웹 사이트 화면에 특정한 뷰(View)를 출력하고자 한다면 componentDidMount() 함수에서 API를 비동기적으로 호출하면 됩니다. 이후에 API에서 응답(Response)이 돌아왔을 때 비로소 뷰(View)가 갱신되므로 화면에 API 응답 결과를 출력할 수 있는 것입니다. 비동기적으로 호출한다는 점에서 API 서버에서 응답을 하지 않으면 사용자에게 로딩 화면만 출력이 됩니다.


▶ App.js


  따라서 Circular Progress 라이브러리를 이용하여 프로그레스 바를 API 로딩 메시지 용도로 사용하도록 하겠습니다.


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';


const styles = theme => ({

root: {

width: "100%",

marginTop: theme.spacing.unit * 3,

overflowX: "auto"

},

table: {

minWidth: 1080

},

progress: {

margin: theme.spacing.unit * 2

}

});


class App extends Component {

state = {

customers: '',

completed: 0

}


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;

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} />

}) :

<TableRow>

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

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

</TableCell>

</TableRow>

}

</TableBody>

</Table>

</Paper>

);

}

}


export default withStyles(styles)(App);


※ 실행 결과 ※


  API를 불러올 때의 화면입니다.



API가 불러와 졌을 때의 결과 화면입니다.



(+ 추가)


  효과적인 로딩 테스트를 위해서는 서버 API의 지연을 발생시키는 것이 좋습니다. 서버에서 응답(Response) 데이터를 보내주는 코드에 Timeout을 적용해 보세요. setTimeout(function() { 소스 코드 }, 지연 시간)의 문법으로 간단히 사용해 볼 수 있습니다.


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
반응형

  이번 시간에는 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
반응형