공부하는 이유
chatterbox server를 express를 이용해서 refactoring하는 것이 이번 과제이다.
미들웨어가 무엇인지 알고 그 중 body parser, cors 라는 미들웨어를 적용해 보는 것이 그 내용이다.
여기서는 과제를 다루기 전 기본적으로 routing에 대해서 이해하고, 미들웨어를 어떻게 작성하는지, 사용하는지 공부한 것을 기록한다.
모든 내용은 express 공식문서의 내용을 바탕으로 한다.
라우팅
라우팅은 URI(또는 경로) 및 특정한 HTTP 요청 메소드(GET, POST 등)인 특정 end point에 대한 클라이언트 요청에 애플리케이션이 응답하는 방법을 결정하는 것을 말한다.
각 라우트는 하나 이상의 handler 함수를 가질 수 있는데, 이러한 함수는 라우터가 일치할 때 실행된다.
app.METHOD(PATH, HANDLER)
METHOD는 미들웨어 함수가 처리하는 요청(GET, PUT,POST 등)의 소문자로 된 HTTP 메소드이다.
사용 예:
애플리케이션의 홈 페이지인 루트 라우트(/)에서 GET 요청에 응답
var express = require('express');
var app = express(); // app은 express의 인스턴스!
app.get('/', function(req, res) { // 루트라우트(애플리케이션의 홈 페이지)에서 GET 요청이 들어오면
res.send('hello world'); // 'hello world'로 응답한다.
});
Express 앱에서 사용할 미들웨어 작성하기
먼저, 미들웨어 함수는
- 요청 오브젝트(req),
- 응답 오브젝트(res),
- 그 다음 미들웨어 함수(next)
에 대한 액세스 권한을 갖는 함수이다.
미들웨어 함수는
- 모든 코드를 실행하거나,
- 요청 및 응답 오브젝트에 대한 변경을 실행하거나,
- 요청-응답 주기를 종료하거나,
- 스택 내의 그 다음 미들웨어를 호출할 수 있다.
* 현재 미들웨어 함수가 요청-응답 주기를 종료하지 않는 경우에는 next()를 호출해서 그 다음 미들웨어 함수에 제어를 전달해야 한다.
그렇지 않으면 해당 요청은 정지된 채 방치된다.
사용 예 1 :
앱이 실행될 때마다 단순히 콘솔에 LOGGED를 출력한다.
var express = require('express');
var app = express();
var myLogger = function(req, res, next) { // myLogger 라는 미들웨어 함수는
consolelog('LOGGED'); // 단순히 콘솔에 LOGGED를 인쇄한다.
next(); // 그 다음 미들웨어를 호출한다.
}
app.use(myLogger); // 미들웨어 함수를 로드하기 위해 app.use()를 호출한다.
app.get('/', function(req, res) {
res.send('Hello World');
});
app.listen(3000);
위 코드는 루트 경로(/)로 라우팅하기 전에 myLogger 미들웨어 함수를 로드한다.
next()함수는 Node.js 또는 Express API의 일부가 아니지만, 미들웨어 함수에 전달되는 세 번째 인수이다.
next() 함수에 다른 이름을 지정할 수도 있지만 일반적으로 next라고 하므로 혼란을 방지하기 위해 이 방식을 사용하는 것이 낫다.
사용 예 2 :
앱의 루트에 대한 req를 실행할 때 앱은 req의 타임스탬프를 브라우저에 표시한다.
var express = require('express');
var app = express();
var requestTime = function(req, res, next){
req.resquestTime = Date.now(); // requestTime이라는 특성을 req에 추가한다.
next();
};
app.use(requestTime);
app.get('/', function(req, res){ // 콜백 함수는 미들웨어 함수가 req에 추가하는 특성을 사용한다.
var responseText = 'Hello world!';
responseText += 'Requested at: ' + req.requestTime + '';
res.send(responseText);
});
app.listen(3000);
미들웨어 사용하기
Express는 자체적인 최소한의 기능을 갖춘 라우팅 및 미들웨어 웹 프레임워크이며,
Express 애플리케이션은 기본적으로 일련의 미들웨어 함수 호출이다.
미들웨어가 주로 쓰이는 상황
- 모든 요청에 대해 url이나 메소드를 알고자 할 때
- POST 요청 등에서 쓰이는 body(payload)를 쉽게 얻어내고자 할 때
- 모든 요청/응답에 CORS 헤더를 붙일 때
- 요청 헤더에 사용자 인증 정보가 담겨있는지 확인하고자 할 때
Express 애플리케이션은 다음과 같은 유형의 미들웨어를 사용할 수 있다.
- 애플리케이션 레벨 미들웨어
- 라우터 레벨 미들웨어
- 오류 처리 미들웨어
- 기본 제공 미들웨어
- Third-party 미들웨어
- 애플리케이션 레벨 미들웨어
app.use() 및 app.METHOD() 함수를 이용해 애플리케이션 미들웨어를 웹 오브젝트(Express)의 인스턴스에 바인드한다.
애플리케이션 레벨 및 라우터 레벨 미들웨어는 선택적인 마운트 경로를 통해 로드할 수 있다.
사용 예 1 :
마운트 경로가 없는 미들웨어 함수이다. 이 함수는 앱이 요청을 수신할 때마다 실행된다.
var app = express();
app.use(function(req, res, next) { // 경로가 지정되어 있지 않다.
console.log('Time: ', Date.now());
next();
});
사용 예 2 :
/user/:id 경로에서 GET 요청이 왔을 때 응답을 주는 미들웨어 함수이다.
app.get('/user/:id', function(req, res, next){
res.send('USER');
});
사용 예 3 :
/user/:id 경로에 마운트되는 미들웨어 함수이다. 이 함수는 /user/:id 경로에 대한 모든 유형의 HTTP 요청에 대해 실행된다.
하나의 경로에 여러 미들웨어 함수를 정의할 수 있다.
app.use('/user/:id', function(req, res, next) {
console.log('Request URL: ', req.originalUrl);
next();
}, function(req, res, next) {
console.log('Request Type: ', req.method);
next();
});
사용 예 4 :
하나의 경로에 여러 라우트를 정의할 수도 있다.
app.get('/user/:id', function (req, res, next) { // 첫번째 라우터
console.log('ID:', req.params.id);
next();
}, function (req, res, next) {
res.send('User Info'); // next()를 호출하지 않기 때문에 두번째 라우터는 호출되지 않는다.
});
// handler for the /user/:id path, which prints the user ID
app.get('/user/:id', function (req, res, next) { // 두번째 라우터
res.end(req.params.id);
});
사용 예 5:
라우터 미들웨어 스택의 나머지 미들웨어 함수들을 건너뛰려면 next('route') 를 호출하여 다음 라우트로 제어를 전달할 수 있다.
app.get('/user/:id', function (req, res, next) { // 첫번째 라우트 , 첫번째 미들웨어함수
if (req.params.id == 0) next('route'); // 참이면 다음 라우트에 제어를 전달한다.
else next(); //그렇지 않으면 이 스택에서 다음 미들웨어 함수에 제어를 전달한다.
}, function (req, res, next) { // 두번째 미들웨어 함수
// render a regular page
res.render('regular');
});
// handler for the /user/:id path, which renders a special page
app.get('/user/:id', function (req, res, next) { // 두번째 라우트
res.render('special');
});
- 라우터 레벨 미들웨어
expres.Router() 인스턴스에 바인드된다는 점을 제외하면 애플리케이션 레벨 미들웨어와 동일한 방식으로 동작한다.
router.use() 및 router.METHOD() 함수를 사용하여 라우터 레벨 미들웨어를 로드할 수 있다.
- 오류 처리 미들웨어
오류 처리 미들웨어는 항상 (err, req, res, next) 4개의 인수를 필요로 한다. next 오브젝트를 사용할 필요는 없지만 시그니처를 유지하기 위해 지정해야 한다.
app.use(function(err, req, res, next) {
console.error(err.stack);
res.status(500).send('Something broke!');
});
- 기본 제공 미들웨어 Express.static(root, [options])
Express의 유일한 기본 제공 미들웨어 함수는 express.static 이다. 이 함수는 Express 애플리케이션의 정적 자산을 제공하는 역할을 한다.
root 인수는 정적 자산의 제공을 시작하는 위치가 되는 루트 디렉토리를 지정한다.
하나의 앱은 2개 이상의 정적 디렉토리를 가질 수 있다.
-Third-Party 미들웨어
필요한 기능을 위한 Node.js 모듈을 설치한 후, 애플리케이션 레벨 또는 라우터 레벨에서 해당 모듈을 앱에 로드하면 된다.
사용 예 :
body parser : Node.js 본문을 파싱하는 미들웨어이다.
req.body의 핸들러에 전달하기 전 미들웨어에서 들어오는 요청 본문의 구문을 분석한다.
//설치
npm install body-parser
//API
var bodyParser = require('body-parser')
body parser는 다음과 같은 모듈을 제공한다.
- JSON body parser
- Raw body parser
- Text body parser
- URL-encoded from body parser
여기서는 JSON body parser를 살펴보려고 한다.
bodyParser.json()
Content-Type 헤더가 type 옵션과 일치하는 요청이 있을 때 json 요청만 파싱하는 미들웨어를 반환한다.
var bodyParser = require('body-parser')
var jsonParser = bodyParser.json()
app.post('/api/users', jsonParser, function(req, res) { // jsonParser를 붙여주었기 때문에
// req.body에는 JSON의 형태로 payload가 담겨져 있다.
'TIL ( CODESTATES)' 카테고리의 다른 글
React 개발 환경 구축하기 (0) | 2021.01.11 |
---|---|
Chatterbox server - Refactoring w/ Express (0) | 2021.01.03 |
Chat Application - client 구현하기 (0) | 2020.12.29 |
node.js TIL (0) | 2020.12.28 |
fetch를 이용해서 웹에서 정보 가져오기 (0) | 2020.12.19 |