코아 소개
- Koa는 Express 뒤에 있는 동일한 사람들이 구축한 새로운 웹 프레임워크로 , 웹 애플리케이션 및 API 개발을 위한 더 작고 표현력이 풍부하며 강력한 빌딩 블록이 되는 것을 목표로 합니다.
- 공식 홈페이지: https://koajs.com/
- GitHub 저장소: https://github.com/koajs/koa
- 번역된 중국어 웹사이트: https://koa.bootcss.com/
- Koa의 원리와 내부 구조는 Express와 매우 유사하지만 구문과 내부 구조가 업그레이드되었습니다.
- Koa 는 내부적으로 ES6로 작성되었으며 차세대 Node.js 웹 프레임워크라고 주장합니다.
- 주요 기능은 비동기 함수를 사용하여 콜백 함수를 폐기하도록 돕는 것입니다.
- Koa 1은 CO 모듈과 결합된 ES2015의 Generator 제너레이터 기능을 기반으로 합니다.
- Koa 2는 Generator 및 co를 완전히 포기하고 ES2017에서 async/await 기능으로 업그레이드합니다.
- Koa는 최신 비동기 처리 방식을 기반으로 하기 때문에 Koa를 사용하여 예외를 처리하기가 더 쉽습니다.
- 컨텍스트 개체는 Koa에서 제공됩니다.
- Koa는 Nodejs에서 req 및 res를 래핑하고 확장합니다.
- Express는 req와 res를 확장합니다.
- Koa는 미들웨어를 번들로 제공하지 않지만 서버 측 애플리케이션을 빠르고 즐겁게 작성하는 데 도움이 되는 일련의 우아한 방법을 제공합니다.
- Koa 자체는 라우팅, 템플릿, 파일 전송, JSONP 및 기타 기능을 지원하지 않으므로 해당 미들웨어를 별도로 설치해야 합니다.
- Koa를 기반으로 하는 많은 개발 도구/프레임워크가 있습니다.
- Koa vs Express 공식 비교
- 다른 의견
- koa 2는 사용하기 쉽고 디자인 면에서 장점이 있습니다. 장점은 더 강력한 기능을 구현할 수 있는 것이 아니라 더 간단하게 완성할 수 있다는 점입니다.
- Koa 2 커뮤니티는 표현하기가 훨씬 열등합니다.
- koa 1은 koa 2와 이념적으로 일치하지만 koa 2 구현이 더 예쁘다.
- Awesome Koa - 일부 Koa 관련 리소스, 자습서, 미들웨어 등을 포함하는 타사 창고입니다.
Koa의 기본 사용법
Koa로 HTTP 서비스 시작
npm init -y
# 安装 koa
npm i koa
// app.js
const Koa = require('koa')
const app = new Koa()
// Koa 没有路由系统,只有中间件功能
// ctx:context 上下文对象,包含请求和响应相关方法
app.use(ctx => {
// 发送响应
ctx.body = 'Hello Koa'
})
app.listen(3000, () => {
console.log('server is running on http://localhost:3000')
})
nodemon ./app.js
Koa의 라우팅
Koa 자체에는 자체 라우팅 기능이 없기 때문에 서로 다른 요청 경로를 분산 처리하려면 프로세스를 수동으로 코딩해야 합니다.
app.use(ctx => {
const path = ctx.path
console.log(path);
if (path === '/') {
ctx.body = 'home page'
} else if (path === '/foo') {
ctx.body = 'foo page'
} else {
ctx.body = '404 Not Found.'
}
})
실제로 Koa는 라우팅 기능을 포함하여 일부 기능을 npm 패키지에 개별적으로 캡슐화합니다.
Koa.js(github.com) 에서 웨어하우스를 검색하면 여러 공식 라우팅 툴킷을 찾을 수 있으며 Express 스타일의 메소드( 등)를 사용하는 koajs / routerroute
사용을 권장합니다 .app.get
app.post
# 安装
npm i @koa/router
// app.js
const Koa = require('koa')
const Router = require('@koa/router')
const app = new Koa()
const router = new Router()
router.get('/', ctx => {
ctx.body = 'home page'
})
router.post('/', ctx => {
ctx.body = 'post /'
})
router.get('/foo', ctx => {
ctx.body = 'foo page'
})
router.get('/bar', ctx => {
// 重定向
ctx.redirect('/foo')
})
router.get('/users/:id', ctx => {
ctx.body = ctx.params
})
app
// 挂载路由配置
.use(router.routes())
// 配置允许的请求方法:OPTIONS 请求的 Allow 请求头
.use(router.allowedMethods())
app.listen(3000, () => {
console.log('server is running on http://localhost:3000')
})
Koa의 정적 리소스 호스팅
koajs/static 모듈은 정적 리소스 호스팅 기능을 캡슐화합니다.
npm i koa-static
// app.js
const Koa = require('koa')
const static = require('koa-static')
const path = require('path')
const app = new Koa()
// http://localhost:3000/css/style.css 访问 /public/css/style.css 文件
app.use(static(path.join(__dirname, './public')))
app.listen(3000, () => {
console.log('server is running on http://localhost:3000')
})
Koa의 미들웨어는 첫 번째 매개 변수를 통해 요청 경로를 설정할 수 없으므로 다음과 같은 방법으로 정적 리소스 디렉터리에 가상 경로를 추가하면 오류가 발생합니다.
app.use('/public', static(path.join(__dirname, './public')))
Koa의 다른 모듈인 koajs/mount를 사용하여 Koa 애플리케이션 또는 미들웨어를 지정된 경로에 마운트할 수 있습니다.
npm i koa-mount
// mount(<路径>, <中间件>)
app.use(mount('/public', static(path.join(__dirname, './public'))))
코아 미들웨어
미들웨어 실행 스택
Express와 마찬가지로 Koa의 가장 큰 특징은 전적으로 미들웨어에 구축된 웹 프레임워크입니다.
Koa 미들웨어와 Express 미들웨어에는 큰 차이가 있습니다. Koa 미들웨어는 완전히 양파 모델을 기반으로 합니다(그림 참조).
- 여러 개의 미들웨어가 스택 구조(중간 스택)를 형성하고 "선입선출"의 순서로 실행됩니다.
- 가장 바깥쪽 미들웨어가 먼저 실행됩니다.
- 함수를 호출 하면
next
다음 미들웨어에 실행권한이 넘어가게 됩니다. - …
- 가장 안쪽의 미들웨어가 마지막으로 실행
- 실행 완료 후 실행 권한은 상위 레이어의 미들웨어로 반환
- …
- 가장 바깥쪽 미들웨어가 실행 권한을 철회한 후 다음 함수 뒤의 코드를 실행합니다.
코드를 통해 미들웨어의 스택 구조를 살펴보겠습니다.
const one = (ctx, next) => {
console.log('>> one')
next()
console.log('<< one')
}
const two = (ctx, next) => {
console.log('>> two')
next()
console.log('<< two')
}
const three = (ctx, next) => {
console.log('>> three')
next()
console.log('<< three')
}
app.use(one)
app.use(two)
app.use(three)
인쇄 결과:
>> one
>> two
>> three
<< three
<< two
<< one
미들웨어 내부에서 함수가 호출되지 않으면 next
실행 권한이 전달되지 않습니다. 예를 들어 two
함수에 주석을 달아 next()
결과를 인쇄합니다.
>> one
>> two
<< two
<< one
비동기 미들웨어
지금까지 미들웨어의 모든 예는 동기식이며 비동기식 작업을 포함하지 않습니다. 비동기 작업(예: 데이터베이스 읽기, 파일 읽기)이 있는 경우 미들웨어는 비동기 함수로 작성되어야 합니다.
const Koa = require('koa')
const path = require('path')
const fsPromises = require('fs').promises
const app = new Koa()
app.use(async (ctx, next) => {
const data = await fsPromises.readFile(path.join(__dirname, './views/index.html'))
// 设置 content-type 为 text/html
// 或者在读取文件的时候设置编码为 `utf8`
ctx.type = 'html'
ctx.body = data
next()
})
app.listen(3000, () => {
console.log('server is running on http://localhost:3000')
})
여러 미들웨어 결합
기본적으로 Koa는 미들웨어를 하나씩만 마운트할 수 있습니다.
app.use(one)
app.use(two)
app.use(three)
미들웨어 조합 도구 koajs/compose를 사용하여 여러 미들웨어를 하나의 미들웨어로 결합하여 마운트할 수 있습니다.
npm i koa-compose
app.use(compose([one, two, three]))
글로벌 예외 처리
오류를 포착하고 수동으로 응답하는 미들웨어는 다음과 같습니다.
app.use(ctx => {
try {
JSON.parse('string')
ctx.body = 'Hello Koa'
} catch (error) {
ctx.response.status = 500
ctx.response.body = '服务端内部错误'
}
})
ctx.throw
Koa에서 제공하는 바로 가기 방법을 사용하여 오류에 응답할 수도 있습니다 .
app.use(ctx => {
try {
JSON.parse('string')
ctx.body = 'Hello Koa'
} catch (error) {
// ctx.response.status = 500
// ctx.response.body = '服务端内部错误'
// ctx.throw(500) // body => Internal Server Error
ctx.throw(404) // body => Not Found
}
})
위의 예는 단일 미들웨어에 대한 오류 캡처 프로세스입니다.프로그램에서 예외를 균일하게 처리하려면 어니언 미들웨어 모델을 사용하여 가장 바깥쪽 레이어에서 오류를 잡기 위한 코드를 작성해야 합니다.
const Koa = require('koa')
const app = new Koa()
// 最外层添加异常捕获的中间件
app.use((ctx, next) => {
try {
next()
} catch (error) {
ctx.response.status = 500
ctx.response.body = error.message
}
})
app.use(ctx => {
JSON.parse('string')
ctx.body = 'Hello Koa'
})
...
Koa가 오류를 처리하는 방식이 Express보다 더 편리하다는 것을 알 수 있습니다. 모든 미들웨어에서 try-catch
오류를 잡아서 next
.
위의 모든 예제는 동기식 미들웨어를 사용한다는 점에 유의하십시오.비동기식 미들웨어인 경우 다음에서 try-catch
사용해야 합니다 await
.
// 最外层添加异常捕获的中间件
app.use(async (ctx, next) => {
try {
// 使用 await 等待下一个中间件处理完成
await next()
} catch (error) {
ctx.response.status = 500
ctx.response.body = error.message
}
})
// 同步中间件:A
app.use((ctx, next) => {
next()
})
// 异步中间件:B
app.use(async ctx => {
// 读取不存在的文件
await fsPromises.readFile('file.txt')
})
그러나 상위 미들웨어 A는 동기식이며 하위 미들웨어의 결과를 기다리지 않고 가장 바깥쪽 오류 처리 미들웨어는 await
미들웨어 A의 실행 결과이기 때문에 이것은 미들웨어 B의 오류를 포착하지 못합니다.
해결책은 다음과 같습니다.
// 方案一,同步中间件返回下层中间件的执行结果
// 同步中间件:A
app.use((ctx, next) => {
return next()
})
// 方案二,将同步中间件改为异步中间件,await next()
// 同步中间件:A
app.use(async (ctx, next) => {
await next()
})
이것은 JS의 Promise 구문 문제이며 Koa 및 미들웨어와 관련이 없습니다.
제안: 모든 미들웨어에 비동기 함수를 사용하고 await를 asycn
사용하십시오 .await
next()
비동기 처리의 또 다른 방법
외부 미들웨어를 사용하여 오류를 잡는 것 외에도 Koa는 error
이벤트를 수신하여 오류를 잡을 수도 있습니다.
// 可以在任意位置监听事件
app.on('error', err => {
console.log(err)
})
**참고:** 외부 미들웨어는 try-catch
오류를 포착하고 처리하는 데 사용되며 error
이벤트는 트리거되지 않습니다.
예외를 처리하고 미들웨어에서 이벤트를 트리거하려는 경우 error
미들웨어에서 수동으로 error
이벤트를 트리거할 수 있습니다.
// 最外层添加异常捕获的中间件
app.use(async (ctx, next) => {
try {
await next()
} catch (error) {
ctx.response.status = 500
ctx.response.body = error.message
// 触发 error 事件
ctx.app.emit('error', error, ctx)
}
})
실제 프로젝트에서는 둘 중 하나를 사용할 수 있습니다(미들웨어 권장).