[TIL] 211121

27677 단어 node.jsTILTIL

📝 오늘 한 것

  1. middlewares - controller / app.use() / Morgan

  2. routers - 라우터 만들고 사용하기


📚 배운 것

1. middlewares

1) middleware와 controller

middlewares란 브라우저의 requests와 서버의 responses의 중간에 있는 소프트웨어를 말한다.

앞에서 사용했던 handler 함수는 사실 controller라고 불린다.
모든 controller는 middleware가 될 수 있고, 마찬가지로 모든 middleware도 contoller가 될 수 있다.
controller가 next() 함수를 호출한다면, 그 controller는 middleware가 된다.

middleware는 request에 응답하지 않고, request를 지속시켜준다.
middleware는 사용자가 웹 사이트의 어디를 가려고 하는지 말해주는 함수로, 필요한 만큼 만들어 사용할 수 있다.

const loggerMiddleware = (req, res, next) => { // controller이자 middleware
  console.log(`Someone is going to: ${req.url}`):
  next();
}

const handleHome = (req, res) => { // controller
  return res.send("Hello!");
};

app.get('/', loggerMiddleware, handleHome);

브라우저가 root 페이지를 갖다달라고 요청하면 express는 loggerMiddleware 함수를 호출한다.
console에 req.url 즉, 사용자가 웹 사이트에서 가려고 하는 url이 출력된다.
그 후, next()에 의해 다음 handleHome 함수가 호출된다.
res.send("Hello!")가 실행되어 화면에 메시지가 뜨면서 request가 종료된다.

그러나, 위의 middleware는 하나의 url에만 적용되어 있어 별로 쓸모가 없다.
이를 고쳐보자.

2) app.use(middleware)

어느 url에도 작동하는 global middleware를 만들 수 있다.

순서가 중요하다. app.use()가 먼저 온 후에 app.get()이 와야 한다.
만약 app.use()가 어떤 route를 인자로 가지는 app.get()보다 뒤에 온다면 그 middleware는 그 route에는 작동하지 않는다.

const loggerMilddleware = (req, res, next) => {
  console.log(`Someone is going to: ${req.url}`); // req.url === req.path
  next();
};

const handleHome = (req, res) => {
  return res.send("Hello!");
};

const handleLogin = (req, res) => {
  return res.end();
};

app.use(loggerMilddleware);
app.get("/", handleHome);
app.get("/login", handleLogin);

파일을 위와 같이 수정한 후 저장한다.

localhost:4000 에 들어가면, 콘솔에 'Someone is going to: /'이 뜬다.
localhost:4000/login 에 들어가면, 콘솔에 'Someone is going to: /login'이 뜬다.

한편 localhost:4000/aaaaa 에 들어가면, 서버가 이 url을 인식하지 못하므로 화면에는 'Cannot GET /aaaa'가 뜨지만 콘솔에는 'Someone is going to: /aaaa'이 뜬다.

즉, 어느 url이 get request 되었든 간에 일단 global middleware는 모든 route에서 실행됨을 알 수 있다.

3) privateMiddleware

const loggerMilddleware = (req, res, next) => {
  // 어떤 request method가 어떤 url로 향하는지 알 수 있도록 코드를 수정했다
  console.log(`${req.method} ${req.url}`);
  next();
};

const privateMiddleware = (req, res, next) => {
  const url = req.url;
  if (url === "/protected") {
    return res.send("<h1>Not Allowed</h1>");
  }
  console.log("Allowed, you may continue.");
  next();
};

const handleHome = (req, res) => {
  return res.send("Hello!");
};

const handleProtected = (req, res) => {
  return res.send("Welcome to the private lounge.");
};

app.use(loggerMilddleware);
app.use(privateMiddleware);
// app.use(loggerMiddleware, privateMiddleware); 라고 적어도 됨
app.get("/", handleHome);
app.get("/protected", handleProtected);

localhost:4000/protected 에 들어가면, 콘솔에는 loggerMiddleware 함수에 의해 'GET /protected'가 뜨고, 화면에는 privateMiddleware 함수에 의해 'Not Allowed'가 뜬다.
즉, privateMiddleware 함수의 if 조건식을 만족하여 request를 지속하는 middleware가 request를 종료하는 controller가 된 것이다.

4) Morgan 설치 (외부 미들웨어 설치)

npm - morgan 참고

Morgan은 무슨 일이 어디에서 일어났는지를 기록하는 데 도움을 주는 node.js 용 request logger middleware이다.
VS code 내장 터미널에 'npm i morgan'을 입력해 설치할 수 있다.
morgan() 함수를 호출하면서 설정을 해줘야 한다.

import morgain from "morgan";

const logger = morgan("dev");

const handleHome = (req, res) => {
  return res.send("Hello!");
};

app.use(logger);
app.get("/", handleHome);

morgan() 함수를 호출하면, req, res, 'next'를 포함한 middleware를 return 한다.
함수의 인자로 들어간 "dev"는 middleware를 설정해준다. dev, combined, tiny, common, short의 5가지 옵션을 넣을 수 있는데 옵션마다 각각 콘솔에서 보여주는 것이 다르다.


2. routers

실제로 wetube 코딩 시작 ❗

