기존 에러관리 코드
// 커스텀 에러 클래스들
import { ValidationMessages } from "@/types/authTypes";
import convertAuthSupabaseErrorToKorean from "./convertAuthSupabaseErrorToKorean";
import convertStorageSupabaseErrorToKorean from "./convertStorageSupabaseErrorToKorean";
export class ApiError extends Error {
constructor(public status: number, message: string) {
super(message);
this.name = "ApiError";
}
}
export class SupabaseAuthError extends Error {
code: string;
constructor(code: string, message: string) {
super(message);
this.code = convertAuthSupabaseErrorToKorean(code);
this.name = "SupabaseAuthError";
// 프로토타입 체인 유지를 위한 설정
Object.setPrototypeOf(this, SupabaseAuthError.prototype);
}
toJSON() {
return {
name: this.name,
message: this.message,
code: this.code,
};
}
}
export class SupabaseStorageError extends Error {
constructor(public code: string, message: string) {
super(message);
this.code = convertStorageSupabaseErrorToKorean(code);
this.name = "SupabaseStorageError";
}
}
export class ValidationError extends Error {
constructor(public fieldErrors: ValidationMessages, public code?: string) {
super(Object.values(fieldErrors)[0]);
this.name = "ValidationError";
}
}
export class PasswordError extends Error {
constructor(message: string, public code?: string) {
super(message);
this.name = "PasswordError";
}
}
에러를 효율적으로 관리하기 위해 class를 만들어 구현하려고 했는데
이 때문에 오히려 점점 복잡해 졌다
결정적으로 server에서 client로 넘길 때 class를 넘기는 것은 안되기 때문에 고치기로 결정
전달 가능한 데이터 타입:
✅ Plain objects ({})
✅ Arrays ([])
✅ Numbers
✅ Strings
✅ Booleans
✅ null
✅ undefined
❌ Class instances
❌ Functions
❌ Dates (직렬화 필요)
❌ Regular Expressions
❌ Maps/Sets
전달 가능한 데이터 타입은 이와 같다고 한다
바뀐 방법은
import { AuthError, PostgrestError } from "@supabase/supabase-js";
interface ValidationError extends Error {
name: "ValidationError";
fieldErrors: Record<string, string[]>;
}
interface PasswordError extends Error {
name: "PasswordError";
}
export function isValidationError(error: ApiError): error is ValidationError {
return error.name === "ValidationError";
}
export function isAuthError(error: ApiError): error is AuthError {
return error.name === "AuthError";
}
export function isPostgrestError(error: ApiError): error is PostgrestError {
return error.name === "PostgrestError";
}
export function isPasswordError(error: ApiError): error is PasswordError {
return error.name === "PasswordError";
}
export type ApiError =
| ValidationError
| AuthError
| PostgrestError
| PasswordError;
이렇게 타입스크립트로 관리하고
하나의 ApiError로 묶어서 관리하기
또한 타입가드들도 생성하여 안정성을 더했다
이렇게 하면 기존의 했던 방법은 요청마다 클래스를 구분해서 넣어줘야 하지만
이 방법은 ApiError로 퉁 칠수 있어서 더욱 편해졌다 또한
import convertAuthSupabaseErrorToKorean from "@/error/convertAuthSupabaseErrorToKorean";
import convertStorageSupabaseErrorToKorean from "@/error/convertStorageSupabaseErrorToKorean";
import {
ApiError,
isAuthError,
isPasswordError,
isPostgrestError,
isValidationError,
} from "@/types/error";
function formatApiErrorForUser(error: ApiError) {
if (isValidationError(error)) {
return {
name: "ValidationError",
message: "입력 값을 확인해주세요.",
fieldErrors: error.fieldErrors,
};
} else if (isAuthError(error)) {
console.log(error);
return {
name: "AuthError",
message:
convertAuthSupabaseErrorToKorean(error.code || "") || error.message,
};
} else if (isPostgrestError(error)) {
return {
name: "PostgrestError",
message: convertStorageSupabaseErrorToKorean(error.code) || error.message,
};
} else if (isPasswordError(error)) {
return {
name: "PasswordError",
message: error.message,
};
} else {
return {
name: "UnknownError",
message: "예기치 않은 오류가 발생했습니다.",
};
}
}
export default formatApiErrorForUser;
통합되지 않은 에러 타입들로 인한 장애와
api에 나오는 메시지는 영어라는 문제를 해결하기 위해
handler를 사용해 불편한 사항들을 모두 해결하였다.
'개발 > NEXTJS' 카테고리의 다른 글
| 모달창에서 스크롤 방지 (0) | 2025.02.10 |
|---|---|
| error.tsx 사용 (0) | 2025.02.10 |
| 사용자 avata image 변경했을 때 (0) | 2025.01.31 |
| 좋은 블로그 글 모음 (1) | 2025.01.27 |
| nextjs에서 swr과 react query 비교 (0) | 2025.01.27 |