1.Node.js -MySQL 연결
이전까지의 MVC 포스팅에서는 MySQL을 연동하지 않았다.
2023.04.05 - [백앤드/Node.js] - [포스코x코딩온] 웹개발자 입문 과정 6주차 | MVC
이번 포스팅 부터는 MySQL을 연동하여 데이터 베이스에서 데이터를 가져온다.
먼저 MySQL을 연동을 위해서는 프로젝트 파일에서 MySQL패키지를 설치해야한다.
가. MySQL패키지 설치
cd 프로젝트 경로
npm install mysql
이후 프로젝트 내 package.json의 "dependencise"에서 mysql설치를 확인한다.
나. MySQL에서 DB 가져오는 방법
1) DB 연결 (model/ Visitor.js)
//1. mysql 불러옴
const mysql = require("mysql");
//2. database 연결
const conn = mysql.createConnection({
host: "localhost", // databse 가 설치된 ip 주소
user: "user", // 데이터베이스 접속 계정명
password: "1234", // 데이터베이스 접속 비번
database: "codingon", // 사용할 데이터베이스 이름
});
먼저 모델 단에서 mysql을 불러온 뒤 아래 처럼 database를 연결해준다.
이때 user로 root 계정을 사용하지 않는 이유는 mysql이
외부에서 root 계정으로 접속하는 것을 허용하지 않기 때문이다.
이때문에 user라는 새로운 계정을 만들어서 외부에서 접근할 수 있도록 해야하는데
아래가 계정을 생성하는 코드이다.
2) user 계정 생성 (sql문)
-- 생성된 계정 정보 확인
SELECT * FROM mysql.user;
-- 사용자 추가
CREATE USER 'user'@'%' IDENTIFIED WITH mysql_native_password BY '1234';
-- user 계정 권한 부여
GRANT ALL PRIVILEGES ON *.* TO 'user'@'%' WITH GRANT OPTION;
-- 현재 사용중인 mysql 캐시 지우고 새로 적용
FLUSH PRIVILEGES;
이 때 CREATE USER 'user'@'%' IDENTIFIED BY '1234'; 를 사용하는 대신
CREATE USER 'user'@'%' IDENTIFIED WITH mysql_native_password BY '1234' ;
를 사용하는 이유는 mysql 버전이 바뀌면서 비밀번호 해싱방식이 변경되었고,
연동하기 위해서는 예전 해싱방식인 mysql_native_password를 사용해야한다고 한다.
3) CRUD (model/ Visitor.js)
//(2) READ: 전체 조회 GET /visitor
exports.getVisitors = (callback) => {
const sql = "SELECT * FROM visitor;";
conn.query(sql, (err, rows) => {
if (err) {
throw err;
}
callback(rows);
});
};
//(3) CREATE: 생성 POST /visitor/write
exports.postVisitor = (data, callback) => {
const sql = `insert into visitor(name, comment) values('${data.name}', '${data.comment}');`;
conn.query(sql, (err, rows) => {
if (err) {
throw err;
}
callback(rows.insertId);
});
};
//(4) DELETE: 삭제 DELETE /visitor/delete
exports.deleteVisitor = (id, callback) => {
const sql = `delete from visitor where id=${id};`;
conn.query(sql, (err, rows) => {
if (err) {
throw err;
}
callback(true);
});
};
//(5) READ: 하나 조회(수정을 위한) GET /visitor/get
exports.getVisitor = (id, callback) => {
const sql = `select * from visitor where id=${id};`;
conn.query(sql, (err, rows) => {
if (err) {
throw err;
}
callback(rows[0]);
});
};
//(5)-4 UPDATE: 수정 PATCH /visitor/edit
exports.patchVisitor = (data, callback) => {
const sql = `update visitor set name='${data.name}', comment='${data.comment}' where id=${data.id};`;
conn.query(sql, (err, rows) => {
if (err) {
throw err;
}
callback();
});
};
모델 단에서 CRUD는 위와 같고 아래처럼 동작하기 위해서는
클라이언트단(ejs) 및 라우터 부분을 수정해야한다.
•Create(생성) - 작성후[등록] 버튼 을누르면 DB에 저장된다
•Read(읽기) - [등록]된 내용이 아래Table 에 [바로]보인다.
•Update(갱신) - [수정]을 누르면 방명록 수정이 가능하다.
•Delete(삭제) - [삭제]를 누르면 방명록이 삭제된다.
주석에서의 괄호 번호 (ex.(2))는 아래 코드에서 같은 번호로 주석이 있을 경우
동일한 부분 (ex.전체 조회) 을 담당한다.
2.클라이언트단, 라우터, 컨트롤러 수정
우선 프로젝트 구조는 아래와 같다.
다 다루지는 않을 것이고, 주요한 부분인 클라이언트단, 라우터부분, 컨트롤러 부분만
다뤄본다.
가. 클라이언트단 (views/visitor.ejs)
1) 생성 POST /visitor/write 폼 [등록] 버튼 클릭시 테이블 데이터 추가
const tbody = document.querySelector("tbody");
const buttonGroup = document.querySelector("#button-group");
//(3) 생성 POST /visitor/write 폼 [등록] 버튼 클릭시 테이블 데이터 추가
function createVisitor() {
const form = document.forms["visitor-form"];
axios({
method: "POST",
url: "/visitor/write",
data: {
name: form.name.value,
comment: form.comment.value,
},
}).then((res) => {
const newVisitor = `
<tr id="tr_${res.data.id}">
<td>${res.data.id}</td>
<td>${res.data.name}</td>
<td>${res.data.comment}</td>
<td><button type="button" onclick="editVisitor(${res.data.id})">수정</button></td>
<td><button type="button" onclick="deleteVisitor(this,${res.data.id})">삭제</button></td>
</tr>`;
// insertAdjacentHTML(): 특정 요소에 html 추가 , jQuery.append()와 동일
// vs. innerHTML: 내부 코드 덮어씌움
tbody.insertAdjacentHTML("beforeend", newVisitor);
});
}
2) 삭제 DELETE /visitor/delete
//(4) 삭제 DELETE /visitor/delete
function deleteVisitor(obj, id) {
console.log("obj", obj);
console.log("id", id);
//alert는 확인버튼만 confirm은 확인, 취소 버튼 2개
// !false = true
if (!confirm("정말 삭제하시겠습니까?")) {
return;
}
// confirm에서 [확인] 버튼 클릭 시 실행할 코드
axios({
method: "DELETE",
url: "/visitor/delete",
data: {
id: id,
},
}).then((res) => {
document.getElementById(`tr_${id}`).remove();
//삭제하는 다른 방법
//obj.parentElement.parentElement.remove();
//obj.closest(`#tr_${id}`).remove(); //가장 가까운 선택자 찾아감
});
}
3)조회(수정을 위한) GET /visitor/get
//(5) 조회(수정을 위한) GET /visitor/get
function editVisitor(id) {
console.log(id);
axios({
method: "GET",
url: "/visitor/get",
params: {
id: id,
},
}).then((res) => {
//(5)-1 클릭한 값 조회
console.log(res.data); //rows[0] { id: 10, name: '아리수', comment: '22' }
//(5)-2 form input 값 넣기
const form = document.forms["visitor-form"];
form.name.value = res.data.name; //input[name='name']에 value 설정
form.comment.value = res.data.comment; //input[name='comment']에 value 설정
//(5)-3 [변경], [취소] 버튼 보여주기 (buttonGroup에 덮어씌움)
const btns = `
<button type='button' onclick='editDo(${id})'>변경</button>
<button type='button' onclick='editCancel()'>취소</button>
`;
buttonGroup.innerHTML = btns;
});
}
4) 수정PATCH /visitor/edit
//(5)-4. PATCH /visitor/edit [변경] 버튼 눌렀을 떄 데이터 수정
async function editDo(id) {
const form = document.forms["visitor-form"];
await axios({
method: "PATCH",
url: "/visitor/edit",
data: {
id: id,
name: form.name.value,
comment: form.comment.value,
},
}).then((res) => {
console.log(res.data);
//(5)-4-1. 수정성공 메세지 띄우기
alert(res.data);
//(5)-4-2. 수정내용 반영
const children = document.querySelector(`#tr_${id}`).children;
// console.log(children); //[td, td, td, td, td]
children[1].textContent = form.name.value;
children[2].textContent = form.comment.value;
});
}
나. 라우터 (routes/index.js)
const express = require("express");
const controller = require("../controller/Cvisitor");
const router = express.Router();
// (1) GET /
router.get("/", controller.main);
// (2) GET /visitor
router.get("/visitor", controller.getVisitors); //'s' 전체 조회
// (3) 생성 POST /visitor/write
router.post("/visitor/write", controller.postVisitor); // 하나 추가
// (4) 삭제 DELETE /visitor/delete
router.delete("/visitor/delete", controller.deleteVisitor); //하나 삭제
// (5) 조회(수정을 위한) GET /visitor/get
router.get("/visitor/get", controller.getVisitor); //하나 조회
// (5)-4 수정 PATCH /visitor/edit
router.patch("/visitor/edit", controller.patchVisitor); //하나 수정
module.exports = router;
다. 컨트롤러(controller/Cvisitor.js)
// Comment = {getComments: ()=>{}}
const Visitor = require("../model/Visitor");
// (1) GET /
exports.main = (req, res) => {
res.render("index");
};
// (2) 조회 GET /visitor
exports.getVisitors = (req, res) => {
//[after] mysql 연결
// rows -> result
Visitor.getVisitors((result) => {
console.log("(2).Cvisitor.js >> ", result);
//[{},{}]
res.render("Visitor", { data: result });
});
};
// (3) 생성 POST /visitor/write
exports.postVisitor = (req, res) => {
console.log("(3)-1. Cvisitor.js >>", req.body);
Visitor.postVisitor(req.body, (result) => {
console.log("(3)-2. Cvisitor.js >>", result); //model 코드에서 데이터를 추가한 결과인 row.insertId
res.send({ id: result, name: req.body.name, comment: req.body.comment });
});
};
// (4) 삭제 DELETE /visitor/delete
exports.deleteVisitor = (req, res) => {
console.log("(4)-1. Cvisitor.js >>", req.body); //{id:n}
Visitor.deleteVisitor(req.body.id, (result) => {
console.log("(4)-2. Cvisitor.js >>", result);
res.send("삭제 성공!!");
});
};
// (5) 조회(수정을 위한) GET /visitor/get
exports.getVisitor = (req, res) => {
console.log("(5)-1. Cvisitor.js >>", req.query); //{id:n}
Visitor.getVisitor(req.query.id, (result) => {
console.log("(5)-2. Cvisitor.js >>", result); //model 코드에서 callback에 넘긴 rows[0]
res.send(result); //{ id: 10, name: '아리수', comment: '22' }
});
};
// (5)-4 수정 PATCH /visitor/edit
exports.patchVisitor = (req, res) => {
console.log("(5)-4-1. Cvisitor.js >>", req.body);
Visitor.patchVisitor(req.body, () => {
res.send("수정 성공!");
});
};
3. 전체 코드
https://github.com/jayoung977/web/tree/main/BackEnd/20230405-20230406/13_mvc_mysql
'백앤드 > Node.js' 카테고리의 다른 글
[포스코x코딩온] 웹개발자 입문 과정 6주차 | Sequelize (0) | 2023.04.10 |
---|---|
[포스코x코딩온] 웹개발자 입문 과정 6주차 | MySQL 서버 설치, pm2 (0) | 2023.04.10 |
[포스코x코딩온] 웹개발자 입문 과정 6주차 | MVC 실습 - 여러 유저 정보 선언 후 로그인 성공 여부 판단하기 (0) | 2023.04.06 |
[포스코x코딩온] 웹개발자 입문 과정 6주차 | MVC (0) | 2023.04.05 |
[포스코x코딩온] 웹개발자 입문 과정 5주차 | 파일 업로드 (0) | 2023.04.03 |