라우트를 작성시 특정 경로에 미들웨어를 등록할 때는 다음과 같이 두번째 인자에 함수를 선언해서 바로 넣을 수 있습니다.
router.get('/', ctx => {
});
하지만 각 라우트 처리 함수의 코드가 길면 라우터 설정을 한눈에 보기 어렵습니다. 이에 라우트 처리 함수들을 다른 파일로 따로 분리하여 관리 할 수 있는데 이렇게 라우트 처리 함수만 모아 놓은 파일을 컨트롤러 라고 합니다.
아직 데이터베이스 없이 자바스크립트의 배열 기능을 사용하여 임시로 기능을 구현해 봅니다.
API 기능을 본격적으로 구현하기 전에 koa-bodyparser 미들웨어를 적용해야 합니다.
이 미들웨어는 POST/PUT/PATCH 같은 메서드의 Request Body에 JSON 형식으로 데이터를 넣어주면 이를 파싱하여 서버에서 사용할 수 있게 합니다.
$ yarn add koa-bodyparser
미들웨어 적용은 router 적용하는 코드의 윗부분에서 해야 합니다.
src>index.js 에 bodyparser를 적용합니다.
const Koa = require('koa');
const Router = require('koa-router');
const bodyParser = require('koa-bodyparser');
const api = require('./api');
const app = new Koa();
const router = new Router();
// 라우터 설정
router.use('/api', api.routes()); // api 라우트 적용
// 라우터 적용 전에 bodyparser 적용
app.use(bodyParser());
// app 인스턴스에 라우터 적용
app.use(router.routes()).use(router.allowedMethods());
app.listen(4000, () => {
console.log('Listening to port 4000');
});
그리고 posts 경로에 posts.ctrl.js 파일을 다음과 같이 만듭니다.
let postId = 1; // id의 초깃값입니다.
// posts 배열 초기 데이터
const posts = [
{
id: 1,
title: '제목',
body: '내용',
},
];
/* 포스트 작성
POST /api/posts
{ title, body }
*/
exports.write = (ctx) => {
// REST API 의 Request Body는 ctx.request.body에서 조회할 수 있습니다.
const { title, body } = ctx.request.body;
postId += 1; // 기존 postId 값에 1을 더합니다.
const post = { id: postId, title, body };
posts.push(post);
ctx.body = post;
};
/* 포스트 작성
POST /api/posts
{title, body}
*/
exports.list = (ctx) => {
ctx.body = posts;
};
/* 특정 포스트 조회
GET /api/posts/:id
*/
exports.read = (ctx) => {
const { id } = ctx.params;
// 주어진 id 값으로 포스트를 찾습니다.
// 파라미터로 받아 온 값은 문자열 형식이므로 파라미터를 숫자로 변환하거나
// 비교할 p.id 값을 문자열로 변경해야 합니다.
const post = posts.find((p) => p.id.toString() === id);
// 포스트가 없으면 오류를 반환합니다.
if (!post) {
ctx.status = 404;
ctx.body = {
message: '포스트가 존재하지 않습니다.',
};
return;
}
ctx.body = post;
};
/* 특정 포스트 제거
DELETE /api/posts/:id
*/
exports.remove = (ctx) => {
const { id } = ctx.params;
// 해당 id를 가진 post가 몇 번째인지 확인합니다.
const index = posts.findIndex((p) => p.id.toString() === id);
// 포스트가 없으면 오류를 반환합니다.
if (index === -1) {
ctx.status = 404;
ctx.body = {
message: '포스트가 존재하지 않습니다.',
};
return;
}
// index번째 아이템을 제거합니다.
posts.splice(index, 1);
ctx.status = 204; // No content
};
/* 포스트 수정(교체)
PUT /api/posts/:id
{ title, body }
*/
exports.replace = (ctx) => {
// PUT 메서드는 전체 포스트 정보를 입력하여 데이터를 통째로 교체할 때 사용합니다.
const { id } = ctx.params;
// 해당 id를 가진 post가 몇번째인지 확인합니다.
const index = posts.findIndex((p) => p.id.toString() === id);
// 포스트가 없으면 오류를 반환합니다.
if (index === -1) {
ctx.status = 404;
ctx.body = {
message: '포스트가 존재하지 않습니다.',
};
return;
}
// 전체 객체를 덮어 씌웁니다.
// 따라서 id를 제외한 정보를 날리고, 객체를 새로 만듭니다.
posts[index] = {
id,
...ctx.request.body,
};
ctx.body = posts[index];
};
/* 포스트 수정(특정 필드 변경)
PATCH /api/posts/:id
{ title, body }
*/
exports.update = (ctx) => {
// PATCH 메서드는 주어진 필드만 교체합니다.
const { id } = ctx.params;
// 해당 id를 가진 post가 몇번째인지 확인합니다.
const index = posts.findIndex((p) => p.id.toString() === id);
// 포스트가 없으면 오류를 반환합니다.
if (index === -1) {
ctx.status = 404;
ctx.body = {
message: '포스트가 존재하지 않습니다.',
};
return;
}
// 기존 값에 정보를 덮어 씌웁니다.
posts[index] = {
...posts[index],
...ctx.request.body,
};
ctx.body = posts[index];
};
컨트롤러를 만들면서 exports.이름 = ... 형식으로 함수를 내보내 줍니다.
이렇게 내보낸 코드는 다음 형식으로 불러올 수 있습니다.
const 모듈이름 = require('파일이름');
모듈이름.이름( );
require('./posts.ctrl') 을 입력하여 방금 만든 posts.ctrl.js 파일을 불러온다면 다음 객체를 불러오게 됩니다.
{
write: Function,
list: Function,
read: Function,
remove: Function,
replace: Function,
update: Function,
};
컨트롤러 함수들을 한번 각 라우트에 연결해봅니다.
const Router = require('koa-router');
const postsCtrl = require('./posts.ctrl');
const posts = new Router();
posts.get('/', postsCtrl.list);
posts.post('/', postsCtrl.write);
posts.get('/:id', postsCtrl.read);
posts.delete('/:id', postsCtrl.remove);
posts.put('/:id', postsCtrl.replace);
posts.patch('/:id', postsCtrl.update);
module.exports = posts;
list, read, remove 를 제외한 API는 요청할 때 Request Body가 필요합니다.
Postman 에서 어떻게 사용하는지 보겠습니다.
메서드를 POST 로 변경하고 Body 탭을 선택하고 raw 를 JSON 으로 선택하여 데이터를 입력합니다.
Send 버튼을 선택하면 하단에 입력된 결과가 보입니다. 신규 글쓰기시 id 가 2 번으로 등록 됩니다.
등록된 post는 GET 메서드로 조회하면 됩니다.
update와 replace 함수는 용도는 비슷하지만 구현 방식이 다릅니다.
update(PATCH) 는 기존 값은 유지하면서 변경되는 값만 업데이트 되며, replace(PUT)은 id 를 제외한 모든 값을 대체합니다.
아래와 같이 post 1번의 title 을 "수정하기" 로 변경하여 비교해봅니다.
PATCH 는 body는 그대로 있고 title 만 변경되고, PUT은 title 만 남고 body 는 삭제됩니다.
지금까지 REST API 작동방법은 자바스크립트 배열을 사용하여 구현하였는데 이렇게 구현하면 서버를 재시작할 때마다 데이터가 소멸됩니다.
실제 프로젝트에서는 데이터베이스에 정보를 저장하여 관리하므로 이제 MongoDB 를 사용하여 백엔드를 구현해보겠습니다.
'리액트(React)' 카테고리의 다른 글
esm으로 ES 모듈 import/export 문법 사용하기 (0) | 2023.07.13 |
---|---|
mongoose의 설치 및 적용 (0) | 2023.07.09 |
블로그 만들기 - Postman의 설치 및 사용 (0) | 2023.07.05 |
블로그 만들기 - koa-router 사용하기 (0) | 2023.07.04 |
블로그만들기 - nodemon 사용하기 (0) | 2023.07.03 |