이번주차의 과제는 간단하게 nodejs와 express를 사용하여 로그인 기능이 없는 CRUD 게시판을 만드는것이다.
실제로 구현까지 많은 시간이 걸리지 않았는데 배포부분은 아직도 잘 모르는것 투성이다.
하지만 늘 그랬듯, 잘하는것이 중요한게 아니라 꾸준히 알아가는것이 중요하기에
포기만 하지 않으면 된다.
이번 과제의 기본적인 구조는 간단한 디자인 패턴중 하나인 MVC모델을 전제로 가져가는것같다.
![]()
몇년전만 해도 MVC가 뭐가 뭔지도 몰랐는데 지금은 너무 간단하다고 생각되는 모델중 하나라니 참 감회롭긴 하다.
일단 가볍게 과제의 기본 세팅인 Express와, res.Body를 쉽게 파싱할 수 있도록 기본 골자를 짜고, 데이터 모델 역시 Connect로 선언해서 가져온다.
const express = require('express') const app = express(); app.use(express.json()); app.use(express.urlencoded({extended: true})); const connect = require('./schemas'); connect(); const boardRouter = require("./routers/board"); app.use('/api', [boardRouter]);
그리고 View로는 가볍게 템플릿 엔진인 ejs를 사용하여 보여주고, Controller부분인 API가 저장된 Router역시 선언해준다
app.set('views', __dirname + '/views'); //경로 설정 부분 app.set('view engine', 'ejs'); //view engine으로 ejs를 사용할것 app.get('/', (req, res) => { res.render('index');
index부분에서 바로 그냥 데이터베이스를 연결하는 로직을 적어줘도 되지만, 그건 너무
우아하지않다
뭐, 우아한건 둘째치고 나중에 수정할때도 불편할수 있으니
차라리 모듈로 빼는게 낫지않은가?
const mongoose = require("mongoose");
const connect = () => {
mongoose
.connect("mongodb://localhost:27017/board", {
useNewUrlParser: true,
ignoreUndefined: true
})
.catch(err => console.log(err));
};
mongoose.connection.on("error", err => {
console.error("몽고디비 연결 에러", err);
});
module.exports = connect;
그래서 위에서 선언한것처럼 module을 connect란 이름으로 exports한 후 index에서 해당 index를 가져와서 함수처럼 사용하기만 하면 끝이다.
또한 데이터베이스를 저장하거나 업데이트 할때, 매 번 데이터베이스의 속성을 선언하고~ 거기에 저장하고~ 할 필요가 많기 때문에 스키마 모델 부분 역시 따로 빼두는게 좋다
const mongoose = require("mongoose");
const { Schema } = mongoose;
const boardSchema = new Schema({
///스키마 속성들...
});
module.exports = mongoose.model("board", boardSchema);
이런식으로 말이다.
나중에 해당 스키마를 가져올때는 그냥 해당 스키마의 위치와 export한 이름을 적어주면 끝이다
const Board = require('../schemas/board');
![]()
![]()
app.get('/', (req, res) => {
res.render('index');
})
처음 접속하게되면 View 화면인 index.ejs를 그려주고,
//index.ejs
$(document).ready(function () {
get_list();
})
에선 get_list()란 함수를 페이지 로딩이 끝나고 요청하게된다.
const get_list = () => {
$('#boardList').empty();
$.ajax({
type: "GET",
url: `/api/lists`,
data: {},
success: function (response) {
let lists = response["lists"]
for (let i = 0; i < lists.length; i++) {
make_list(lists[i], lists.length-i)
}
}
})
}
해당 함수는 컨트롤러에 /api/lists라는 api를 요청하게 되는데,
/api로 시작하기에 routers/board라는 라우터를 사용하게 된다.
const router = express.Router();
router.get("/lists", async (req, res, next) => {
try {
const lists = await Board.find({showing: 1}).sort("-postId");
res.json({ lists: lists });
list api는 요청이 성공적으로 마무리 됫을경우 response에 json파일로 요청한 데이터를 넘겨주게되고, 위의 get_list가 json파일을 받아 화면에 그려주게 된다.
이 얼마나 아름답고 간결하고 완벽한 일련의 동작인지...
이맛에 다들 api를 하는게 아닐까?
![]()
비밀번호같은 경우에는 그냥 귀찮아서 대강 박아 넣으려다가,
그래도 명색이 비밀번호인데 해쉬처리는 좀 해줘야 하지 않겠는가?
비밀번호같은 경우에는 가볍게 bcrypt모듈을 이용하여 구현하였다.
const bcrypt = require('bcrypt');
...
const encryptedPassowrd = bcrypt.hashSync(password, 10);
....
bcrypt.compare(password, posted['password'], function(err, msg){
if(msg === true){
console.log('비번맞음');
res.send({ result: "success" });
}
else{
res.send({ result: "fail" });
}
})
이쁘게 해시값으로 변환되고, 원래 비밀번호하고 비교했을때 동일하다면 수정, 삭제가 가능하도록, 그렇지 않다면 Alert창을 띄우도록 했다.
가볍게 해쉬처리를 하게 만들어준다는게 참 신기할 따름이다
여담이지만, 처음 비밀번호를 비교하려 했을때 무의식적으로 비밀번호를 '보내준다' 는 생각 대신 비교한 값을 '받아준다' 라는 개념으로 생각하여 Post로 입력한 비밀번호를 보내주는게 아니라 get으로 입력한 비밀번호를 보내주어 작동이 안되서 30분동안 끙끙댄적이 있다.
정말 당혹스러운 경험이였다
![]()
이전에 만들어놓은 ec2 인스턴스에 이번 과제를 올리려햇는데 이게 뭘 잘못햇는지 몽고디비도 안되고, 모듈도 잘 안깔리고, npm도 안먹혓다.
그래서 별수없이 새로 프리티어를 하나 사서 거기에 올리니 한방에 해결됬다.
나중에... 진짜 좀 이친구좀 손봐야할것같다
기본적인 개념이 조금 부족한것 같으니 다른 강의들도 조금씩 보며 좀더 머릿속의 개념을 확립시키는것이 중요한것같다.
한걸음씩 꾸준히, 잘하는것이 중요한게 아니라 꾸준한것이 중요하다