nodeJS
[Node.js] Router 객체로 라우팅 분리
sang969
2023. 9. 13. 16:25
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를 ./routes로 require할 수 있는 이유는 index.js는 생략할 수 있기 때문입니다. require('./routes/index.js') 와
require('./routes') 는 같습니다. index.js 와 user.js는 모양이 거의 비슷하지만, 다른 주소의 라우터 역할을 하고 있습니다.
app.use 로 연결할 때의 차이 때문입니다. indexRouter는 app.use('/use') 에 연결했습니다. indexRouter는 use의 ' / ' 와 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.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')
});