fix: 이미지 업로드 실패 사유를 화면에 남긴다
업로드가 실패하면 Server Action이 사유를 버리고 "이미지를 업로드하지 못했습니다."만 돌려줘, 확장자 거부인지 용량 초과인지 저장소 설정이 없는 것인지 화면에서 구분할 수 없었다. 백엔드가 사유를 준 경우에는 괄호로 덧붙이고, 통신 실패일 때만 종전 문구로 떨어진다. 문구를 필드 오류로 옮겨 어느 항목 때문인지도 함께 보이게 했다. BackendRequestError의 code로 두 경우를 가른다 — 통신 실패는 code가 -1(COMMUNICATION_ERROR_CODE)로 고정이고 메시지도 일반화돼 있어 덧붙일 값이 없다. 그래서 그 상수를 export했다. Co-Authored-By: Claude Opus 5
@768b1cf02410c03c7bdffe2ea494cc92a096ab58
--- app/(protected)/(basic)/decoration-items/_actions.ts
+++ app/(protected)/(basic)/decoration-items/_actions.ts
... | ... | @@ -2,6 +2,10 @@ |
| 2 | 2 |
|
| 3 | 3 |
import { revalidatePath } from 'next/cache';
|
| 4 | 4 |
import { verifySession } from '@/lib/auth/dal';
|
| 5 |
+import {
|
|
| 6 |
+ BackendRequestError, |
|
| 7 |
+ COMMUNICATION_ERROR_CODE, |
|
| 8 |
+} from '@/lib/http/backend-fetch'; |
|
| 5 | 9 |
import { fetchCommonCodes } from '@/lib/data/repositories/common-code-repository';
|
| 6 | 10 |
import {
|
| 7 | 11 |
createDecorationItem, |
... | ... | @@ -43,6 +47,15 @@ |
| 43 | 47 |
const SAVE_FAILED_MESSAGE = '저장하지 못했습니다. 잠시 후 다시 시도해 주세요.'; |
| 44 | 48 |
const DELETE_FAILED_MESSAGE = '삭제하지 못했습니다. 잠시 후 다시 시도해 주세요.'; |
| 45 | 49 |
const IMAGE_UPLOAD_FAILED_MESSAGE = '이미지를 업로드하지 못했습니다.'; |
| 50 |
+ |
|
| 51 |
+// 백엔드가 사유를 준 경우(확장자·용량·저장소 설정 등)에는 그 말을 그대로 보여준다. |
|
| 52 |
+// 통신 실패는 사유가 일반화된 문구뿐이라 그때만 위 메시지로 떨어진다. |
|
| 53 |
+function describeUploadFailure(error: unknown): string {
|
|
| 54 |
+ if (error instanceof BackendRequestError && error.code !== COMMUNICATION_ERROR_CODE) {
|
|
| 55 |
+ return `${IMAGE_UPLOAD_FAILED_MESSAGE} (${error.message})`;
|
|
| 56 |
+ } |
|
| 57 |
+ return IMAGE_UPLOAD_FAILED_MESSAGE; |
|
| 58 |
+} |
|
| 46 | 59 |
|
| 47 | 60 |
function readString(formData: FormData, key: string): string {
|
| 48 | 61 |
const value = formData.get(key); |
... | ... | @@ -140,8 +153,8 @@ |
| 140 | 153 |
} |
| 141 | 154 |
try {
|
| 142 | 155 |
imageFileId = await uploadDecorationItemImage(newFile); |
| 143 |
- } catch {
|
|
| 144 |
- return { status: 'error', message: IMAGE_UPLOAD_FAILED_MESSAGE };
|
|
| 156 |
+ } catch (error) {
|
|
| 157 |
+ return { status: 'error', errors: { imageFileId: describeUploadFailure(error) } };
|
|
| 145 | 158 |
} |
| 146 | 159 |
} |
| 147 | 160 |
|
... | ... | @@ -190,8 +203,8 @@ |
| 190 | 203 |
} |
| 191 | 204 |
try {
|
| 192 | 205 |
imageFileId = await uploadDecorationItemImage(newFile); |
| 193 |
- } catch {
|
|
| 194 |
- return { status: 'error', message: IMAGE_UPLOAD_FAILED_MESSAGE };
|
|
| 206 |
+ } catch (error) {
|
|
| 207 |
+ return { status: 'error', errors: { imageFileId: describeUploadFailure(error) } };
|
|
| 195 | 208 |
} |
| 196 | 209 |
} |
| 197 | 210 |
|
--- lib/http/backend-fetch.ts
+++ lib/http/backend-fetch.ts
... | ... | @@ -19,7 +19,7 @@ |
| 19 | 19 |
*/ |
| 20 | 20 |
|
| 21 | 21 |
const REQUEST_TIMEOUT_MS = 10_000; |
| 22 |
-const COMMUNICATION_ERROR_CODE = -1; |
|
| 22 |
+export const COMMUNICATION_ERROR_CODE = -1; |
|
| 23 | 23 |
const COMMUNICATION_ERROR_MESSAGE = |
| 24 | 24 |
'서버와 통신할 수 없습니다. 잠시 후 다시 시도해 주세요.'; |
| 25 | 25 |
|
Add a comment
Delete comment
Once you delete this comment, you won't be able to recover it. Are you sure you want to delete this comment?