반응형

라우팅

요청에 따라 수행할 로직들은 각기 달라진다. 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

 

반응형

+ Recent posts