다음은 책 리액트를 다루는 기술을 읽고 공부한 내용을 바탕으로 작성된 글입니다.
기존 src/index.js 파일 하나에 모두 작성한 라우터들을 여러 파일에 분리시켜서 작성하여 모듈화 시킨 뒤, 다시 src/index.js 파일에서 불러와 적용하였다.
- src/api/index.js
const Router = require('koa-router');
const api = new Router();
api.get('/test', (ctx) => {
ctx.body = '성공';
});
// 라우터를 내보낸다.
module.exports = api;
- src/index.js
const Koa = require('koa');
const Router = require('koa-router');
const api = require('./api');
const app = new Koa();
const router = new Router();
// 라우터 설정
router.use('/api', api.routes()); // api 라우트 적용
// app 인스턴스에 라우터 적용
app.use(router.routes()).use(router.allowedMethods());
app.listen(4000, () => {
console.log('Listening to port 4000');
});
localhost:4000/api/test 경로로 들어가면, '성공' 이 뜬다.
posts 라우트 생성
- src/api/posts/index.js
const Router = require('koa-router');
const posts = new Router();
const printInfo = (ctx) => {
ctx.body = {
method: ctx.method,
path: ctx.path,
params: ctx.params,
};
// 문자열이 아닌 JSON 객체를 반환, 현재 요청의 메서드, 경로, 파라미터를 담음
};
// posts 라우트에 여러 종류의 라우터를 설정한 후 모두 printInfo 함수를 호출하도록 설정
posts.get('/', printInfo);
posts.post('/', printInfo);
posts.get('/:id', printInfo);
posts.delete('/:id', printInfo);
posts.put('/:id', printInfo);
posts.patch('/:id', printInfo);
module.exports = posts;
- src/api/index.js
const Router = require('koa-router');
const posts = require('./posts');
const api = new Router();
api.use('/posts', posts.routes());
// 라우터를 내보낸다.
module.exports = api;
localhost:4000/api/posts 경로로 들어가면,
{"method":"GET","path":"/api/posts","params":{}}
과 같이 뜨는 것을 확인 할 수 있다.
GET 메서드를 사용하는 API는 웹 브라우저에서 주소를 입력하여 테스팅할 수 있지만, 이외의 POST, DELETE, PUT, PATCH 메서드를 사용하는 API는 자바스크립트로 호출하여야 한다.
REST API 요청 테스팅을 쉽게 할 수 있는 프로그램으로는 Postman이 있다.
컨트롤러 파일 작성
라우트를 작성하는 과정에서 특정 경로에 미들웨어를 등록할 때는 다음과 같이 두 번째 인자에 함수를 선언해서 바로 넣어줄 수 있다.
router.get('/', ctx=> {
});
하지만 각 라우트 처리 함수의 코드가 길면 라우터 설정을 한눈에 보기가 힘드므로, 라우트 처리 함수들을 다른 파일로 따로 분리해서 관리할 수 있다.
이렇게 라우트 처리 함수만 모아 놓은 파일을 '컨트롤러' 라고 한다.
koa-bodyparser
미들웨어로, POST/PUT/PATCH 와 같은 메서드의 Request Body에 JSON 형식으로 데이터를 넣어주면, 이를 파싱하여 서버에서 사용 가능하게 한다.
-터미널
yarn add koa-bodyparser
- src/index.js
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;
};
/* 포스트 목록 조회
GET /api/posts
*/
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를 가진 포스트가 몇 번째인지 확인
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를 가진 포스트가 몇 번째인지 확인
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('파일이름');
모듈이름.이름();
- src/api/posts/index.js
const Router = require('koa-router');
const postsCtrl = require('./posts.ctrl');
// 모듈 불러오기
const posts = new Router();
const printInfo = (ctx) => {
ctx.body = {
method: ctx.method,
path: ctx.path,
params: ctx.params,
};
// 문자열이 아닌 JSON 객체를 반환, 현재 요청의 메서드, 경로, 파라미터를 담음
};
// 모듈에서 exports 한 함수들 사용
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;
'Front-End > React' 카테고리의 다른 글
[React] 블로그 만들기 2 - 데이터 생성, 조회, 삭제, 수정 기능 구현 (0) | 2022.03.14 |
---|---|
[React] 블로그 만들기 1 - MongoDB를 이용하여 스키마, 모델 만들기 (0) | 2022.03.11 |
[React] Koa를 이용한 개발 / Koa, koa-router, nodemon (0) | 2022.03.07 |
[React] Render Props (0) | 2022.03.04 |
[React] 중첩된 라우트 , Outlet (0) | 2022.03.01 |