개요
-Node.js의 프레임워크인 Express를 이용하여 이전에 node.js로 작성한 서버를 리팩토링한다.
-Express는 Node.js 환경에서 웹 서버 및 API를 조금 더 편리하게 구축하기 위해서 사용된다.
-Express의 핵심 기능은 MiddleWare와 Router이다.
1. Express
-Basic structure (https://expressjs.com/en/starter/hello-world.html)
const express = require('express');
const app = express();
// express의 인스턴스인 app은 서버를 시작하고 포트 3000번을 연결한다.
const port = 3000;
app.get('/', (req, res) => {
// 루트(root) URL( / ) 혹은 루트 라우트(route)에 대한 요청에 "Hello World!"로 응답한다.
// 이때 다른 모든 경로(path)에 대한 요청에는 404 Not Found로 응답한다.
res.send('Hello World!');
});
app.listen(port, () => {
console.log(`http server listen on localhost:${port}`);
});
-MiddleWare Function (http://expressjs.com/en/guide/writing-middleware.html)
var express = require('express');
var app = express();
const myLogger = function (req, res, next) {
console.log('LOGGED');
next(); // 반드시 요청-응답 사이클을 끝내거나 next를 호출해야한다.
};
// express 내에서 작성하는 일반적인 함수를 일컫는 말이다.
// 미들웨어의 역할은 다음과 같다 : 1.코드를 실행함 / 2.req&res 객체를 조작함 / 3. 요청-응답 사이클을 끝냄 / 4. 다음 미들웨어를 호출함
// 미들웨어는 인자로 request 객체, response 객체 그리고 next middleware function을 받는다.
// 이때 next middleware function은 말그대로 뒤이어서 실행되는 미들웨어를 말한다. (제어(control)를 넘긴다라는 표현을 사용한다)
// 이 미들웨어 함수의 이름은 일반적으로 next라 부른다.
// 미들웨어는 라우트의 콜백함수로 사용하며 비동기적인 http 통신 작업을 수행한다.
app.use(myLogger);
// 미들웨어 함수는 use()를 사용하여 로드한다.
// 모든 경로에 대해서 HTTP 요청을 받으면 작성된 순서대로 실행된다. (This shows a middleware function with no mount path. The function is executed every time the app receives a request.)
app.use('/user', myLogger);
// myLogger를 /user 경로에 마운트한다. 이 경로에 대한 모든 유형의 HTTP 요청에 의해 실행된다.
app.get('/user/:id', (req, res, next) => {
if (req.params.id === '0') next('route');
// 만약 user ID가 0 이라면, 다음 route로 넘어간다.
// next('route')와 같이 next()에 인자를 전달하는 형태는 app.METHOD()이나 router.METHOD()내에서 미들웨어가 로드될 때만 적용된다.
else next();
// 아니라면 현재 라우트 스택의 다음 middleware로 넘어간다.
}, (req, res, next) => {
res.send('regular');
});
app.get('/user/:id', (req, res, next) => {
// 위에서 user ID가 0 일때 실행되는 라우트이다.
res.send('special');
})
-Routing(분기) (https://expressjs.com/en/guide/routing.html)
// *** app.METHOD(PATH, HANDLER) ***
// HTTP 메소드에 대응하는 Express app 객체의 메소드는 지정된 request를 'listen(수신)'하며
// 요청을 감지하면 handler function을 콜백한다.
// 여러 요청들에 대해서 각자에 맞는 응답을 지정해준다고 생각하면 쉽다.
// *** Route Paths
// Route : Part of a URL that identifies a resource.
// 리소스의 endpoints를 지정한다.
// 경로는 문자열 혹은 정규표현식으로 작성한다. (기호 등 특수문자 삽입은 공식문서 참고)
app.get('/', (req, res) => {
// root(/) 경로의 'GET' Request를 처리한다.
res.send('Hello World!');
});
app.put('/user', (req, res) => {
// /user 경로의 'POST' Request를 처리한다.
res.send('My name is Withlaw');
});
// 다음 /book 경로에 대한 여러 HTTP 메소드 요청을 아래와 같이 chaining을 통해 한꺼번에 처리 할 수 있다.
// route module은 중복과 오타를 감소시여 코드를 효율적으로 관리 할 수 있게 한다.
app.route('/book')
.get((req, res) => {
res.send('~');
})
.post((req, res) => {
res.send('~')
})
.put((req, res) => {
res.send('~')
});
// 어느 특정 경로에 대한 모든 HTTP 요청을 다음과 같이 처리 할 수도 있다.
app.all('/~', fn);
// or
app.use('/',['/user', '/book'], fn); // path 생략 가능
Route Handlers (middleware system)
// 라우팅 메소드는 하나 이상의 콜백함수를 인자로 받는다.
// 만일 여러 콜백함수를 사용할 경우 각 콜백함수에 next를 추가로 전달하고 함수 내부에서 next()를 호출하여
// 다음 콜백함수에게 바톤을 넘긴다.
app.get('/', (req, res, next) => {
...
next();
}, (req, res) => {
res.send('~');
});
// 일련의 여러 미들웨어로 구성된 것을 stack이라 부른다.
// 배열로 인자를 받는 경우
const cb0 = function (req, res, next) {
...
next();
};
const cb1 = function (req, res, next) {
...
next();
};
const cb2 = function (req, res) {
res.send('Hello from C!')
};
app.get('/', [cb0, cb1, cb2]);
// 둘을 동시에 사용하는 경우
app.get('/', [cb0, cb1], (req, res, next) => {
...
next();
}, (req, res) => {
res.send('~');
});
*Request Methods
// 1. request.query
// query string은 흔히 리소스의 어떤 데이터를 고유하지 않은 정보를 이용하여 검색(필터링)할 때 사용한다.
// 다음 요청에 대해 request.query는 쿼리 데이터 객체를 반환한다.
// 'GET: http://localhost:3001/flight?departure=CJU&destination=ICN'
request.query;
{
departure: "CJU",
destination: "ICN",
}
// 2. request.params
// path parameter는 리소스의 어떤 데이터를 고유한 정보를 이용하여 검색할 때 사용한다.
router.get('/flight/:uuid', findById);
// 서버에서 위와 같이 ~path/:[parameter] 형식으로 어떤 값에 대해 매개변수를 지정하고 라우팅한 후,
// 아래와 같은 요청 메시지를 받으면 파라미터 데이터 객체를 반환한다.
// 'GET: http://localhost:3001/flight/a55c-da65-47dd-af23-578'
request.params;
{
uuid: "a55c-da65-47dd-af23-578",
}
*Response Methods
Router module
const express = require('express');
const router = express.Router();
// express.Router 클래스를 통해 모듈처럼 장착(mount)할 수 있는 새로운 router 인스턴스를 생성할 수 있다.
// router 혹은 route module이라 부르며, 라우팅 및 미들웨어 기능만 수행하는 mini-app 같은 것이다.
router.get('/', (req, res) => {
res.send('Birds home page');
});
router.get('/about', (req, res) => {
res.send('About birds');
});
module.exports = router;
// birds.js 라는 이름으로 파일을 저장한 후
// 다른 파일에서 위에서 작성한 라우터를 다른 경로에 라우팅 시킬 수 있다.
const birds = require('./birds');
...
app.use('/birds', birds);
2. Refactoring by using Express
(https://sanxang.tistory.com/68)
const express = require("express");
const cors = require("cors");
const bodyParser = require("body-parser");
// cors와 bodyParser는 third-party 미들웨어로 Node.js에서 모듈을 설치한 후에 사용할 수 있다.
// $ npm i cors bodyParser
//init
const PORT = 4999;
const ip = "localhost";
const app = express();
//Middle Ware
const jsonParser = bodyParser.json({ strict: false });
//Routing
app.use(cors(), jsonParser);
/*
app.options("/upper", (req, res) => {
res.send("<h2>Welcome coedestates</h2>");
});
*/
app.get("/", (req, res) => {
res.send("<h1>Welcome coedestates</h1>");
});
app.post("/upper", (req, res) => {
// res.send(JSON.stringify(req.body.toUpperCase()));
res.json(req.body.toUpperCase());
});
app.post("/lower", (req, res) => {
res.json(req.body.toLowerCase());
});
app.listen(PORT, ip, () => {
console.log(`http server listen on ${ip}:${PORT}`);
});
*Third-party middleware
(https://expressjs.com/en/resources/middleware.html)
1) body-parser
-POST 요청 등에 포함된 body(payload)를 쉽게 얻을 수 있다. (이전에는 네트워크 상의 chunk를 Buffer로 합치고 문자열로 변환하는 복잡한 작업을 필요로 했음)
-요청 메시지의 Content-Type 헤더와 body-parser모듈의 type option이 일치할 때만 req.body 프로퍼티 값이 반환된다.
-만약 서로 다르거나, 파싱할 본문 데이터가 아예 없거나, 중간에 에러가 발생하면 req.body 프로퍼티에 빈 객체가 반환된다.
- *bodyParser.json([options]) : [options] 조건에 맞는 json 데이터만 파싱하여 반환한다. 기본적으로 배열이나 객체 값만 파싱하는데, { strict: false } 옵션 설정을 통해 모든 타입의 데이터를 파싱할 수 있다.
-최근에는 Express 내장 미들웨어인 express.json()을 사용한다. 작성과 사용 방법은 동일하다.
2) CORS
-어떤 요청에 대해 CORS 허용을 알아서 응답 처리해주는 미들웨어이다.
-특정 오리진이나 메소드에 대한 설정 방법은 다음 공식 문서를 읽어 볼 것
(http://expressjs.com/en/resources/middleware/cors.html)
*API reference
-express, router, req & res 등에 관한 다른 여러 프로퍼티와 메소드에 대한 설명은 다음 공식 문서를 읽어 볼 것
(https://expressjs.com/ko/4x/api.html)
*용어집
(https://expressjs.com/en/resources/glossary.html)
3. StateAirline Server 과제
-파일 구조 및 API 분석
'Node.js' 카테고리의 다른 글
Module System (0) | 2022.09.13 |
---|---|
[Web Server] CORS (0) | 2022.08.14 |
-Node.js- (0) | 2022.08.14 |
[Web Server] HTTP Transaction (0) | 2022.08.11 |