라우팅
요청에 따라 수행할 로직들은 각기 달라진다. url과 HTTP 메소드에 따라 어떤 응답을 할지 정의하는 것이 필요하다.
URI와 응답하는 HTTP 방식을 정의하는 것을 라우팅이라고 한다.
미들웨어 이용한 라우트 핸들링
예제 ) 계층적 구조의 라우팅
/users 경로 하위에 userRouter가 연결되어 있고, 그 하위 /pets 경로에 petsRouter를 추가할 수 있다.
index.js
'/users' 경로에 userRouter 라우터를연결한다.
const express = require('express');
const userRouter = require('./routes/users');
const app = express();
app.get('/', (req, res) => {
res.send("OK");
});
/* 라우터를 '/users' 경로에 연결 */
app.use('/users', userRouter);
app.listen(8080);
userRouter (위치: routes/users.js)
'/:userId/pets' 경로에 petsRouter를 연결한다.
petsRouter를 연결할 때 path parameter를 사용하는 경로 '/:userId/pets' 를 추가하여, petsRouter가 처리할 수 있게 한다.
const { Router } = require('express');
const petsRouter = require('./pets')
const router = Router();
router.get('/', (req, res) => {
res.send('GET /users');
});
/* /:userId/pets 경로에 petsRouter 연결 */
router.use('/:userId/pets', petsRouter)
module.exports = router;
petsRouter (위치: routes/pets.js)
최종적으로 '/users/:userId/pets' 라는 요청이 들어오면 petsRouter로 연결된다.
그리고 이전 라우터의 path parameter를 사용하려면
Router ( { mergeParams : true } )로 선언해야 req.params.userId로 path parameter에 접근이 가능하다.
const { Router } = require('express');
const router = Router({ mergeParams: true });
/* GET 라우팅 추가 */
router.get('/', (req, res) => {
const userId = req.params.userId;
res.send(`Pets of user ${userId}`);
});
module.exports = router;
예제 ) 다중 미들웨어 연결
app.use("/", middleware1, middleware2, ...) 이렇게 미들웨어를 여러 개 연속하여 사용할 수 있다.
const express = require("express");
const usersRouter = require("./routes/users");
const adminRouter = require("./routes/admin");
const setUser = require("./middlewares/set-user");
const adjuerQuery = require("./middlewares/adjust-query");
const app = express();
app.use(adjuerQuery);
app.get("/", (req, res) => {
res.send("OK");
});
app.use("/users", setUser(), usersRouter);
app.use("/admin", setUser("admin"), adminRouter);
app.listen(8080);
로직 설명
관리자(admin)에 대한 라우터 정보를 /admin?userName=alex 로 요청하고,
사용자(user)에 대한 라우터 정보를 /admin?userName=elice 로 요청하면
userName에 해당하는 값을 각각의 admin.json 과 users.json 파일에서 찾아 데이터를 전달하는 구조이다.
1. 클라이언트 사이드(웹브라우저)에서 사용자 별 정보를 요청하는 URL을 보낸다.
- user인 elice에 대한 정보 요청 : http://localhost:8080/users?userName=alice
- admin인 alex에 대한 정보 요청: http://localhost:8080/admin?userName=alex
2. 서버에서는 요청에 정의된 라우터에 따라 미들웨어가 실행된다.
라우터 users로 끝나는 'users/elice' 요청은 미들웨어 함수 2번을 거친다.
setUser()함수 호출 -> usersRouter()를 순서대로 호출한다.
app.use("/users", setUser(), usersRouter);
라우터 admin으로 끝나는 'admin/alex' 요청 또한 아래와 같이 미들웨어 함수 2번을 거친다.
단, 첫번째 미들웨어인 setUser( ) 함수가 실행될 때 인자로 'admin'이 넘어가는 것을 볼 수 있다.
app.use("/admin", setUser("admin"), adminRouter);
3-1. 첫번째로 실행할 미들웨어 setUser( )
alex 처럼 /admin/alex 로 요청이 오면 setUser("admin")이 실행되므로
./data/admins.json 에서 불러온 객체 중에 값을 찾아 response를 전달해준다.
반면 elice 처럼 users/elice로 요청이 오면 setUser()가 실행되므로
./data/users.json 에서 불러온 객체 중에 값을 찾아 response를 전달해준다.
따라서 아래처럼 setUser ( ) 는 인자가 포함된 경우와 포함되지 않는 경우를 나눠서 정의되어 있어야 한다.
const users = require('../data/users');
const admins = require('../data/admins');
const setUser = (type) => {
if (type == 'admin') {
return (req, res, next) => {
const { userName } = req.query;
req.user = admins[userName];
next();
};
}
else {
return (req, res, next) => {
const { userName } = req.query;
req.user = users[userName];
next();
};
}
};
3-2. 두번째 실행할 미들웨어 adminRouter / userRouter
앞의 setUser()에서 userName 검색한 결과값을 전달 받아, 두번째 미들웨어 함수를 실행한다.
"alex": { "name": "alex", "level": 99 },
"alice": { "name": "alice", "level": 1 }
routes/admin.js
const { Router } = require("express");
const router = Router();
router.get("/", (req, res) => {
const { name, level } = req.user || { name: "NotFound", level: 0 };
res.send(`ADMIN: ${name}, ${level}`);
});
module.exports = router;
routes/users.js
const { Router } = require("express");
const router = Router();
router.get("/", (req, res) => {
const { name, level } = req.user || { name: "NotFound", level: 0 };
res.send(`USER: ${name}, ${level}`);
});
module.exports = router;
4. 그 결과
- user인 elice에 대한 정보 요청 : http://localhost:8080/users?userName=alice
- admin인 alex에 대한 정보 요청: http://localhost:8080/admin?userName=alex
'백엔드 > node.js' 카테고리의 다른 글
[node] REST API 구현, Postman 테스트 (0) | 2022.10.21 |
---|---|
[node] 미들웨어 함수 및 오류처리 (0) | 2022.10.20 |
[node] express.js와 라우팅 (0) | 2022.10.17 |
[node] HTTP 서버 / 웹 프레임워크 (0) | 2022.10.13 |
[node] 모듈 ( es, os, process, fs ) (0) | 2022.10.12 |