tRPC 에러 처리
tRPC 에러 처리 (Error Handling)
tRPC procedure에서 에러가 나면 클라이언트에 error 프로퍼티를 가진 객체가 전달돼요. 그 안에 에러를 다루는 데 필요한 정보가 모두 담겨 있어요. 에러 코드와 HTTP 상태 코드의 대응을 알면 클라이언트·서버 양쪽에서 일관되게 처리할 수 있어요.
예를 들어 입력 검증이 실패했을 때 이런 응답이 와요.
{
"id": null,
"error": {
"message": "\"password\" must be at least 4 characters",
"code": -32600,
"data": {
"code": "BAD_REQUEST",
"httpStatus": 400,
"stack": "...",
"path": "user.changepassword"
}
}
}
기본적으로 error.data.stack은 isDev가 true일 때만 포함돼요. initTRPC.create()는 process.env.NODE_ENV !== 'production'을 기본 isDev로 삼아요. 런타임 간에 결정적 동작이 필요하면 직접 initTRPC.create({ isDev: false })처럼 지정해요.
tRPC가 정의한 에러 코드는 각각 대응하는 HTTP 코드를 가져요. 자주 만나는 것만 보면,
| 코드 | 설명 | HTTP |
|---|---|---|
BAD_REQUEST |
클라이언트 오류로 판단되는 요청 | 400 |
UNAUTHORIZED |
유효한 인증 자격 부족 | 401 |
FORBIDDEN |
접근 권한 없음 | 403 |
NOT_FOUND |
리소스를 찾을 수 없음 | 404 |
CONFLICT |
리소스 현재 상태와 충돌 | 409 |
TOO_MANY_REQUESTS |
레이트 리밋 초과 | 429 |
INTERNAL_SERVER_ERROR |
명시되지 않은 오류 | 500 |
에러에서 HTTP 코드를 추출하고 싶다면 getHTTPStatusCodeFromError 헬퍼를 써요.
import { getHTTPStatusCodeFromError } from '@trpc/server/http';
const error = new TRPCError({ code: 'BAD_REQUEST', message: '...' });
const httpCode = getHTTPStatusCodeFromError(error); // 400
procedure 안에서 의도한 에러를 만들 땐 TRPCError를 던져요. code를 지정하면 그에 맞는 HTTP 상태와 에러 코드로 응답이 나가요. 모든 procedure 에러는 클라이언트로 보내기 전에 onError 메서드를 거쳐요. 여기서 로깅을 하거나 INTERNAL_SERVER_ERROR면 버그 리포트로 보내는 식으로 가로챌 수 있어요. onError에는 error, type(query/mutation/subscription/unknown), path, input, ctx, req가 담긴 객체가 전달돼요.
더 알아보기
- 더 세밀한 에러 필드 제어: Error Formatting
- 서버 사이드 호출에서의 에러 처리 예시: Server Side Calls