Express 웹서버 만들기_Router 객체로 라우팅 분리하기

이애옹·2022년 12월 30일
0

Node.js

목록 보기
22/32
post-thumbnail

📝 Express의 Router

http 서버를 이용할 경우, 라우터를 만들기 위해서 요청 메서드와 주소별로 분기 처리를 해야하기때문에 코드가 매우 복잡해진다.

하지만 express 사용할 경우 라우팅을 깔끔하게 할 수 있다는 장점이 있다.

var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
...
app.use('/', indexRouter);
app.use('/users', usersRouter);

익스프레스 앱과는

app.use('/', indexRouter);
app.use('/users', usersRouter);

로 연결되어있다. app.use를 사용하기때문에 라우터도 일종의 미들웨어라고 볼 수 있다.

또한, 다른 미들웨어와 다르게 앞에 주소가 붙어있는데, 이와 같이 라우팅 미들웨어는 첫 번째 인자로 주소를 받아서 특정 주소에 해당하는 요청이 들어왔을때만 미들웨어가 동작하게 제어할 수 있다.

주소가 / 로 시작하면 routes/index.js를, /users로 시작하면, routes/users.js로 호출하라는 의미이다.

또한 use 대신 get, post, put, patch, delete 같은 HTTP 매서드를 사용할 수도 있다.

다만, use 매서드는 모든 HTTP 매서드에 대해 요청 주소만 일치하면 실행되지만 get, post,... 는 요청 주소뿐만 아니라, HTTP 메서드까지 일치하는 요청일 때만 실행된다.

📝 Router 파일 알아보기

이제 라우터 객체에 대해 알아보면, 라우터 파일들은 routers 폴더에 들어있다.

  • index.js
var express = require('express');
var router = express.Router();

/* GET home page. */
router.get('/', function(req, res, next) {
  res.render('index', { title: 'Express' });
});

module.exports = router;
  • users.js
var express = require('express');
var router = express.Router();

/* GET users listing. */
router.get('/', function(req, res, next) {
  res.send('respond with a resource');
});

module.exports = router;

router 객체express.router()로 만든다.
또, 마지막에는 module.exports = router로 라우터를 모듈로 만들어준다.

router도 app처럼 use, get, post, put, patch, delete와 같은 메서드를 붙일 수 있지만, use를 제외하고는 각각 HTTP 요청 메서드와 상응한다.

또, app.use 처럼 router 하나에 여러개의 미들웨어를 장착할 수도 있다! 실제 라우터 로직이 실행되는 미들웨어 전에 로그인 여부 또는 관리자 여부를 체크하는 미들웨어를 중간에 넣는다고 한다.

router.get('/', middleware1, middleware2...);

router.get('/') 이면 / 주소로 GET 요청을 하는 것과 같다. 또, res.render 메서드로 클라이언트에 응답을 보낸다. 익스프레스가 응답 객체에 새로 추가한 메서드로, 이 메서드는 템플릿 엔진을 사용하는 부분이다.

users.js 파일의 경우 /users/로 GET 요청을 했을 때 이 라우터의 콜백 함수가 실행된다.

라우터에서는 반드시 요청에 대한 응답을 보내거나, 에러 핸들러로 요청을 넘겨야한다! 이때 res 객체에 들어 있는 메서드들로 응답을 보낸다.

또, next 함수에서는 라우터에서만 동작하는 특수 기능이 있다.
next('route')를 이용하면 라우터에 연결된 나머지 미들웨어를 건너뛰고 실행한다.

또, 라우터 주소에는 특수한 패턴을 사용할 수 있는데,

router.get('/users/:id', function(req,res){
console.log(req.params, res.query);
});

이 코드에서 주소에 :id 란 문자가 있는 것을 확인할 수 있다.

문자 그대로 :id를 의미하는 것이 아니라, req.params 객체 안에 들어있는 id 값을 가져오는것을 의미한다.
id가 아니라 type이 들어갔을 경우 req.params.type 값을 가져온다.

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

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

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

단, 이 패턴을 사용할때 주의해야하는 점은 일반 라우터보다 뒤애 위치해야 한다는 점이다. 일반 라우터 뒤에 위치하지 않을 경우, 다른 라우터를 방해할 수 있다.

에러가 발생하지 않았다면, 라우터는 요청을 보낸 클라이언트에게 응답을 보내줘야한다.

📝 Router의 응답 메서드

응답 메서드의 종류는 send, sendFile, json, redirect, render 등이 있다.

  • send : 버퍼 데이터나 문자열, HTML 코드, JSON 등을 전송
  • sendFile : 파일을 응답으로 보냄
  • json : JSON 데이터를 보냄
  • redirect : 응답을 다른 라우터로 보냄
    (예를 들어 로그인 완료 후 다시 메인 화면으로 돌아갈 때, res.redirect(메인 화면 주소)를 입력)

응답 메서드 사용법은 다음과 같다.

  • res.send(버퍼 또는 문자열 또는 HTML 또는 JSON)
  • res.sendFile(파일 경로)
  • res.json(JSON 데이터)
  • res.redirect(주소)
  • res.render('템플릿 파일 경로',{변수})

redirect(302)를 제외하고 기본적으로 200 HTTP 상태 코드를 응답하지만, status 메서드를 이용해 직접 바꿀 수도 있다.

res.status(404).send('Not Found')

render 메서드템플릿 엔진렌더링할 때 사용한다. views 폴더 안 pug 확장자를 가지고 있는 파일들이 템플릿 엔진이다.

마지막으로, 라우터가 요청을 처리하지 못할 때는 다음 미들웨어로 넘어가는데, 404 HTTP 상태 코드를 보내줘야하기 때문에 다음 미들웨어에서 새로운 에러를 만들고 에러의 상태코드를 404로 설정한 뒤, 에러 처리를 미들웨어로 넘겨버린다.

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  next(createError(404));
});

// error handler
app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});

응답을 여러번 보내는 경우
하나의 요청은 한번의 응답만 보낼 수 있다.
응답을 여러번 보낼 경우 Can't set headers after they are sent 에러가 발생한다.

profile
안녕하세요

0개의 댓글