Hono: 어디서든 돌아가는 초경량 웹 프레임워크
Express를 대체할 차세대 웹 프레임워크 Hono의 설치부터 라우팅, 미들웨어, 다양한 런타임 배포까지 핵심 기능을 알아봅니다.
Node.js 백엔드를 구축할 때 대부분의 개발자가 가장 먼저 떠올리는 프레임워크는 Express다. 10년 넘게 사실상의 표준 역할을 해왔으니 당연한 일이다. 하지만 Cloudflare Workers, Deno, Bun 같은 새로운 런타임이 등장하면서, Express만으로는 커버하기 어려운 영역이 생겼다.
Hono는 이 문제를 정면으로 해결한다. 이름은 일본어로 "불꽃(炎)"이라는 뜻으로, 이름값을 하듯 빠르고 가볍다.
Hono가 뭔가요?
Hono는 Web Standards 위에 구축된 초경량 웹 프레임워크다. 가장 큰 특징은 하나의 코드로 거의 모든 JavaScript 런타임에서 동작한다 는 점이다.
- Cloudflare Workers
- Deno
- Bun
- Node.js
- AWS Lambda
- Vercel
- Netlify
Express가 Node.js에 종속되어 있는 것과 달리, Hono는 표준 Web API(Request, Response, fetch)를 기반으로 만들어졌기 때문에 런타임을 가리지 않는다.
설치 및 시작
프로젝트를 새로 만들 때는 공식 CLI를 사용하면 편하다.
npm create hono@latest my-app
실행하면 어떤 런타임용 템플릿을 사용할지 선택할 수 있다. Node.js, Cloudflare Workers, Bun 등 다양한 옵션이 나온다.
기존 프로젝트에 추가하고 싶다면 직접 설치하면 된다.
npm install hono
기본 사용법
Express를 써본 적이 있다면 매우 익숙하게 느껴질 것이다.
import { Hono } from 'hono'
const app = new Hono()
app.get('/', (c) => {
return c.text('Hello, Hono!')
})
app.get('/api/posts', (c) => {
return c.json({ posts: [] })
})
export default app
c는 Context 객체로, 요청 정보를 읽고 응답을 생성하는 역할을 한다. c.text(), c.json(), c.html() 등 응답 타입별 헬퍼가 준비되어 있어서 직관적이다.
라우팅
Hono의 라우터는 JavaScript 세계에서 가장 빠르다고 알려져 있다. 내부적으로 RegExpRouter라는 최적화된 라우터를 사용한다.
// 경로 파라미터
app.get('/posts/:id', (c) => {
const id = c.req.param('id')
return c.json({ id })
})
// 그룹 라우팅
const api = new Hono()
api.get('/users', (c) => c.json({ users: [] }))
api.get('/posts', (c) => c.json({ posts: [] }))
app.route('/api', api)
그룹 라우팅을 지원하기 때문에 대규모 API를 구조적으로 관리할 수 있다.
미들웨어
Hono는 배터리가 포함된 프레임워크다. 자주 쓰는 미들웨어가 내장되어 있어서 별도 패키지를 설치할 필요가 없다.
import { Hono } from 'hono'
import { cors } from 'hono/cors'
import { logger } from 'hono/logger'
import { bearerAuth } from 'hono/bearer-auth'
const app = new Hono()
app.use('*', logger())
app.use('/api/*', cors())
app.use('/admin/*', bearerAuth({ token: 'my-secret' }))
CORS, 로깅, 인증, 캐싱, ETag, 압축 등 실무에서 자주 필요한 것들이 모두 내장되어 있다.
TypeScript 지원
Hono의 타입 지원은 단순한 타입 정의 수준을 넘어선다. 라우트 정의에서 요청/응답 타입이 자동으로 추론된다.
const route = app.get('/posts/:id', (c) => {
const id = c.req.param('id') // string으로 자동 추론
return c.json({ id, title: 'Hello' })
})
// 클라이언트에서 타입 안전한 API 호출
import { hc } from 'hono/client'
const client = hc<typeof route>('http://localhost:8787')
const res = await client.posts[':id'].$get({ param: { id: '1' } })
const data = await res.json() // { id: string, title: string }
hono/client를 사용하면 별도의 API 스키마 정의 없이도 서버와 클라이언트 간 타입 안전성을 확보할 수 있다. tRPC와 비슷한 개발 경험을 프레임워크 자체에서 제공하는 셈이다.
Express와 비교하면?
| 항목 | Express | Hono |
|---|---|---|
| 번들 크기 | ~200KB+ 의존성 포함 | ~14KB (hono/tiny) |
| 런타임 지원 | Node.js | 거의 모든 JS 런타임 |
| TypeScript | 별도 @types 필요 | 네이티브 지원 |
| 미들웨어 | 서드파티 의존 | 내장 미들웨어 제공 |
| 타입 안전 클라이언트 | 없음 | hono/client 내장 |
Express가 나쁜 프레임워크라는 뜻은 아니다. 다만 2026년 시점에서 새로운 프로젝트를 시작한다면, 특히 엣지 환경이나 서버리스 배포를 고려하고 있다면 Hono가 더 적합한 선택일 수 있다.
마무리
Hono는 GitHub 스타 수가 4만을 넘었고, 생태계도 빠르게 성장하고 있다. 풀스택 메타 프레임워크인 HonoX도 등장했다.
Express를 잘 쓰고 있다면 당장 바꿀 필요는 없다. 하지만 새 프로젝트를 시작하거나, 엣지 환경에 API를 배포해야 한다면 한 번쯤 써볼 가치가 있다. Web Standards 기반이라 나중에 런타임을 바꾸더라도 코드를 그대로 가져갈 수 있으니까.