버그 해치우기 - 업로드 모달 업로드 오류

정영찬·2023년 7월 3일
0
post-thumbnail

문제 상황

파일을 업로드 하는것에서 조건이 존재하지만, 이 조건을 만족하지 않은 파일을 업로드하면 분명 에러 메시지가 업로드 컴포넌트 하단에 표시되어있어야했다.

  1. 조건을 만족하지 않는 파일을 업로드 했을때 사이트 자체 오류가 발생!
    TypeError: Failed to execute 'createObjectURL' on 'URL': Overload resolution failed.
  2. 온보딩 모달을 세팅하지 않은 상태에서 업로드 모달 취소 버튼 클릭시 모달이 사라지지 않는 현상 발생

1번 문제 분석

  1. TypeError: Failed to execute 'createObjectURL' on 'URL': Overload resolution failed. 이게 무슨 에러임?

URL.createObjectURL({param}) 에서 param에 Blob ,file, MediaSourceObject가 아닌 다른 것을 사용하면 발생하는 오류

라는 것은 현재 작성한 코드에서 imageUrl 이 위의 3가지가 아니라는 것인데, 현재 imageUrl은 file을 사용해서 URL.createObjectUrl(file)을 사용해서 이미지 url을 생성하려고 하고있으며

const file = uploadModal?.formData?.get('file') as File;
const imageUrl = file ? URL.createObjectURL(file) : '';
							{uploadModal?.formData?.get('file') ? (
								<Image
									src={imageUrl}
									alt="로고 이미지"
									width={32}
									height={32}
									className="object-cover"
									onClick={() => configDispatch(toggleUploadModal())}
								/>
							) : (
								<Image
									src="/img/upload_logo.svg"
									alt="로고 이미지"
									fill
									className="absolute left-[40px] top-[20px]"
									onClick={() => configDispatch(toggleUploadModal())}
								/>

file은 바로 uploadModal의 initialState 중에서 formData를 사용한다. 이때 formData의 타입은 아래와 같다.

export interface FormDataPreview extends FormData {
	preview: Blob;
}
formData: FormDataPreview | null;

FormData에서 preview 인수가 추가된 형태로 구성되어있으며, 여기서 나는 formData에서 가져온 정보를 사용하면 구현이 가능할줄 알았다. 실제로 제대로 선택한 파일의 경우는 제대로 업로드가 진행되는 것을 볼수 있었다. 잘못된 파일을 업로드한 상황에서는 initialState가 업데이트가 되지 않기 때문에 file의 값이 null이 된다.

가설 1 : 그럼 null, undefined 예외 설정을 하면 되지 않을까?

	const file = uploadModal?.formData?.get('file') as File;
	const imageUrl =
		file !== null && file !== undefined
			? URL.createObjectURL(file)
			: '/img/upload_logo.svg';

imageUrl을 선언할때 file이 null, undefined가 아닐때에만 파일을 적용하고 아니면 기본 업로드 로고로 설정했다

실패! 같은 오류가 발생

가설 2 : formData 말고 그냥 file을 사용하면 되지 않을까?

업로드 미리보기 기능 구현 관련 블로그를 돌아다녀 봤는데, 업로드한 이미지 파일을 formData로 만들지 않고 그대로 파일을 사용해서 URL.createObjectURL(file)로 src를 사용하는 것을 보고어쩌면 formData 자체가 문제일거라고 생각해서 initialState에 file type의 요소를 생성했다.

export interface FileWithPreview extends File {
	preview: string;
}
previewImg: FileWithPreview | null;

react-dropzone 라이브러리를 사용해서 제작한 dropzone 컴포넌트에서 드래그앤 드랍으로 업로드를 했을때, formData를 추가하는 것 뿐만 아니라 업로드한 파일을 previewImg에 갱신하는 로직을 추가했다.

const onDrop = useCallback((acceptedFiles: File[]) => {
		const filesWithPreview = acceptedFiles.map((file) =>
			Object.assign(file, {
				preview: URL.createObjectURL(file),
			}),
		) as FileWithPreview[];

		const formData = new FormData();
		formData.append('file', filesWithPreview[0]);
		uploadDispatch(setFormData(formData));
  // 이미지 파일 update Dispatch
		uploadDispatch(setPreviewImg(filesWithPreview[0]));

		setFiles(filesWithPreview);
	}, []);

그리고 해당 이미지파일을 사용해서 이전의 코드를 수정해봤다.

const { previewImg } = uploadModal;

성공!

아무래도 formData자체를 사용하는것보다는 file을 가져와서 구현하는것이 좀더 안정적인 것 같다. 조건을 만족하는 파일의 업로드에서는 문제가 없지만 예외의 조건에서는 url.createObject쪽에서 에러가 발생하는 모양이다.

2번 문제 분석

이 문제는 아마 색상 설정 모달과 같은 원인이 아닐까 싶다. 온보딩 모달 팝업 여부, 초기 설정 여부 에 따라서 optional setting을 제대로 하지 않아서 발생한 오류라고 생각했다.

색상 설정 모달과 마찬가지로 온보딩 모달에서는 다음 모달을 보여줘야하기 때문에 스타일 속성에서 transform을 변수값에 따라 추가했다. 온보딩 모달을 설정하지 않고 로고 업로드 아이콘을 눌러서 모달을 팝업시키고 취소를 눌렀음에도 transform이 일어난다는것은 바로 초기 세팅을 진행하지 않았을때 온보딩 모달 팝업 여부에 따라 다른 메소드를 호출해야겠다고 바로 파악했다.

before

const toggleModalOpen = () => {
		// nextModalOpen 값을 토글

		priceModal.isCardSet
			? [configDispatch(toggleUploadModal()), uploadDispatch(setFormData(null))]
			: [setNextModalOpen(!nextModalOpen), uploadDispatch(setFormData(null))];
	};

after

isCardSet이 false 일 때(초기 설정 skip 한 상황) isOnboardingModalOpen(온보딩 모달 팝업 여부) 에 따라서 다음 모달을 보여줄지, 업로드 모달만 끄게 할지 설정했다.

성공!

업로드중..

좌측 상단의 로고 아이콘을 클릭해서 업로드 모달을 팝업시키고 나중에 하기 버튼을 누르면 바로 꺼지는 것을 확인했다.

profile
개발자 꿈나무

0개의 댓글