타임아웃 미들웨어
타임아웃 미들웨어는 애플리케이션에서 요청 타임아웃을 쉽게 관리할 수 있게 해준다. 요청의 최대 지속 시간을 설정할 수 있으며, 지정된 타임아웃을 초과할 경우 커스텀 오류 응답을 정의할 수도 있다.
Import
ts
import { Hono } from 'hono'
import { timeout } from 'hono/timeout'사용 방법
Timeout Middleware를 기본 설정과 커스텀 설정으로 사용하는 방법은 다음과 같다.
기본 설정
ts
const app = new Hono()
// 5초 타임아웃 적용
app.use('/api', timeout(5000))
// 라우트 처리
app.get('/api/data', async (c) => {
// 라우트 핸들러 로직
return c.json({ data: 'Your data here' })
})커스텀 설정
ts
import { HTTPException } from 'hono/http-exception'
// 커스텀 예외 생성 함수
const customTimeoutException = (context) =>
new HTTPException(408, {
message: `요청이 ${context.req.headers.get(
'Duration'
)}초 후 타임아웃되었습니다. 나중에 다시 시도해 주세요.`,
})
// 정적 예외 메시지
// const customTimeoutException = new HTTPException(408, {
// message: '작업 시간이 초과되었습니다. 나중에 다시 시도해 주세요.'
// });
// 1분 타임아웃과 커스텀 예외 적용
app.use('/api/long-process', timeout(60000, customTimeoutException))
app.get('/api/long-process', async (c) => {
// 긴 작업 시뮬레이션
await new Promise((resolve) => setTimeout(resolve, 61000))
return c.json({ data: 'This usually takes longer' })
})주의사항
타임아웃 지속 시간을 밀리초 단위로 지정할 수 있다. 지정한 시간을 초과하면 미들웨어가 자동으로 Promise를 거부하고 오류를 발생시킬 수 있다.
타임아웃 미들웨어는 스트림과 함께 사용할 수 없다. 따라서
stream.close와setTimeout을 함께 사용한다.
ts
app.get('/sse', async (c) => {
let id = 0
let running = true
let timer: number | undefined
return streamSSE(c, async (stream) => {
timer = setTimeout(() => {
console.log('스트림 타임아웃 도달, 스트림 닫기')
stream.close()
}, 3000) as unknown as number
stream.onAbort(async () => {
console.log('클라이언트가 연결을 닫음')
running = false
clearTimeout(timer)
})
while (running) {
const message = `현재 시간: ${new Date().toISOString()}`
await stream.writeSSE({
data: message,
event: 'time-update',
id: String(id++),
})
await stream.sleep(1000)
}
})
})미들웨어 충돌 문제
미들웨어 순서에 주의해야 한다. 특히 오류 처리나 타이밍 관련 미들웨어를 사용할 때, 타임아웃 미들웨어의 동작에 영향을 줄 수 있다.