😄 Koa
- Node.js 환경에서 웹 서버를 구축할 때는 보통 Express, Hapi, Koa 등의 웹 프레임워크를 사용한다.
- Koa, Next generation web framework for node.js
- Express는 미들웨어, 라우팅, 템플릿, 파일 호스팅 등의 다양한 기능이 자체적으로 내장되어 있음
- Koa는 미들웨어 기능만 갖추고 있으며 나머지는 다른 라이브러리를 적용하여 사용한다.
- Koa가 Express보다 훨씬 가볍다.
- Koa는 Async/await 문법을 정식으로 지원하기 때문에 비동기 작업을 더 편하게 관리할 수 있다.
😎 Middleware
- Koa의 미들웨어의 배열로 구성되어 있다.
- app.use 함수는 미들웨어 함수를 애플리케이션에 등록한다.
- 미들웨어 함수는
(ctx, next) => { }
구조로 작성된다.
- ctx는 Context의 줄임말로 웹 요청과 응답에 관한 정보를 지니고 있다.
- next는 현재 처리 중인 미들웨어의 다음 미들웨어를 호출하는 함수이다.
- next를 호출하지 않으면, 그다음 미들웨어를 처리하지 않는다.
- next 함수는 Promise를 반환한다.
- 이 점이 Koa가 Express와 차별화되는 부분이다.
- Koa는 async/await를 정식으로 지원한다(Express는 오류 처리가 제대로 되지 않아 3rd 라이브러리가 필요하다)
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');
});
😜 Nodemon
- 서버 코드에 변경사항이 있을 때마다 서버를 자동으로 재시작 시켜준다.
- yarn add --dev nodemon
- 실행은
nodemon --watch src/ src/index.js
로 한다.
- src 폴더 아래에 변경사항이 생기면 src/index.js를 재시작하라는 의미이다.
😍 Koa-router
- parameter는 ctx.params에서 찾을 수 있다
- parameter는 url에 :name 처럼 적을 수 있다
- :name? 마지막 '?'는 name이 선택사항임을 가리킨다
- query는 ctx.query로 찾을 수 있다
...
const Router = require('koa-router');
const router = new Router();
...
router.get('/about/:name?', (ctx) => {
const { name } = ctx.params;
ctx.body = name ? `${name}의 소개` : '소개';
});
router.get('/posts', (ctx) => {
const { id } = ctx.query;
ctx.body = id ? `포스트 #${id}` : '포스트 아이디가 없음이야~';
});
...
😱 Route 모듈화
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());
app.use(router.routes()).use(router.allowedMethods());
app.listen(4000, () => {
console.log('Listening to port 4000');
});
const Router = require('koa-router');
const api = new Router();
api.get('/test', (ctx) => {
ctx.body = '성공!';
});
module.exports = api;
🤓 REST API
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;
const Router = require('koa-router');
const posts = require('./posts');
const api = new Router();
api.use('/posts', posts.routes());
module.exports = api;
🧐 Koa-bodyparser
- 이 미들웨어는 POST/PUT/PATCH 같은 메서드의 Request Body에 JSON 형식으로 데이터를 넣어주면 이를 파싱하여 서버에서 사용할 수 있게 한다.
...
const bodyParser = require('koa-bodyparser');
...
app.use(bodyParser());
app.use(router.routes()).use(router.allowedMethods());
...
🥶 REST API2
let postId = 1;
const posts = [
{
id: 1,
title: 'title',
body: 'contents',
},
];
exports.write = (ctx) => {
const { title, body } = ctx.request.body;
postId += 1;
const post = { id: postId, title, body };
posts.push(post);
ctx.body = post;
};
exports.list = (ctx) => {
ctx.body = posts;
};
exports.read = (ctx) => {
const { id } = ctx.params;
const post = posts.find((p) => p.id.toString() === id);
if (!post) {
ctx.status = 404;
ctx.body = {
message: 'post doesnt exist',
};
return;
}
ctx.body = post;
};
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: 'post doesnt exist',
};
return;
}
posts.splice(index, 1);
ctx.status = 204;
};
exports.replace = (ctx) => {
const { id } = ctx.params;
const index = posts.findIndex((p) => p.id.toString() === id);
if (index === -1) {
ctx.status = 404;
ctx.body = {
message: 'post doesnt exist',
};
return;
}
posts[index] = {
id,
...ctx.request.body,
};
ctx.body = posts[index];
};
exports.update = (ctx) => {
const { id } = ctx.params;
const index = posts.findIndex((p) => p.id.toString() === id);
if (index === 1) {
ctx.status = 404;
ctx.body = {
message: 'post doesnt exist',
};
return;
}
posts[index] = {
...posts[index],
...ctx.request.body,
};
ctx.body = posts[index];
};
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;