- 학습 내용
express는 웹 모바일 앱을 위한 Node.js 웹 애플리케이션 프레임워크이다. express는 HTTP 유틸리티 메소드 및 미들웨어를 통해 쉽고 빠르게 API를 작성할 수 있다. 즉, express를 활용하면 서버 구축의 측면에서 훨씬 단순하고 직관적으로 할 수 있는 것이다.
- 설치
npm init 명령을 사용하여 먼저 package.json 파일을 작성한 뒤, 이 것을 실행하면 앱 이름 및 버전과 같은 몇 가지 정보에 대해 프롬프트 한다. 이후 npm install express를 통해 해당 디렉토리에 express를 설치할 수 있다. --save 옵션을 사용하면 종속 항목 목록에 저장할 수도 있다.
- Hello world 예제
해당 js파일에 다음과 같은 코드를 작성한다.
const express = require('express')
const app = express()
const port = 3000
app.get('/', (req, res) => {
res.send('Hello World!')
})
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`)
})
이것을 node app.js를 통해 실행하면 3000번 포트에서 연결한다. 여기서 루트URL(/) 또는 라우트에 대한 요청으로 'Hello Wolrd!'로 응답할 것이다. 다른 모든 경로는 404 Not Found로 응답한다.
- 기본 라우팅
라우팅은 URI(또는 경로) 및 특정한 HTTP 요청 메소드(GET, POST 등)인 특정 엔드포인트에 대한 클라이언트 요청에 앱이 응답하는 방법을 결정하는 것을 말한다. 각 라우트는 하나 이상의 핸들러 함수를 가질 수 있고, 이러한 함수는 라우트가 일치할 때 실행된다. 라우트는 이러한 구조로 작성한다.
app.METHOD(PATH, HANDLER)
app은 express의 인스턴스이고, METHOD는 HTTP 요청 메소드이다. PATH는 서버의 경로이고, HANDLER는 라우트가 일치할 때 실행되는 함수이다.
app.get('/', function (req, res) {
res.send('Hello World!');
});
- Express에서 정적 파일 제공
이미지나 CSS파일 및 JavaScript파일과 같은 정적 파일을 제공할 때는 Express의 기본 제공 미들웨어 함수인 express.static을 사용하면 된다. 정적 파일이 포함된 디렉토리의 이름을 express.static 미들웨어 함수에 전달하면 파일의 직접적인 제공을 할 수 있다. 예를 들면 이런 식이다.
app.use(express.static('public'));
이렇게 하면 public 디렉토리 안에 있는 파일을 불러올 수 있다. 아래와 같이 호출하면 public 디렉토리에 있는 파일을 응답할 것이다.
http://localhost:3000/images/kitten.jpg
http://localhost:3000/css/style.css
http://localhost:3000/js/app.js
여러 개의 정적 자산 디렉토리를 이용할 때는 express.static 미들웨어 함수를 여러 번 호출하면 된다.
또 express.static 함수를 통해 제공되는 파일에 가상 경로를 작성할 수도 있다. 예를 들면,
app.use('/static', express.static('public'))
이렇게 쓰면 아래의 가상 경로로부터 파일을 불러올 수 있다.
http://localhost:3000/static/images/kitten.jpg
http://localhost:3000/static/css/style.css
http://localhost:3000/static/js/app.js
그러나 함수에서 이렇게 작성하여 만드는 경로는 node 프로세스가 실행하는 원래 디렉토리에 대해 상대적이기 때문에 이왕이면 절대 경로를 사용하는 것이 안전하다.
app.use('/static', express.static(_dirname + '/pubilc'));
- 라우팅
라우팅이란 앱 엔드 포인트(URI)를 정의하고 그 URI가 클라이언트 요청에 응답하는 방식을 의미한다. 기본적으로 라우트 메소드는 HTTP 메소드를 따온다.
// GET 메소드 라우트
app.get('/', function(req, res) {
res.send('GET request to the homepage');
});
// POST 메소드 라우트
app.post('/', function(req, res) {
res.send('POST request to the homepage');
});
여기에 있어 사용 가능한 메소드는 아래와 같다.
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 |
단, all의 경우 HTTP 메소드를 불러오지 않는다. 단지 모든 요청 메소드에 대해 한 경로에서 미들 웨어 함수를 불러오는 데 사용된다.
app.all('/secret', function (req, res, next) {
console.log('Accessing the secret section ...');
next();
});
- 라우트 핸들러
라우트는 콜백 함수를 제공하여 요청을 처리할 수 있다. 이것은 미들웨어와 유사하다. 유일한 차이점은 next('route')를 호출하여 나머지 라우트 콜백을 우회할 수 있다는 것이다.
app.get('/example/a', function(req, res) {
res.send('Hello from A!');
});
2개 이상의 콜백 함수를 하나의 라우트에서 처리할 수 있다. 그러나 반드시 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!');
});
배열을 사용해서 여러 콜백 함수를 하나의 라우트로 처리할 수도 있다.
let cb0 = function(req, res, next) {
console.log('CB0');
next()
}
let cb1 = function (req, res, next) {
console.log('CB1')
next()
}
let cb2 = function (req, res, next) {
console.log('Hello from C!')
}
app.get('/example/c', [cb0,cb1,cb2]);
마찬가지로 배열과 함수를 같이 사용해서 콜백 함수를 라우트로 처리할 수도 있다.
let cb0 = function(req, res, next) {
console.log('CB0');
next();
}
let 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!');
});
- app.route()
app.route()를 이용하면 라우트 경로에 대해서 체인이 가능하다. 경로를 한 곳으로 지정하고 모듈식으로 라우트를 작성하면 된다.
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라는 이름의 라우터 파일을 앱 디렉토리에 작성한다.
let express = require('express');
let router = express.Router();
router.use(function timeLog(req, res, next) {
console.log('Time: ', Data.now());
next();
});
router.get('/', function(req,res) {
res.send('Birds home page');
});
router.get('/about', function(req, res) {
res.send('About birds');
});
module.exports = router;
// 앱 내에서 라우터 모듈을 불러올 수 있다.
let birds = require('./birds')
app.use('/birds', birds);
- 미들웨어
미들웨어 함수란 요청 오브젝트(req), 응답 오브젝트(res), 그리고 앱의 요청-응답을 주고받는 동안 그다음의 미들웨어 함수에 대한 액세스 권한을 갖는 함수를 말한다. 쉽게 말하면 요청-응답을 하는 동안 작동하는 함수라고 할 수 있다.
일단 미들웨어 함수를 불러오려면 미들웨어 함수를 지정하여 use를 사용하여 호출한다. 이렇게 사용하면 미들웨어 함수를 불러올 수 있다.
let express = require('express');
let app = express();
let myLogger = function (req, res, next) {
console.log('LOGGED');
next();
};
app.use(myLogger);
app.get('/', function(req, res) {
res.send('Hello World!');
});
app.listen(3000);
이렇게 쓰면 앱이 요청을 수신할 때마다 미들웨어 함수를 사용한다. 위의 경우 불러올 때마다 LOGGED를 불러올 것이다. 또한 미들웨어는 순서에 따라 불러져온다.
- express의 요청 객체(Resquest) 메소드
req.params | 이름 붙은 라우트 파라미터를 담음. ex) app.get('/:id', (req,res) => { res.send(req.params.id) } |
req.query | GET 방식으로 넘어오는 쿼리 스트링 파라미터를 담고 있음 |
req.body | POST 방식으로 넘어오는 파라미터를 담고있음. HTTP의 BODY부분에 담겨져있는데, 이부분을 파싱하기 위해 body-parser와 같은 패키지가 필요함 |
req.route | 현재 라우트에 관한 정보를 보여줌. 디버깅용. |
req.cookies (req.signedCookes) |
클라이언트가 전달한 쿠키 값을 가짐. |
req.headers | HTTP의 Header 정보를 가지고 있음. |
req.accepts([types]) | 클라이언트가 해당하는 타입을 받을 수 있는지 확인하는 메소드. |
req.ip | 클라이언트의 ip address. |
req.path | 클라이언트가 요청한 경로, 프로토콜, 호스트, 포트, 쿼리스트링을 제외한 순수 경로를 불러온다. |
req.host | 요청 호스트 이름을 반환하는 간단한 메소드. 보안의 위험이 있어 사용에 유의해야한다. |
req.xhr | 요청이 ajax 호출로 시작되었으면 true를 반환함. |
req.protocol | 현재 요청의 프로토콜을 출력함. |
req.secure | 현재 요청이 보안 요청이면 true를 반환함. |
req.url (req.originalUrl) |
URL경로와 쿼리 스트링을 반환. 원본 요청을 logging하는 목적으로 많이 쓰임. |
req.acceptedLanguages | 클라잉너트가 선호하는 자연어 목록을 반환함. header에서 파싱하면 다국어를 지원하는 앱이면 초기 언어 선택에 도움을 줄 수 있다. |
- express의 응답 객체(Response) 메소드
res.status(code) | HTTP응답 코드를 설정한다. 응답 코드가 redirect(30x)라면, res.redirect를 쓰는게 나음. |
res.set(name, value) | 응답 헤더를 설정함. |
res.cookie(name, value, [option]) |
클라이언트에 저장될 쿠키를 설정하거나 제거한다. cookie-parser 패키지가 필요함. |
res.redirect([status],url) | redirect. 기본 응답 값은 302이다. |
res.send(body), res.send(status, body) |
클라이언트에 응답을 보낸다. 상태 코드의 경우 옵션으로 넣을 수 있다. 기본 콘텐츠 타입은 text/html이다. 그래서 text/plain을 보내려면 res.set('Content-Type', 'text/plain')을 먼저 호출해야 한다. JSON을 보낼때는 res.json을 사용하는 것이 좋다. |
res.json(json), res.json(status, json) |
클라이언트로 JSON 값을 보냄. |
res.jsonp(json), res.jsonp(status, json) |
클라이언트로 JSONP 값을 보냄. |
res.type(type) | Contents-Type 헤더를 설정할 수 있는 간단한 메소드. |
res.format(object) | Accept 요청에 따라 다른 콘텐츠를 전송할 수 있는 메소드. |
res.attachment([filename]), res.download(path, [filename],[callbakc]) |
클라이언트에게 파일을 표시하지 말고 다운로드 받으라고 전송함. filename을 주면 파일 이름이 명시되며, res.attachment는 헤더만 설정하므로 다운로드를 위한 node코드가 따로 필요함.ion |
res.sendFile(path, [option], [callback]) | path의 파일을 읽고 해당 내용을 클라이언트로 전송한다. |
res.links(links) | Links 응답 헤더를 설정한다. |
res.locals, res.render(view, [locals], callback) |
res.lacals는 뷰를 렌더링하는 기본 콘텍스트를 포함하는 객체다. res.render는 jade와 같은 템플릿 엔진을 사용하여 뷰를 렌더링한다. |
'아키텍처' 카테고리의 다른 글
[배포] Amazon Web Service (0) | 2022.06.29 |
---|---|
네트워크 심화 (0) | 2022.06.27 |
클라이언트 빌드와 배포 (0) | 2021.12.08 |
[Web Server] 기초 (0) | 2021.12.08 |
네트워크 기초 (0) | 2021.11.03 |