-
[Node.js] for MacOS / VSCdoe + express + mysql + CRUD 예제Node.js 2022. 6. 5. 16:45반응형
개요
- Node.js의 Express 프레임 워크로 MySQL에 연동해서 서버를 구축
구축방법
- Express 웹 서버 실행.
- MySQL 데이터베이스 Configuration 설정
- School 라는 샘플 모델 생성 후 컨트롤러 작성
- CRUD 작업을 처리하기 위한 routes를 정의
1. 테이블 생성하기
CREATE TABLE `school_tb` ( `id` int(11) NOT NULL, `nm` varchar(100) DEFAULT NULL, `age` varchar(100) DEFAULT NULL, `class` varchar(100) DEFAULT NULL, `grade` varchar(100) DEFAULT NULL, PRIMARY KEY (`seq`) )
2. 편한 방법으로 프로젝트 폴더 생성하기
// mkdir로 생성해도 된다.
3. 프로젝트 폴더에서 npm init 실행
npm init
엔터를 계속 치면 프로젝트 내부에 package.json 파일이 생성된다.
4. Express, mysql, body-parser 모듈을 설치
npm install express mysql body-parser --save
package-lock.json 파일이 생성되고 안에 의존성관련 내용들이 있다.
5. Express 웹 서버 세팅
server.js 파일을 생성 후 내용을 입력한다.
const express = require("express"); const bodyParser = require("body-parser"); const app = express(); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({extended: true})); app.get("/", (req, res)=>{ res.json({message: "Hello Node!"}); }); // 포트넘버 설정 app.listen(3000, ()=>{ console.log("Server is running on port 3000."); })
- Express, bodyParser 모듈 import. (Express: Restapi 구축을 위한 프레임워크 / Body-parser: request를 분석하고, routes에 엑세스 해야 하는 req.body 개체를 만들기 위해 사용)
- express app을 만든다음 app.use()를 사용해서 body-parser 미들웨어 추가
- 테스트 하기 쉽게 간단한 get 경로 정의
- 포트 3000에서 request 요청 수신
6. 실행 테스트
- 터미널 실행 테스트
//노드 실행 node server.js //결과 console.log Server is running on port 3000.
- 브라우저 실행 테스트
//출력 확인 {"message":"Hello Node!"}
7.MySQL configuration 작성 및 연동
- app/config 폴더를 생성후 안에 db.config.js파일을 생성한다. 그리고 데이터베이스 계정 접속 정보 내용을 추가한다.
module.exports = { HOST: "localhost", USER: "root", PASSWORD: "1234", DB: "study" };
8. model 정의
- app/model 폴더를 생성후 school.model.js 파일을 생성한다. 이 파일에는 학급 객체에 대한 생성자를 정의하고, 데이터베이스 연결을 사용해서 CRUD 기능일 실행한다.
작성할 CURD Function
1. 새 학생 생성
2. id로 학생 테이블 조회
3. 전체 테이블 조회
4. id로 학생 데이터 업데이트
5. id로 학생 데이터 삭제
6. 전체 고객 데이터 삭제
school.model.js 작성
const sql = require("./db.js"); //생성자 const School = function(school){ this.nm = school.nm; this.age = school.age; this.grade = school.grade; this.class = school.class; }; // school 인서트 School.insert = (newSchool, result)=>{ sql.query("INSERT INTO school SET ?", newSchool, (err, res)=>{ if(err){ console.log("error: ", err); result(err, null); return; } console.log("Insert school: ",{id:res.inseertId, ...newSchool }); result(null, {id: res.inseertId, ...newSchool}); }); }; // school id로 조회 School.findOne = (schoolID, result)=>{ console.log("::::findOne "+schoolID); console.log("::::result "+result); sql.query('SELECT * FROM school WHERE id = ?',schoolID, (err, res)=>{ if(err){ console.log("error: ", err); result(err, null); return; } if(res.length){ console.log("found school: ", res[0]); result(null, res[0]); return; } // 결과가 없을 시 result({kind: "not_found"}, null); }); }; // school 전체 조회 School.getAll = result =>{ sql.query('SELECT * FROM school ', (err, res)=>{ if(err){ console.log("error: ", err); result(err, null); return; } console.log("school: ", res); result(null, res); }); }; // school id로 수정 School.update = (id, school, result)=>{ console.log("::::update "+id); console.log("::::school "+school); sql.query('UPDATE school SET nm = ?, age = ?, grade = ?, class = ? WHERE id = ?', [school.age, school.grade, school.class, id], (err, res)=>{ if(err){ console.log("error: ", err); result(err, null); return; } if(res.affectedRows ==0){ // id 결과가 없을 시 result({kind: "not_found"}, null); return; } console.log("update school: ", {id:id, ... school}); result(null, {id:id, ...school}); }); }; // school id로 삭제 School.remove = (id, result)=>{ console.log("::::remove "+id); console.log("::::result "+result); sql.query('DELETE FROM school WHERE id = ?',id, (err, res)=>{ if(err){ console.log("error: ", err); result(err, null); return; } if(res.affectedRows ==0){ // id 결과가 없을 시 result({kind: "not_found"}, null); return; } console.log("deleted school with id: ", id); result(null, res); }); }; // school 전체 삭제 School.removeAll = result =>{ sql.query('DELETE FROM school',(err, res)=>{ if(err){ console.log("error: ", err); result(err, null); return; } if(res.affectedRows ==0){ // id 결과가 없을 시 result({kind: "not_found"}, null); return; } console.log('deleted ${res.affectedRows} school '); result(null, res); }); }; module.exports = School;
9.Routes 정의
HTTP 요청(GET, POST, PUT, DELETE)을 받았을 때 어떻게 응답할지 route 정의하는 것
- /school: GET, POST, DELETE
- /school/:schoolID: GET, PUT, DELETE
app/routes 폴더 생성하고 school.routes.js 파일을 작성한다.
module.exports = app =>{ const school = require("../controllers/school.controller.js"); // 인서트 app.post("/school", school.insert); // 전체 조회 app.get("/school", school.findAll); // id로 조회 app.get("/school/:schoolId", school.findOne); // id로 수정 app.put("/school/:schoolId", school.update); // id로 삭제 app.delete("/school/:schoolId", school.delete); // 전체 삭제 app.delete("/school", school.deleteAll); };
작성한 routes.js 파일을 server.js에 포함시킨다.
server.js
const express = require("express"); const bodyParser = require("body-parser"); const app = express(); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({extended: true})); app.get("/", (req, res)=>{ res.json({message: "Hello Node!"}); }); require("./app/routes/school.routes.js")(app); // 포트넘버 설정 app.listen(3000, ()=>{ console.log("Server is running on port 3000."); })
10. Controller 작성
app/controller 폴더를 생성하고 school.controller.js 파일을 작성한다. 컨트롤레 안에 CRUD function을 구현할 것
const School = require("../models/school.model.js"); // 새 객체 생성 exports.insert = (req,res)=>{ if(!req.body){ res.status(400).send({ message: "Content can not be empty!" }); }; const school = new School({ nm: req.body.nm, age: req.body.age, grade: req.body.grade, class: req.body.class }); // 데이터베이스에 저장 School.insert(school, (err, data) =>{ if(err){ res.status(500).send({ message: err.message || "Some error occured while creating th School." }); }else { res.send("저장을 성공 하였습니다."); } }) }; // 전체 조회 exports.findAll = (req,res)=>{ School.getAll((err, data) => { if (err) res.status(500).send({ message: err.message || "Some error occurred while retrieving school." }); else res.send(data); }); }; // id로 조회 exports.findOne = (req,res)=>{ School.findOne(req.params.schoolId, (err, data) => { if (err) { if (err.kind === "not_found") { res.status(404).send({ message: `Not found School with id ${req.params.schoolId}.` }); } else { res.status(500).send({ message: "Error retrieving School with id " + req.params.schoolId }); } } else res.send(data); }); }; // id로 갱신 exports.update = (req,res)=>{ // Validate Request if (!req.body) { res.status(400).send({ message: "Content can not be empty!" }); } School.update( req.params.schoolId, new School(req.body), (err, data) => { if (err) { if (err.kind === "not_found") { res.status(404).send({ message: `Not found School with id ${req.params.schoolId}.` }); } else { res.status(500).send({ message: "Error updating School with id " + req.params.schoolId }); } } else res.send(data); } ); }; // id로 삭제 exports.delete = (req,res)=>{ School.remove(req.params.schoolId, (err, data) => { if (err) { if (err.kind === "not_found") { res.status(404).send({ message: `Not found School with id ${req.params.schoolId}.` }); } else { res.status(500).send({ message: "Could not delete School with id " + req.params.schoolId }); } } else res.send({ message: `School was deleted successfully!` }); }); }; // 전체 삭제 exports.deleteAll = (req,res)=>{ School.removeAll((err, data) => { if (err) res.status(500).send({ message: err.message || "Some error occurred while removing all school." }); else res.send({ message: `All School were deleted successfully!` }); }); };
11. API 테스트 (with postman)
VS code 터미널에서 다음 명령어를 입력해서 실행한다.
node server.js // npm start 도 가능.
#서버 구동시 아래의 에러 발생시 해결방법
Error: listen EADDRINUSE: address already in use :::3000
찾기
lsof -i :포트번호
ex) lsof -i :3000
//포트 목록이 나온다.
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
node 2309 devmk 23u IPv6 0xd4b4f63f02931517 0t0 TCP *:hbci (LISTEN)
kill하기 (pid 입력)
kill -9 PID번호
ex) kill -9 2309
PID입력하여 비정상으로 종료된 중복 포트를 제거한다.
다시 서버를 구동하면 아래의 메세지가 출력된다면 정상이다.
- POST /school 인서트
- GET /school 전체 칼럼 조회
- GET /school/:id 단건조회
- PUT /school/:id 단건수정
- DELETE /school/:id 단건삭제
- DELETE /school/ 전체삭제
본문의 출처
https://expressjs.com/ko/
https://1-day-1-coding.tistory.com/51
반응형