테스트주도개발(TDD)로 만드는 NodeJS API 서버 - 002
익스프레스(ExpressJS) 기초Permalink
익스프레스(ExpressJS) 소개Permalink
ExpressJS 는 nodejs 로 만들어진 간결한 웹프레임워크
ExpressJS 기능
- 어플리케이션
- 미들웨어
- 라우팅
- 요청객체
- 응답객체
ExpressJS 설치
# node-api/
$ npm i express
어플리케이션Permalink
익스프레스 인스턴스를 어플리케이션이라 함
서버에 필요한 기능인 미들웨어를 어플리케이션에 추가함
라우팅 설정을 할 수 있음
서버를 요청 대기 상태로 만들 수 있음
index.js
// node-api/index.js
const express = require('express');
const app = express(); // 어플리케이션
app.listen(3000, function(){
console.log('Server is running');
});
미들웨어 만들기Permalink
미들웨어는 함수들의 연속이다
로깅 미들웨어를 만들어 보자
써드파티 미들웨어를 사용해 보자
일반 미들웨어 vs 에러 미들웨어
404, 500 에러 미들웨어를 만들어 보자
index.js
// node-api/index.js
const express = require('express');
const app = express(); // 어플리케이션
function logger(req, res, next) {
console.log('I am logger');
next();
}
app.use(logger);
app.listen(3000, function(){
console.log('Server is running');
});
실행
# node-api/
$ node index.js
Server is running
접속확인
$ curl -X GET 'localhost:3000'
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Error</title>
</head>
<body>
<pre>Cannot GET /</pre>
</body>
</html>
서버로그
Server is running
I am logger
미들웨어 실행 순서Permalink
미들웨어 추가하기
index.js
// node-api/index.js
...
function logger(req, res, next) {
console.log('I am logger');
next();
}
function logger2(req, res, next) {
console.log('I am logger2');
next();
}
app.use(logger);
app.use(logger2);
...
실행
# node-api/
$ node index.js
Server is running
접속확인
$ curl -X GET 'localhost:3000'
# 실행결과 출력
서버로그
Server is running
I am logger
I am logger2
미들웨어에서 next() 호출하는 것은 중요
만약 next() 를 호출하지 않으면 I am logger
에서 멈춤
다른 개발자가 만든 미들웨어 사용하기Permalink
expressJS 에서 외부 logger(morgan) 사용하기
# node-api/
$ npm insall morgan
// node-api/index.js
const express = require('express');
const morgan = require('morgan');
const app = express();
...
app.use(logger2);
app.use(morgan('dev'));
...
실행
# node-api 폴더에서
$ node index.js
Server is running
접속확인
$ curl -X GET 'localhost:3000'
# 실행결과 출력
서버로그
Server is running
I am logger
I am logger2
GET / 404 2.096 ms - 139
에러 미들웨어Permalink
미들웨어는 일반 미들웨어 / 에러 미들웨어가 있음
일반 미들웨어는 param 을 3개 받음 : req, res, next
에러 미들웨어는 param 을 4개 받음 : err, req, res, next
// node-api/index.js
const express = require('express');
const app = express();
function commonmw(req, res, next) {
console.log('commonmw');
next(new Error('error ouccered'));
}
function errormw(err, req, res, next) {
console.log(err.message);
// 에러를 처리하거나
next();
}
app.use(commonmw);
app.use(errormw);
app.use(morgan('dev'));
app.listen(3000, fuction() {
console.log('Server is running');
})
실행
# node-api 폴더에서
$ node index.js
Server is running
접속확인
$ curl -X GET 'localhost:3000'
서버로그
Server is running
commonmw
error ouccered
라우팅Permalink
요청 URL 에 대해 적절한 핸들러 함수를 연결해주는 기능을 라우팅이라고 부름
어플리케이션의 get(), post() 메소드로 구현할 수 있음
라우팅을 위한 전용 Router 클래스를 사용할 수 있음
// node-api/index.js
const http = require('http');
const hostname = '127.0.0.1';
const port = 3000;
const server =http.createServer((req, res) => {
if(req.url === '/') {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plan');
res.end('Hello World\n');
} else if(req.url === '/users') {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plan');
res.end('User list');
} else {
res.statusCode = 404;
res.end('Not Found');
}
});
server.listen(port, hostname, () => {
console.log(`Server running as http://${hostname}:${port}/`);
});
어떤 요청이 왔을 때 그 요청에 해당하는 응답을 연결시켜 주는 것을 라우팅이라고 함
http 모듈에서는 라우팅이 위처럼 다소 장황하게 작성됨
요청객체와 응답객체Permalink
요청객체Permalink
클라이언트 요청 정보를 담은 객체를 요청(Request) 객체라고 함
http 모듈의 request 객체를 래핑한 것
req.params(), req.query(), req.body() 메소드를 주로 사용함
응답객체Permalink
클라이언트 응답 정보를 담은 객체를 응답(Response) 객체라고 함
http 모듈의 response 객체를 래핑한 것
res.send(), res.status(), res.json() 메소드를 주로 사용함
Hello world 익스프레스 버전Permalink
index.js
// node-api/index.js
var express = require('express');
var app = express();
app.get('/', function (req, res) {
res.send('Hello World!');
});
app.listen(3000, function () {
console.log('Example app listening on port 3000!');
});
npm 에 대해 좀 더 알아보기Permalink
npm1Permalink
$ npm install express
위 명령어로 express 를 설치했는데 어디에 설치되었을까?
node_modules 폴더에 설치됨
node_modules 폴더에 가면 express 말고 다른 모듈들이 있음
express 가 사용하는 다른 모듈들이 같이 설치된 것
git 에 소스를 올릴 때는 node_modules 폴더는 올리지 않음, 용량문제
그렇게 되면 git 에 index.js 를 올리더라도 다른 사용자는 실행해 볼 수 없음
npm init
을 통해 package.json 파일을 만들어 올릴 수 있음
$ npm init
package.json 안에 dependencies 에 express 를 추가해줌
만약 node_modules 가 없는 폴더에서 npm init
을 하게 되면 dependencies 는 비어있음
npm install express --save
를 통해 설치와 동시에 package.json 의 dependencies 에 추가할 수 있음
$ npm install express --save
이 후 package.json 의 dependencies 에 모듈이 있는 상황에서는 npm install
만으로 모듈들을 설치할 수 있음
$ npm install
npm2Permalink
“script” 에 “start” 추가
package.json
{
"name": "node-api",
"version": "1.0.0",
"description": "",
"main": "index.js",
"dependencies": {
"express": "^4.15.2",
"morgan": "^1.8.1",
},
"devDependencies": {},
"script": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node index.js"
},
"author": "",
"license": "ISC"
}
실행
# node-api 폴더에서
$ npm start
Example app listening on port 3000!
REST API란Permalink
요청 형식Permalink
HTTP 메서드
자원에 대한 행동을 나타냄
- GET : 자원을 조회
- POST : 자원을 생성
- PUT : 자원을 갱신
- DELETE : 자원을 삭제
이는 익스프레스 어플리케이션의 메소드로 구현되어 있음
REST API 예시
# 유저목록을 조회할 때
$ curl -X GET 'localhost:3000/users'
# 유저목록 중 1번회원을 조회할 때
$ curl -X GET 'localhost:3000/users/1'
index.js
// node-api/index.js
...
// get 방식 요청에 대한 처리
app.get('/users', function(req, res) {
res.send('users list');
});
// post 방식 요청에 대한 처리
app.post('/users', function(req, res) {
// create user...
res.send(user);
})
...
응답 형식Permalink
HTTP 상태코드
- 1xx : 아직 처리중
- 2xx : 자, 여기있어
- 200 : 성공(success), GET, PUT
- 201 : 작성됨(created), POST
- 204 : 내용 없음(No Content), DELETE
- 3xx : 잘 가~
- 4xx : 니가 문제임
- 400 : 잘못된 요청(Bad Request)
- 401 : 권한 없음(Unauthorized)
- 404 : 찾을 수 없음(Not found)
- 409 : 충돌(Conflict)
- 5xx : 내가 문제임
- 500 : 서버 에러(Internal server error)
첫번째 API 만들기: 사용자 목록 조회 APIPermalink
GET /users
사용자 목록을 조회하는 기능
// node-api/index.js
var express = require('express');
var morgan = require('morgan');
var app = express();
var users = [
{id: 1, name: 'alice'},
{id: 2, name: 'beck'},
{id: 3, name: 'chris'},
];
app.use(morgan('dev'));
app.get('/users', function(req, res) {
res.json(users);
});
app.listen(3000, function() {
console.log('Example app listening on port 3000!');
})
실행
# node-api 폴더에서
$ npm start
Example app listening on port 3000!
요청
$ curl -X GET 'localhost:3000/users' -v
서버로그
Example app listening on port 3000!
GET /users 200 2.815 ms - 71
요청 결과
Note: Unnecessary use of -X or --request, GET is already inferred.
* Trying 127.0.0.1...
* TCP_NODELAY set
* connected to 127.0.0.1 (127.0.0.1) port 3000 (#0)
# > 은 요청값
> GET /usrs HTTP/1.1
> Host: 127.0.0.1:3000
> User-Agent: curl/7.51.0
> Accept: */*
>
# < 은 응답값
< HTTP/1.1 200 OK
< X-Powered-By: Express
< Content-Type: application/json; charset=utf-8
< Content-Length: 71
...
[{"id":1,"name":"alice"},{"id":2,"name":"beck"},{"id":3,"name":"chris"}]