일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 스컬킹점수
- 코딩
- MBTI
- 옥길그릭요거트
- 스컬킹
- 광명파티룸
- 해외여행
- 옥길동요거트
- 휴식
- 가장존경하는인물
- 취미
- 옥길요거트
- 웹개발
- 스페이스우일
- 서울파티룸
- 존경하는위인
- 개발자
- 옥길동파티룸
- 보드게임점수
- 일
- mysql
- 착한코딩
- 구로파티룸
- 부천파티룸
- 파티룸
- 옥길파티룸
- 스컬킹점수계산
- 부천공간대여
- 보드게임점수계산
- 그릭요거트
- Today
- Total
SIMPLE & UNIQUE
1-4강 : AWS DB서버 연결, 데이터 조회해 리스트 페이지에 노출 본문
1_4 목표 : 이미 테이블과 데이터가 세팅되어 있는 튜터의 AWS DB서버(RDS)를 연결한다. SELECT문을 사용해 데이터를 조회하고, 조회 결과를 리스트 페이지에 출력한다.
다음 2회차 1강에서 각자 AWS 계정을 만들고, RDS mysql 서버를 프리티어(1년무료) 버전의 인스턴스를 생성한다. 그리고 테이블 생성 후, 더미 데이터를 삽입할 것이다.
1회차 4강에서는 이미 세팅이 완료된 튜터의 DB 서버에 접속해 실습한다.
App.js에서 SoftwareTool 관련 부분을 주석처리해 놨었다. 페이지 사용을 위해 아래와 같이 주석을 해제한다.
import React, { Component } from 'react';
import { Route, Switch } from "react-router";
import Api_test from './Api_test'
// css
import '../css/new.css';
// header
import HeaderAdmin from './Header/Header admin';
// footer
import Footer from './Footer/Footer';
// login
import LoginForm from './LoginForm';
// admin floatingPopulationList
import floatingPopulationList from './Floating_population/floatingPopulationList';
// admin softwareinfo
import SoftwareList from './SoftwareToolsManage/SoftwareList';
import SoftwareView from './SoftwareToolsManage/SoftwareView';
class App extends Component {
render () {
return (
<div className="App">
<HeaderAdmin/>
<Switch>
{/* <Route exact path='/' component={Api_test} /> // root 경로일 경우 라우팅 */}
<Route exact path='/' component={LoginForm} />
<Route path='/Api_test' component={Api_test} />
<Route path='/floatPopulationList' component={floatingPopulationList} />
<Route path='/SoftwareList' component={SoftwareList} />
<Route path='/SoftwareView/:swtcode' component={SoftwareView} />
</Switch>
<Footer
footer_address={this.props.footer_address}
footer_tel={this.props.footer_tel}
footer_email={this.props.footer_email}
footer_mobile={this.props.footer_mobile}
/>
</div>
);
}
}
App.defaultProps = {
// footer value
footer_address: '[34234] 서울특별시 강남구 삼성동 111-114',
footer_tel: '02-1234-5678',
footer_email: 'ljung5@naver.com',
footer_mobile: '010-3288-3398',
};
export default App
1. SoftwareTools 파일을 세팅한다.
react 경로 C:\react200\client\src\components에 SoftwareToolsManage폴더를 생성한다. 생성한 폴더안에 SoftwareList.js와 SoftwareView.js 파일을 만든다.
SoftwareView에 아래 소스를 붙여넣는다.
import React, { Component } from 'react';
import {Link} from 'react-router-dom';
class SoftwareView extends Component {
render () {
return (
<section class="sub_wrap">
<article class="s_cnt mp_pro_li ct1">
<div class="li_top">
<h2 class="s_tit1">Software Tools 등록/수정</h2>
</div>
<div class="bo_w re1_wrap re1_wrap_writer">
<form name="frm" id="frm" action="" onsubmit="" method="post" >
<input id="is_Swtcode" type="hidden" name="is_Swtcode" />
<input id="is_Email" type="hidden" name="is_Email" value="guest" />
<input id="is_beforeSwtcode" type="hidden" name="is_beforeSwtcode" value={this.state.before_swtcode} />
<article class="res_w">
<p class="ment" style={{"text-align": "right"}}>
<span class="red">(*)</span>표시는 필수입력사항 입니다.
</p>
<div class="tb_outline">
<table class="table_ty1">
<tr>
<th>
<label for="is_Swt_toolname">툴 이름<span class="red">(*)</span></label>
</th>
<td>
<input type="text" name="is_Swt_toolname" id="is_Swt_toolname" class="" />
</td>
</tr>
<tr>
<th>
<label for="is_Swt_demo_site">데모 URL<span class="red">(*)</span></label>
</th>
<td>
<input type="text" name="is_Swt_demo_site" id="is_Swt_demo_site" class="" />
</td>
</tr>
<tr>
<th>
<label for="is_Giturl">Github URL<span class="red">(*)</span></label>
</th>
<td>
<input type="text" name="is_Giturl" id="is_Giturl" class="" />
</td>
</tr>
<tr>
<th>
<label for="is_Comments">설명<span class="red">(*)</span></label>
</th>
<td>
<textarea name="is_Comments" id="is_Comments" rows="" cols=""></textarea>
</td>
</tr>
<tr class="div_tb_tr fileb">
<th>
메뉴얼 파일 #1
</th>
<td class="fileBox fileBox_w1">
<label for="uploadBtn1" class="btn_file">파일선택</label>
<input type="text" id="manualfile" class="fileName fileName1"
readonly="readonly" placeholder="선택된 파일 없음"/>
<input type="file" id="uploadBtn1" class="uploadBtn uploadBtn1"
onChange={e => this.handleFileInput('manual',e)}/>
<div id="upload_menual">
</div>
</td>
</tr>
<tr>
<th>
메인 이미지
</th>
<td className="fileBox fileBox1">
<label htmlFor='imageSelect' className="btn_file">파일선택</label>
<input type="text" id="imagefile" className="fileName fileName1"
readOnly="readonly" placeholder="선택된 파일 없음"/>
<input type="file" id="imageSelect" className="uploadBtn uploadBtn1"
onChange={e => this.handleFileInput('file',e)}/>
<div id="upload_img">
</div>
</td>
</tr>
<tr>
<th>
라벨 이미지
</th>
<td className="fileBox fileBox2">
<label htmlFor='imageSelect2' className="btn_file">파일선택</label>
<input type="text" id="imagefile2" className="fileName fileName1"
readOnly="readonly" placeholder="선택된 파일 없음"/>
<input type="file" id="imageSelect2" className="uploadBtn uploadBtn1"
onChange={e => this.handleFileInput('file2',e)}/>
<div id="upload_img2">
</div>
</td>
</tr>
<tr>
<th>
<label for="is_Swt_function">상세 기능<span class="red">(*)</span></label>
</th>
<td>
<textarea name="is_Swt_function" id="is_Swt_function" rows="" cols=""></textarea>
</td>
</tr>
</table>
<div class="btn_confirm mt20" style={{"margin-bottom": "44px"}}>
<Link to={'/SoftwareList'} className="bt_ty bt_ty1 cancel_ty1">취소</Link>
<a href="javascript:" className="bt_ty bt_ty2 submit_ty1 saveclass"
onClick={(e) => this.submitClick('save', e)}>저장</a>
<a href="javascript:" className="bt_ty bt_ty2 submit_ty1 modifyclass"
onClick={(e) => this.submitClick('modify', e)}>수정</a>
</div>
</div>
</article>
</form>
</div>
</article>
</section>
);
}
}
export default SoftwareView;
AdminSoftwareList 에 아래 소스를 붙여넣는다.
import React, { Component } from 'react';
import {Link} from 'react-router-dom';
import axios from "axios";
class SoftwareList extends Component {
constructor(props) {
super(props);
this.state = {
responseSwtoolList: '',
append_SwtoolList: '',
}
}
componentDidMount() {
this.callSwToolListApi()
}
callSwToolListApi = async () => {
axios.post('/api/Swtool?type=list', {
})
.then( response => {
try {
this.setState({ responseSwtoolList: response });
this.setState({ append_SwtoolList: this.SwToolListAppend() });
} catch (error) {
alert('작업중 오류가 발생하였습니다.');
}
})
.catch( error => {alert('작업중 오류가 발생하였습니다.');return false;} );
}
SwToolListAppend = () => {
let result = []
var SwToolList = this.state.responseSwtoolList.data
for(let i=0; i<SwToolList.json.length; i++){
var data = SwToolList.json[i]
var date = data.reg_date
var year = date.substr(0,4)
var month = date.substr(4,2)
var day = date.substr(6,2)
var reg_date = year +'.'+month+'.'+day
result.push(
<tr class="hidden_type">
<td>{data.swt_toolname}</td>
<td>{data.swt_function}</td>
<td>{reg_date}</td>
<td>
<Link to={'/SoftwareView/'+data.swt_code}
className="bt_c1 bt_c2 w50_b">수정</Link>
<a href="#n" class="bt_c1 w50_b" id={data.swt_code}
onClick={(e) => this.deleteSwtool(e)}>삭제</a>
</td>
</tr>
)
}
return result
}
render () {
return (
<section class="sub_wrap" >
<article class="s_cnt mp_pro_li ct1 mp_pro_li_admin">
<div class="li_top">
<h2 class="s_tit1">Software Tools 목록</h2>
<div class="li_top_sch af">
<Link to={'/SoftwareView/register'} className="sch_bt2 wi_au">Tool 등록</Link>
</div>
</div>
<div class="list_cont list_cont_admin">
<table class="table_ty1 ad_tlist">
<tr>
<th>툴 이름</th>
<th>기능</th>
<th>등록일</th>
<th>기능</th>
</tr>
</table>
<table class="table_ty2 ad_tlist">
{this.state.append_SwtoolList}
</table>
</div>
</article>
</section>
);
}
}
export default SoftwareList;
이 상태에서 서버를 구동하면 axios.post('/api/Swtool?type=list' 에서 node api를 호출하는데, node코드에 관련 라우터가 없어서 오류가 발생할 것이다.
2. node 코드를 수정하기전에 필요한 패키지들을 다운받는다.
cmd 또는 터미널을 열고 node경로 C:\react200에서 아래 명령어로 패키지들을 설치해 준다. mysql을 사용할 것이고, node 코드와 sql코드를 분리하기 위해 mybatis를 사용할 것이다. body-parser는 http 통신으로 request, response 데이터를 주고 받을 때, body에 있는 데이터를 파싱하기 위해 사용된다.
//node 경로로 이동
CD C:\react200
npm install --save mysql
npm install --save mybatis-mapper
npm install --save body-parser
## 참고 ##
mybatis는 자바 퍼시스턴트 프레임워크이다. persistent란 사용한 프로그램이 종료되어도 데이터는 남는다는 의미로, 쉽게 말해서 데이터베이스를 사용한다는 것이다.
자바에서 ORM(Object Relational Mapping)중 가장 많이 사용한다. 사용하는 가장 큰 이유는 비즈니스 소스와 sql 소스를 분리해서 개발할 수 있다는 점이다.
node도 마찬가지로 node 코드 사이에 sql을 깨워서 개발하는 방법보다는, 따로 분리시켜 개발 편의성과 유지보수 효율성을 높이기 위해 사용했다.
3. node 라우터, 모듈, 모델, db connection 관련 소스를 세팅한다.
node경로 C:\react200에서 server.js 파일을 열고 아래 소스를 붙여넣는다.
swtool관련 호출을 라우팅하는 코드가 추가되었다.
var express = require('express');
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var swtoolRouter = require("./routes/SwtoolRout");
var app = express();
app.use('/', indexRouter);
app.use('/users', usersRouter);
app.use("/api/Swtool", swtoolRouter);
const port = process.env.PORT || 5000;
app.listen(port, () => console.log(`Listening on port ${port}`));
node경로 C:\react200\routes에 SwtoolRout.js, dbconnect_Module.js 파일을 추가한다.
SwtoolRout.js파일에 아래 소스를 붙여넣는다.
var express = require('express');
var router = express.Router();
const bodyParser = require('body-parser');
router.use(bodyParser.urlencoded({ extended: true }));
router.use(bodyParser.json());
router.post('/', (req, res, next) => {
var type = req.query.type;
if(type == 'list'){
//Swtool 리스트 조회
try {
// Mysql Api 모듈(CRUD)
var dbconnect_Module = require('./dbconnect_Module');
//Mysql 쿼리 호출 정보 입력
req.body.mapper = 'SwToolsMapper';//mybatis xml 파일명
req.body.crud = 'select';//select, insert, update, delete 중에 입력
req.body.mapper_id = 'selectSwToolsList';
router.use('/', dbconnect_Module);
next('route')
} catch (error) {
console.log("Module > dbconnect error : "+ error);
}
}
});
module.exports = router;
dbconnect_Module.js 파일에 아래 소스를 붙여넣는다.
## 참고 ##
아래 코드에서 createPool()함수는 node서버와 mysql 서버 사이에 connection pool을 생성한 것이다. cp가 없다면 사용자마다 실행하는 쿼리마다 1개씩 커넥션이 생기고, 데이터 호출 후에 연결이 끊긴다. cp는 생성된 연결을 끊지 않고 유지시켜, 연결에 소모되는 자원을 줄일 수 있게 해준다.
connectionLimit : 66은 사용하고 있는 rds 서버 max connection수(동시접속허용수)가 66개 이기 때문에, 최대값으로 세팅했다.
서버가 켜지자마자 66개의 연결이 생기는 건 아니고, 커넥션이 생길 때마다 1개씩 증가해 그때까지 생성된 연결을 유지한다.
var express = require("express");
var router = express.Router();
const mysql = require("mysql");
const bodyParser = require("body-parser");
router.use(bodyParser.json());
router.use(bodyParser.urlencoded({ extended: true }));
// Connection Pool 세팅
const pool = mysql.createPool({
connectionLimit: 66,
waitForConnections: true,
host: "react200.#########.ap-northeast-2.rds.amazonaws.com",
port: "3306",
database: 'react',
user: "admin",
password: "react200RDS",
});
router.post("/", (req, res) => {
const mybatisMapper = require("mybatis-mapper");
var param = req.body;
//mybatis mapper경로 설정
mybatisMapper.createMapper(['./models/'+param.mapper+'.xml']);
var time = new Date();
console.log('## '+time+ ' ##');
console.log("\n Called Mapper Name = "+param.mapper);
var format = { language: 'sql', indent: ' ' };
//mysql 쿼리 정보 세팅
var query = mybatisMapper.getStatement(param.mapper, param.mapper_id, param, format);
console.log("\n========= Node Mybatis Query Log Start =========");
console.log("* mapper namespce : "+param.mapper+"."+param.mapper_id+" *\n");
console.log(query+"\n");
try {
pool.getConnection(function(err,connection){
connection.query(query, function (error, results) {
if (error) {
console.log("db error************* : "+error);
}
var time2 = new Date();
console.log('## '+time2+ ' ##');
console.log('## RESULT DATA LIST ## : \n', results);
if(results != undefined){
string = JSON.stringify(results);
var json = JSON.parse(string);
if (req.body.crud == "select") {
res.send({ json });
}else{
res.send("succ");
}
}else{
res.send("error");
}
connection.release();
console.log("========= Node Mybatis Query Log End =========\n");
});
})
} catch (error) {
console.log("pool error : "+error);
}
});
module.exports = router;
node경로 C:\react200\models\models 에 SwToolsMapper.xml 파일을 추가한다.
SwToolsMapper.xml 파일에 아래 소스를 붙여넣는다.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="SwToolsMapper">
<select id="selectSwToolsList">
SELECT
swt_code
, swt_toolname
, swt_function
, swt_imagepath
, swt_big_imgpath
, swt_comments
, swt_demo_site
, swt_manual_path
, swt_github_url
, reg_date
FROM react.react_swtool
<if test="is_Swtcode != null && is_Swtcode != ''">
WHERE swt_code = #{is_Swtcode}
</if>
ORDER BY update_date DESC
</select>
</mapper>
yarn dev 명령어로 서버를 다시 시작하고, 헤더에서 software tools 관리를 선택하면 아래와 같은 화면이 나온다.
이때, cmd 또는 터미널에 관련 쿼리와 결과 리스트가 출력된다.
리스트페이지에서 Tool 등록 버튼을 누르면, 아래와 같이 등록페이지가 노출된다.
https://taling.me/Talent/Detail/19341
강의 문의 : ljung5@naver.com
'탈잉 강의 자료 > 2020_비전공자도 가능한 웹 프로젝트' 카테고리의 다른 글
2-2강 : AWS RDS 서버 기타 설정 (0) | 2020.08.01 |
---|---|
2-1강 : AWS 회원 가입, RDS 인스턴스 생성, DB 서버 연결 (0) | 2020.08.01 |
1-3강 : html, css, img파일 세팅, 공공데이터 API 호출 (0) | 2020.08.01 |
1-2강 : react, node 개발환경 세팅, 프록시 설정 (0) | 2020.07.31 |
수업 목차 (0) | 2020.07.31 |