[ 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 |