학사 연구원 8개월차 (velog에 썼던 2022년 11월 글입니다..ㅎㅎ)
교수님께서 oracle18c와 node.js를 연동시켜보라고 주문하셨다.
하지만 MacOS 환경에서 npm을 이용해서는 oracledb 모듈을 설치할 수가 없었다 🥲
눈물을 머금고 MySQL을 이용해서 최대한 비슷하게 연습하고,
Windows 환경으로 코드를 옮겨서 연결할 DB만 바꾸는 식으로 진행하고자 했다.
구조는 mySQL에서 데이터를 불러와 서버에 던져주면, 받은 데이터를 웹 페이지 상에 출력하는 형태다.
맨땅에 헤딩하듯 node.js를 이용해서 첫 결과물을 만들어냈는데, 처음에는 감도 안잡히고 너무 어려웠지만 여러 개발자분들의 블로그를 읽어보면서 하나하나 만들어보니 나름대로 개념도 좀 잡히는 느낌이고 자신감도 생겼다!
다른 개발자분들도 이 글을 보고 도움을 받았으면 하는 마음에 글을 적어본다!
📌 실행 화면
📄 메인페이지
데이터가 출력될 테이블의 틀만 생성해두었다.
버튼을 눌러서 필요한 작업을 하면 된다.
⚙️ 데이터 불러오기 기능
지정된 query를 수행해서 화면과 같이 테이블을 조회해서 페이지로 뿌려주는 기능을 한다!
⚙️ 데이터 지우기 기능
마땅한 단어가 떠오르지 않아서 데이터 지우기 버튼이라고 이름을 지었는데,
글을 쓰다보니 데이터 감추기라고 하는게 좋아보여 이름을 수정했다.
테이블의 데이터를 지우는 버튼이 아니라, 출력된 테이블을 다시 감추는 기능을 한다!
⚙️ 데이터 입력 기능
테이블에 새로 입력할 데이터를 입력한 뒤, 데이터 입력버튼을 누르면 query를 수행하는 기능을 한다!
유효성 검사나 데이터 입력이 되면 alert하는 기능도 구현하고 싶었는데, 우선 간단히 해보는 것이라 나중에 시간이 되면 해볼 것 같다.
✅ 데이터 입력이 완료된 경우
아래 14번째 row에 입력했던 데이터들이 잘 삽입된 것을 확인할 수 있었다.
✅ MySQL에서의 반영 여부 확인
MySQL 상에서도 잘 연동되어 수행한 작업들이 적용되어 있는 모습이다!
📌 소스코드
📄 config.js
const mysql = require('mysql');
module.exports = {
getConnection : mysql.createConnection({
host:'호스트명',
user:'유저ID',
password:'유저PW',
database:'연결할 DB'
})
}
host, user, password, database를 개별 환경에 맞춰 선언하고, mysql.createConnection으로 MySQL DB에 접속할 수 있도록 한다.
getConnection을 exports 해주면, 이후 다른 js파일에서 require()을 통해 불러올 수 있게 된다!
보통 mysql.createConnection을 메인 코드에 같이 작성해도 되는데, 그렇게 되면 연결 정보가 그대로 메인 코드에 노출되므로 분리된 코드로 작성했다.
📄 main.js
const express = require('express');
const app = express();
const fs = require('fs');
const ejs = require('ejs');
const mainPage = fs.readFileSync('./index.ejs', 'utf8');
const inputPage = fs.readFileSync('./input.ejs', 'utf8');
const bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({extended : true}));
app.use(bodyParser.json());
const config = require('./config');
var conn = config.getConnection;
var n1, n2, n3, v1, v2, v3;
app.get('/', (req, res) => {
var page = ejs.render(mainPage, {
title: "MySQL DB",
});
res.send(page);
});
app.get('/getdata', (req, res) => {
conn.query("SELECT * FROM general;", function(err, result){
if(err) throw err;
else{
var page = ejs.render(mainPage, {
title: "MySQL DB",
data: result,
});
res.send(page);
}
});
});
app.get('/move', (req, res) => {
var page = ejs.render(inputPage, {
title: "Input",
});
res.send(page);
});
app.post('/submit', (req, res) => {
n1 = req.body.n1;
n2 = req.body.n2;
n3 = req.body.n3;
v1 = req.body.v1;
v2 = req.body.v2;
v3 = req.body.v3;
conn.query("INSERT INTO general VALUES('"+n1+"','"+n2+"','"+n3+"','"+v1+"','"+v2+"','"+v3+"');", function(err, result) {
if(err) throw err;
else {
}
});
res.redirect('/move');
});
app.listen(3400, () => {
console.log('Server Running... (port:3400);
});
DB에서 불러온 데이터를 효과적으로 페이지에 출력할 방법을 찾던 도중, ejs에 대해 알게 되어서 이를 사용하게 되었다.
ejs는 html에 JSP에서 사용했던 것처럼 스크립틀릿을 이용해서 자바스크립트 코드를 넣을 수 있는 느낌이었다.
이를 이용하기 위해서 fs모듈과 ejs모듈을 불러왔다.
데이터베이스에서 불러온 데이터를 페이지에 띄울 수 있도록 파싱을 하기 위해 body-parser 모듈도 불러왔는데, 사실 현재는 express 모듈에 자체적으로 body-parser가 내장되어 있어서 따로 불러올 필요는 없다고 들었다.
그래도 혹시 몰라서 불러와서 사용하는 쪽으로 코드를 짰다..ㅎㅎ
라우터에 .use(bodyParser.urlencoded({extended : true})); 속성과 .use(bodyParser.json());을 지정해주어야 사용할 수 있다고 한다.
fs.readFileSync를 이용해 미리 만들어준 페이지들을 변수에 저장해주는 과정도 거쳐야 한다.
다음으로 라우팅을 통해 url별로 이벤트를 나눠주었다.
라우터를 사용하기 위해 공부하면서 들은 설명 중에서는 일종의 **네비게이션** 역할이라고 하는 설명이 가장 와닿았던것 같다!
경로가 '/'인 경우에는 MySQL DB라는 제목의 페이지를 띄울 수 있도록 하였다.
'/getdata'의 경우에는 select 쿼리를 수행하도록 하였으며 결과에 대해서 function을 적용했는데, 잘 수행될 경우에는 그 결과인 result를 data에 담아서 메인페이지로 전송하도록 하였다.
'/move'의 경우에는 데이터를 입력받아 DB로 전송하기 위한 페이지인 input페이지로 이동시켜준다.
마지막으로 '/submit'인데, post 방식으로 데이터를 교환하도록 하였다.
**_(사실 아무것도 모르고 get방식으로 코드를 짰다가 한참 안되서 골머리를 앓았다.)_**
요청한 페이지의 body에 있는 n1~v3에 해당하는 데이터들을 받아와 변수에 저장하고, 이들을 insert 쿼리로 db에 저장하도록 했다.
수행이 완료되면 다시 아무것도 입력하기 전인 input페이지로 돌아오도록 하기 위해 '/move'로 redirect 시켜주었다.
마지막으로 app.listen을 통해 3400번 포트로 서버를 뚫어주었다.
📄 index.ejs
<!DOCTYPE html>
<html>
<head>
<title>
<%= title %>
</title>
<meta charset="utf-8">
</head>
<style>
body {
background-color: black;
color: white;
line-height: 25pt;
}
h2 {
text-align: center;
}
#btn1 {
width: 50vw;
margin-left : 25vw;
text-align: center;
font-size: 20px;
}
p {
text-align: center;
font-size: large;
font-weight: bold;
}
table {
width: 50vw;
margin-left : 25vw;
}
</style>
<body>
<h2> [MySQL DB 데이터 불러오기] </h2>
<form action="/getdata" method="GET" id="btn1">
<button type="submit">데이터 불러오기</button>
</form>
<form action="/" method="GET" id="btn1">
<button type="submit"> 데이터 감추기 </button>
</form>
<form action="/move" method="GET" id="btn1">
<button type="submit"> 데이터 입력 </button>
</form>
<hr>
<p> General Table </p>
<hr>
<br>
<table border="1" bordercolor="white">
<th width = 50> </th>
<th> 소음 데이터1 </th>
<th> 소음 데이터2 </th>
<th> 소음 데이터3 </th>
<th> 진동 데이터1 </th>
<th> 진동 데이터2 </th>
<th> 진동 데이터3 </th>
<% if(locals.data){ %>
<% var i = 1 %>
<% data.forEach(function(val){ %>
<tr align = "center">
<td width = 50> <%= i %> </td>
<td> <%= val.n1 %> </td>
<td> <%= val.n2 %> </td>
<td> <%= val.n3 %> </td>
<td> <%= val.v1 %> </td>
<td> <%= val.v2 %> </td>
<td> <%= val.v3 %> </td>
</tr>
<% i = i + 1 %>
<% }) %>
<% } %>
</table>
</body>
</html>
메인페이지에 해당하는 페이지이다.
스타일은 지극히 개인취향이며,
테이블에 if문과 for문을 이용해, 데이터가 존재할 시에는 테이블 칼럼명을 이용해 원하는 데이터를 적절한 위치에 출력할 수 있도록 했다.
form 태그의 action에는 아까 라우팅으로 지정한 이벤트 명을 넣어 해당 기능을 수행하도록 해주면 된다!
📄 input.ejs
<!DOCTYPE html>
<html>
<head>
<title>
<%= title %>
</title>
<meta charset="utf-8">
</head>
<style>
body {
background-color: black;
color: white;
line-height: 25pt;
}
input {
width: 30px;
margin-left: 10px;
text-align: center;
}
#btn1 {
width: 50vw;
margin-left : 25vw;
text-align: center;
font-size: 20px;
}
div {
width: 50vw;
margin-left: 39vw;
}
div.txt {
width: 50vw;
margin-left: 39.8vw;
word-spacing: 13px;
}
h2 {
text-align: center;
}
</style>
<body>
<h2> DB에 입력할 데이터 입력 </h2>
<hr>
<div class="txt">
소음1 소음2 소음3 진동1 진동2 진동3
</div>
<form action="/submit" method="POST" id="btn1">
<input type="text" name="n1" autofocus="true">
<input type="text" name="n2">
<input type="text" name="n3">
<input type="text" name="v1">
<input type="text" name="v2">
<input type="text" name="v3">
<br>
<button type="submit"> 데이터 입력 </button>
</form>
<form action="/" method="GET" id="btn1">
<button type="submit"> 메인 페이지로.. </button>
</form>
</body>
</html>
input페이지에 해당하는 페이지로,
특별한 부분 없이 그저 데이터를 입력받기 위한 페이지이다!
📌 어려웠던 점
bodyparser의 존재를 잘 몰라서 처음에는 데이터 포맷이 맞지 않아 자꾸만 원하는 대로 데이터가 출력되지 않고 에러나 깨짐이 발생해서 머리가 너무 아팠는데, bodyparser 모듈과 ejs파일을 통해서 데이터를 출력해보니 너무 잘 되어서 기분이 너무 좋았었다.