From b804db993b4e9b0d29f622e495587e00caca3a9d Mon Sep 17 00:00:00 2001 From: dasosann Date: Mon, 30 Mar 2026 14:47:10 +0900 Subject: [PATCH 1/5] =?UTF-8?q?feat:=20Select=20=EC=95=A8=EB=B2=94=20?= =?UTF-8?q?=EC=8B=9C=20=EC=9D=B4=EB=AA=A8=EC=A7=80=20=EB=A1=9C=EB=94=A9=20?= =?UTF-8?q?=EC=8B=9C=EA=B0=84=20=ED=86=B5=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/SelectAlbumBody.tsx | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/feature/album-select/components/SelectAlbumBody.tsx b/src/feature/album-select/components/SelectAlbumBody.tsx index 74cea9dd..b87d5809 100644 --- a/src/feature/album-select/components/SelectAlbumBody.tsx +++ b/src/feature/album-select/components/SelectAlbumBody.tsx @@ -19,6 +19,9 @@ type ImageWithUrl = { isOversized: boolean; }; +const MIN_WAIT_TIME_MS = 3000; +const PER_PHOTO_PROCESSING_TIME_MS = 1000; + export default function SelectAlbumBody() { const isUploaded = useUploadingStore((state) => state.isUploaded); const handleUpload = async () => { @@ -62,7 +65,7 @@ export default function SelectAlbumBody() { const { mutate: reportFailed } = useReportFailed(); const { mutate: uploadMutate } = usePresignedAndUploadToNCP({ - onSuccess: (result) => { + onSuccess: async (result) => { if (result.failed > 0) { Toast.alert(`${result.failed}개 파일 업로드에 실패했어요`); if ( @@ -73,13 +76,26 @@ export default function SelectAlbumBody() { } } else { revokeAllObjectUrls(); - useUploadingStore.getState().setUploaded(true); - useUploadingStore.getState().setUploadedCount(result.success); - router.replace(`/album/detail/${albumId}`); + try { + useUploadingStore.getState().setUploaded(true); + useUploadingStore.getState().setUploadedCount(result.success); + + // 백엔드 이미지 처리를 위해 인위적인 대기 시간 추가 (handleFileUpload와 동일) + const waitTime = Math.max( + MIN_WAIT_TIME_MS, + result.success * PER_PHOTO_PROCESSING_TIME_MS, + ); + await new Promise((resolve) => setTimeout(resolve, waitTime)); + + router.replace(`/album/detail/${albumId}`); + } finally { + useUploadingStore.getState().setUploaded(false); + } } }, onError: (e) => { revokeAllObjectUrls(); + useUploadingStore.getState().setUploaded(false); console.error('에러 발생', e); alert('사진을 업로드하는 중 오류가 발생했습니다. 다시 시도해주세요.'); }, From f2f703ae226d8bfa842127ad121312b3ac34aff7 Mon Sep 17 00:00:00 2001 From: dasosann Date: Mon, 30 Mar 2026 14:57:07 +0900 Subject: [PATCH 2/5] =?UTF-8?q?feat:=20=EC=83=81=EC=88=98=20=EB=B6=84?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../album-select/components/SelectAlbumBody.tsx | 14 +++++--------- src/feature/create-album/utils/handleFileUpload.ts | 8 +++----- src/global/constants/upload.ts | 2 ++ src/global/utils/upload.ts | 13 +++++++++++++ 4 files changed, 23 insertions(+), 14 deletions(-) create mode 100644 src/global/constants/upload.ts create mode 100644 src/global/utils/upload.ts diff --git a/src/feature/album-select/components/SelectAlbumBody.tsx b/src/feature/album-select/components/SelectAlbumBody.tsx index b87d5809..d94a14c8 100644 --- a/src/feature/album-select/components/SelectAlbumBody.tsx +++ b/src/feature/album-select/components/SelectAlbumBody.tsx @@ -12,6 +12,8 @@ import { useUploadingStore } from '@/store/useUploadingStore'; import { useParams, useRouter } from 'next/navigation'; import { useEffect, useMemo, useState } from 'react'; +import { calculateUploadWaitTime } from '@/global/utils/upload'; + type ImageWithUrl = { id: string; file: File; @@ -19,9 +21,6 @@ type ImageWithUrl = { isOversized: boolean; }; -const MIN_WAIT_TIME_MS = 3000; -const PER_PHOTO_PROCESSING_TIME_MS = 1000; - export default function SelectAlbumBody() { const isUploaded = useUploadingStore((state) => state.isUploaded); const handleUpload = async () => { @@ -64,7 +63,7 @@ export default function SelectAlbumBody() { const { mutate: reportFailed } = useReportFailed(); - const { mutate: uploadMutate } = usePresignedAndUploadToNCP({ + const { mutate: uploadMutate, isPending } = usePresignedAndUploadToNCP({ onSuccess: async (result) => { if (result.failed > 0) { Toast.alert(`${result.failed}개 파일 업로드에 실패했어요`); @@ -81,10 +80,7 @@ export default function SelectAlbumBody() { useUploadingStore.getState().setUploadedCount(result.success); // 백엔드 이미지 처리를 위해 인위적인 대기 시간 추가 (handleFileUpload와 동일) - const waitTime = Math.max( - MIN_WAIT_TIME_MS, - result.success * PER_PHOTO_PROCESSING_TIME_MS, - ); + const waitTime = calculateUploadWaitTime(result.success); await new Promise((resolve) => setTimeout(resolve, waitTime)); router.replace(`/album/detail/${albumId}`); @@ -241,7 +237,7 @@ export default function SelectAlbumBody() { diff --git a/src/feature/create-album/utils/handleFileUpload.ts b/src/feature/create-album/utils/handleFileUpload.ts index 6ad8eeb5..7035c645 100644 --- a/src/feature/create-album/utils/handleFileUpload.ts +++ b/src/feature/create-album/utils/handleFileUpload.ts @@ -1,6 +1,8 @@ import { EP } from '@/global/api/ep'; import { presignedAndUploadToNCP } from '@/global/api/presignedAndUploadToNCP'; import Toast from '@/global/components/toast/Toast'; +import { MIN_WAIT_TIME_MS } from '@/global/constants/upload'; +import { calculateUploadWaitTime } from '@/global/utils/upload'; import { useUploadingStore } from '@/store/useUploadingStore'; import { QueryClient } from '@tanstack/react-query'; import { ChangeEvent } from 'react'; @@ -10,9 +12,6 @@ import { saveFilesToStore } from './saveFilesToStore'; import { sortImagesByDate } from './sortImagesByDate'; import { validateUpload } from './validateUpload'; -const MIN_WAIT_TIME_MS = 3000; -const PER_PHOTO_PROCESSING_TIME_MS = 1000; - async function refreshAlbumQueries( queryClient: QueryClient, albumId: string, @@ -100,8 +99,7 @@ export async function handleFileUpload( // 백엔드 이미지 처리를 위한 추가 대기 시간 // 기본 로딩 애니메이션을 위해 최소 대기 시간을 유지합니다. - const backendProcessingTime = files.length * PER_PHOTO_PROCESSING_TIME_MS; - const waitTime = Math.max(MIN_WAIT_TIME_MS, backendProcessingTime); + const waitTime = calculateUploadWaitTime(files.length); await new Promise((resolve) => setTimeout(resolve, waitTime)); if (options?.queryClient) { diff --git a/src/global/constants/upload.ts b/src/global/constants/upload.ts new file mode 100644 index 00000000..a93937a4 --- /dev/null +++ b/src/global/constants/upload.ts @@ -0,0 +1,2 @@ +export const MIN_WAIT_TIME_MS = 3000; +export const PER_PHOTO_PROCESSING_TIME_MS = 1000; diff --git a/src/global/utils/upload.ts b/src/global/utils/upload.ts new file mode 100644 index 00000000..ff4e3986 --- /dev/null +++ b/src/global/utils/upload.ts @@ -0,0 +1,13 @@ +import { + MIN_WAIT_TIME_MS, + PER_PHOTO_PROCESSING_TIME_MS, +} from '../constants/upload'; + +/** + * 전송 완료 후 백엔드 이미지 처리를 위해 필요한 대기 시간을 계산합니다. + * @param fileCount 업로드된 파일 개수 + * @returns 대기 시간 (ms) + */ +export const calculateUploadWaitTime = (fileCount: number): number => { + return Math.max(MIN_WAIT_TIME_MS, fileCount * PER_PHOTO_PROCESSING_TIME_MS); +}; From 73ca7289d54db14e78302d6587901cf052753fa3 Mon Sep 17 00:00:00 2001 From: dasosann Date: Mon, 30 Mar 2026 14:57:33 +0900 Subject: [PATCH 3/5] fix: format --- src/feature/album-select/components/SelectAlbumBody.tsx | 4 +++- src/global/utils/upload.ts | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/feature/album-select/components/SelectAlbumBody.tsx b/src/feature/album-select/components/SelectAlbumBody.tsx index d94a14c8..09c4f350 100644 --- a/src/feature/album-select/components/SelectAlbumBody.tsx +++ b/src/feature/album-select/components/SelectAlbumBody.tsx @@ -237,7 +237,9 @@ export default function SelectAlbumBody() { diff --git a/src/global/utils/upload.ts b/src/global/utils/upload.ts index ff4e3986..d9e8606a 100644 --- a/src/global/utils/upload.ts +++ b/src/global/utils/upload.ts @@ -1,6 +1,6 @@ import { - MIN_WAIT_TIME_MS, - PER_PHOTO_PROCESSING_TIME_MS, + MIN_WAIT_TIME_MS, + PER_PHOTO_PROCESSING_TIME_MS, } from '../constants/upload'; /** From 96972d9e3ac94dc8137c98d03e69c0b5ba387d6e Mon Sep 17 00:00:00 2001 From: dasosann Date: Mon, 30 Mar 2026 15:06:44 +0900 Subject: [PATCH 4/5] =?UTF-8?q?fix:=20=EB=8C=80=EA=B8=B0=20=EC=8B=9C?= =?UTF-8?q?=EA=B0=84=20=EB=B3=B4=EC=88=98=EC=A0=81=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EC=A6=9D=EA=B0=80=EC=8B=9C=ED=82=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/global/utils/upload.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/global/utils/upload.ts b/src/global/utils/upload.ts index d9e8606a..cff522f8 100644 --- a/src/global/utils/upload.ts +++ b/src/global/utils/upload.ts @@ -1,6 +1,6 @@ import { - MIN_WAIT_TIME_MS, - PER_PHOTO_PROCESSING_TIME_MS, + MIN_WAIT_TIME_MS, + PER_PHOTO_PROCESSING_TIME_MS, } from '../constants/upload'; /** @@ -9,5 +9,5 @@ import { * @returns 대기 시간 (ms) */ export const calculateUploadWaitTime = (fileCount: number): number => { - return Math.max(MIN_WAIT_TIME_MS, fileCount * PER_PHOTO_PROCESSING_TIME_MS); + return MIN_WAIT_TIME_MS + fileCount * PER_PHOTO_PROCESSING_TIME_MS; }; From 8a3992c7475f2021791fb1246578525da9de3a50 Mon Sep 17 00:00:00 2001 From: dasosann Date: Mon, 30 Mar 2026 15:08:02 +0900 Subject: [PATCH 5/5] format: prettier --- src/global/utils/upload.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/global/utils/upload.ts b/src/global/utils/upload.ts index cff522f8..9e2508ee 100644 --- a/src/global/utils/upload.ts +++ b/src/global/utils/upload.ts @@ -1,6 +1,6 @@ import { - MIN_WAIT_TIME_MS, - PER_PHOTO_PROCESSING_TIME_MS, + MIN_WAIT_TIME_MS, + PER_PHOTO_PROCESSING_TIME_MS, } from '../constants/upload'; /**