express없이 라우터를 만들면 요청 메서드와 주소별로 분기 처리하여 코드가 매우 복잡하다.
if문으로 분기하게 되어 코딩하여 가독성도 떨어지며 확장하기도 어렵다.
Node.js Example server에 적용한 코드를 바탕으로 정리하였다.
express를 사용하는 이유 중 하나가 라우팅을 깔끔하게 관리할 수 있다는 점이다.
send me email if you have any questions.
Router 연결
// Router init
const userRouter = require("./routes/User");
const calenderRouter = require("./routes/Calendar");
const publicMoneyRouter = require("./routes/PublicMoney");
const BoardRouter = require("./routes/Board");
...
// Route Start
app.use("/user", userRouter);
app.use("/calendar", calenderRouter);
app.use("/publicmoney", publicMoneyRouter);
app.use("/board", BoardRouter);
app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(specs));
...
app.js 일부
다른 미들웨어와는 다르게 앞에 주소가 붙어 있다.
이와 같이 라우팅 미들웨어는 첫 번째 인자로 주소를 받아서 특정 주소에 해당하는 요청이 왔을 때만 미들웨어가 동작하게 할 수도 있다.
-
주소가 /user로 시작하면 routes/User.js를, /calendar로 시작하면 routes/Calendar.js를 호출하라는 의미이다.
-
use 대신, GET, POST, PUT, DELETE와 같은 HTTP메서드를 사용할 수도 있다.
- use메서드는 모든 HTTP 메서드에 대해 요청 주소만 일치하면 실행
- GET, POST, PUT, DELETE 같은 메서드는 주소뿐만 아니라 HTTP 메서드까지 일치 하는 요청일 때만 실행
미들웨어 함수는 요청 오브젝트(req), 응답 오브젝트 (res), 그리고 애플리케이션의 요청-응답 주기 중 그 다음의 미들웨어 함수 대한 액세스 권한을 갖는 함수이다. 그 다음의 미들웨어 함수는 일반적으로 next라는 이름의 변수로 표시된다. 미들웨어 함수는 다음과 같은 태스크를 수행할 수 있다.
- 모든 코드를 실행.
- 요청 및 응답 오브젝트에 대한 변경을 실행.
- 요청-응답 주기를 종료.
- 스택 내의 그 다음 미들웨어 함수를 호출.
Router 동작
// Router init
const express = require("express");
const router = express.Router();
...
router.get("/info", function (req, res) {
console.log("\nUser data GET request");
sql =
"SELECT Name, studentID, Department, Grade, PhoneNumber, Email, Part, Status, Warning, Permission FROM UserInfo";
connection.query(sql, function (err, rows, fields) {
if (err) {
console.log(err);
res.status(500).send("Server Error");
} else if (rows[0] == null) {
console.log("Empty");
res.status(200).send("Empty");
} else {
console.log("User infomation inquiry success");
res.status(200).send(rows);
}
});
});
...
module.exports = router;
User.js 일부
router 객체는 express.Router()로 만들며 코드 가장 하단부에 module.exprots = router;로 라우터를 모듈로 만든다.
- router에도 app처럼 use, get, post, put, delete같은 메서드를 사용할 수 있다.
- app.use처럼 하나의 router에 여러개의 middleware를 장착할 수 있다.
- 실제 라우터 로직이 실행되는 미들웨어전에 로그인 여부 또는 관리자 여부를 체크하는 미들웨어를 중간에 넣어 두곤한다.
다음과 같은 것이 가능하다는 뜻이다.router.get('/', middleware1, middleware2, middleware3);
- 실제 라우터 로직이 실행되는 미들웨어전에 로그인 여부 또는 관리자 여부를 체크하는 미들웨어를 중간에 넣어 두곤한다.
주소 route과정
위의 코드에서 router.get(“/info”)를 볼 수 있는데 app.js에서 app.use(‘/user’, userRouter)로 연결하였기 때문에 router.get(“/info”)에 접근하기 위해서는 /user/info로 get요청을 보내야 한다.
express router를 사용하지 않고 app.js에서 app.get(“/”, middleware), app.get(“/user”, middleware)로 코딩하여도 동일하게 동작한다.
router를 분리하는 이유는 코드 관리 및 유지보수를 위해서이다.
기타 주의사항
- 라우터에서는 반드시 요청에 대한 응답을 보내거나 에러 핸들러로 요청을 넘겨야 한다.
- 라우터에 연결된 나머지 미들웨어들을 건너뛰고 싶을 때 next(‘route’)를 사용한다.
- next함수의 라우터에서만 동작하는 특수 기능
- 하나의 요청에 대한 응답은 한 번만 보내야 하며 두 번 이상 보내면 다음과 같은 에러가 발생한다.
Error: Can’t set headers after they are sent.
at validateHeader (_http_outgoing.js:489:11)
at ServerResponse.setHeader(_http_outgoing.js:496:3)
…- 위의 에러가 발생했다면 라우터에서 res 객체의 응답 메서드가 두 번 이상 사용되지 않았는지 점검이 필요하다.