본문 바로가기

Programming/Express

Routing


[ ROUTING ? ]



라우팅이란 클라이언트의 요청에 따른 어플리케이션의 응답을 정의한 것을 말합니다.



기본 골격은 다음과 같습니다.

var express = require('express');
var app = express();

// respond with "hello world" when a GET request is made to the homepage
app.get('/', function(req, res) {
  res.send('hello world');
});


라우팅 메서드는 HTTP 메서드들에서 비롯되었으며, express 객체에 내장되어 있습니다.



get외 에도 post, put, 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, and connect.



// GET method route
app.get('/', function (req, res) {
  res.send('GET request to the homepage');
});

// POST method route
app.post('/', function (req, res) {
  res.send('POST request to the homepage');
});




이 외에도 특수한 라우팅 메서드가 하나 있으니 'all(...)'이라고 합니다.


기존의 HTTP메서드에서 파생된 건 아닙니다.

이 메서드는 어떠한 경로에 대한 요청에 대해서도 응답을 합니다.


다음 코드에서는 '/omnibus' 로 들어오는 모든 요청에 대해 핸들러가 실행됩니다.


그 요청이 GET이든 POST든 PUT든 DELETE든 말이죠.

이 외에도 http module에서 지원하는 모든 요청 메서드에 대해서도 가능합니다.



