바닐라 node에 대한 지식이 전무했을 때 적은 express 관련 글이다. 한 번 훑고 express를 공부해보자.
express-generator
노마드 코더에서 youtube-clone에서는 다음과 같이 기본 폴더 구조를 생성했다.
controllers에서 서버 로직을 짜고 (req, res) => ...
models에서 DB 구조를 짰으며
routers에서 라우팅을 처리하고
views에서 렌더링할 pug 또는 ejs를 저장하였다.
이렇게 폴더의 구조를 직접 만들어 할 수도 있지만 필요한 패키지와 기본 폴더 구조까지 만들어 주는 express-generator라는 패키지를 이용해보자.
npm i -g express-generator
express-generator를 전역 설치했으므로 명령창에 express를 입력할 수 있게 되었다.
express learn-express --view=pug
learn-express라는 폴더 이름 아래에 views, routes, public 등이 만들어지고 템플릿 엔진은 pug로 설정합니다. 물론 ejs를 선호하는 분도 계시고 저도 그렇지만 진행합니다.
여담으로, express-generator는 기본 폴더 구조를 살펴보기 위함이니 남용하지 말고 직접 파일을 만들어서 관리하는 게 속도 편하고 관리하기에도 편합니다.
오른쪽은 express generator로 생성된 파일 구조입니다.
package-lock.json이나 node_modules이 없으므로 npm init후 여러 패키지를 설치해봅시다.
npm init
시작 후에는 express generator가 만든 dependencies를 설치하기 위해 npm install을 진행합시다.
npm i
중앙 통제실 app.js
여기서 npm start를 입력하면 package.json에 설정한 대로 실행이 됩니다. express generator의 기본 포트는 3000번 입니다. 그런데 bin/www에서 실행되는 서버 로직을 살펴보면 app.js입니다.
생각해보면 그동안 express를 사용할 때 관습처럼 app.js를 생성한 후 모듈로 export 했습니다.
import express from "express"
const app = express();
...
app.get("/", (req, res) => res.send(console.log(`<h1>hello</h1>`)))
...
export default app;
app.js는 중앙 통제실이라고 생각하면 됩니다. (미들웨어를 포함한) 라우터를 조립하는 공간입니다. 대체적으로 app.js는 다음과 같은 순서로 작성됩니다.
미들웨어와 use(), next()
노마드 코더에서 다음과 같이 미들웨어를 설치하여 운용한 경험이 있을 겁니다.
// middleware
app.use(helmet());
app.set("view engine", "pug"); //미들웨어가 아니다. express 설정이다.
app.use(cookiePaser());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(morgan("dev"));
여기서 눈여겨 볼 것은 app.get, app.post와 같이 http 메소드가 아닌 use와 set이 사용되었다는 것입니다.
set은 익스프레스 설정, 값 저장을 의미하고 use는 미들 웨어 장착 및 사용을 의미합니다. 여기서 주의할 점은 라우터도 미들웨어라는 것입니다. use가 사용되었다면 미들웨어라고 생각합시다.
// 라우터도 미들웨어다!
app.use(routes.home, globalRouter);
app.use(routes.users, userRouter);
app.use(routes.videos, videoRouter);
한편, 미들웨어는 req와 res 사이에서 작동하기 때문에 요청과 응답을 제어할 수 있다.
app.js에 다음 내용을 추가하고 로컬 호스트로 접근해보면 콘솔에 다음 내용이 출력되는 것을 볼 수 있다. 여기서 눈여겨볼 점은 인자에 next가 있고 다음 미들웨어로 넘어가기 위해 next()를 적었다는 것이다. 두번째 미들웨어에서는 next()를 호출하지 않았기 때문에 다음으로 넘어가지 않는다. 이를 이용해 특정 미들웨어까지만 진행하게 만들기도 한다.
app.use((req, res, next) => {
console.log("내가 만든 미들웨어");
if (+new Date() % 2 === 0) {
next();
} else {
res.send("당첨"); //next()가 없으므로 여기서 끝난다.
}
});
생각해보면 app.get 이나 app.post에는 next()를 호출한 적이 없을 것이다. 이는 메소드를 처리하면 더 이상 다음으로 넘어갈 일이 없기 때문이다.
한편, 유용하고 자주 쓰이는 미들웨어가 있으니 개발 시에 설치하고 app.js에 세팅하자. 미들웨어는 예전에 다룬 적이 있으니 첨부한다.
morgan, body-parser(4.16.0부터 express 내장), cookie-parser, express-session, flash, helmet, passport 등
기본적으로 다음과 같이 설정한다.
app.use(helmet());
app.use(logger("dev"));
app.use(express.static(path.join(__dirname, "public")));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookiePaser("secret code"));
app.use(
session({
resave: false, //세션 객체에 수정 사항이 없어도 저장합니까?
saveUninitialized: false, //처음 빈 세션 객체를 저장합니까?
secret: "secret code", // cookieParser의 인자와 같은 값이어야 함
cookie: {
httpOnly: true,
secure: false
}
})
);
app.use(flash());
404 not found와 에러처리
'Node, Nest, Deno > 🚀 Node.js (+ Express)' 카테고리의 다른 글
PUG 뷰 엔진 마스터하기 (0) | 2020.03.12 |
---|---|
404 NOT Found, Error 처리 미들웨어 (0) | 2020.03.12 |
npm (Node Package Manager) 개론 (0) | 2020.03.10 |
Vanilla Node로 REST API 살펴보기 (0) | 2020.03.10 |
Vanilla Node로 간단한 웹 서버 만들기 (0) | 2020.03.07 |