diff --git a/components/UserProfile.tsx b/components/UserProfile.tsx
index 714afd7..ac945a4 100644
--- a/components/UserProfile.tsx
+++ b/components/UserProfile.tsx
@@ -52,7 +52,7 @@ function UserProfile({
}
return (
-
+
{label}
{data[field]}
@@ -122,7 +122,7 @@ function UserProfile({
void) => {
const [isLoading, setIsLoading] = useState(false);
const [previewImage, setPreviewImage] = useState(null);
const fileInputRef = useRef(null);
+ const { showSnackbar } = useSnackbar();
useEffect(() => {
return () => {
@@ -18,24 +26,55 @@ export const useProfileImage = (onImageChange: (url: string) => void) => {
fileInputRef.current?.click();
};
+ // 파일명 바꿔주기
+ const sanitizeFileName = (file: File): File => {
+ // 현재 시간을 이용한 유니크한 파일명 생성
+ const timestamp = new Date().getTime();
+ const randomString = Math.random().toString(36).substring(7);
+ const extension = file.name.split('.').pop()?.toLowerCase() || '';
+ const newFileName = `profile_${timestamp}_${randomString}.${extension}`;
+
+ // 새로운 파일 객체 생성
+ return new File([file], newFileName, { type: file.type });
+ };
+
+ const validateFile = (file: File): boolean => {
+ const validExtensions = ['jpg', 'jpeg', 'png', 'gif'];
+ const extension = file.name.split('.').pop()?.toLowerCase();
+
+ if (!extension || !validExtensions.includes(extension)) {
+ showSnackbar(NOT_ALLOWED_TYPE_MESSAGE, 'fail');
+ return false;
+ }
+
+ if (file.size > MAX_FILE_SIZE) {
+ showSnackbar(SIZE_LIMIT_MESSAGE, 'fail');
+ return false;
+ }
+
+ return true;
+ };
+
const handleFileChange = async (e: React.ChangeEvent) => {
const file = e.target.files?.[0];
if (!file) return;
- const fileExtension = file.name.toLowerCase().split('.').pop();
- if (fileExtension === 'svg') {
- alert('SVG 파일은 업로드할 수 없습니다.');
- e.target.value = '';
+ // 파일 유효성 검증
+ if (!validateFile(file)) {
+ if (fileInputRef.current) {
+ fileInputRef.current.value = '';
+ }
return;
}
- const objectUrl = URL.createObjectURL(file);
+ const sanitizedFile = sanitizeFileName(file);
+ const objectUrl = URL.createObjectURL(sanitizedFile);
setPreviewImage(objectUrl);
setIsLoading(true);
try {
const formData = new FormData();
- formData.append('image', file);
+ formData.append('image', sanitizedFile);
const response = await instance.post<{ url: string }>(
'/images/upload',
@@ -47,11 +86,30 @@ export const useProfileImage = (onImageChange: (url: string) => void) => {
}
);
onImageChange(response.data.url);
- } catch (error) {
- alert('이미지 업로드에 실패했습니다.');
+ } catch (error: unknown) {
+ // 서버 에러 상세 처리
+ let errorMessage = '이미지 업로드에 실패했습니다.';
+
+ if (error instanceof AxiosError && error.response) {
+ // HTTP 에러 상태 코드별 처리
+ switch (error.response.status) {
+ case 400:
+ errorMessage = '잘못된 파일 형식입니다.';
+ break;
+ case 500:
+ errorMessage =
+ '서버 오류가 발생했습니다. 잠시 후 다시 시도해주세요.';
+ break;
+ }
+ }
+
+ showSnackbar(errorMessage, 'fail');
setPreviewImage(null);
} finally {
setIsLoading(false);
+ if (fileInputRef.current) {
+ fileInputRef.current.value = ''; // 입력 필드 초기화
+ }
}
};