diff --git a/app/error.tsx b/app/error.tsx
new file mode 100644
index 00000000..0c788e08
--- /dev/null
+++ b/app/error.tsx
@@ -0,0 +1,44 @@
+'use client';
+
+import { useRouter } from 'next/navigation';
+import { startTransition } from 'react';
+import Button from '@/shared/ui/button';
+
+export default function ErrorBoundary({
+ error,
+ reset,
+}: {
+ error: Error;
+ reset: () => void;
+}) {
+ const router = useRouter();
+
+ return (
+
+
+
+ 서비스 이용에 불편드려 죄송합니다.
+
+
+
+ 에러가 발생하여 페이지를 표시할 수 없습니다.
+
+
+ 잠시 뒤에 다시 시도해주세요.
+
+
+
+
+
+ );
+}
diff --git a/src/entities/review/model/use-review-query.ts b/src/entities/review/model/use-review-query.ts
index 26d994a0..cbaf66a3 100644
--- a/src/entities/review/model/use-review-query.ts
+++ b/src/entities/review/model/use-review-query.ts
@@ -9,6 +9,7 @@ import {
UserPositiveKeywordsRequest,
} from '@/entities/review/api/review-types';
import { getKoreaDate } from '@/shared/lib/time';
+import { isApiError } from '@/shared/tanstack-query/api-error';
import {
addStudyReview,
getUserPositiveKeywords,
@@ -32,6 +33,15 @@ export const useAddStudyReviewMutation = () => {
// todo: 모달로 변경
alert('후기 작성이 완료되었습니다.');
},
+ onError: (error) => {
+ if (isApiError(error)) {
+ if (error.errorCode === 'CMM001') {
+ alert('이미 후기를 작성했습니다.');
+ } else if (error.errorCode === 'CMM003') {
+ alert('스터디 또는 스터디 멤버가 존재하지 않습니다.');
+ }
+ }
+ },
});
};
diff --git a/src/entities/user/model/use-user-profile-query.ts b/src/entities/user/model/use-user-profile-query.ts
index 38d00741..bbec6c9f 100644
--- a/src/entities/user/model/use-user-profile-query.ts
+++ b/src/entities/user/model/use-user-profile-query.ts
@@ -6,6 +6,7 @@ import {
} from '@/entities/user/api/get-user-profile';
import type { GetUserProfileResponse } from '@/entities/user/api/types';
import { hashValue } from '@/shared/lib/hash';
+import { isApiError } from '@/shared/tanstack-query/api-error';
export const useUserProfileQuery = (memberId: number) => {
return useQuery({
@@ -45,10 +46,18 @@ export const usePatchAutoMatchingMutation = () => {
return { prev };
},
- onError: (_err, { memberId }, ctx) => {
+ onError: (error, { memberId }, ctx) => {
if (ctx?.prev) {
qc.setQueryData(['userProfile', memberId], ctx.prev);
}
+
+ if (isApiError(error)) {
+ if (error.errorCode === 'MEM004') {
+ alert('아직 스터디를 신청하지 않았습니다. 먼저 스터디 신청해주세요.');
+ } else if (error.errorCode === 'MEM001') {
+ alert('회원 정보가 존재하지 않습니다.');
+ }
+ }
},
onSuccess: async (_data, { memberId, autoMatching }) => {
diff --git a/src/features/auth/model/use-auth-mutation.ts b/src/features/auth/model/use-auth-mutation.ts
index b81c0725..712e67ff 100644
--- a/src/features/auth/model/use-auth-mutation.ts
+++ b/src/features/auth/model/use-auth-mutation.ts
@@ -5,6 +5,7 @@ import { useMutation, useQueryClient } from '@tanstack/react-query';
import { useRouter } from 'next/navigation';
import { logout, signUp, uploadProfileImage } from '@/features/auth/api/auth';
import { hashValue } from '@/shared/lib/hash';
+import { isApiError } from '@/shared/tanstack-query/api-error';
import { deleteCookie, getCookie } from '@/shared/tanstack-query/cookie';
import { SignUpResponse } from './types';
@@ -16,6 +17,13 @@ export const useSignUpMutation = () => {
{ name: string; imageExtension: string }
>({
mutationFn: (data: any) => signUp(data),
+ onError: (error) => {
+ if (isApiError(error)) {
+ if (error.errorCode === 'DUPLICATE_MEMBER') {
+ alert('이미 가입된 회원입니다.');
+ }
+ }
+ },
});
};
diff --git a/src/features/my-page/model/use-update-user-profile-mutation.ts b/src/features/my-page/model/use-update-user-profile-mutation.ts
index d49cdaf7..5b34e273 100644
--- a/src/features/my-page/model/use-update-user-profile-mutation.ts
+++ b/src/features/my-page/model/use-update-user-profile-mutation.ts
@@ -1,5 +1,6 @@
import { useMutation, useQuery } from '@tanstack/react-query';
import { useRouter } from 'next/navigation';
+import { isApiError } from '@/shared/tanstack-query/api-error';
import {
UpdateUserProfileInfoRequest,
UpdateUserProfileRequest,
@@ -24,6 +25,15 @@ export const useUpdateUserProfileMutation = (memberId: number) => {
onSuccess: () => {
router.refresh();
},
+ onError: (error) => {
+ if (isApiError(error)) {
+ if (error.errorCode === 'MPR001') {
+ alert('관심사가 중복됐습니다.');
+ } else if (error.errorCode === 'MEM001') {
+ alert('회원 정보가 존재하지 않습니다.');
+ }
+ }
+ },
});
};