Deno
Deno는 V8 엔진 기반의 JavaScript 런타임이다. Node.js와는 다르다.
Hono는 Deno에서도 동작한다.
Hono를 사용해 TypeScript로 코드를 작성하고, deno 커맨드로 애플리케이션을 실행하며, "Deno Deploy"에 배포할 수 있다.
1. Deno 설치
먼저 deno 커맨드를 설치한다. 자세한 내용은 공식 문서를 참고한다.
2. 설정
Deno를 위한 스타터 프로젝트를 사용할 수 있다. "create-hono" 명령어로 프로젝트를 시작한다.
deno init --npm hono my-app이 예제에서는 deno 템플릿을 선택한다.
my-app 디렉터리로 이동한다. Deno의 경우 Hono를 별도로 설치할 필요가 없다.
cd my-app3. Hello World
첫 번째 애플리케이션을 작성해 보자.
import { Hono } from 'hono'
const app = new Hono()
app.get('/', (c) => c.text('Hello Deno!'))
Deno.serve(app.fetch)4. 실행
단순히 이 커맨드를 실행하면 된다:
deno task start포트 번호 변경하기
main.ts 파일에서 Deno.serve의 인자를 수정해 포트 번호를 지정할 수 있다:
Deno.serve(app.fetch)
Deno.serve({ port: 8787 }, app.fetch) 정적 파일 제공하기
정적 파일을 제공하려면 hono/middleware.ts에서 serveStatic을 가져와 사용한다.
import { Hono } from 'hono'
import { serveStatic } from 'hono/deno'
const app = new Hono()
app.use('/static/*', serveStatic({ root: './' }))
app.use('/favicon.ico', serveStatic({ path: './favicon.ico' }))
app.get('/', (c) => c.text('You can access: /static/hello.txt'))
app.get('*', serveStatic({ path: './static/fallback.txt' }))
Deno.serve(app.fetch)위 코드는 다음 디렉터리 구조에서 잘 동작한다.
./
├── favicon.ico
├── index.ts
└── static
├── demo
│ └── index.html
├── fallback.txt
├── hello.txt
└── images
└── dinotocat.pngrewriteRequestPath
http://localhost:8000/static/*을 ./statics로 매핑하려면 rewriteRequestPath 옵션을 사용할 수 있다:
app.get(
'/static/*',
serveStatic({
root: './',
rewriteRequestPath: (path) =>
path.replace(/^\/static/, '/statics'),
})
)mimes
mimes를 사용해 MIME 타입을 추가할 수 있다:
app.get(
'/static/*',
serveStatic({
mimes: {
m3u8: 'application/vnd.apple.mpegurl',
ts: 'video/mp2t',
},
})
)onFound
요청한 파일을 찾았을 때의 처리를 onFound로 지정할 수 있다:
app.get(
'/static/*',
serveStatic({
// ...
onFound: (_path, c) => {
c.header('Cache-Control', `public, immutable, max-age=31536000`)
},
})
)onNotFound
요청한 파일을 찾을 수 없을 때 onNotFound를 사용해 처리 방식을 지정할 수 있다:
app.get(
'/static/*',
serveStatic({
onNotFound: (path, c) => {
console.log(`${path} is not found, you access ${c.req.path}`)
},
})
)precompressed 옵션
precompressed 옵션은 .br이나 .gz와 같은 확장자를 가진 파일이 있는지 확인하고, Accept-Encoding 헤더를 기반으로 해당 파일을 제공한다. 이 옵션은 Brotli를 가장 우선시하고, 그다음 Zstd, Gzip 순으로 우선순위를 둔다. 사용 가능한 압축 파일이 없으면 원본 파일을 제공한다.
app.get(
'/static/*',
serveStatic({
precompressed: true,
})
)Deno Deploy
Deno Deploy는 Deno를 위한 엣지 런타임 플랫폼이다. 이 플랫폼을 통해 전 세계 어디서나 애플리케이션을 배포할 수 있다.
Hono도 Deno Deploy를 지원한다. 자세한 내용은 공식 문서를 참고한다.
테스트
Deno에서 애플리케이션을 테스트하는 것은 간단하다. Deno.test를 사용해 테스트를 작성하고, @std/assert에서 제공하는 assert나 assertEquals를 활용할 수 있다.
deno add jsr:@std/assertimport { Hono } from 'hono'
import { assertEquals } from '@std/assert'
Deno.test('Hello World', async () => {
const app = new Hono()
app.get('/', (c) => c.text('Please test me'))
const res = await app.request('http://localhost/')
assertEquals(res.status, 200)
})그리고 다음 커맨드를 실행한다:
deno test hello.tsnpm: 스펙
npm:hono도 사용할 수 있다. deno.json을 수정해서 적용한다:
{
"imports": {
"hono": "jsr:@hono/hono"
"hono": "npm:hono"
}
}npm:hono와 jsr:@hono/hono 중 하나를 선택해 사용할 수 있다.
npm:@hono/zod-validator 같은 타사 미들웨어를 타입스크립트 타입 추론과 함께 사용하려면 npm: 스펙을 사용해야 한다.
{
"imports": {
"hono": "npm:hono",
"zod": "npm:zod",
"@hono/zod-validator": "npm:@hono/zod-validator"
}
}