[노마드코더] 유튜브 클론 강의 Express.js
노마드코더 유튜브 클론 강의 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' 부분.
Author And Source
이 문제에 관하여([노마드코더] 유튜브 클론 강의 Express.js), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://velog.io/@seomoon/210120-Express.js
저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
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);
- GET : 브라우저가 서버로부터 정보를 받아옴
- POST : 브라우저가 서버에 정보를 전달함
자바스크립트 컴파일러
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);
미들웨어로 할 수 있는 일 :
- 유저의 로그인 여부 체크
- 파일을 전송할 때 중간에서 가로챌 수 있음
- 모든 접속에 대해 로그를 작성하기
- 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 도달
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
: 해당 변수만 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.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
- Model : data (database)
- View : how does the data look (template)
- Controller : function that looks for the data (Logic)
Pattern : 구조
*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' 부분.
Author And Source
이 문제에 관하여([노마드코더] 유튜브 클론 강의 Express.js), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@seomoon/210120-Express.js저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)