05. 라우팅 처리
1. 라우팅(Routing)
- 특정 엔드 포인트에 대한 클라이언트 요청에 애플리케이션이 응답하는 방법을 결정하는 것을 말한다.
특정 엔드 포인트란 URI(경로)와 HTTP 요청 메소드(GET, POST 등)로 구분된 클라이언트에서 서버로 요청 보낼 수 있는
문이라고 생각하면 된다.
- 익스프레에서 라우트는 다음과 같은 구조를 가진다.
app.METHOD(PATH, HANDLER)
app: express의 인스턴스
METHOD: HTTP 요청 메소드(GET, POST 등)
PATH: 서버에서의 경로
HANDLER: 라우트가 일치할 때 실행되는 함수
- 다음은 가장 기본적인 라우트 처리 예시이다.
const express = require('express');
const app = express();
// 클라이언트에서 HTTP 요청 메소드 GET 방식으로 'host:port'를 호출했을 때
app.get('/', function(req, res) {
res.send('root'); // 클아이언트에 root 문자열 전송
});
2. 라우트(Route) 메소드
- 익스프레스는 HTTP 메소드에 다음과 같은 라우트 메소드를 지원한다.
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
- 클라이언트에서 서버로 요청을 보낼 때 사용한 HTTP 요청 메소드에 맞는 익스프레스 라우트 메소드로 처리된다.
예를 들어 클라이언트에서 get을 사용해서 HTTP 요청 메소드를 서버로 요청 보냈다면, 익스프레스 라우트 메소드 역시 get으로
되어 있어야 연결된다.
const express = requrie('express');
const app = express();
app.listen(3000, () => {
// 3000번 포트로 웹 서버 실행
console.log('Server started. port 3000');
});
// 클라이언트에서 HTTP 요청 메소드 GET 방식으로 'host:3000/customer'를 호출했을 때
app.get('/customer', function(req, res) {
res.send('get 요청에 대한 응답');
});
// 클라이언트에서 HTTP 요청 메소드 POST 방식으로 'host:3000/customer'를 호출했을 때
app.post('/customer', function(req, res) {
res.send('post 요청에 대한 응답');
});
- 'localhost:3000/customer'라는 주소를 사용해 서버로 요청을 보낼 때 HTTP 요청 메소드로 get을 사용하느냐 post를 사용하느냐에
따라 호출되는 익스프레스 라우터가 달라진다.
- 웹 서버개발 시 가장 많이 사용하는 익스프레스 라우트는 get, post, put, delete이다.
만약 종류에 상관없이 하나의 익스프레스 라우트 메소드를 사용하고 싶다면 app.all() 라우트 메소드를 사용하면 된다.
3. 라우트(Route) 경로
- 라우트 경로는 요청 메소드와의 조합을 통해 요청이 이루어질 수 있는 엔드포인트를 정의한다.
- 문자열, 문자열 패턴, 정규식을 이용해서 만들 수 있다.
- 문자열 기반으로 하는 라우트 경로의 예
// 클라이언트에서 HTTP 요청 메소드 GET 방식으로 'host:port'를 호출했을 때
app.get('/', function(req, res) {
res.send('root'); // 클라이언트에 root 문자열 발송
});
// 클라이언트에서 HTTP 요청 메소드 GET 방식으로 'host:port/about'을 호출했을 때
app.get('/about', function(req, res) {
res.send('about'); // 클라이언트에 about 문자열 전송
});
// 클라이언트에서 HTTP 요청 메소드 POST 방식으로 'host:port/customer'을 호출했을 때
app.post('/customer', function(req, res) {
res.send('customer'); // 클라이언트에 customer 문자열 전송
});
- 문자열 패턴을 기반으로 하는 라우트 경로의 예
// GET 방식으로 'host:port/acd' 혹은 'host:port/abcd'를 호출했을 때
// 'b?'는 문자 'b'가 0개 혹은 1개 있다는 것을 의미
app.get('/ab?cd', function(req, res) {
res.send('ab?cd');
});
// 클라이언트에서 요청한 라우트 경로가 abcd, abbcd, abbbcd 등과 일치
// 'b+'는 문자 'b'가 1개 이상 있다는 것을 의미
app.get('/ab+cd', function(req, res) {
res.send('ab+cd');
});
// 클라이언트에서 요청한 라우트 경로가 abcd, abxcd, abanycd, ab123cd 등과 일치
// 'ab*cd'는 문지 'ab'와 문자 cd' 사이에 문자가 없거나 혹은 어떤 문자도 올 수 있음을 의미
app.get('/ab*cd', function(req, res) {
res.send('ab*cd');
});
// 클라이언트에서 요청한 라우트 경로가 abe 혹은 abcde와 일치
// '(cd)?'는 문자 'cd'가 0번 혹은 1번 있을 수 있음을 의미
app.get('/ab(cd)?e', function(req, res) {
res.send('ab(cd)?e');
});
- 정규식을 기반으로 하는 라우트 경로의 예
// 클라이언트에서 요청한 라우트 경로에 'a'가 포함되어 있는 경우
app.get(/a/, function(req, res) {
res.send('/a/');
});
// 클라이언트에서 요청한 라우트 경로가 문자 'insert로 시작하는 경우
// insertCustomer, insertProduct
app.get(/^insert/, function(req, res) {
res.send('/^insert/');
});
4. 라우트(Route) 핸들러
- 클라이언트 요청에 따라 라우트가 일치할 때 실행되는 콜백 함수이다.
- 파라미터는 아래와 같다.
- req: Request
- res: Response
- next: 다음 미들웨어 함수를 가리키는 오브젝트이다.
app.get('/contact', function(req, res) {
res.send('contact');
});
- 하나의 라우트에서 next 오브젝트를 사용해 2개 이상의 콜백 함수를 실행할 수 있다.
// 콜백 함수의 세 번째 파라미터로 next 오브젝트 사용
app.get('/example', function(req, res, next) {
console.log('첫 번쨰 콜백 함수');
next(); // 다음 콜백 함수 호출
}, function(req, res) {
res.send('두 번째 콜백 함수'); // 클라이언트로 응답
});
- 아래와 같이 콜백 함수 배열로 라우트 처리 가능.
const ex0 = function(req, res, next) {
console.log('첫 번째 콜백 함수');
next(); // 다음 콜백 함수 호출
}
const ex1 = function(req, res, next) {
console.log('두 번째 콜백 함수');
next(); // 다음 콜백 함수 호출
}
const ex2 = function(req, res, next) {
res.send('세 번째 콜백 함수'); // 클라이언트로 응답
}
app.get('/example', [ex0, ex1, ex2]); // 콜백 함수 배열로 정의
5. 응답 메소드
- 클라이언트로부터 요청이 오면 라우트에서 아래 메소드 중 한 가지 방법으로 응답을 저송하고 요청(request)-응답(response) 주기를
종료할 수 있다. 라우트 핸들러 함수에서 아래 메소드 중 하나라도 호출되지 않은 경우에는 클라이언트 요청이 응답받지 못하고 정지된
채로 있다.
메소드 | 설명 |
res.download() | 파일을 다운로드하도록 프롬프트 |
res.end() | 응답 프로세스를 종료 |
res.json() | JSON 응답을 전송 |
res.jsonp() | JSONP 지원을 통해 JSON 응답을 전송 |
res.redirect() | 요청의 경로를 재지정 |
res.render() | 뷰(view) 템플릿을 렌더링 |
res.send() | 다양한 유형의 응답을 전송 |
res.sendFile() | 파일을 octet 스트림으로 전송 |
res.sendStatus() | 응답 상태 코드를 설정한 후 해당 코드를 응답 본문(body)에 담아서 전송 |
6. app.route()
- app.route()를 이용하면 get, post, put과 같은 라우트 메소드를 한 곳에서 작성할 수 있다.
모듈식 라우트를 작성하면 중복성이 감소하여 코드를 좀 더 효율적으로 관리할 수 있다.
// 모듈식 라우터 - 하나의 라우트 경로로 각 라우트 메소드 처리
app.route('/customer')
.get(function(req, res) { //HTTP 메소드 GET 요청에 대한 조회 처리
res.send('고객 정보 조회');
})
.post(function(req, res) { //HTTP 메소드 POST 요청에 대한 저장 처리
res.send('고객 정보 추가');
})
.put(function(req, res) { //HTTP 메소드 PUT 요청에 대한 수정 처리
res.send('고객 정보 수정');
})
.delete(function(req, res) { //HTTP 메소드 DELETE 요청에 대한 삭제 처리
res.send('고객 정보 삭제');
})
7. express.Router
- 라우트 처리를 하나의 파일에서 하는 것이 아니라 여러 개의 파일로 분리해서 각각의 용도(기능)에 맞게 구현하여 사용할 수 있다.