Koa#
Koa는 Express.js 팀이 개발한 새로운 세대의 웹 프레임워크.
Node.js를 위한 더 가벼운 미들웨어 아키텍처를 제공하면서도, 현대적인 JavaScript 기능들을 활용할 수 있도록 설계되었다.
async/await를 기본적으로 지원하여 비동기 코드를 더 우아하게 작성할 수 있게 해주며, 더 작고 표현력 있는 기반을 제공한다.
주요 특징#
- 비동기 함수 지원: Koa는 async/await를 사용하여 비동기 코드를 간결하게 작성할 수 있다.
- 미들웨어 기반 아키텍처: 요청 처리 흐름을 제어하는 미들웨어를 사용하여 유연한 구조를 제공한다.
- 경량화: Koa는 기본적으로 미들웨어를 포함하지 않으며, 필요한 기능을 플러그인 형태로 추가할 수 있다.
- 컨텍스트 객체: 각 요청에 대해
ctx
객체를 제공하여 요청 및 응답을 쉽게 처리할 수 있다. - 모듈화된 구조: Koa는 다양한 기능을 모듈화하여 필요한 기능만 선택적으로 사용할 수 있다.
- 높은 성능: Koa는 미니멀한 디자인 덕분에 빠른 성능을 제공한다.
- 개발자 친화적: 직관적인 API와 간결한 코드로 개발자 경험이 향상된다.
- 유연성: 필요에 따라 미들웨어를 추가하거나 제거할 수 있어 프로젝트 요구에 맞게 조정 가능하다.
- 최신 JavaScript 기능 활용: ES6와 async/await 문법을 통해 현대적인 코드 작성을 지원한다.
단점 및 한계#
- 작은 커뮤니티: Express.js에 비해 상대적으로 작은 커뮤니티와 생태계를 가지고 있다.
- 미들웨어 부족: 기본적으로 제공되는 미들웨어가 없기 때문에 필요한 기능을 직접 구현하거나 외부 라이브러리를 찾아야 한다.
- 학습 곡선: 비동기 프로그래밍에 익숙하지 않은 개발자에게는 다소 복잡할 수 있다.
사용 방법#
설치:
기본 서버 생성:
1
2
3
4
5
6
7
8
9
10
| const Koa = require('koa');
const app = new Koa();
app.use(async ctx => {
ctx.body = 'Hello World';
});
app.listen(3000, () => {
console.log('Server running on http://localhost:3000');
});
|
주요 명령어#
app.use(middleware)
: 미들웨어 등록app.listen(port)
: 서버 시작ctx.body
: 응답 본문 설정ctx.request
: 요청 정보 접근ctx.response
: 응답 정보 접근
기본적인 Koa 애플리케이션의 설정과 실행 예시#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
| const Koa = require('koa');
const Router = require('@koa/router');
const bodyParser = require('koa-bodyparser');
const app = new Koa();
const router = new Router();
// 에러 처리 미들웨어
app.use(async (ctx, next) => {
try {
await next();
} catch (err) {
ctx.status = err.status || 500;
ctx.body = { error: err.message };
ctx.app.emit('error', err, ctx);
}
});
// 로깅 미들웨어
app.use(async (ctx, next) => {
const start = Date.now();
await next();
const ms = Date.now() - start;
console.log(`${ctx.method} ${ctx.url} - ${ms}ms`);
});
// body 파싱 미들웨어
app.use(bodyParser());
// 라우터 설정
router.get('/', async (ctx) => {
ctx.body = { message: 'Welcome to Koa API' };
});
// 사용자 관리 API 예시
let users = new Map();
router.post('/users', async (ctx) => {
const user = ctx.request.body;
const id = users.size + 1;
user.id = id;
users.set(id, user);
ctx.status = 201;
ctx.body = user;
});
router.get('/users/:id', async (ctx) => {
const id = parseInt(ctx.params.id);
const user = users.get(id);
if (!user) {
ctx.status = 404;
ctx.body = { error: 'User not found' };
return;
}
ctx.body = user;
});
router.put('/users/:id', async (ctx) => {
const id = parseInt(ctx.params.id);
const updatedUser = ctx.request.body;
if (!users.has(id)) {
ctx.status = 404;
ctx.body = { error: 'User not found' };
return;
}
updatedUser.id = id;
users.set(id, updatedUser);
ctx.body = updatedUser;
});
router.delete('/users/:id', async (ctx) => {
const id = parseInt(ctx.params.id);
if (!users.has(id)) {
ctx.status = 404;
ctx.body = { error: 'User not found' };
return;
}
users.delete(id);
ctx.status = 204;
});
// 라우터 미들웨어 등록
app.use(router.routes());
app.use(router.allowedMethods());
// 서버 시작
app.listen(3000, () => {
console.log('Server running on port 3000');
});
|
Koa의 고급 기능#
커스텀 미들웨어와 컨텍스트 확장#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
| const Koa = require('koa');
const app = new Koa();
// 커스텀 미들웨어: 인증 체크
const authMiddleware = async (ctx, next) => {
const token = ctx.get('Authorization');
if (!token) {
ctx.status = 401;
ctx.body = { error: 'Authentication required' };
return;
}
// 토큰 검증 로직을 여기에 추가
ctx.state.user = { id: 1, name: 'Test User' };
await next();
};
// 컨텍스트 확장
app.context.sendError = function(message, status = 400) {
this.status = status;
this.body = { error: message };
};
app.context.sendSuccess = function(data, status = 200) {
this.status = status;
this.body = { success: true, data };
};
// 미들웨어 체이닝 예시
app.use(async (ctx, next) => {
const start = Date.now();
await next();
const ms = Date.now() - start;
ctx.set('X-Response-Time', `${ms}ms`);
});
// 보안 미들웨어 예시
app.use(async (ctx, next) => {
ctx.set('X-XSS-Protection', '1; mode=block');
ctx.set('X-Frame-Options', 'DENY');
ctx.set('X-Content-Type-Options', 'nosniff');
await next();
});
// 에러 처리
app.on('error', (err, ctx) => {
console.error('server error', err);
});
|
파일 업로드 처리 예시#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| const Koa = require('koa');
const multer = require('@koa/multer');
const Router = require('@koa/router');
const app = new Koa();
const router = new Router();
const upload = multer({
dest: 'uploads/',
limits: {
fileSize: 5 * 1024 * 1024 // 5MB 제한
}
});
router.post('/upload', upload.single('file'), async (ctx) => {
ctx.body = {
filename: ctx.file.filename,
size: ctx.file.size,
mimetype: ctx.file.mimetype
};
});
|
세션 처리 예시#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| const session = require('koa-session');
app.keys = ['some secret key']; // 쿠키 서명을 위한 키
const CONFIG = {
key: 'koa.sess',
maxAge: 86400000,
autoCommit: true,
overwrite: true,
httpOnly: true,
signed: true,
rolling: false,
renew: false,
};
app.use(session(CONFIG, app));
router.get('/session-test', async (ctx) => {
// 세션 데이터 설정
ctx.session.views = (ctx.session.views || 0) + 1;
ctx.body = {
views: ctx.session.views
};
});
|
참고 및 출처#
Koa - next generation web framework for node.js