https://github.com/LE123123/KoaServer
GitHub - LE123123/KoaServer
Contribute to LE123123/KoaServer development by creating an account on GitHub.
github.com
Koa는 Express의 기존 개발 팀이 개발한 프레임워크입니다. 기존 Express에서 고치고 싶었던 점들을 개선하면 내부 설계가 완전히 바뀌
기 때문에 개발 팀이 아예 새로운 프레임워크를 개발했다고 합니다.
Express는 미들웨어, 라우팅, 템플릿, 파일 호스팅과 같은 다양한 기능이 자체적으로 내장되어있는 반면, Koa는 미들웨어 기능만 갖추고 있으며 나머지는 다른 라이브러리를 적용하여 사용합니다. 즉 Koa는 우리가 필요한 기능들만 붙여서 서버를 만들 수 있기 때문에 Express보다 훨씬 가볍습니다.
추가로 Koa는 asymc/await문법을 정식으로 지원하기 때문에 비동기 작업을 더 편하게 관리할 수 있습니다.
Koa 시작
// src/index.js const Koa = require('koa'); const app = new Koa(); app.use((ctx, next) => { console.log(ctx.url); console.log(1); if (ctx.query.authorized !== '1') { ctx.status = 401; return; } next().then(() => { console.log('END'); }); }); app.use((ctx, next) => { console.log(2); next(); }); app.use((ctx) => { ctx.body = 'hello world!'; }); app.listen(4000, () => { console.log('Listening to port 4000'); });
next 함수를 호춣하면 Promise를 반환합니다. 이는 Koa가 Express와는 차별화되는 부분입니다. next함수가 반환하는 Promise는 다음에 처리해야 할 미들웨어가 끝나야 완료됩니다. 다음과 같이 next함수 호출 이후에 then을 사용하여 Promise가 끝난 다음 콘솔에 END를 기록하도록 수정했습니다.
// src/index.js const Koa = require('koa'); const app = new Koa(); app.use(async (ctx, next) => { console.log(ctx.url); console.log(1); if (ctx.query.authorized !== '1') { ctx.status = 401; return; } await next(); console.log('END'); }); app.use((ctx, next) => { console.log(2); next(); }); app.use((ctx) => { ctx.body = 'hello world!'; }); app.listen(4000, () => { console.log('Listening to port 4000'); });
이와같이 async/await도 지원합니다.
Koa-router
앞에서 리액트를 배울 떄 웹 브라우저의 라우팅을 돕는 리액트 라우터 라이브러리를 사용해 보았습니다. Koa를 사용할 때도 다른 주소로 요청이 들어올 경우 다른 작업을 처리할 수 있도록 라우터를 사용해야 합니다. Koa 자체에 이 기능이 내장되어 있지는 않으므로, koa-router 모듈을 설치해야 합니다.
// src/index.js const Koa = require('koa'); const Router = require('koa-router'); const app = new Koa(); const router = new Router(); router.get('/', (ctx) => { ctx.body = '홈'; }); router.get('/about', (ctx) => { ctx.body = '소개'; }); router.get('/about/:name', (ctx) => { const { name } = ctx.params; // name의 존재 유무에 따라 다른 결과 출력 ctx.body = name ? `${name}의 소개` : '소개'; }); router.get('/posts', (ctx) => { const { id } = ctx.query; // id의 존재 유무에 따라 다른 결과 출력 ctx.body = id ? `포스트 #${id}` : '포스트 아이디가 없습니다.'; }); app.use(router.routes()).use(router.allowedMethods()); app.listen(4000, () => { console.log('Listening to port 4000'); });
- http://localhost:4000/about/react
- http://localhost:4000/posts
- http://localhost:4000/posts?id=10
위의 경로로 들어가면 페이지에 따라 다른 결과물이 나타나게 될 것입니다.
REST API
// src/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, }; }; 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;

다음과 같이 postman에서 patch요청을 보낸 결과 완벽하게 작동함을 확인할 수 있습니다.
컨트롤러 파일 작성
// src/api/posts/posts.ctrl.js let postId = 1; // id의 초깃값 // posts 배열 초기 데이터 let 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; const post = { id: postId, title, body }; posts = [...posts, post]; ctx.body = post; }; /** * 포스트 목록 조회 * GET /api/posts */ exports.list = (ctx) => { ctx.body = posts; }; /** * 특정 포스트 조회 * GET /api/posts/:id */ exports.read = (ctx) => { const { id } = ctx.params; const post = posts.find((p) => p.id.toString() === id); if (!post) { ctx.status = 404; ctx.body = { message: '포스트가 존재하지 않습니다.', }; return; } ctx.body = post; }; /** * 특정 포스트 제거 * DELETE /api/post/:id */ exports.remove = (ctx) => { const { id } = ctx.params; const index = posts.findIndex((p) => p.id.toString() === id); if (index === -1) { ctx.status = 404; ctx.body = { message: '포스트가 존재하지 않습니다.', }; return; } posts.slice(index, 1); ctx.status = 204; }; /** * 포스트 수정(교체) * PUT /api/posts/:id * { title, body } */ exports.replace = (ctx) => { // PUT 메서드는 전체 포스트 정보를 입력하여 데이터를 통째로 교체할 때 사용합니다. const { id } = ctx.params; const index = posts.findIndex((p) => p.id.toString() === id); if (index === -1) { ctx.status = 404; ctx.body = { message: '포스트가 존재하지 않습니다.', }; } posts[index] = { id, ...ctx.request.body, }; ctx.boy = posts[index]; }; /** * 포스트 수정(특정 필드 변경) * PATCH /api/posts/:id * { title, body } */ exports.update = (ctx) => { // PATCH 메서드는 주어진 필드만 교체합니다. const { id } = ctx.params; const index = posts.findIndex((p) => p.id.toString() === id); if (index === -1) { ctx.status = 404; ctx.body = { message: '포스트가 존재하지 않습니다.', }; } // 기존 값에 정보를 덮어 씌웁니다.\ posts[index] = { ...posts[index], ...ctx.request.body, }; ctx.body = posts[index]; };
// src/api/posts/index.js const Router = require('koa-router'); const posts = new Router(); const postsCtrl = require('./posts.ctrl'); const printInfo = (ctx) => { ctx.body = { method: ctx.method, path: ctx.path, params: ctx.params, }; }; 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;
// src/index.js const Koa = require('koa'); const Router = require('koa-router'); const bodyParser = require('koa-bodyparser'); // const api = require('./api'); const posts = require('./api/posts'); const app = new Koa(); const router = new Router(); // 라우터 설정 // api 라우트 적용 // router.use('/api', api.routes()); // posts 라우트 적용 router.use('/api/posts', posts.routes()); // 라우터 적용 전에 bodeyParser 적용 app.use(bodyParser()); // app 인스턴스에 라우터 적용 app.use(router.routes()).use(router.allowedMethods()); app.listen(4000, () => { console.log('Listening to port 4000'); });
postman을 통해서 REST API가 정상 작동하는지 확인하겠습니다.


위와 같이 정상 작동함을 확인했습니다.
'React > ReactJs' 카테고리의 다른 글
React - API의 활용을 위한 prototype (0) | 2022.03.13 |
---|---|
React - mongoDB ( mongoose ) (0) | 2022.03.12 |
나만의 Webpack 개발환경 만들기 plugin ( React ) (0) | 2022.02.27 |
HTML - History API (0) | 2022.02.23 |
React - ServerSideRendring (0) | 2022.02.22 |