프로그래밍 언어/NODE JS

Router 객체로 라우팅 분리하기

· 코딩마이데이

app.js에서 app.get 같은 메서드가 라우터 부분입니다. 라우터를 많이 연결하면 app.js 코드가 매우 길어지므로 익스프레스에서는 라우터를 분리할 수 있는 방법을 제공합니다. routes 폴더를 만들고 그 안에 index.js와 user.js를 작성합니다.

 

routes/index.js

const express = require("express");

const router = express.Router();

// GET / 라우터
router.get("/", (req, res) => {
  router.send("Hello, Express");
});

module.exports = router;

 

routes/user.js

const express = require("express");

const router = express.Router();

// GET /user 라우터
router.get("/", (req, res) => {
  res.send("Hello, User");
});

module.exports = router;

 

만들었던 index.js와 user.js를 app.use를 통해 appp.js에 연결합니다. 또한, 에러 처리 미들웨어 위에 404 상태 코드를 응답하는 미들웨어를 하나 추가합니다.

const express = require("express");
const morgan = require("morgan");
const cookieParser = require("cookie-parser");
const session = require("express-session");
const dotenv = require("dotenv");
const path = require("path");

dotenv.config();
const indexRouter = require("./routes");
const userRouter = require("./routes/user");
const app = express();
app.set("port", process.env.PORT || 3000);

app.use(morgan("dev"));
app.use("/", express.static(path.join(__dirname, "public")));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser(process.env.COOKIE_SECRET));
app.use(
  session({
    resave: false,
    saveUninitialized: false,
    secret: process.env.COOKIE_SECRET,
    cookie: {
      httpOnly: true,
      secure: false,
    },
    name: "session-cookie",
  })
);

app.use("/", indexRouter);
app.use("/user", userRouter);

app.use((req, res, next) => {
  console.log("모든 요청에 다 실행됩니다.");
  next();
});
app.get(
  "/",
  (req, res, next) => {
    console.log("GET / 요청에서만 실행됩니다.");
    next();
  },
  (req, res) => {
    throw new Error("에러는 에러 처리 미들웨어로 갑니다.");
  }
);

app.use((req, res, next) => {
  res.status(404).send("Not Found");
});

app.use((err, req, res, next) => {
  console.error(err);
  res.status(500).send(err.message);
});

app.listen(app.get("port"), () => {
  console.log(app.get("port"), "번 포트에서 대기 중");
});

 

indexRouter를 ./routes로 require할 수 있는 이유는 index.js는 생략할 수 있기 때문입니다. require('./routes/index.js')와 require('./routes')는 같습니다.

index.js와 user.js는 모양이 거의 비슷하지만, 다른 주소의 라우터 역할을 하고 있습니다. app.use로 연결할 때의 차이 때문입니다. indexRouter는 app.use('/')에 연결했고, userRouter는 app.use('/user')에 연결했습니다. indexRouter는 use의 '/'와 get의 '/'가 합쳐져 GET / 라우터가 되었고, userRouter는 use의 '/user'와 get의 '/'가 합쳐져 GET /user 라우터가 되었습니다. 이렇게 app.use로 연결할 때 주소가 합쳐진다는 것을 염두에 두면 됩니다.

서버를 실행한 뒤 localhost:3000과 localhost:3000/user로 접속하면 각각에 해당하는 응답을 받을 수 있습니다.

localhost:3000, localhost:3000/user 화면

 

이전 절에서 next 함수에 다음 라우터로 넘어가는 기능이 있다고 소개했는데, 바로 next('route')입니다. 이 기능은 라우터에 연결된 나머지 미들웨어들을 건너뛰고 싶을 때 사용합니다.

router.get('/', (req, res, next) => {
  next('route');
}, (req, res, next) => {
  console.log('실행되지 않습니다');
  next();
}, (req, res, next) => {
  console.log('실행되지 않습니다');
  next();
});
router.get('/', (req, res) => {
  console.log('실행됩니다');
  res.send('Hello, Express');
});

 

