강의를 통해 배우는 첫 백엔드 설정 예제를 진행해보았다.
mongoDB와 node.js를 연결하고 백엔드 설정을해서 프론트엔드와 소통하는 할일 앱을 만드는 과제.
사실 한번에 너무 방대한 양을 배우는 데다가 페이지가 잘게 쪼개져 있어서 아직도 좀 아리송한 부분들은 있지만 대략적으로는 백엔드와 프론트엔드가 어떻게 돌아가는지 알게 된 것 같다.
시작 전에 npm을 이용해서 express, mongoose, body-parser를 설치. (바디파서는 이제 설치 필요 없음)
express를 이용해서는 서버를 간편하게 열 수 있었고 mongoose를 이용해서 mongoDB 스키마를 설계할 수 있었다.
const express = require('express');
const mongoose = require('mongoose');
const indexRouter = require('./routes/index');
const cors = require("cors");
const app = express();
app.use(cors()); //제일 먼저 있어야 함
app.use(express.json());
app.use(indexRouter);
const mongoURI = `mongodb://127.0.0.1:27017/todo-app`
mongoose.connect(mongoURI).then(() => {
console.log('mongoose connected!');
}).catch((err) => {
console.log('DB connection fail!', err);
});
app.listen(5001, () => {
console.log('server on 5001!');
});
app.js
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const taskSchema = Schema({
task: {
type: String,
required: true
},
isComplete: {
type: Boolean,
required: true
}
},
{ timestamps: true }
);
const Task = mongoose.model('Task', taskSchema);
module.exports = Task;
model/Task.js
gpt에게 물어보니 body-parser는 최신 express를 설치하면 포함되어있다고해서 따로 필요 없다고 했다.
원래 설치를하고 불러와서 아래 코드를 해줬어야했는데
app.use(bodyParser.json());
이제 익스프레스만 설치하고 이렇게 적어주면 된다.
app.use(express.json());
api 관리는 라우팅이라는 방식으로 했는데 꽤 흥미있는 지점이었다.
아직 복잡하지 않은 코드여서 실효성이 크진 않았는데 파일이 복잡해지면 실효성이 클 것 같다.
const express = require('express');
const router = express.Router();
const taskApi = require('./task.api')
router.use('/tasks', taskApi);
module.exports = router;
routes/index.js
const express = require('express');
const taskController = require('../controller/task.controller');
const router = express.Router();
router.post('/', taskController.createTask);
router.get('/', taskController.getTask);
router.put('/:id', taskController.updateTask);
router.delete('/:id', taskController.deleteTask);
module.exports = router;
routes/task.api.js
가장 메인작업은 컨트롤러라는 파일에서 이루어졌다.
CRUD라 불리는 백엔드의 4가지 큰 기능을 여기서 세부적으로 짰다.
생성이나 읽기는 강의를 들어가며 큰 어려움 없이 짤 수 있었다.
const Task = require('../model/Task')
const taskController = {};
taskController.createTask = async (req, res) => {
try{
const {task, isComplete} = req.body;
const newTask = new Task({task, isComplete});
await newTask.save();
res.status(200).json({status:'ok', data:newTask});
} catch(err){
res.status(400).json({status:'fail', error:err});
}
};
taskController.getTask = async (req, res) => {
try{
const taskList = await Task.find({}).select("-__v");
res.status(200).json({status:'ok', data:taskList});
} catch(err){
res.status(400).json({status:'fail', error:err});
}
};
컨트롤러 코드 중 읽기, 생성 코드
그런데 업데이트 부분은 처음 마주하는 개념들이 많아서 햇갈렸는데 gpt에게 물어가며 조금씩 이해해갔다.
taskController.updateTask = async (req, res) => {
try {
const task = await Task.findById(req.params.id);
if (!task) {
throw new Error("App can not find the task");
}
const fields = Object.keys(req.body);
fields.map((item) => (task[item] = req.body[item]));
await task.save();
res.status(200).json({ status: "success", data: task });
console.log(fields);
} catch (error) {
res.status(400).json({ status: "fail", error });
}
};
taskController.deleteTask = async (req, res) => {
try {
const deleteItem = await Task.findByIdAndDelete(req.params.id);
res.status(200).json({ status: "success", data: deleteItem });
} catch (error) {
res.status(400).json({ status: "fail", error });
}
};
module.exports = taskController;
여기서 req.params.id는 프론트에서 url /tasks 뒷부분에 붙여보내는 id 값이며
이 값은 곧 mongoDB에서 자동생성된 고유 id 값이기도 하다.
const fields = Object.keys(req.body);
fields.map((item) => (task[item] = req.body[item]));
이 코드도 햇갈렸었는데 분석해보면 프론트에서 보내는 바디 객체의 ‘키’ 값,
즉 키밸류 중 키 부분들만 fields라는 변수에 배열로 저장한다. 지금 예제의 경우 task와 isComplete라는 값이다.
프론트로부터 수정된 body값을 가져와서 map기능을 이용해서 기존 task에 덮어씌워 저장하는 방식.
delete도 req.params.id를 통해 제어한다는게 특이할 뿐 그 이상의 특이점은 없었다.
이렇게 첫 백엔드 구축 완료!
프론트엔드 구축 전 백엔드 테스트용으로 포스트맨 (post man)이라는 사이트를 이용해봤는데
쉽게 백엔드 테스트를 해볼 수 있어서 좋았다.
특히 포스트나 업데이트같은 부분은 프론트 구축이 안되어있으면 테스트가 힘든데 포스트맨을 이용하니 즉석으로 테스트 해볼 수 있었다.
postman으로 POST를 테스트한 장면
프론트엔드는 제대로 todo-app ui를 만들기 전에 서버와 통신이 잘 되는지만 간단하게 테스트 해보았다.
처음 시도하면 cors에러가 나는데 이를 해결하기 위해서는 npm install cors로 cors문제 해결 모듈을 설치해주고
const express = require('express');
const mongoose = require('mongoose');
const indexRouter = require('./routes/index');
const cors = require("cors");
const app = express();
app.use(cors()); //제일 먼저 있어야 함
app.use(express.json());
app.use(indexRouter);
서버측 app.js에서 이런식으로 cors를 가져와서 사용을 해줘야한다. (use(cors())의 순서 중요!)
일단 간단하게 네 개 버튼을 만들고 fetch api를 이용해서 내가 만든 서버 데이터를 가져와보는 테스트를 해보았고 생각보다 잘 가져와졌다.
프론트엔드 테스트
강의는 리액트 기반으로 프론트엔드가 구축되는데 나는 생 자바스크립트로 도전해볼 생각이다.
아직은 감을 잡아나가는 단계지만 백엔드는 백엔드만의 묘미가 있어 재미있게 느껴진다.