Node.js
Node.js는 오픈 소스이며 크로스 플랫폼을 지원하는 JavaScript 런타임 환경이다.
Hono는 처음부터 Node.js를 위해 설계되지 않았다. 하지만 Node.js Adapter를 사용하면 Node.js에서도 실행할 수 있다.
INFO
Node.js 18.x 이상 버전에서 동작한다. 구체적으로 필요한 Node.js 버전은 다음과 같다:
- 18.x => 18.14.1 이상
- 19.x => 19.7.0 이상
- 20.x => 20.0.0 이상
기본적으로 각 주요 릴리스의 최신 버전을 사용하면 된다.
1. 설정
Node.js를 위한 스타터 프로젝트를 사용할 수 있다. "create-hono" 커맨드로 프로젝트를 시작한다. 이 예제에서는 nodejs 템플릿을 선택한다.
npm create hono@latest my-appyarn create hono my-apppnpm create hono my-appbun create hono@latest my-appdeno init --npm hono my-appmy-app 디렉터리로 이동한 후 의존성을 설치한다.
cd my-app
npm icd my-app
yarncd my-app
pnpm icd my-app
bun i2. Hello World
src/index.ts 파일을 수정한다:
import { serve } from '@hono/node-server'
import { Hono } from 'hono'
const app = new Hono()
app.get('/', (c) => c.text('Hello Node.js!'))
serve(app)3. 실행
로컬에서 개발 서버를 실행한다. 웹 브라우저에서 http://localhost:3000에 접속한다.
npm run devyarn devpnpm dev포트 번호 변경하기
port 옵션을 사용해 포트 번호를 지정할 수 있다.
serve({
fetch: app.fetch,
port: 8787,
})Node.js API 직접 사용하기
c.env.incoming과 c.env.outgoing을 통해 Node.js API에 접근할 수 있다.
import { Hono } from 'hono'
import { serve, type HttpBindings } from '@hono/node-server'
// HTTP2를 사용한다면 `Http2Bindings`를 사용
type Bindings = HttpBindings & {
/* ... */
}
const app = new Hono<{ Bindings: Bindings }>()
app.get('/', (c) => {
return c.json({
remoteAddress: c.env.incoming.socket.remoteAddress,
})
})
serve(app)정적 파일 제공하기
serveStatic을 사용하면 로컬 파일 시스템에서 정적 파일을 제공할 수 있다. 예를 들어, 디렉터리 구조가 다음과 같다고 가정해 보자:
./
├── favicon.ico
├── index.ts
└── static
├── hello.txt
└── image.png/static/* 경로로 접근이 들어오면 ./static 아래의 파일을 반환하도록 다음과 같이 작성할 수 있다:
import { serveStatic } from '@hono/node-server/serve-static'
app.use('/static/*', serveStatic({ root: './' }))디렉터리 루트에 있는 favicon.ico를 제공하려면 path 옵션을 사용한다:
app.use('/favicon.ico', serveStatic({ path: './favicon.ico' }))/hello.txt 또는 /image.png 경로로 접근이 들어오면 ./static/hello.txt 또는 ./static/image.png 파일을 반환하도록 다음과 같이 설정할 수 있다:
app.use('*', serveStatic({ root: './static' }))rewriteRequestPath
http://localhost:3000/static/*를 ./statics로 매핑하려면 rewriteRequestPath 옵션을 사용한다.
app.get(
'/static/*',
serveStatic({
root: './',
rewriteRequestPath: (path) =>
path.replace(/^\/static/, '/statics'),
})
)http2
Hono를 Node.js http2 서버에서 실행할 수 있다.
암호화되지 않은 HTTP/2
import { createServer } from 'node:http2'
const server = serve({
fetch: app.fetch,
createServer,
})암호화된 HTTP/2
import { createSecureServer } from 'node:http2'
import { readFileSync } from 'node:fs'
const server = serve({
fetch: app.fetch,
createServer: createSecureServer,
serverOptions: {
key: readFileSync('localhost-privkey.pem'),
cert: readFileSync('localhost-cert.pem'),
},
})Dockerfile
다음은 Dockerfile 예제이다.
FROM node:20-alpine AS base
FROM base AS builder
RUN apk add --no-cache gcompat
WORKDIR /app
COPY package*json tsconfig.json src ./
RUN npm ci && \
npm run build && \
npm prune --production
FROM base AS runner
WORKDIR /app
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 hono
COPY --from=builder --chown=hono:nodejs /app/node_modules /app/node_modules
COPY --from=builder --chown=hono:nodejs /app/dist /app/dist
COPY --from=builder --chown=hono:nodejs /app/package.json /app/package.json
USER hono
EXPOSE 3000
CMD ["node", "/app/dist/index.js"]이 작업을 수행하기 전에 다음 단계를 미리 진행해야 한다.
tsconfig.json의compilerOptions섹션에"outDir": "./dist"를 추가한다.tsconfig.json에"exclude": ["node_modules"]를 추가한다.package.json의script섹션에"build": "tsc"를 추가한다.npm install typescript --save-dev를 실행한다.package.json에"type": "module"을 추가한다.