[노마드코더] 유튜브 클론 강의 Express.js

seomoon·2021년 1월 20일
0

노마드코더 유튜브 클론 강의 Express.js 파트를 듣고 메모한 내용입니다.
강의를 듣지 않았다면 이해하기 어려울 수 있습니다.

Express.js

Express.js로 웹 서버 생성하기

const express = require('express');
const app = express();

const PORT = 4000;

const handleListening = function() {
	console.log(`Listening on: http://localhost:${PORT}`);
}

app.listen(PORT, handleListening);

route 생성하고 응답하기

const express = require('express');
const app = express();

const PORT = 4000;

const handleListening = function() {
	console.log(`Listening on: http://localhost:${PORT}`);
}

function handleHome(req, res) {
    res.send('Hello from home'); //응답하기
}

function handleProfile(req, res) {
    res.send('You are on my profile');
}

//route 생성
app.get('/', handleHome);
app.get('/profile', handleProfile);

app.listen(PORT, handleListening);
  • GET, POST 메소드 :
    - GET : 브라우저가 서버로부터 정보를 받아옴
    - POST : 브라우저가 서버에 정보를 전달함

Babel

  • Babel : 최신 자바스크립트 코드를 표준 코드로 변환해주는
    자바스크립트 컴파일러
  • babel node : node.js에서 사용할 수 있는 babel 버전
    npm install @babel/node
  • preset : -env preset 사용 (최신 preset이지만 실험적인 수준은 아님)
    npm install @babel/preset-env
  • .babelrc 작성하기
     {
       "presets": ["@babel/preset-env"]
     }

index.js의 코드를 최신 자바스크립트 코드로 다시 작성하기

//require 메소드 대신 import 키워드 사용 가능
import express from "express";

//arrow function 사용
const handleListening = () => 
	console.log(`Listening on: http:://localhost:${PORT}`);

const handleHome = (res, req) => res.send("Hello from home");

const handleProfile = (res, req) => res.send("You are on my profile");
  • pacakge.json의 start 스크립트를 node index.js -> babel-node index.js로 변경한다.
  • 에러 해결 : npm install @babel/core

devDependencies 패키지 설치하기 (package.json의 dependencies와 별개로 패키지 설치하기)

  • devDepdendencies : 프로젝트를 실행하는데 필요한 패키지가 아니라 개발자가 편하게 개발하기 위해 필요한 패키지들
    npm install nodemon -D (-D 옵션 추가)

  • nodemon? : 파일을 저장할 때마다, 변경사항이 있는지 확인하고 변경사항이 있으면 자동으로 서버를 restart 해준다.

  • 서버가 두 번 restart되는 이슈 :
    저장 -> Babel이 코드 변환 -> 서버 재시작 -> nodemon이 코드변화 감지 -> 서버 재시작
    => start 스크립트 수정으로 해결
    --delay 2 옵션 추가 (bebel 코드변환을 기다려주기)

Middlewares

  • Middlewares : 유저의 요청과 서버의 마지막 응답 사이에 존재하는 것.
    express에서 모든 함수는 미들웨어가 될 수 있다.

  • 미들웨어 선언하기

    const betweenHome = (req, res, next) => {
        console.log("I'm between");
        next(); //다음 미들웨어 호출
    }
    
    app.get("/", betweenHome, handleHome);
  • 미들웨어로 할 수 있는 일 :

    • 유저의 로그인 여부 체크
    • 파일을 전송할 때 중간에서 가로챌 수 있음
    • 모든 접속에 대해 로그를 작성하기
    • IP주소 체크
  • 미들웨어 호출 순서

    app.use(betweenHome); //모든 route에 미들웨어 적용하기
    
    app.get("/", handleHome);
    
    app.get("/profile", handleProfile);

    미들웨어의 호출 순서가 중요하다.
    접속이 있으면 위에서부터 아래로 실행되기 때문에
    route 설정 전에 미들웨어를 선언해야 미들웨어가 실행된다.

  • 미들웨어의 종류
    1) Morgan
    logging (접속 기록)에 도움을 주는 middleware
    -> npm install morgan

      ```
      import morgan from "morgan";
      import logger from "morgan"; //nickname은 변경 가능함
    
      app.use(morgan("tiny"));
      ```
      tiny, combined, common, dev 등의 옵션이 있다.  

    2) Helmet
    node.js 어플리케이션의 보안에 도움을 주는 Middleware
    -> npm install helmet

      ```
      import helmet from "helmet";
    
      app.use(helmet()); //for security
      ```

    3) body parser
    request object의 body로 부터 정보를 얻을 수 있게 하는 미들웨어
    -> npm install body-parser

    4) cookie parser
    cookie에 유저 정보를 저장해 세션을 다루기 위한 미들웨어
    -> npm install cookie-parser

    import cookieParser from "cookie-parser";
    import bodyParser from "body-parser";
    
    app.use(cookieParser());
    app.use(bodyParser.json()); //서버가 json을 파싱하도록 설정
    app.use(bodyParser.urlencoded({ extended: true })); //서버가 html from을 파싱하도록 설정
  • app.js에서 미들웨어 호출 순서 :
    연결 => cookieParser -> bodyParser -> helmet -> morgan => route 도달


