시작으로
라우팅(Routing)
이란 애플리케이션 엔드 포인트(URI)의 정의 및 특정한 HTTP
요청 방식(GET
, POST
등)에 대한 클라이언트의 요청에 따라 응답하는 방법을 결정하는 것이다.
각 라우트는 하나 이상의 핸들러 함수를 가질 수 있으며, 이러한 함수는 라우트가 일치할 경우 실행된다.
만약 다수의 핸들러 함수를 지정하려면 함수 로직 끝에 next()
를 붙여야 한다. 그래야 다음 함수로 넘어가기 때문이다.
HTTP 요청 방식
다양한 요청 방식이 존재하지만 보통 REST API를 구현할 때 4가지만 알아도 충분하다.
보통 개발할 때 CRUD기준으로 메소드를 사용한다.
- GET (READ)
- POST (CREATE)
- PUT (UPDATE)
- DELETE (DELETE)
HTTP
메소드는 동사 역할을한다. 그리고 동사에 대한 목적어가 바로 엔드 포인트(URI)
이다.
간단한 예시:
-
(GET)
localhost:port/users - 유저정보를 조회를 요청 -
(POST)
localhost:port/users - 유저정보를 생성을 요청 -
(PUT)
localhost:port/users/:user_id - user_id 유저의 정보 수정을 요청 -
(DELETE)
localhost:port/users/:user_id - user_id 유저의 정보 삭제를 요청
라우팅 정의
기본적인 라우트 정의 구조는 아래와 같다.
app.METHOD(PATH, HANDLER)
아래 코드는 아주 기본적인 라우트의 예시이다.
var express = require('express');
var app = express();
app.get('/', function(req, res) {
res.send('GET');
});
라우트 메소드
여기서 app은 Express의 인스턴스를 담은 변수이다. Express는 HTTP 메소드를 가지고 있다.
- GET : app.get()
- POST : app.post()
- PUT : app.put()
- DELETE : app.delete()
Express는 다음과 같은 라우팅 메소드를 제공한다.
get, post, put, head, delete, options, trace, copy, lock, mkcol, move, purge, propfind, proppatch, unlock, report, mkactivity, checkout, merge, m-search, notify, subscribe, unsubscribe, patch, search 및 connect.
라우트 경로
라우트 경로는, 요청 메소드와 조합을 통해 요청이 이루어질 수 있는 엔드포인트(URI)
를 정의한다. 라우트 경로는 문자열, 문자열 패턴 또는 정규식으로 작성할 수 있다.
문자열을 기반으로 작성한 라우트 경로 예시 :
// 라우트 경로 /
app.get('/', function (req, res) {
res.send('root');
});
// 라우트 경로 /users
app.get('/users', function (req, res) {
res.send('users');
});
// 라우트 경로 /random.text
app.get('/random.text', function (req, res) {
res.send('random.text');
});
문자열 패턴을 기반으로 작성한 라우트 경로 예시 :
// 라우트 경로 /acd 및 /abcd
app.get('/ab?cd', function(req, res) {
res.send('ab?cd');
});
// 라우트 경로 /abcd, /abbcd 및 /abbbcd
app.get('/ab+cd', function(req, res) {
res.send('ab+cd');
});
// 라우트 경로 /abcd, /abxcd, /abRABDOMcd 및 /ab123cd
app.get('/ab*cd', function(req, res) {
res.send('ab*cd');
});
// 라우트 경로 /abe 및 /abcde
app.get('/ab(cd)?e', function(req, res) {
res.send('ab(cd)?e');
});
정규식을 기반으로 작성한 라우트 경로 예시 :
// 라우트 이름에 “a”가 포함된 모든 항목
app.get(/a/, function(req, res) {
res.send('/a/');
});
// 라우트 경로는 butterfly 및 dragonfly와 일치하지만
// butterflyman 및 dragonfly man 등과 일치하지 않는다.
app.get(/.*fly$/, function(req, res) {
res.send('/.*fly$/');
});
응답 메소드
밑의 표에 표시된 응답 오브젝트에 대한 메소드(res)는 응답을 클라이언트로 전송하고 요청-응답 주기를 종료할 수 있다.
만약 라우트 핸드러부터 다음 메소드 중 어느 하나도 호출되지 않는 경우, 클라이언트 요청은 정지된 채로 방치된다.
그 이유는 HTTP 방식은 동기 방식이므로 요청이 있으면 응답이 반드시 있어야 하기 때문이다.
공식 문서에 자세히 설명되어 있으니 참고하자.
메소드 | 설명 |
---|---|
res.download() | 파일이 다운로드되도록 프롬프트 한다. |
res.end() | 응답 프로세스를 종료한다. |
res.json() | JSON 응답을 전송한다. |
res.jsonp() | JSONP 지원을 통해 JSON 응답을 전송합니다. |
res.redirect() | 요청의 경로를 재지정합니다. |
res.render() | 보기 템플리트를 렌더링합니다. |
res.send() | 다양한 유형의 응답을 전송합니다. |
res.sendFile() | 파일을 옥텟 스트림의 형태로 전송합니다. |
res.sendStatus() | 응답 상태 코드를 설정한 후 해당 코드를 문자열로 표현한 내용을 응답 본문으로서 전송합니다. |
app.route()
app.route()
을 이용하면 라우트 경로에 대하여 체인 가능한 라우트 핸드러를 작성할 수 있다.
경로는 한 곳에 지정되어 있으므로 모듈식 라우트를 작성하면 중복성과 오타가 감소하여 도움이 된다.
app.route('/book')
.get(function(req, res) {
res.send('Get a random book');
})
.post(function(req, res) {
res.send('Add a book');
})
.put(function(req, res) {
res.send('Update the book');
});
라우팅 모듈화
라우트 정의가 몇개 없다면 상관없지만, 서비스 및 기능별로 제공하는 라우트가 많다면 한 곳에 관리하기 어렵다. 또한, 중복되는 자원들이 많다면 어떨까? 그럴 땐 모듈화로 나누어 관리하는 것이 좋다.
express.Router
클래스를 사용하면 모듈식 마운팅이 가능한 핸들러를 작성할 수 있다. Router 인스턴스는 인스턴스는 완전한 미들웨어이자 라우팅 시스템이다.
이것을 "미니 앱(mini-app)"
이라고도 불린다.
자 밑의 라우트 정의들이 있다고 가정해보자.
var express = require('express');
var app = express();
app.get('/users', function (req, res, next) {
res.send('get users');
});
app.get('/users/:id', function (req, res, next) {
res.send('get a user');
});
app.post('/users', function (req, res, next) {
res.send('post user');
});
app.put('/users/:id', function (req, res, next) {
res.send('put a user');
});
app.delete('/users/:id', function (req, res, next) {
res.send('delete a user');
});
중복되는 users
경로를 모두 명시할 필요 없이 /users
로 모듈화를 해보자.
-
/route
폴더에users
폴더를 생성하고 안에index.js
를 생성한다. - 그리고 아래와 같이 작성하면 express는
/route폴더
밑에 생성한users
를 공통 라우터로 사용할 수 있다.
var express = require("express")
var router = express.Router()
router.get('/', function (req, res, next) {
res.send('get users');
});
router.get('/:id', function (req, res, next) {
res.send('get a user');
});
router.post('/', function (req, res, next) {
res.send('post user');
});
router.put('/:id', function (req, res, next) {
res.send('put a user');
});
router.delete('/:id', function (req, res, next) {
res.send('delete a user');
module.exports = router
- 모듈화된 라우터를 app.js에 import하여
app.use()
에 등록만하면 된다.
// app.js
var express = require('express');
var app = express();
var usersRouter = require('./router/users');
app.use('/users', usersRouter);