본문 바로가기
Backend2026년 4월 21일9분 읽기

Hono Framework 실전 — Edge·Bun·Node·Cloudflare Workers 모두 지원

YS
김영삼
조회 1
Hono Framework 실전 — Edge·Bun·Node·Cloudflare Workers 모두 지원

핵심 요약

Hono는 일본 개발자가 만든 초경량(11KB) 웹 프레임워크. Express처럼 단순한 API + 모든 JS 런타임 지원 + 매우 빠름. 2026년 4월 기준 GitHub 별 25만 개. Cloudflare Workers·Vercel Edge·AWS Lambda 등 엣지 런타임의 사실상 표준.

  • 11KB 번들 (zero dependency)
  • Edge·Bun·Deno·Node·Workerd 모두 지원
  • TypeScript 1급 — RPC 타입 자동 추론
  • HTTP 요청 처리 ~120K req/s (Bun 기준)

1. 기본 사용

import { Hono } from 'hono'

const app = new Hono()

app.get('/', (c) => c.text('Hello!'))
app.get('/users/:id', (c) => {
  const id = c.req.param('id')
  return c.json({ id })
})

export default app

이 코드 그대로 Bun·Cloudflare Workers·Vercel Edge에서 동작. 런타임별 어댑터만 다름.

2. 미들웨어

import { logger } from 'hono/logger'
import { cors } from 'hono/cors'
import { jwt } from 'hono/jwt'

app.use('*', logger())
app.use('/api/*', cors())
app.use('/api/admin/*', jwt({ secret: process.env.JWT_SECRET! }))

cors·jwt·rate-limit·etag·compression 등 자주 쓰는 미들웨어 모두 내장.

3. RPC — 타입 안전한 API 호출

Hono의 가장 강력한 기능. 서버 정의가 자동으로 클라이언트 타입이 됨.

// server.ts
import { Hono } from 'hono'
import { hc } from 'hono/client'

const route = app.post('/api/login', async (c) => {
  const { email, password } = await c.req.json<{ email: string; password: string }>()
  return c.json({ token: '...', userId: 123 })
})

export type AppType = typeof route

// client.ts
import { hc } from 'hono/client'
import type { AppType } from './server'

const client = hc<AppType>('http://localhost:3000')
const res = await client.api.login.$post({
  json: { email: 'a@b.com', password: '...' }
  // 타입 자동 — 빠진 필드는 컴파일 에러
})
const data = await res.json()
// data: { token: string; userId: number } — 자동 추론

tRPC와 비슷한 타입 안전성을 zero-config로.

4. 런타임별 배포

Bun

// index.ts
import app from './server'
Bun.serve({ port: 3000, fetch: app.fetch })

Cloudflare Workers

// wrangler.toml
name = "my-app"
main = "src/index.ts"

// src/index.ts
import app from './server'
export default app

Vercel Edge

// app/api/[[...path]]/route.ts
import { handle } from 'hono/vercel'
import app from '@/server'
export const runtime = 'edge'
export const GET = handle(app)
export const POST = handle(app)

Node.js

import { serve } from '@hono/node-server'
import app from './server'
serve({ fetch: app.fetch, port: 3000 })

5. Validation — Zod 통합

import { zValidator } from '@hono/zod-validator'
import { z } from 'zod'

const schema = z.object({
  email: z.string().email(),
  age: z.number().int().min(18)
})

app.post(
  '/api/users',
  zValidator('json', schema),
  (c) => {
    const data = c.req.valid('json') // 타입 자동
    return c.json({ ok: true })
  }
)

6. 성능 비교 (Bun 런타임 기준)

프레임워크req/s지연 (p99)번들
Hono185K3ms11KB
Elysia192K3ms32KB
Fastify78K5ms180KB
Express32K11ms270KB

7. 실전 — 풀스택 예시

Cloudflare Workers + D1 + Hono로 만드는 30줄 풀스택:

import { Hono } from 'hono'

type Bindings = { DB: D1Database }
const app = new Hono<{ Bindings: Bindings }>()

app.get('/api/posts', async (c) => {
  const { results } = await c.env.DB.prepare('SELECT * FROM posts ORDER BY id DESC LIMIT 20').all()
  return c.json(results)
})

app.post('/api/posts', async (c) => {
  const { title, content } = await c.req.json()
  await c.env.DB.prepare('INSERT INTO posts (title, content) VALUES (?, ?)').bind(title, content).run()
  return c.json({ ok: true })
})

export default app

실무 운영 노하우

  • logger 미들웨어는 production에서 제거 (CPU 낭비)
  • cors는 명시적 origin 화이트리스트 사용 (와일드카드 금지)
  • JWT 검증은 정적 시크릿보다 KV·D1에서 동적 가져오기
  • 큰 응답은 streaming (c.streamText)로 메모리 절약
  • 에러 핸들링: app.onError 전역 등록

자주 묻는 질문

Express에서 마이그레이션 부담은?

가벼움. req/res가 c (context) 하나로 통합. 미들웨어 형태는 거의 동일. 약 1~2일이면 작은 프로젝트 마이그레이션 가능.

tRPC와 Hono RPC 차이?

tRPC는 RPC 전용, 더 풍부한 기능. Hono는 일반 HTTP + RPC 옵션. 단순함이 우선이면 Hono.

Edge 환경에서 Prisma 사용?

Prisma Accelerate 또는 Driver Adapter (D1·Neon·PlanetScale) 필요. 기본 Prisma는 Edge 호환 안 됨.

댓글 0

아직 댓글이 없습니다.
Ctrl+Enter로 등록