Routing

  • index.js -> app.js, init.js로 분리하기

  • start 스크립트 : index.js 대신 init.js 실행하도록 변경

  • init.js

    import app from "app";
    
    const PORT = 4000;
    
    const handleListening = () => console.log(`Listening on: http://localhost:${PORT}`);
    
    app.listen(PORT, handleListening);
  • es6 자바스크립트 모듈 : 다른 js 파일의 코드를 가져와 활용할 수 있다.
    app.js : export default app;
    누군가 app.js를 import하면 app 오브젝트를 전달하겠다는 뜻

Router

  • Router를 이용해 복잡한 여러 개의 Routes들을 작은 파일 단위로 쪼개서 정리할 수 있다.

  • router.js

    import express from "express";
    
    export const userRouter = express.Router();
    
    userRouter.get("/", (req, res) => res.send('user index'));
    userRouter.get("/edit", (req, res) => res.send('user edit'));
    userRouter.get("/password", (req, res) => res.send('user password'));
  • app.js

    import { userRouter } from "./router";
    //default로 export한 게 아니기 때문에 { } 안에 작성해야한다.
    
    app.use("/user", userRouter); // /user로 접속하면 userRouter를 사용하겠다는 뜻
    • export default : 파일 전체를 export / export : 해당 변수만 export
  • express.js에서는 이런 방식으로 긴 파일들을 아주 작은 파일로 쪼개서 사용할 수 있다.

  • routers 폴더에 Router.js 파일들 넣기 : globalRouter, userRouter, videoRouter

  • routes.js

    // Global
    const HOME = "/";
    const JOIN = "/join";
    const LOGIN = "/login";
    const LOGOUT = "/logout";
    const SEARCH = "/search";
    
    // Users
    const USERS = "/users";
    const USER_DETAIL = "/:id";
    const EDIT_PROFILE = "/edit-profile";
    const CHANGE_PASSWORD = "/change-password";
    
    // Videos
    const VIDEOS = "/videos";
    const UPLOAD = "/upload";
    const VIDEO_DETAIL = "/:id";
    const EDIT_VIDEO = "/:id/edit";
    const DELETE_VIDEO = "/:id/delete";
    //id 앞에 ':' : 값이 변한다는 것을 express에 알려줌
    
    const routes = {
      home: HOME,
      join: JOIN,
      login: LOGIN,
      logout: LOGOUT,
      search: SEARCH,
      users: USERS,
      userDetail: USER_DETAIL,
      editProfile: EDIT_PROFILE,
      changePassword: CHANGE_PASSWORD,
      videos: VIDEOS,
      upload: UPLOAD,
      videoDetail: VIDEO_DETAIL,
      editVideo: EDIT_VIDEO,
      deleteVideo: DELETE_VIDEO,
    };
    
    export default routes;

    routes.js 파일안에 routes 정리해두기 -> 전체 url 구조 기억할 필요 없이 쉽게 필요한 경로를 찾을 수 있음

  • app.js

    import routes from "./routes";
    
    app.use(routes.home, globalRouter);
    app.use(routes.users, userRouter);
    app.use(routes.videos, videoRouter);
  • globalRouter.js
    globalRouter.get(routes.home, (req, res) => res.send("Home"));
    globalRouter.get(routes.join, (req, res) => res.send("join"));
    globalRouter.get(routes.login, (req, res) => res.send("login"));
    globalRouter.get(routes.logout, (req, res) => res.send("logout"));
    globalRouter.get(routes.search, (req, res) => res.send("search"));

MVC Pattern

  • MVC : Model, View, Controller

    • Model : data (database)
    • View : how does the data look (template)
    • Controller : function that looks for the data (Logic)
  • Pattern : 구조

Controller

  • Controller : functions, 로직에 관한 부분.
  • controllers 폴더에 userController.js, videoController.js 생성
  • *router.js 파일들의 함수를 *Controller.js로 분리하기



정리

  • init.js : app.js에서 import한 app이 있음

  • app.js : express import -> create app (const app = express())
    -> use middlewares

  • middlewares

    • cookieParser : cookie를 전달받아서 사용할 수 있도록 만들어주는 미들웨어. 사용자 인증 같은 곳에서 쿠키를 검사할 때 사용함
    • bodyParser : 사용자가 웹 사이트로 전달하는 정보들을 검사하는 미들웨어. request에서 from이나 json 형태로 된 body를 검사한다. 사진이나 비디오를 업로드할 때 제목, 댓글 같은 정보를 전달할 때 form에 담아서 업로드해야하기 때문.
    • helmet : application이 더 안전하도록 만들어주는 미들웨어
    • morgan : application에서 발생하는 모든 일을 logging하는 미들웨어
  • 3개의 router 사용

    • globalRouter : /home, /search, /join, /login, /logout url이 담겨 있음
    • userRouter : /user/* url이 담겨 있음
    • videoRouter : /video/* url이 담겨 있음
  • url 주소들은 모두 routes.js에 정의해둠. (routes.js만 수정하면 전부 적용될 수 있도록)

  • 모든 router의 로직(함수)들은 controller에 정의되어 있음.
    controller = MVC의 'C' 부분.

  • Pug : express에서 View를 다루는 방법 중 하나. Pug를 사용하면 express로 HTML을 보여줄 수 있다. res.send('message') 대신 실제 HTML을 전달한다.
    Pug = MVC의 'V' 부분.

profile
💛💛 🖥🏐🛋🥗💵📖 💛💛

0개의 댓글