ë°ąěëě ë°ě´í° ě ěĽíë ë˛ (array database ě´ěŠ)
ě ë ę˛˝ëĄ / ěë ę˛˝ëĄ / GET method / POST method / res.redirect() / req.body
ě§ę¸ě ë°ě´í°ëĽź ë°ę¸°ë§ íęł ěë¤. ë°ě´í°ëĽź ě ěĽí ě¤ ěěěź íë¤.
MongoDB뼟 ë°°ě°ę¸° ě , ěźë¨ě ě¤ě ë°ě´í°ë˛ ě´ě¤ę° ěëëź ë°°ě´ëĄ ë ë°ě´í°ë˛ ě´ě¤(ę°ě§ ë°ě´í°ë˛ ě´ě¤)뼟 ěŹěŠí ę˛ě´ë¤.
ěźë¨, videos ë°°ě´ě ę° video ę°ě˛´ě id ěěąě 1, 2, 3ě´ëźęł ěěëëĄ ëśě¸ë¤.
videos ë°°ě´ě trending 읨í¸ëĄ¤ëŹ ë°ěźëĄ ëšźë´, 모ë 읨í¸ëĄ¤ëŹěě ěŹěŠí ě ěëëĄ íë¤.
// videoController.js
let videos = [
{
title: "First Video",
rating: 5,
comments: 2,
createdAt: "2 months ago",
views: 59,
id: 1,
},
{
title: "Second Video",
rating: 5,
comments: 2,
createdAt: "2 months ago",
views: 59,
id: 2,
},
{
title: "Third Video",
rating: 5,
comments: 2,
createdAt: "2 months ago",
views: 59,
id: 3,
},
];
Homeě ę°ě§ ë°ě´í°ë˛ ě´ě¤ě ěë 모ë ëšëě¤ë¤ě ëě´í´ěź íë¤.
ě´ě ęłľëśěě ě´ëŻ¸ ěëŁí ëśëśě´ë¤.
video mixině ě´ěŠíěŹ, video(info)ě id뼟, (Homeěě í´ëŚí video íě´íě) urlě ëŁě´ě¤Źë¤.
//- home.pug
extends base
include mixins/video
block content
h2 Welcome here you will see the trending videos
each potato in videos
+video(potato)
else
li Sorry nothing found.
//- video.pug
mixin video(info)
div
h4
a(href=`/videos/${info.id}`)=info.title
//- íě´í í´ëŚ ě '/videos/id ëë˛'ëĄ ě´ë
ul
li #{info.rating}/5.
li #{info.comments} comments.
li Posted #{info.createdAt}.
li #{info.views} views.
íě´íě í´ëŚí늴, /videos/id ëë˛ëĄ ě´ëíę˛ë
ë§ë ë¤.ě´ëĽź ěí´ě video.pug íěźěě HTMLě ë§ë¤ęł ěěźëŻëĄ ě´ íěźě ě´í´ěź íë¤.
video.pug íěźěě h4뼟 ěě íë¤.
//- video.pug
h4
a(href=`/videos/${info.id}`)=info.title
đĄ pug íěź ěěą ęˇěš
- ëłě + í ě¤í¸ â #{ëłě}
- ë¨, href, id, class ëą 'ěěą'ěěë ě´ë ę˛ í ě ěë¤. ěë°ě¤íŹëŚ˝í¸ě ęˇěšě ë°ëźěź íë¤.
( " " + or í í댿 돸ěě´)
/videos/id ëë˛ëĄ ě´ëíě ë, í´ëŚí íě´íě videoę° ëł´ě´ę˛ë
ë§ë ë¤.videoController.js íěźěě see 읨í¸ëĄ¤ëŹëĽź ěě íë¤.
â see 읨í¸ëĄ¤ëŹě req.params(íëźëŻ¸í°)뼟 ěśë Ľí´ëł´ë ě˝ë뼟 ěśę°íë¤.
꡸ í ěí ěźě second video íě´íě í´ëŚí´ localhost:4000/videos/2ëĄ ë¤ě´ę°ë¤.
VS codeě ë´ěĽ í°ëŻ¸ëě ěëí ëëĄ { id: '2' }ę° ěśë Ľëë ę˛ě íě¸íë¤.
// videoRouter.js
videoRouter.get("/:id(\\d+)", see);
//- video.pug
h4
a(href=`/videos/${info.id}`)=info.title
// videoController.js ěě
export const see = (req, res) => {
console.log(req.params); // { id: '2' }
}
⥠ě´ëĽź ě´ěŠí´ videoě id뼟 ę°ě ¸ě¨ë¤.
( videos ë°°ě´ě video(info)ě id === video íě´ě§ urlě íëźëŻ¸í° )
// videoController.js
export const see = (req, res) => {
const { id } = req.params; // const id = req.params.id; ě ę°ë¤
}
⢠ę°ě ¸ě¨ video id뼟 ě´ěŠí´ videos ë°°ě´ ěěě ꡸ video뼟 ę°ě ¸ě¨ë¤.
ę°ě ¸ě¨ video뼟 ě´ěŠí´ ꡸ video íě´íě ěśë Ľíë¤.
// videoController.js
export const see = (req, res) => {
const { id } = req.params; // ëšëě¤ ěě´ë뼟 ę°ě ¸ě´
const video = videos[id - 1]; // ëšëě¤ëĽź ę°ě ¸ě´
return res.render("see", { pageTitle: `Seeing ${video.title}` }); // ëšëě¤ íě´íě ëł´ěŹě¤
}
ě§ę¸ě ę°ě§ ë°ě´í°ë˛ ě´ě¤ëĽź ěŹěŠ ě¤ě´ëź ě¤ě ëĄ videoě íěí ěë ěë¤.
꡸ëŹë, ę°ëľíę˛ ëĄě§ě ě ě´ëł´ě늴đ video íě´ě§ě urlě ě´ë¤ id뼟 ę°ě§ë¤.
đ ꡸ id뼟 ěťě´ě ꡸ id뼟 ę°ě§ęł ěë video뼟 ě°žëë¤.
đ ꡸ videoě ě 보뼟 ë°íěźëĄ video íě´ě§ě ě´ę˛ě ę˛ě render íë¤.
⣠ę°ě ¸ě¨ video뼟 see í í댿ěźëĄ ëł´ë¸ë¤. see.pug íěźěě video (object)뼟 ë¤ëŁ° ě ěę˛ ëěë¤.
// videoController.js
export const see = (req, res) => {
const { id } = req.params;
const video = videos[id - 1];
return res.render("see", { pageTitle: `Seeing ${video.title}`, video }); // video: videoě ę°ë¤
}
⤠ę°ě ¸ě¨ video ě 보뼟 ě´ěŠí´ see.pug íěźě ěě íë¤.
기쥴ě See Video í
ě¤í¸ ëě ě video.views뼟 ëł´ěŹěŁźë ¤ęł íë¤.
ěźí 쥰깴 ě°ě°ě뼟 ě´ěŠí´ ë¨Âˇëłľěě 경ě°ëĽź ëëě´ view ëë views뼟 ëł´ěŹě¤ë¤.
//- see.pug
extends base.pug
block content
h3 #{video.views} #{video.views === 1 ? "view" : "views"}
ěě ěě íě´ě§ëĄ ě´ëíë ë§íŹëĽź ë§ë ë¤.
â ë§íŹë ě ë 경ëĄě ěë ę˛˝ëĄ ě¤ 'ěë 경ëĄ'뼟 ě´ěŠí´ěź íë¤.
íěŹ íě´ě§(/videos/id ëë˛)ěě, ě´ëí´ěź í기 ë돸ě´ë¤.
//- home.pug
extends base.pug
block content
h3 #{video.views} #{video.views === 1 ? "view" : "views"}
a(href=`${video.id}/edit`) Edit Video → //- ěśę° â
đĄ ě ë 경ëĄě ěë 경ëĄ
ě ë 경ëĄ
hrefě ě머댏ě /edit ě ëśě´ëŠ´, íěŹ ě´ë¤ íě´ě§ě ěëě§ě ěę´ěě´,
root 경ëĄ
+ /editěźëĄ ě´ëíë¤.localhost:4000/profile/edit-profile/password =====> a(href="/potato") localhost:4000/potato
ěë 경ëĄ
hrefě ě머댏ě ęˇ¸ëĽ edit ě ëśě´ëŠ´,
íěŹ íě´ě§ěě
/eidtěźëĄ ě´ëíë¤. (âľ videoRouter.js)localhost:4000/profile/edit-profile/password =====> a(href="potato") localhost:4000/profile/edit-profile/potato
/videos/id ëë˛/editěźëĄ ě´ëíě ë, ěě íë ¤ë videoę° ëł´ě´ę˛ë
ë§ë ë¤.â ě´ë˛ěë ěě í video뼟 ę°ě ¸ěěź íëŻëĄ, videoController.js íěźěě ěě see 읨í¸ëĄ¤ëŹëĽź ěě í ëëĄ, edit 읨í¸ëĄ¤ëŹ
ë ëę°ě´ ěě íë¤. ===> (2)ě â ~ ⣠ë°ëłľ
// videoController.js
export const edit = (req, res) => {
const { id } = req.params;
const video = videos[id - 1];
return res.render("edit", { pageTitle: `Editing: ${video.title}`, video });
};
⥠ę°ě ¸ě¨ video ě 보뼟 ě´ěŠí´ edit.pug íěźě ěě íë¤.
ě´ íě´ě§ěě userę° videoě titleě ěě í ě ěę˛ë íë ¤ęł íë¤.
formęłź text input, submit input í꡸
뼟 ë§ë ë¤.
//- edit.pug (ěě 미ě)
extends base.pug
block content
h4 Change Title of Video
form(action="")
input(name="title", placeholder="Video Title", value=`${video.title}`, required)
input(value="save", type="submit")
cf. form í꡸ě action ěěą â
íź ë°ě´í°(form data)뼟 ěë˛ëĄ ëł´ëź ë í´ëš ë°ě´í°ę° ëě°Ší url
ě´ ę˛˝ě°ěë ë°ëĄ action ěěąě ę°ě ě ě´ěŁźě§ ěëë¤ëŠ´
기본ě ěźëĄ localhost:4000/videos/id ëë˛/edit ě´ ëë¤.
꡸ëŹë, ě ě˝ëë ěě§ ěě ě´ íěí 미ěěą ě˝ëě´ë¤.
ě§ę¸ęšě§ í ę˛ě ë°ąěëěě ëšëě¤ëĽź ę°ě ¸ě¤ë ę˛ě´ěë¤.
ě´ě ěě í ë´ěŠě ë¤ě ë°ąěëëĄ ëł´ëź ě°¨ëĄě´ë¤.
ěŚ, save ë˛íźě ë뼴늴 inputě ě
ë Ľí ëšëě¤ě ěëĄě´ titleě´ ë°ąěëě ě ěĽëëëĄ í´ěź íë¤.
ë°ě´í°ëĽź ë°ěěŹ ëë GET request ěŚ, videoRouter.get("url", 읨í¸ëĄ¤ëŹ)ě ěŹěŠíë¤.
ë°ě´í°ëĽź ëł´ëź ëë POST request ěŚ, videoRouter.post("url", 읨í¸ëĄ¤ëŹ)ě ěŹěŠí´ěź íë¤.
đĄ GET method VS POST method (with ěě )
method
: formęłź ë°ą ěë ěŹě´ě ě ëł´ ě ěĄ ë°Šě
GET method
- 기본ě ěźëĄ method="GET"ě´ ě¤ě ëě´ ěë¤.
- ë°ě´í°ëĽź ë°ë ę˛ ëŞŠě ěź ë ěŹěŠëë¤.
- 꾏ę¸ě´ë ë¤ě´ë˛ ëąěě ę˛ěí ë ěŹěŠëë¤. (ę˛ěě´ę° url 죟ěě íŹí¨ëë¤.)
//- see.pug form(action="/save-changes") input(name="title", placeholder="Video Title", value=`${video.title}`, required) input(value="save", type="submit")
form í꡸ě action ěěąě ěśę°íë¤.
â save ë˛íźě í´ëŚ ělocalhost:4000/save-changes?title=Third+Video
ëĄ ě´ëíë¤. formě ěë ě ëł´ę° urlě ë¤ě´ę° ę˛ě´ë¤.
â í늴ěëCannot GET /save-changes
ëźęł ëŹë¤. ěë˛ë (ë¤ëĽ¸ GETě ëí´ě ěë ë°ę° ěě§ë§) GET /save-changesě ëí´ě ěë ë°ę° ě기 ë돸ě´ë¤.
POST method
- 기본ę°ě´ GETě´ëŻëĄ POST request뼟 ěŹěŠí기 ěí´ěë method="POST"뼟 ěśę°í´ěź íë¤.
- ë°ě´í°ëĽź ě ë°ě´í¸íë ę˛ ëŞŠě ěź ë ěŹěŠëë¤.
- íěźě ëł´ë´ęą°ë ëĄęˇ¸ě¸ě íęą°ë ë°ě´í°ë˛ ě´ě¤ě ěë ę°ě ë°ęż ë ěŹěŠëë¤.
//- see.pug form(action="/save-changes", method="POST") input(name="title", placeholder="Video Title", value=`${video.title}`, required) input(value="save", type="submit")
form í꡸ě method ěěąě ěśę°íë¤.
â save ë˛íź í´ëŚ ělocalhost:4000/save-changes
ëĄ ě´ëíë¤. (?title=...ě íěëě§ ěëë¤.)
â í늴ěëCannot POST /save-changes
ëźęł ëŹë¤. ěë˛ë POSTě ëí´ě ěë ë°ę° ě기 ë돸ě´ë¤.
ě ë´ěŠě ě°¸ęł í´ě edit.pug íěźě ë¤ě ěëě ę°ě´ ěě íë¤.
//- edit.pug
form(method="POST")
input(name="title", placeholder="Video Title", value=`${video.title}`, required)
input(value="save", type="submit")
ěë˛ë ěě§ POSTě ëí´ě ěë ë°ę° ěë ěíě´ë¤.
save ë˛íź(submit input)ě í´ëŚí ë formě íëě íľě
íęł ě íë¤.â ěë˛ě í´ëš POSTě ëí´ ěë ¤ěŁźę¸° ěí´ videoRouter.js íěźěě ëę°ě urlëĄ post request뼟 ëł´ë´ë
ě˝ë뼟 ěěąíë¤.
getęłź post뼟 꾏ëśí ě ěëëĄ ę¸°ěĄ´ě edit 읨í¸ëĄ¤ëŹě ě´ëŚě getEditěźëĄ ëłę˛˝íë¤. (videoController.js ěěë)
// videoRouter.js
// videoRouter.get("/:id(\\d+)/edit", getEdit);
// videoRouter.post("/:id(\\d+)/edit", postEdit);
// ě ë ě¤ě ě˝ëë, ěë í ě¤ě ě˝ëëĄ ë°ężě¸ ě ěë¤.
videoRouter.route("/:id(\\d+)/edit").get(getEdit).post(postEdit);
⥠videoController.js íěźě postEdit 읨í¸ëĄ¤ëŹ
뼟 ěśę°íë¤.
ěźë¨ě ě돴ę˛ë ë°ííě§ ěęł , íěë§ ěěąí´ě¤Źë¤.
â getEdit 읨í¸ëĄ¤ëŹë formě render í´ě¤ë¤.
â postEdit 읨í¸ëĄ¤ëŹë video뼟 ěě í´ě¤ë¤. (ěě§ ě˝ë ěěą x)
// videoController.js
export const getEdit = (req, res) => {
const { id } = req.params;
const video = videos[id - 1];
return res.render("edit", { pageTitle: `Editing: ${video.title}`, video });
};
export const postEdit = (req, res) => {}; // ěśę°
ě´ě localhost:4000/videos/3/edit ěźëĄ ë¤ě´ę°ëŠ´, Cannot POST ę° ëě¤ě§ ěęł ë¸ëźě°ě ë 돴í ëĄëŠě íë¤.
ěë˛ě postę° ëě§ë ěë ¤ě¤Źě§ë§, post request뼟 ë°ěě ë ë í´ěź íëě§ë ě í´ěŁźě§ ěěěźëŻëĄ ěë˛ë ě´ë¤ ě˛ëŚŹë íě§ ěě ěą ë¸ëźě°ě ě ěëľíě§ ěě ë¸ëźě°ě ę° ëŹ´í ë기 ěíě¸ ę˛ě´ë¤.
ë°ëźě, ěë˛ę° post request뼟 ě˛ëŚŹ ë° ěëľí ě ěëëĄ postEdit 읨í¸ëĄ¤ëŹëĽź ë§ě ěěąí´ě¤ěź íë¤.
postEdit 읨í¸ëĄ¤ëŹě ěí ě video뼟 ěě íë ę˛ě¸ë° ěŹę¸°ěë videoě titleë§ě ë°ężëł´ě.
input ę°ě ě´ěŠí´ videoě titleě ě
ë°ě´í¸
íëëĄ íë¤.â postEdit 읨í¸ëĄ¤ëŹě res.redirect()
뼟 ěśę°íë¤.
res.redirect()ë 'ě§ě í urlëĄ ë¸ëźě°ě ę° ěëěźëĄ ě´ë'íëëĄ íë¤.
ěŹę¸°ěë save ë˛íźě ë뼴늴 see íě´ě§(ěŚ, /videos/id ëë˛)ëĄ ëěę°ëëĄ í ę˛ě´ë¤.
// videoController.js
export const postEdit = (req, res) => {
const { id } = req.params;
return res.redirect(`/videos/${id}`);
};
⥠postEdit 읨í¸ëĄ¤ëŹě req.body
뼟 ěśę°íë¤.
ěě req.params뼟 íľí´ urlě íëźëŻ¸í° ę°(=video(info)ě id)뼟 ë°ěěë ę˛ě˛ëź
req.body뼟 íľí´ 'formě value뼟 ë°ěěŹ ě ěë¤.'
꡸ ě ě 먟ě , expressę° formě ë¤ëŁ° ě ěëëĄ, server.jsě middleware뼟 ěśę°í´ěź íë¤.
(ěěšę° ě¤ěíë¤. videoRouterëł´ë¤ ě ě ěśę°í´ěź íë¤. ꡸ëěźë§ ě´ë¤ requestę° videoRouter.postě ě´ëĽ´ë ě ë ě´ëŻ¸ req.bodyę° ě¤ëšëě´ ěě ě ěë¤.)
express.urlencoded()
ë expressę° formě value뼟 ě´í´í í ěë°ě¤íŹëŚ˝í¸ object íěěźëĄ ëłííëëĄ íë¤.
extended ěľě
ě formě bodyě ěë ě ëł´ë¤ě´ 보기 ě˘ě íěě ę°ěśëëĄ íë¤.
// server.js
app.use(express.urlencoded({ extended: true }))
// videoController.js
export const postEdit = (req, res) => {
const { id } = req.params;
const { title } = req.body;
videos[id - 1].title = title; // ę°ě§ ë°ě´í°ë˛ ě´ě¤ ěŹěŠ ě¤ě´ëź ě´ë ę˛ ě
ë°ě´í¸í´ě¤ ę˛. ě¤ě ëĄë ě´ë ę˛ ěí¨
return res.redirect(`/videos/${id}`);
};
ëĄě§ ě 댏
đ íě´ě§ëĽź get í´ě ë¤ě´ę°ë¤.
đ (ë¤ě 돴ěě¸ę°ëĽź í´ëŚí´ ë¤ě´ę°ě) formě ëę°ëĽź ě ë Ľí í submit ë˛íźě ë뼸ë¤.
đ submit ë˛íźě ëëŹě post request뼟 ëł´ë´ëŠ´, post 읨í¸ëĄ¤ëŹę° ě¤íëë¤.
đ post 읨í¸ëĄ¤ëŹë req.bodyëĄëśí° formě ě ë Ľí ę°ě ěťě´, ě´ëĽź ë°íěźëĄ ě´ę˛ě ę˛ě íë¤.
(3) ëłľěľěŠ parcticeě´ë¤
ěŹę¸°ě ëšëě¤ëĽź ě
ëĄëíë¤ë ę˛ě
ę°ě§ ë°ě´í°ë˛ ě´ě¤(array database)ě video ę°ě˛´ëĽź íë ë ěśę°íë¤ë ëťě´ë¤.
//- base.pug
doctype html
html(lang="ko")
head
title #{pageTitle} | Wetube
link(rel="stylesheet" href="https://unpkg.com/mvp.css")
body
header
h1=pageTitle
nav
ul
li
a(href=`/videos/upload`) Upload Video →
main
block content
include partials/footer.pug
//- upload.pug
extends base.pug
block content
form(method="POST")
input(name="title", placeholder="Video Title", required)
input(value="upload", type="submit")
// videoRouter.js
import express from "express";
import {
see,
getEdit,
postEdit,
getUpload,
postUpload,
} from "../controllers/videoController";
const videoRouter = express.Router();
videoRouter.get("/:id(\\d+)", see);
videoRouter.route("/:id(\\d+)/edit").get(getEdit).post(postEdit);
videoRouter.route("/upload").get(getUpload).post(postUpload); // ěśę°
export default videoRouter;
// videoController.js
const videos = [
{
title: "First Video",
rating: 5,
comments: 2,
createdAt: "2 months ago",
views: 1,
id: 1,
},
// ě´í ěëľ
];
export const trending = (req, res) => {
return res.render("home", { pageTitle: "Home", videos });
};
export const getUpload = (req, res) => {
return res.render("upload", { pageTitle: "Upload Video" });
};
export const postUpload = (req, res) => {
const { title } = req.body;
const newVideo = { // ę°ě§ ë°ě´í°ë˛ ě´ě¤ ěŹěŠ ě¤ě´ëź ě´ë ę˛ ě¨ě¤ ę˛. ě¤ě ëĄë ě´ë ę˛ ěí¨
title,
rating: 0,
comments: 0,
createdAt: "just now",
views: 0,
id: videos.length + 1,
};
videos.push(newVideo); // ă
return res.redirect("/");
};
+ë§ě§ë§ěźëĄ 모ë pug íěź ěěě .pug ěě íęł , see video뼟 watch videoëĄ ë°ęż
ę°ě ęłě ëŁę¸°
wsl2 ěŹě¤ěš, MongoDB ě¤ěš