본문 바로가기

nodeJS

[Node.js] Router 객체로 라우팅 분리

 

Router

라우터를 만들 때는 요청 메서드와 주소 별로 분기 처리를 하느라 코드가 매우 복잡했습니다. if 문으로 분기하면서 코딩했기 때문에 보기에도 좋지 않고 확장하기도 어려웠습니다. 익스프레스를 사용하는 이유 중 하나는 바로 라우팅을 깔끔하게 관리할 수 있다는 점입니다.

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) => {
  res.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를 통해 app.js에 연결합니다. 또한, 에러 처리 미들웨어 위에 404 상태 코드를 응답하는 미들웨어를 하나 추가합니다.

//app.js

...
const path = require('path');

dotenv.config();

const indexRouter = require('./routes');
const userRouter = require('./routes/user')
...
app.use('/', indexRouter)
app.use('/user', userRouter)

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

app.use((err, req, next) => {
  ..
})

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

require('./routes') 는 같습니다. index.js user.js는 모양이 거의 비슷하지만, 다른 주소의 라우터 역할을 하고 있습니다.

app.use 로 연결할 때의 차이 때문입니다. indexRouter는 app.use('/use') 에 연결했습니다. indexRouteruse의 ' / ' 와 get 의 ' / ' 가 합쳐져 GET /  라우터가 되었고 , userRouter는 use 의 '/user' 와 get의 ' / ' 가 합쳐져 GET/user 라우터가 되었습니다. 이렇게 app.use로 연결 할 때 주소가 합쳐진다는 것을 염두에 두면 됩니다.

 

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('/use/: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 객체 안에 들어 있습니다.

예를 들어 /user/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.routerouter.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')
});

 

'nodeJS' 카테고리의 다른 글

[Node.js] 예외 처리하기  (0) 2023.09.07
[NodeJS] express  (5) 2023.09.04
[Node.js] Net 모듈  (0) 2023.08.31
[Node.js] 통신(네트워크)  (0) 2023.08.30
[Node.js] 내장 모듈 , require  (0) 2023.08.29