Express를 사용해서 RESTful API를 만들어 보자
익스프레스는 노드를 만든 패키지의 일종으로 웹 서버를 만들기 위한 것이라고 볼수 있습니다.
클라이언트와 서버는 HTTP라는 규칙을 이용해서 서로 통신하게 됩니다. 웹에서도 이 HTTP를 이용해 페이지를 주고 받습니다. 익스프레스가 웹 프레임웍이긴 하지만 똑같은 HTTP 기반의 API 서비스를 개발하는 것이기 때문에 API 서버에서도 사용하는 것입니다.
또한 프레임웍을 사용하게 되면 노드로만 코드를 작성하는것 보다 훨씬 빠른시간에 효율적으로 서버를 개발할수 있는 이점도 있습니다.
익스프레스는 크게 네 가지 부분으로 이해한다.
불러온 익스프레스 객체에는 하나의 함수가 할당되는데 그 함수를 실행하면 익스프레스 객체가 생성된다. 익스프레스 클래스를 이용해 익스프레스 객체를 만든다고 생각하면 된다. 이것을 익스프레서 어플리케이션 (Application)이라고 한다.
콜백함수에서 전달해 주는 1번째 파라미터 req는 익스프레스 요청 (Request) 객체라고 한다. 요청 객체는 말 그대로 서버로 요청한 클라이언트의 대한 정보를 담고 있다. 하나의 객체 형태로 되어 있고 키와 함수들로 구성되어 있다.
+ req.params: url 파라미터 정보를 조회
+ req.query: 쿼리 문자열을 조회
+ req.body: 요청 바디를 조회
콜백함수에서 전달해 주는 2번째 파라미터 res는 익스프레스 응답 객체 (Response)라고 한다. 응답 객체는 요청한 클라이언트에게 응답하기 위한 함수들로 구성된 객체로, 아래 함수들을 사용한다.
+ res.send()
+ res.json()
+ res.status()
어플리케이션을 이용해 라우팅 조직을 만들 수 있지만 익스프레스에는 별도로 *Router()** 클래스를 제공한다. 라우터 클래스를 이용하면 라우팅 조직을 좀 더 구조적으로 만들 수 있다.
서버 데이터를 구조적으로 사용하기 위한 API 디자인을 REST API라고 한다.
클라이언트측 REST API
서버측 REST API
클라이언트측에서 요청에 대한 서버의 응답은 두 부분으로 구분할 수 있다.
헤더와 바디, 바디는 Json 타입으로 응답하는 것이다. 헤더의 상태코드 (Status Code)를 잘 사용하면 다양한 정보를 담아 클라이언트에게 전송할 수 있다.
응답 헤더의 상태코드는 세 자리 정수로 되어있는데 크게 세 분류가 있다.
+ 200 - **Success** 대부분의 성공 응답에 200 코드를 사용
+ 400 - **Bad Request** 클라이언트에서 파라미터를 포함해 서버 API를 요청하는데 파라미터가 잘못되었을 경우 응답하는 코드
+ 500 - **Internal Server Error** 서버에서 클라이언트 요청 처리 중 에러
이제 express를 설치하고 서버를 만들어 보자.
npm init --yes
npm i express
const express = require("express");
const app = express();
app.get();
app.post();
app.put();
app.delete();
app.get("/api/courses", (req, res) => {
res.send([1, 2, 3]);
});
app.listen(3000, () => console.log("Listening on port 3000..."));
node index.js
를 터미널에서 실행시키면 포트 3000서버가 실행된다.
Hello World가 잘 나타나는 것을 확인할 수 있다.
/api/courses 로 url을 변경시키면 send() 로 내보낸 배열이 잘 나타난다.
파일을 수정하고 확인할 때 마다 터미널에서 node index.js 명령어를 반복적으로 입력해 확인해야 하는 불편함을 해결해주는 모듈인 nodemon을 설치해준다.
nodemon은 디렉토리의 파일 변경이 감지되면 노드 응용 프로그램을 자동으로 다시 시작하여 node.js 기반 응용 프로그램을 개발하는 데 도움이되는 도구입니다.
npm i -g nodemon
nodemon index.js
app.get("/api/posts/:year/:month", (req, res) => {
res.send(req.params);
});
const courses = [
{ id: 1, name: "courses1" },
{ id: 2, name: "courses2" },
{ id: 3, name: "courses3" }
];
app.get("/", (req, res) => {
res.send("Hello World");
});
app.get("/api/courses", (req, res) => {
res.send(courses);
});
// 해당하는 ID를 찾아서 Respon
app.get("/api/courses/:id", (req, res) => {
const course = courses.find(c => c.id === parseInt(req.params.id));
if (!course) res.status(404).send(`ID was not found`);
res.send(course);
});
// PORT
const port = process.env.PORT || 3000;
app.listen(port, () => console.log(`Listening on port ${port}...`));
app.use(express.json());
app.post("/api/courses", (req, res) => {
const course = {
id: courses.length + 1,
name: req.body.name
};
courses.push(course);
res.send(course);
});
Postman에서 확인
Joi를 사용하여 Express 애플리케이션의 입력을 검증한다.
const Joi = require("joi");
app.post("/api/courses", (req, res) => {
const schema = {
name: Joi.string()
.min(3)
.required()
};
const result = Joi.validate(req.body, schema);
console.log(result);
if (result.error) {
// 400 Bad Request
res.status(400).send(result.error);
return;
}
new one 값을 제출 시
비어있는 값 제출 시
app.put("/api/courses/:id", (req, res) => {
const course = courses.find(c => c.id === parseInt(req.params.id));
if (!course) res.status(404).send(`ID was not found`);
Schema , Validate, // return 400 error
const schema = {
name: Joi.string()
.min(3)
.required()
};
const result = Joi.validate(req.body, schema); // validate
if (result.error) {
// 400 Bad Request
res.status(400).send(result.error);
return;
}
course.name = req.body.name;
res.send(course);
});
app.delete("api/courses/:id", (req, res) => {
// 1. Look up the course
const course = courses.find(c => c.id === parseInt(req.params.id));
// 2. Not existing, return 404
if (!course) return res.status(404).send(`ID was not found`);
// 3. Delete
const index = courses.indexOf(course);
courses.splice(index, 1);
// 4. Return the same course
res.send(course);
});
http://webframeworks.kr/tutorials/nodejs/api-server-by-nodejs-02/