Node.js Express router

 

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 객체의 응답 메서드가 두 번 이상 사용되지 않았는지 점검이 필요하다.