tRPC 에러 처리

tRPC 에러 처리 (Error Handling)

tRPC procedure에서 에러가 나면 클라이언트에 error 프로퍼티를 가진 객체가 전달돼요. 그 안에 에러를 다루는 데 필요한 정보가 모두 담겨 있어요. 에러 코드와 HTTP 상태 코드의 대응을 알면 클라이언트·서버 양쪽에서 일관되게 처리할 수 있어요.

출처: https://trpc.io/docs/server/error-handling

예를 들어 입력 검증이 실패했을 때 이런 응답이 와요.

{
  "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.stackisDevtrue일 때만 포함돼요. 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가 담긴 객체가 전달돼요.

더 알아보기