1) Node.js
1-1) express를 활용한 게시판 구현(CRUD)
1-2) Router 나누기
1-3) 게시판 코드 실습 - Router 나누기
1) Node.js
1-1) express를 활용한 게시판 구현(CRUD)
"프레임워크"와 "라이브러리"의 차이
express는 실제로 "마이크로 프레임워크"지만 "라이브러리"에 가깝다고 볼 수 있다!
1. 프레임워크의 특징 : 디렉토리가 정해져 있음!
2. 라이브러리의 특징 : 디렉토리 구조가 없음
3. 프레임워크와 라이브러리의 공통점 : 둘 다 다른 사람들이 만들어 놓은 것을 가져다 쓰는 개념이다!
(단, 가져와서 쓸 때, 즉 사용법이 다르다는 차이가 있다!)
$ npm init -y #package.json 파일 생성
$ npm install express nunjucks #외장모듈인 express, nunjucks 설치 및 node_modules 디렉토리 생성
server.js
const express = require("express");
const nunjucks = require("nunjucks");
const app = express();
const items = [
{
subject: "첫번째 게시물",
content: "content",
name: "name...",
},
];
app.use(express.urlencoded({ extended: false }));
app.set("view engine", "html");
nunjucks.configure("views", {
express: app,
});
app.get("/", (req, res) => {
res.render("index.html");
});
app.get("/list", (req, res) => {
res.render("board/list.html", { items }); // path.join
});
app.get("/write", (req, res) => {
res.render("board/write.html");
});
app.post("/write", (req, res) => {
const { content, subject, name } = req.body;
items.push({ content, subject, name });
res.redirect(`/view?index=${items.length - 1}`);
});
app.get("/view", (req, res) => {
const { index } = req.query;
const item = {
...items[index],
index,
};
res.render("board/view.html", { item });
});
app.get("/modify", (req, res) => {
const { index } = req.query;
const item = {
...items[index],
index,
};
res.render("board/modify.html", { item });
});
app.post("/modify", (req, res) => {
const { index, subject, content, name } = req.body;
items[index].subject = subject;
items[index].content = content;
items[index].name = name;
// 바로 위의 코드들을 간략히 표현한 코드(rest 활용)
// const { index, ...rest } = req.body;
// items[index] = rest;
res.redirect(`/view?index=${index}`);
});
app.get("/delete", (req, res) => {
const { index } = req.query;
items.splice(index, 1);
res.redirect("/list");
});
app.listen(3000, () => {
console.log("server start");
});
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<h1>hello world!</h1>
<a href="/list">리스트 바로가기</a>
</body>
</html>
views/board
list.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<table>
<tr>
<th>번호</th>
<th>제목</th>
<th>작성자</th>
<th>작성일</th>
<th>조회수</th>
</tr>
{% for item in items %}
<tr>
<td>{{loop.index - 1}}</td>
<td><a href="/view?index={{loop.index - 1}}">{{item.subject}}</a></td>
<td>{{item.name}}</td>
<td>2022-12-20</td>
<td>0</td>
</tr>
{% endfor %}
</table>
<a href="/write">글작성</a>
</body>
</html>
write.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<h2>write</h2>
<form method="post" action="/write">
<ul>
<li>제목 : <input type="text" name="subject" /></li>
<li>작성자 : <input type="text" name="name" /></li>
<li>
내용 : <br />
<textarea name="content"></textarea>
</li>
</ul>
<button type="submit">submit</button>
</form>
</body>
</html>
view.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<h2>view page</h2>
<ul>
<li>제목 : {{item.subject}}</li>
<li>작성자 : {{item.name}}</li>
<li>내용 : {{item.content}}</li>
</ul>
<a href="/list">목록가기</a>
<a href="/modify?index={{item.index}}">수정</a>
<a href="/delete?index={{item.index}}">삭제</a>
</body>
</html>
modify.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<h2>modify page</h2>
<form method="post" action="/modify">
<input type="hidden" name="index" value="{{item.index}}" />
<ul>
<li>
제목 : <input type="text" name="subject" value="{{item.subject}}" />
</li>
<li>
작성자 : <input type="text" name="name" value="{{item.name}}" />
</li>
<li>
<textarea name="content">
{{item.content}}
</textarea
>
</li>
</ul>
<button type="submit">submit</button>
</form>
</body>
</html>
1-2) Router 나누기("[x]" 현재는 구현 안 한 directory를 의미함)
/root
|-- [x]models
|-- middlewares
|-- controllers
|-- [x]services
|-- routes
|-- public
|-- views
|-- server.js
app.get('/', (req, res) => {});
Router 안에 들어간 "callback(미들웨어)" 함수는 "요청 객체"와 "응답 객체"를 주는 함수들이다!!
const modifyController = (req, res) => {
const index = req.query.index;
// 데이터 조작
items[index].subject = ...;
res.render('modify.html');
}
app.get('/modify', modifyController);
app.get('/', (req, res) => {});
app.get('/list', (req, res) => {});
app.get('/write', (req, res) => {});
app.get('/view', (req, res) => {});
app.get('/modify', (req, res) => {});
app.get('/delete', (req, res) => {});
const express = require('express');
const router = express.Router();
게시판이 3가지 형태(board, notice, gallery)가 있다고 가정함!
/board/list
/board/write
/board/view
/board/modify
/board/delete
/notice/list
/notice/write
/notice/view
/notice/modify
/notice/delete
/gallery/list
/gallery/write
/gallery/view
/gallery/modify
/gallery/delete
$ npm init -y
$ npm install express
app.use(
"/board/",
router.get("/list", (req, res) => {
res.send("/ page");
})
)
// 위의 코드의 동작 방식 표현
if (req.path.include("/board")) {
if (req.method === "GET" && req.path="/board/list") {
res.send("/ page");
}
}
app.get('/', (req, res) => {
res.send('hello world');
})
// 위의 코드의 동작 방식 표현
if (req.method === "GET" && req.path === "/") {
res.send('hello world');
}
server.js
const express = require("express");
const app = express();
// const board = require("./routes/board.route");
// const notice = require("./routes/notice.route");
// const gallery = require("./routes/gallery.route");
const router = require("./routes");
const nunjucks = require("nunjucks");
const { login } = require("./middlewares/index");
app.set("view engine", "html");
nunjucks.configure("views", {
express: app,
});
app.use(express.static("public"));
app.use(express.urlencoded({ extended: false }));
app.use(login);
/*
// /board/list
app.get("/board/list", (req, res) => {
res.send("/ page");
});
*/
/*
{
method: "get",
path: "list",
callback: (req, res) => {
res.send("/ page")
}
}
*/
/*
// localhost:3000/board/list
router.get("/board/list", (req, res) => {
res.send("/ page");
}); // 등록형태(router를 쉽게 만들어 줄 수 있는 객체임을 의미함!)
*/
// app.use(router); // 앞서 router를 통해 등록한 것이 실제 실행은 여기서 이루어짐!
/*
router.get("/list", (req, res) => {
res.send("/ list");
});
router.get("/write", (req, res) => {
res.send("/ write");
});
router.get("/modify", (req, res) => {
res.send("/ modify");
});
*/
// app.use("/board", board); // board/list, write, modify
// app.use("/notice", notice); // notice/list, write, modify
// app.use("/gallery", gallery); // gallery/list, write, modify
app.use(router);
// app.get("/", (req, res) => {
// res.send("/ page");
// });
app.listen(3000, () => {
console.log("server start");
});
routes
index.js
const express = require("express");
const router = express.Router();
const board = require("./board.route");
const notice = require("./notice.route");
const gallery = require("./gallery.route");
router.use("/board", board);
router.use("/notice", notice);
router.use("/gallery", gallery);
module.exports = router;
board.route.js
// router
const express = require("express");
const router = express.Router(); // {}
const controller = require("../controllers/board.controller");
router.get("/list", controller.list);
router.get("/write", controller.write);
router.get("/view", (req, res) => {
res.send("board/ view 입니다.");
});
router.get("/delete", (req, res) => {
res.send("board/ delete 입니다.");
});
module.exports = router;
notice.route.js
// router
const express = require("express");
const router = express.Router(); // {}
router.get("/list", (req, res) => {
res.send("notice/ list 입니다.");
});
router.get("/write", (req, res) => {
res.send("notice/ write 입니다.");
});
router.get("/view", (req, res) => {
res.send("notice/ view 입니다.");
});
router.get("/delete", (req, res) => {
res.send("notice/ delete 입니다.");
});
module.exports = router;
gallery.route.js
// router
const express = require("express");
const router = express.Router(); // {}
router.get("/list", (req, res) => {
res.send("gallery/ list 입니다.");
});
router.get("/write", (req, res) => {
res.send("gallery/ write 입니다.");
});
router.get("/view", (req, res) => {
res.send("gallery/ view 입니다.");
});
router.get("/delete", (req, res) => {
res.send("gallery/ delete 입니다.");
});
module.exports = router;
controllers
board.controller.js
const items = [];
exports.list = (req, res) => {
res.send("list page");
};
exports.write = (req, res) => {
res.send("write page");
};
exports.modify = (req, res) => {
res.send("modify page");
};
middlewares
index.js
exports.login = (req, res, next) => {
req.login = "web7722";
next();
};
1-3) 게시판 코드 실습 - Router 나누기
server.js
const express = require("express");
const router = require("./routes");
const app = express();
const nunjucks = require("nunjucks");
app.set("view engine", "html");
nunjucks.configure("views", {
express: app,
});
app.use(express.static("public"));
app.use(express.urlencoded({ extended: false }));
app.use(router);
app.get("/", (req, res) => {
res.render("index.html");
});
app.listen(3000, () => {
console.log("server start");
});
views(board와 notice 디렉토리를 나눠서 구현했지만 각 html의 내용이 거의 유사하므로 board만 소개하기로 함!!)
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<link rel="stylesheet" href="/css/index.css" />
<script src="/js/index.js" type="text/javascript"></script>
</head>
<body>
<h1>hello~~!!</h1>
<a href="/board/list">board 리스트 바로가기</a>
<a href="/notice/list">notice 리스트 바로가기</a>
</body>
</html>
board
list.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<table>
<tr>
<th>번호</th>
<th>제목</th>
<th>작성자</th>
<th>작성일</th>
<th>조회수</th>
</tr>
{% for item in items %}
<tr>
<td>{{loop.index}}</td>
<td>
<a href="/board/view?index={{loop.index - 1}}">{{item.subject}}</a>
</td>
<td>{{item.name}}</td>
<td>2022-12-20</td>
<td>0</td>
</tr>
{% endfor %}
</table>
<a href="/board/write">글작성</a>
</body>
</html>
write.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<h2>write page</h2>
<form method="post" action="/board/write">
<ul>
<li>제목 : <input type="text" name="subject" /></li>
<li>작성자 : <input type="text" name="name" /></li>
<li>
내용 : <br />
<textarea name="content"></textarea>
</li>
</ul>
<button type="submit">submit</button>
</form>
</body>
</html>
view.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<ul>
<li>제목 : {{item.subject}}</li>
<li>작성자 : {{item.name}}</li>
<li>내용 : {{item.content}}</li>
</ul>
<a href="/board/list">리스트 가기</a>
<a href="/board/modify?index={{item.index}}">수정</a>
<a href="/board/delete?index={{item.index}}">삭제</a>
</body>
</html>
modify.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<h2>modify page</h2>
<form method="post" action="/board/modify">
<input type="hidden" name="index" value="{{item.index}}" />
<ul>
<li>
제목 : <input type="text" name="subject" value="{{item.subject}}" />
</li>
<li>
작성자 : <input type="text" name="name" value="{{item.name}}" />
</li>
<li>
<textarea name="content">
{{item.content}}
</textarea
>
</li>
</ul>
<button type="submit">submit</button>
</form>
</body>
</html>
public
css
index.css
* {
margin: 0;
padding: 0;
}
body {
background: #beb;
}
js
index.js
alert("welcome to our board~~");
routes
index.js
const express = require("express");
const router = express.Router();
const board = require("./board.route");
const notice = require("./notice.route");
router.use("/board", board);
router.use("/notice", notice);
module.exports = router;
board.route.js
// router
const express = require("express");
const router = express.Router(); // {}
const controller = require("../controllers/board.controller");
router.get("/list", controller.list);
router.get("/write", controller.getWrite);
router.post("/write", controller.postWrite);
router.get("/view", controller.view);
router.get("/modify", controller.getModify);
router.post("/modify", controller.postModify);
router.get("/delete", controller.delete);
module.exports = router;
notice.route.js
const express = require("express");
const router = express.Router();
const controller = require("../controllers/notice.controller");
router.get("/list", controller.list);
router.get("/write", controller.getWrite);
router.post("/write", controller.postWrite);
router.get("/view", controller.view);
router.get("/modify", controller.getModify);
router.post("/modify", controller.postModify);
router.get("/delete", controller.delete);
module.exports = router;
controllers
board.controller.js
const items = [
{
subject: "첫번째 게시물",
content: "content",
name: "name...",
},
];
exports.list = (req, res) => {
res.render("board/list.html", { items });
};
exports.getWrite = (req, res) => {
res.render("board/write.html");
};
exports.postWrite = (req, res) => {
const { content, subject, name } = req.body;
items.push({ content, subject, name });
res.redirect(`view?index=${items.length - 1}`);
};
exports.view = (req, res) => {
const { index } = req.query;
const item = {
...items[index],
index,
};
res.render("board/view.html", { item });
};
exports.getModify = (req, res) => {
const { index } = req.query;
const item = {
...items[index],
index,
};
res.render("board/modify.html", { item });
};
exports.postModify = (req, res) => {
const { index, subject, content, name } = req.body;
items[index].subject = subject;
items[index].content = content;
items[index].name = name;
// 바로 위의 코드들을 간략히 표현한 코드(rest 활용)
// const { index, ...rest } = req.body;
// items[index] = rest;
res.redirect(`view?index=${index}`);
};
exports.delete = (req, res) => {
const { index } = req.query;
items.splice(index, 1);
res.redirect("list");
};
notice.controller.js
const items = [
{
subject: "첫번째 게시물",
content: "content",
name: "name...",
},
];
exports.list = (req, res) => {
res.render("notice/list.html", { items });
};
exports.getWrite = (req, res) => {
res.render("notice/write.html");
};
exports.postWrite = (req, res) => {
const { content, subject, name } = req.body;
items.push({ content, subject, name });
res.redirect(`view?index=${items.length - 1}`);
};
exports.view = (req, res) => {
const { index } = req.query;
const item = {
...items[index],
index,
};
res.render("notice/view.html", { item });
};
exports.getModify = (req, res) => {
const { index } = req.query;
const item = {
...items[index],
index,
};
res.render("notice/modify.html", { item });
};
exports.postModify = (req, res) => {
const { index, subject, content, name } = req.body;
items[index].subject = subject;
items[index].content = content;
items[index].name = name;
res.redirect(`view?index=${index}`);
};
exports.delete = (req, res) => {
const { index } = req.query;
items.splice(index, 1);
res.redirect("list");
};
※ 자세한 코드는 여기 제 github 저장소(https://github.com/sangbeomhwang/board_express.git)를 참조해주시기 바랍니다.
'Node.js' 카테고리의 다른 글
Node.js(12) - 비동기 통신 댓글 CRUD, Postman 및 Database 활용 (0) | 2023.01.04 |
---|---|
Node.js(11) - AJAX 기본 포맷, server 분리(front/back) 구현 (0) | 2023.01.03 |
Node.js(9) - express를 활용한 게시판 구현 (0) | 2022.12.19 |
Node.js(8) - express (0) | 2022.12.14 |
Node.js(7) - HTTP, 동적 웹 페이지 구현 (0) | 2022.12.13 |