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)