Node - koa 프레임워크를 사용하며 느낀점
요번에 koa 프레임워크로 개발하게 되어 koa 프레임워크에서 REST API를 처리하는 간단한 코드를 만들어 보았습니다.
예제 코드
const Koa = require('koa');
const Router = require('@koa/router');
const app = new Koa();
const router = new Router();
var userList = [];
router.get('/', (ctx) => {
ctx.body = 'Hello World!';
});
router.post('/users', (ctx) => {
const name = ctx.query.name;
if (checkDuplicates(userList, name)) {
ctx.body = 'User duplicate!!';
} else {
ctx.body = 'User created!';
userList.push(name);
}
});
// 사용자 정보 수정
router.put('/users/:id', (ctx) => {
const userId = ctx.params.id;
const newName = ctx.query.name; // 새로운 이름을 요청 Body에서 가져옵니다
// userList에서 userId와 일치하는 사용자 찾기
const userIndex = userList.indexOf(userId);
// 변경하려는 이름과 기존 이름이 같은 경우 예외처리.
if (newName === userId) {
ctx.body = 'User Same!';
} else if (userIndex !== -1) {
// userId를 찾았을 경우, 새로운 이름으로 업데이트
userList[userIndex] = newName;
ctx.body = `User ${userId} updated to ${newName}!`;
} else {
ctx.body = `User ${userId} not found.`; // 사용자를 찾지 못했을 경우 처리
}
});
// 유저 삭제
router.delete('/users/:id', (ctx) => {
const userId = ctx.params.id;
// userList에서 userId와 일치하는 사용자 찾기
const userIndex = userList.indexOf(userId);
if (userIndex !== -1) {
// userId를 찾았을 경우, 해당 사용자를 삭제
const deletedUser = userList.splice(userIndex, 1);
ctx.body = `User ${deletedUser} deleted!`;
} else {
ctx.body = `User ${userId} not found.`; // 사용자를 찾지 못했을 경우 처리
}
});
router.get('/users', (ctx) => {
console.log("userList.toString() ", userList);
if (userList.length === 0 ) {
ctx.body = 'No users';
} else {
ctx.body = userList.toString();
}
});
app.use(router.routes());
app.use(router.allowedMethods());
app.listen(4000, () => {
console.log('Server started on port 4000');
});
function checkDuplicates(arr, name) {
return arr.includes(name); // 이미 리스트에 있는 이름이면 중복으로 처리
}
Express와 차이
1. Context Object
Express에서는 request와 response 객체를 개별적으로 다뤘다면
app.get('/', function (req, res, next) => {
try {
myfunction(req, res, next);
} catch (err) {
next(err);
}
});
koa에서는 Context 객체를 사용하는데 이 안에는 request, response, 미들웨어, 데이터 등을 포함하여 다루고 있었어요.
app.use((ctx, next) => {
try {
const result = await myfunction();
ctx.body = result;
} catch (err) {
ctx.throw(500, err);
}
await next();
});
2. Routing
Express의 경우 별도의 라우팅 라이브러리 없이 라우팅이 가능했지만
const express = require('express');
const app = express();
app.get('/', (req, res) => {
res.send('Hello World!');
});
app.post('/users', (req, res) => {
// 새로운 사용자 추가
res.send('User created!');
});
koa의 경우 koa-router라는 라이브러리를 사용해야 했어요.
const Koa = require('koa');
const Router = require('@koa/router');
const app = new Koa();
const router = new Router();
var userList = [];
router.get('/', (ctx) => {
ctx.body = 'Hello World!';
});
router.post('/users', (ctx) => {
const name = ctx.query.name;
if (checkDuplicates(userList, name)) {
ctx.body = 'User duplicate!!';
} else {
ctx.body = 'User created!';
userList.push(name);
}
});
3. 미들웨어의 처리 방식의 차이
Express는 미들웨어의 콜백함수들이 Promise를 반환하지 않기 때문에 미들웨어 함수들을 async/await 문법과 사용하기 위해서는 콜백 함수를 promise 변환해주는 함수를 구현하여 사용해야 합니다.
function myMiddleware(req, res, next) {
return new Promise((resolve, reject) => {
// 비동기 작업 수행
doSomethingAsync()
.then(result => {
res.send(result);
resolve();
})
.catch(err => {
reject(err);
});
});
}
...
...
app.get('/', async (req, res, next) => {
try {
await myMiddleware(req, res, next);
} catch (err) {
next(err);
}
});
하지만 koa 프레임워크의 미들웨어의 콜백함수들이 Promise를 반환하기 때문에 별도의 promise 변환 작업이 필요하지 않죠.
(이러한 장점 때문에 사용하는 사람이 있습니다.)
const Koa = require('koa');
const app = new Koa();
app.use(async (ctx, next) => {
try {
const result = await doSomethingAsync();
ctx.body = result;
} catch (err) {
ctx.throw(500, err);
}
await next();
});
app.listen(3000);
4. Express 프레임워크 생태계보다 적은 Middleware.
koa 프레임워크의 Middleware수가 Express 프레임워크의 Middleware 보다 적어 개발자가 구현하는 경우가 많습니다.
정리
koa에선 Express에서 기본으로 내장되어있는 미들웨어수가 적지만 미들웨어의 콜백함수들에 대하여 따로 프로미스 반환함수를 구현하지 않고 async/await를 사용할 수 있기 때문에 편했습니다.
하지만 개인적으로 express가 사용자가 더 많아 관련 정보량이 더 많았기 때문에 구글링하여 정보를 찾기가 더 쉽다는 장점과 필요에 따른 기능이 express에서 대부분 구현되있어 가져다 쓰기만 되기 때문에 express가 더 좋았던 것 같습니다.
그래서 개인 프로젝트로 개발한다면 koa보다 express 프레임워크로 개발하는 것을 더 선호하게 되었습니다.