노마드코더 유튜브 클론 강의 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);
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);
npm install @babel/node
-env
preset 사용 (최신 preset이지만 실험적인 수준은 아님)npm install @babel/preset-env
{
"presets": ["@babel/preset-env"]
}
//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");
node index.js
-> babel-node index.js
로 변경한다. npm install @babel/core
devDepdendencies : 프로젝트를 실행하는데 필요한 패키지가 아니라 개발자가 편하게 개발하기 위해 필요한 패키지들
npm install nodemon -D (-D 옵션 추가)
nodemon? : 파일을 저장할 때마다, 변경사항이 있는지 확인하고 변경사항이 있으면 자동으로 서버를 restart 해준다.
서버가 두 번 restart되는 이슈 :
저장 -> Babel이 코드 변환 -> 서버 재시작 -> nodemon이 코드변화 감지 -> 서버 재시작
=> start 스크립트 수정으로 해결
--delay 2
옵션 추가 (bebel 코드변환을 기다려주기)
Middlewares : 유저의 요청과 서버의 마지막 응답 사이에 존재하는 것.
express에서 모든 함수는 미들웨어가 될 수 있다.
미들웨어 선언하기
const betweenHome = (req, res, next) => {
console.log("I'm between");
next(); //다음 미들웨어 호출
}
app.get("/", betweenHome, handleHome);
미들웨어로 할 수 있는 일 :
미들웨어 호출 순서
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 도달
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를 이용해 복잡한 여러 개의 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
: 해당 변수만 exportexpress.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.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 : Model, View, Controller
Pattern : 구조
*router.js
파일들의 함수를 *Controller.js
로 분리하기init.js : app.js에서 import한 app이 있음
app.js : express import -> create app (const app = express())
-> use middlewares
middlewares
3개의 router 사용
/home, /search, /join, /login, /logout
url이 담겨 있음/user/*
url이 담겨 있음/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' 부분.