app.all('/omnibus', function (req, res, next) { console.log('Accessing the secret section ...'); next(); // pass control to the next handler });




[Route paths]



라우팅 경로는 요청 메서드와 함께 요청이 들어올 종점을 생성합니다.


라우팅 경로는 문자열, 문자열 패턴이나 심지어 정규식이 될 수도 있습니다

.

단 ' . ', ' - ' 은 문자 그대로 해석합니다.


'Regular Expression(정규식)'에 대한 선행지식이 있을 경우 쉽게 이해 하실 수 있습니다.



예제를 보며 설명하겠습니다.

// 다음 라우팅 경로는 '/'로 들어오는 응답에 대해서만 응답합니다. app.get('/', function (req, res) { res.send('root'); }); // 다음 라우팅 경로는 '/about'로 들어오는 응답에 대해서만 응답합니다. app.get('/about', function (req, res) { res.send('about'); });

// 다음 라우팅 경로는 '/random.txt'에 대해서만 응답합니다.

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' 등과 같이 '+'를 선행하는 문자 1개 이상에 대해 매칭됩니다.

// 예를 들어 'ba+c'일 경우, 'baaac', 'bac'와 같이 말입니다. app.get('/ab+cd', function(req, res) { res.send('ab+cd'); }); // '*'은 어떠한 문자에 대해서도 매칭됩니다.

// 'abxxxcd', 'abcd', 'abRANDOMNCIDcd', 'ab1251cd' 등 그 경우의 수는 매우 많습니다. app.get('/ab*cd', function(req, res) { res.send('ab*cd'); }); // '?'은 선행하는 문자가 0개 또는 1개가 나타날 경우(옵션)에 대해 매칭욉니다.

// '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/'); }); // 다음 경로는 어떠한 문자로 시작해도 되지만 그 끝은 'fly'로만 끝나야 하는 규칙을 지정하고 있습니다.

// 'butterfly'나 'dragonfly'는 매칭되지만, 'flyman' 은 매칭되지 않습니다. app.get(/.*fly$/, function(req, res) { res.send('/.*fly$/'); });




[Route parameters]



라우팅 파라미터는 URL에 지정된 위치에 명시된 값을 가져오려 할 때 사용합니다.



이렇게 가져온 값은 'req.params'란 객체를 사용해 접근할 수 있습니다.

만약 유저아이디의 파라미터명을 'userid'라 지정했을 경우, req.params.userid를 콘솔로 출력해보면 34가 나옵니다.


다음 코드가 아닌 설명을 위한 구문입니다.

Route path: /users/:유저아이디/books/:책아이디 // '/users/:유저아이디/books/:책아이디'란 경로로 라우팅을 했습니다. Request URL: http://localhost:3000/users/34/books/8989 // 실제 요청 URI에선 ':유저아이디'를 34로 ':책아이디'를 8989로 지정했습니다. req.params: { "유저아이디": "34", "책아이": "8989" } // 파라미터에 대해선 다음과 같이 접근합니다.


위 구문은 다음과 같이 작성할 수 있습니다.


#1

app.get('/users/:userId/books/:bookId', function(req, res) {
  res.send(req.params);
});


#2 - ' . ', ' - '은 문자 그대로 해석되기 때문에 다음과 같은 형식의 라우팅을 지정할 수도 있습니다.

Route path: /flights/:from-:to Request URL: http://localhost:3000/flights/KOR-FRA // :from => KOR :to => FRA req.params: { "from": "KOR", "to": "FRA" } Route path: /plantae/:sentry.:century Request URL: http://localhost:3000/plantae/gun.4 // :sentry => gun :century => 4 req.params: { "sentry": "gun", "century": "4" }





[Route handlers] - 라우팅 핸들러


Express라우팅, 미들웨어 웹 프레임워크입니다. 

Express를 사용해 만든 어플리케이션은 결국 미들웨어 함수 호출의 연속이라 할 수 있습니다.


Middleware(미들웨어) 함수란 request, response 객체와 request-response 주기 내에 있는

next란 함수에 접근할 수 있는 함수들을 말합니다.


미들웨어 함수는 다음과 같은 기능을 제공합니다.

- 함수 내 코드를 실행하고

- request, reponse 객체를 변경할 수 있고

- request-response 주기를 종료시킬 수도 있고

- 스택 내의 다음 미들웨어 함수를 호출할 수 있습니다.( next( ) 사용 )


Express에선 클라이언트의 요청을 처리하기 위해 미들웨어와 같이

 다수의 콜백 함수를 사용할 수도 있습니다. 하지만 여기에 예외도 있습니다.

콜백 함수를 실행하다가도 next('라우팅 경로')를 사용해

콜백 함수 내 나머지 구문을 띄어 넘을 수도 있습니다.


특정 콜백 함수를 실행하다가도 나머지 구문의 실행이 필요없을 경우

위와 같은 상황이 연출되기도 합니다.


라우팅 핸들러는 함수 형태로도 존재할 수 있고, 함수 배열 형태로도 존재할 수 있으며,

두 형태가 혼재 할수도 있습니다.



예제를 보며 설명하도록 하겠습니다.



// 일반적인 단일 콜백 함수의 예는 다음과 같습니다.

app.get(
'/example/a', function (req, res) { res.send('Hello from A!'); }); // 다수의 콜백 함수도 가능합니다. 이 경우엔 next 객체를 명시해주세요.


 app.get('/example/b', function (req, res, next) { console.log('the response will be sent by the next function ...'); next(); // 다음 콜백 함수로 제어를 옮깁니다. }, function (req, res) { res.send('Hello from B!'); }); // 콜백 함수의 배열을 사용해 라우팅을 처리할 수도 있습니다.

// 단 잘못된 next()의 사용으로 인한 무한루프를 초래하는 일이 없도록 해야합니다. var cb0 = function (req, res, next) { console.log('CB0'); next(); // 명시 필수 } var cb1 = function (req, res, next) { console.log('CB1'); next(); // 명시 필수 } var cb2 = function (req, res) { res.send('Hello from C!'); } app.get('/example/c', [cb0, cb1, cb2]); // cb0, cb1, cb2 순으로 호출됩니다. // 위와 다르게 자체적으로 독립적인 콜백 함수와 배열을 동시에 사용할 수도 있습니다.

// 출력은 다음과 같습니다.

//

// CB0

// CB1

// the response will be sent by the next function...

// Hello from D! var cb0 = function (req, res, next) { console.log('CB0'); next(); } var cb1 = function (req, res, next) { console.log('CB1'); next(); } app.get('/example/d', [cb0, cb1], function (req, res, next) { console.log('the response will be sent by the next function ...'); next(); }, function (req, res) { res.send('Hello from D!'); });



[Response methods]

응답 메서드


response 객체에 있는 메서들은 다음과 같습니다.

이 메서드들은 클라이언트에 응답을 보내거나,  요청-응답 주기를 종료할 수도 있습니다.

다음 메서드 중 하나도 호출이 되지 않는다면,

요청이 제대로 종료되지 않고 대기 상태로만 있게 됩니다.


메서드

 설명

 res.download()

 파일을 다운로드합니다.

 res.end()

응답 프로세스를 종료합니다.

 res.json()

JSON 형식의 응답을 전송합니다.

 res.jsonp()

 JSON 형식의 응답을 전송합니다. (JSONP 지원)

 res.redirect()

 요청을 리다이렉트합니다.

res.render()

뷰 템플릿을 렌더링합니다.

res.send()

다양한 종류의 응답을 전송할 수 있습니다.

res.sendFile()

옥텟 스트림으로 파일을 전송합니다.

res.sendStatus()

응답 상태 코드를 설정하고 body에 현 상태를 담아 전송합니다.





[ app.route( ) ]



라우팅 핸들링의 일환으로 채이닝(channing) 기법을 사용할 수도 있습니다.


라우팅 메서드별로 분기를 해야하는데 라우팅 경로는 동일할 때 유용하게 사용할 수 있습니다.


다음과 같이 사용할 수 있습니다.


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 ]



express.Router( )를 사용해 라우팅 핸들러를 모듈화 시킬 수 있습니다.


Router 객체는 하나의 완성된 미들웨어로 'mini-app'이라고도 합니다.


다음 예제는 모듈화된 라우터를 생성한 후 내부에 미들웨어 함수와


라우팅 경로와 그에 따른 핸들러를 정의하고 있습니다.



예제를 보며 설명하겠습니다.



// birds.js

var
express = require('express'); var router = express.Router(); // Router 생성 // 미들웨어 정의 router.use(function timeLog(req, res, next) { console.log('Time: ', Date.now()); next(); });

// 홈 페이지 라우팅 경로 정의 router.get('/', function(req, res) { res.send('Birds home page'); });

// about 페이지 라우팅 경로 정의 router.get('/about', function(req, res) { res.send('About birds'); }); module.exports = router; // 생성한 라우터를 다른 파일에서도 사용할 수 있습니다.

// node.js 의 document를 참조해주세요.



app.js에서 모듈화한 라우터를 불러옵니다.


같은 app.js와 birds.js는 같은 레벨의 디렉토리에 있다고 가정하겠습니다.



// app.js

var
birds = require('./birds'); ... app.use('/birds'
, birds);



위 예제에서는 /birds, /birds/about 에 대한 라우팅 핸들러, timeLog 미들웨어가 포함되어 있습니다.




라우팅에 대한 설명은 이상입니다.




수고하셨습니다.

















'Programming > Express' 카테고리의 다른 글

2. Installing & 'Hello World!'  (0) 2016.08.14
1. Introduction to Express  (0) 2016.08.14