Array Database
결국에는 백엔드에 데이터를 저장하는 게 요점이기 때문에,
백엔드에 데이터를 어떻게 보내는지를 먼저 배워보자.
지금은 데이터를 받기만 하니 저장하는 법도 알아보자!
그러기 위해서는 get 말고 post 개념도 알아야 한다.
우선 array로 된 database를 사용해보자. (trending 의 const는 let으로 바꿔주고, 안에 있는 비디오를 바꿔주려 한다.
우선 trending 안의 let부터의 내용을 trending 밖으로 빼준다. (return 전까지의 내용)
그러면 이제 내 비디오 array는 모든 controller에서(trending, see, edit...) 사용 가능해진다.
일단 비디오를 리스트업하는 것에는 성공했고, 이제는 유저가 한 비디오를 보게 하고 싶다. (+ 영상 업로드, 수정도!)
그러기 위해서는 see 컨트롤러를 바꿔줘야 한다.
왜냐하면 아래 url이 나를 위해 작동했으면 좋겠기 때문 (/:id 부분)
// videoRouter.js
videoRouter.get("/:id(\\d+)", see);
가짜 데이터의 id를 1, 2, 3으로 수정해준다. (나중에 id는 데이터베이스가 알아서 수정해줄 것)
그리고 mixin에 영상 이름을 클릭하면 해당 페이지로 갈 수 있도록 설정해준다.
${ } 사용할 때에는 따옴표가 아니라 백틱을 사용해야 하는 점 주의하기!
mixin video(video)
div
h4
a(href=`/videos/${video.id}`)=video.title
// a(href="/videos/" + video.id)=video.title 도 가능
ul
li #{video.rating}/5
li #{video.comments} comments.
li Posted #{video.createdAt}
li #{video.views} viewes.
이제 see 컨트롤러를 수정해보자.
이렇게 하면 req.params 에서 id를 받았고(/:id),
다음에 id를 통해서 영상을 찾을거다.
그리고 watch 라는 template 을 render 해준다.
export const watch = (req, res) => {
const { id } = req.params;
// const id = req.params.id; 와 같음. 하지만 ES6인 윗 방법 추천.
const video = videos[id - 1];
// 숫자를 0부터 세기 때문에 id는 -1해서 찾게끔 하기
return res.render("watch", { pageTitle: `Watching ${video.title}`, video });
// watch 렌더하기. video라는 오브젝트 생성.
};
이제 see를 전부 watch로 바꿔주고
watch.pug 를 수정한다.
if문을 사용해도 되지만, ternary operator 를 사용해본다 (라고 하셨는데 내가 공부 덜 한 부분인듯.. 찾아보자)
만약 video.views 가 1이라면, view라는 string을 반환하고, 아니면 views를 반환하라는 내용.
(조회수가 1이면 view, 아니면 views라서)
//watch.pug
extend base.pug
block content
h3 #{video.views} #{video.views === 1 ? "view" : "views" }
이젠 영상을 편집할 수 있는 페이지를 만들어보자.
a태그로 영상 편집 링크를 만들고, 오른쪽 화살표를 넣는다. (→ 붙여쓰기)
이걸 클릭하면 편집 화면으로 가게 하기.
이때, href의 링크 앞에 / 를 넣어주면, 내가 지금 어디에 있든 상관 없이 root경로 + /edit 으로 가게 된다.
만약에 / 가 없다면 지금 현재 링크의 제일 끝에 링크를 넣어서 간다 (ex. "edit" -> 4000/videos/edit)
/ 앞에 뭔가를 줄줄이 쓰고 싶지 않다면 그냥 / 쓰지 말고 할 것.
이게 바로 relative 와 absolute url 의 차이점임!
// watch.pug
extend base.pug
block content
h3 #{video.views} #{video.views === 1 ? "view" : "views" }
a(href=`${video.id}/edit`) Edit Video →
Edit Video
우선 edit 부분도 watch 처럼 수정해준다. 방법 똑같음
//videoController.js
export const watch = (req, res) => {
const { id } = req.params;
const video = videos[id - 1];
return res.render("watch", { pageTitle: `Watching ${video.title}`, video });
};
export const edit = (req, res) => {
const { id } = req.params;
const video = videos[id - 1];
return res.render("edit", { pageTitle: `Editing: ${video.title}`, video });
};
그리고 폼을 만들어서 placeholder와 submit(save) 버튼을 생성해준다.
// edit.pug
extend base.pug
block content
h4 Change Title of Video
form(action="")
input(placeholder="Video Title", value=video.title, required)
input(value="Save", type="submit")
그럼 이제 save 하면 내용이 backend로 가게 해야한다.
데이터가 가게 될 곳은 action이라는 속성에 들어가는 값이다. (서버가 가져야 하는 url)
get method를 사용하는 url을 우리는 이미 가지고 있는데(/edit),
여기서는 method를 POST로 바꿔준다.
이제 post 서버에 대해서 가르쳐주는 내용을 작성해보자.
// videoRouter.js 세번째줄에 post 추가
videoRouter.get("/:id(\\d+)", watch);
videoRouter.get("/:id(\\d+)/edit", getEdit);
videoRouter.post("/:id(\\d+)/edit", postEdit);
videoRouter.get("/:id(\\d+)/delete", deleteVideo);
videoRouter.get("/upload", upload);
그리고 함수를 작성해준다.
이때 getEdit은 form을 화면에 보여주는 녀석이고,
postEdit은 변경사항을 저장해주는 녀석이다.
// 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) => {}
그리고 getEdit 과 postEdit 을 import 해준다.
// videoRouter.js
import express from "express";
import {
watch,
upload,
deleteVideo,
getEdit,
postEdit
} from "../controllers/videoController";
const videoRouter = express.Router();
videoRouter.get("/:id(\\d+)", watch);
videoRouter.get("/:id(\\d+)/edit", getEdit);
videoRouter.post("/:id(\\d+)/edit", postEdit);
videoRouter.get("/:id(\\d+)/delete", deleteVideo);
videoRouter.get("/upload", upload);
export default videoRouter;
그리고 안쓰는 update와 deletevideo, search를 삭제해놓는다.
*** globalRouter 에서 search 를 쓰고 있기 때문에 반드시 지워줘야 한다. 이것 때매 오류 생겨서 한참 고생함 ㅠㅠ
이전 강의에서는 submit 버튼을 클릭할 때 form 의 행동을 어떻게 통제하는지 다뤄봤다.
method라는 게 바로 form과 백엔드 사이의 정보 전송 방식이라는 걸 배웠지!!
만약 get method를 사용하면, 그 form 에 있는 정보가 url에 들어가게 된다.
그냥 데이터를 받는 게 목적이라면, get을 사용하면 된다.
그런데 이 데이터베이스에 들어가는 데이터가 수정되어야 하나? 편집이나 삭제가 필요한가? 에 대해서 생각해 봤을 때
예를 들어 영상 삭제나 편집 페이지 같은 경우라면, 우리는 POST 를 써야 한다.
그리고 action 을 사용하면 특정한 url로 보낼 수 있다는 것도 배웠다. (우리는 안쓸거지만)
아직까지는 postEdit (videoController.js에 적은 내용) 에 아무 것도 주고 있지 않기 때문에
save 를 누르면 계속해서 로딩만 뜨고 있다. 이 부분을 수정해야 한다.
우선 router를 만들어서 ( get과 post 관련 내용 중 id 부분이 겹치므로 ) getEdit와 postEdit를 하나로 합쳐서 작성해준다.
아래 내용은 get이면 getEdit으로, post면 postEdit으로 가라는 뜻이다.
// videoRouter.js
videoRouter.get("/:id(\\d+)", watch);
videoRouter.route("/:id(\\d+)/edit").get(getEdit).post(postEdit);
이제 videoControlller의 postEdit 을 res.redirect로 바꿔보자.
res.redirect() 는, 브라우저가 redirect ( 자동으로 이동) 하도록 하는 것이다. 브라우저는 우리가 준 url대로 이동할 것!
아래와 같이 작성하면
1. 우선 유저가 getEdit 으로 온다.
2. 그러면 우리는 편집용 form 을 render 시켜주고,
3. 유저가 submit을 하면 우리의 post request 로 이동해서 postEdit가 처리를 해줄 텐데
4. postEdit 은 route 로부터 id를 얻어와서 /videos/id 페이지로 redirect 시켜줄 것이다.
한 마디로 save 하면 다시 watch 페이지로 돌아온다는 것!
그러면 위 내용은 구현이 완료됐고,
다음으로는 제목을 수정하고 저장하면 그 데이터가 저장이되었으면 좋겠다.
이때 req.params와 같은 req.body 를 사용해 볼 것이다.
우리는 application 에게 form 을 처리하고 싶다고 말해야 한다. form을 이해할 수 있게 해야 한다.
그러기 위해서 우리는 express function 의 method 중 express.urlencoded 를 사용해보려고 한다.
얘는 form 의 body 를 이해하는 녀석임!
이걸 설치하기 전에 고려해야 할 사항은
middleware를 route (server,js에서 globalRouter 부터의 부분) 사용하기 전에 사용해야 된다는 것이다.
그러니까 바로 그 위인 app.use("logger"); 밑줄에 써야 한다.
// server.js
app.set("view engine", "pug");
app.set("views", process.cwd() + "/src/views");
app.use(logger);
app.use(express.urlencoded({ extended: true }));
app.use("/", globalRouter);
app.use("/users", userRouter);
app.use("/videos", videoRouter);
이렇게 되면 express application 이 form 의 value 들을 이해할 수 있도록 하고
우리가 쓸 수 있는 자바스크립트 형식으로 변형시켜주게 된다.
그리고 postEdit를 수정해준다.
req.params에서 id를 얻었고, form 에서 오는 body에서 title을 얻었다.
그런 다음 비디오를 업데이트해준다. 그리고 우린 다시 그 비디오로 돌려보낸다. 다시 /videos/${id} 로 redirect 해준다.
그러면 watch controller가 해당하는 video를 찾고 우리에게 보여준다.
// 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}`);
};
결과물: edit video -> 이름 jia video로 바꿈, save -> title에 watching Jia Video 라고 뜸 -> 홈으로 돌아가면 Jia Video라고 첫 영상에 이름이 바뀌어있음
More Practice
컨트롤러 만들기 -> 라우터 만들기 -> 컨트롤러 사용.
/upload로 가는 링크 만들기
post 로 지정해주고 폼 만들기
req.body를 사용해서 유저가 input에 작성한 data 얻기
(input 에 이름이 없으면 request.body에 아무것도 나타나지 않음!)
비디오를 우리의 videos array 에 넣기
새 비디오를 만들어보자
const newVideo~
이걸 array에 넣어보자 videos.push(newVideo)
'Study > Youtube Clone' 카테고리의 다른 글
[유튜브 클론] Query, Schema (0) | 2022.08.21 |
---|---|
[유튜브 클론] Mongo DB를 시작해보자! (0) | 2022.08.19 |
[유튜브 클론] Routers (0) | 2022.08.14 |
[유튜브클론] External Middlewares: Morgan (0) | 2022.08.12 |
[유튜브클론] Middlewares, Servers, Controllers (0) | 2022.08.11 |