1) router(라우터)란?

프로젝트에서 어떤 종류의 데이터를 이용할 것인지 생각해야 한다.
wetube 프로젝트에서는 크게 두 가지의 데이터를 다룬다.
첫 번째는 '비디오(영상)'이고, 두 번째는 'user(사용자)'이다.
이를 wetube 프로젝트의 도메인이라고 할 수 있다.

이를 url 차원에서 생각해보면, 아래와 같은 url 리스트를 작성할 수 있다.

💡 글로벌 라우터

/ → Home
/join → Join 페이지
/login → Login 페이지
/search → Search 페이지

💡 user 라우터

/users/edit → Edit user 페이지
/users/delete → Delete user 페이지

💡 video 라우터

/videos/watch → Watch video 페이지
/videos/edit → Edit video 페이지
/videos/delete → Delete video 페이지
/videos/comments → comment on a video 페이지
/videos/comments/delete → Delete a comment of a video 페이지

router(라우터)란 작업 중인 주제를 기반으로 url을 그룹화하는 것을 말한다.

라우터는 도메인(이 경우, video와 user) 별로 나눌 수 있다.
예를 들어, /videos로 시작하는 모든 url들은 'video 라우터'라는 하나의 라우터로 그룹화할 수 있다.

2) global router(글로벌 라우터)

글로벌 라우터는 홈에서 바로 갈 수 있는 페이지들을 담고 있다

/ → Home
/join → Join 페이지
/login → Login 페이지
/serch → Search 페이지

사실 위에서 배운 대로라면 위 url들은 규칙에 어긋난 듯 보인다.
join과 login을 하는 것은 user이고 search 되는 것은 videos라면, url은 아래처럼 되어야 하지 않을까?

/
/users/join
/users/login
/videos/search

그러나 실제로 보통은 이렇게 url을 만들지 않는다.
url을 깔끔하게 만들기 위해 가끔은 규칙을 어기고 예외를 만들기도 한다.

3) router 만들고 사용하기

(1) express.Router()

아래와 같이 세 개의 라우터를 만들 수 있다.

const globalRouter = express.Router();
const userRouter = express.Router();
const videoRouter = express.Router();

(2) app.use("루트 url", 라우터 이름)

라우터를 만든 후 사용하기 위해 설정을 해야 한다

app.use("/", globalRouter);
app.use("/users", userRouter);
app.use("/videos", videoRouter);

첫 번째 인자로 '루트 url'을, 두 번째 인자로 '라우터 이름'을 가져온다.
이때 루트 url이란 글로벌 라우터의 경우 '/'를, user 라우터의 경우 '/users'를, video 라우터의 경우 '/videos'를 의미한다.

이제 우리의 앱은 다른 url을 이해할 준비가 되었다.

(3) 각 라우터의 첫 페이지 만들기

이를 바탕으로 각각의 라우터의 첫 페이지를 만들 수 있다.
임의로 글로벌 라우터의 첫 페이지는 '/(즉, Home)'로 하고, user 라우터의 첫 페이지는 'users/edit'으로 하고, video 라우터의 첫 페이지는 '/videos/watch'로 하기로 한다.

🔎 코드

// 라우터 만들기
// controller 정의
// Router.get("라우터의 첫 페이지 url", controller);

const globalRouter = express.Router();
const handleHome = (req, res) => res.send("Home");
globalRouter.get("/", handleHome);

const userRouter = express.Router();
const handleEditUser = (req, res) => res.send("Edit User");
userRouter.get("/edit", handleEditUser);

const videoRouter = express.Router();
const handleWatchVideo = (req, res) => res.send("Watch Video");
videoRouter.get("/watch", handleWatchVideo);

app.use("/", globalRouter);
app.use("/users", userRouter);
app.use("/videos", videoRouter);

🔎 결과

브라우저의 주소 창에 localhost:4000/ 이라고 입력해 들어가면, 화면에 Home 이라고 뜬다.
브라우저의 주소 창에 localhost:4000/users/edit 라고 입력해 들어가면, 화면에 Edit User 라고 뜬다.
브라우저의 주소 창에 localhost:4000/videos/watch 라고 입력해 들어가면, 화면에 Watch Video 라고 뜬다.

무슨 일이 일어난 걸까?
video 라우터를 예시로 들어 설명해보겠다.

🔎 설명

const videoRouter = express.Router(); // 2
const handleWatchVideo = (req, res) => res.send("Watch Video"); // 3
videoRouter.get("/watch", handleWatchVideo); // 2, 3

app.use("/videos", videoRouter); // 1
  1. 누군가 /videos로 시작하는 url을 찾으면(이 경우에는 사용자가 /videos/watch 를 입력했다고 하자.), express는 video 라우터 안으로 들어간다.

  2. express는 video 라우터 안에서 사용자가 입력한 url의 나머지 주소(즉, /watch)를 찾는다. video 라우터는 /watch 라는 1가지 루트를 가지므로 우리는 /videos 안의 /watch 에 있게 된다.

  3. 그 다음에 express가 handleWatchVideo 함수를 실행함으로써 화면에는 Watch Video가 표시된다.


✨ 내일 할 것

  1. 강의 계속 듣기

좋은 웹페이지 즐겨찾기