위 예제처럼 같은 주소의 라우터를 여러 개 만들어도 됩니다. 라우터가 몇 개든 간에 next()를 호출하면 다음 미들웨어가 실행됩니다.

첫 번째 라우터의 첫 번째 미들웨어에서 next() 대신 next('route')를 호출했습니다. 이 경우에는 두 번째, 세 번째 미들웨어는 실행되지 않습니다. 대신 주소와 일치하는 다음 라우터로 넘어갑니다.

유용한 팁이 하나 더 있습니다. 라우터 주소에는 정규표현식을 비롯한 특수한 패턴을 사용할 수 있습니다. 여러 가지 패턴이 있지만, 자주 쓰이는 패턴 하나만 알아보겠습니다. 라우트 매개변수라고 하는 패턴입니다.

router.get('/user/:id', (req, res) => {
  console.log(req.params, req.query);
});

 

 

주소에 :id가 있는데요. 문자 그대로 :id를 의미하는 것이 아닙니다. 이 부분에는 다른 값을 넣을 수 있습니다. /users/1이나 /users/123 등의 요청도 이 라우터가 처리하게 됩니다. 이 방식의 장점은 :id에 해당하는 1이나 123을 조회할 수 있다는 점이며, req.params 객체 안에 들어 있습니다. :id이면 req.params.id로, :type이면 req.params.type으로 조회할 수 있습니다.

단, 이 패턴을 사용할 때 주의할 점이 있습니다. 일반 라우터보다 뒤에 위치해야 한다는 것입니다. 다양한 라우터를 아우르는 와일드카드 역할을 하므로 일반 라우터보다는 뒤에 위치해야 다른 라우터를 방해하지 않습니다.

router.get('/user/:id', (req, res) => {
  console.log('얘만 실행됩니다.');
});
router.get('/user/like', (req, res) => {
  console.log('전혀 실행되지 않습니다.');
});

 

/user/like와 같은 라우터는 /user/:id 같은 라우트 매개변수를 쓰는 라우터보다 위에 위치해야 합니다.

주소에 쿼리스트링을 쓸 때도 있습니다. 쿼리스트링의 키-값 정보는 req.query 객체 안에 들어 있습니다.

예를 들어 /users/123?limit=5&skip=10이라는 주소의 요청이 들어왔을 때 req.params와 req.query 객체는 다음과 같습니다.

{ id: '123' } { limit: '5', skip: '10' }

 

app.js에서 에러 처리 미들웨어 위에 넣어둔 미들웨어는 일치하는 라우터가 없을 때 404 상태 코드를 응답하는 역할을 합니다. 미들웨어가 존재하지 않아도 익스프레스가 자체적으로 404 에러를 처리해주기는 하지만, 웬만하면 404 응답 미들웨어와 에러 처리 미들웨어를 연결해주는 것이 좋습니다.

app.use((req, res, next) => {
  res.status(404).send('Not Found');
});

 

이 미들웨어를 제거하고 localhost:3000/abc에 접속하면 404 상태 코드와 함께 Cannot GET /abc 메시지가 응답됩니다.

라우터에서 자주 쓰이는 활용법으로 app.route나 router.route가 있습니다.

다음과 같이 주소는 같지만 메서드는 다른 코드가 있을 때 이를 하나의 덩어리로 줄일 수 있습니다.

router.get('/abc', (req, res) => {
  res.send('GET /abc');
});
router.post('/abc', (req, res) => {
  res.send('POST /abc');
});

 

다음과 같이 관련 있는 코드끼리 묶여 있어 더 보기 좋아집니다.

router.route('/abc')
  .get((req, res) => {
    res.send('GET /abc');
  })
  .post((req, res) => {
    res.send('POST /abc');
  });

 

'프로그래밍 언어 > NODE JS' 카테고리의 다른 글

템플릿 엔진 사용하기 - 퍼그(제이드)  (0) 2025.07.09
req, res 객체 살펴보기  (1) 2025.07.06
multer  (0) 2025.06.30
미들웨어 특성 활용하기  (1) 2025.06.27
expression-session  (0) 2025.06.26