Project : 의미없는 데이터 update는 그만 2탄 feat: Refactoring

lunaxislu·2024년 2월 19일

project

목록 보기
16/17

1탄

meta image도 조건부로 db로 올리는 것까지 감안하여야 해서 정말 부끄럽고, 안타까운 코드가 만들어졌다.

const submitEditCard = async (e: FormEvent<HTMLFormElement>) => {
    e.preventDefault();
    const editData: EditPlatFormType = {
      ...editPlatForm,
    };

    let comparedData = Object.entries(editData).reduce((acc, [key, value]) => {
      if (prevData[key as keyof EditPlatFormType] !== value) {
        acc[key as keyof EditPlatFormType] = value;
      }
      return acc;
    }, new Object() as EditPlatFormType);

    if (isEmptyObject(comparedData) && prevData.image_url === prevImg) {
      resetIsRegist();
      resetEditPlatForm();
      resetPrevData();
      return;
    }

    if (comparedData.link_url) comparedData.id = editData.id;
    comparedData.store_id = editData.store_id;
    comparedData.createdAt;
    comparedData.id = editData.id;
    if (meta) {
      console.log('meta');
      // 기존 이미지가 있고 이미지 변경 했을 때
      if (prevData.image_url) {
        if (prevData.image_url.includes(SUPABASE_STORAGE_URL)) {
          //  opengraph 이미지가 아니면 삭제
          await removePlatFormImage(prevData);
        }
        const { file, createdAt, metaImage, ...updateTarget } = comparedData;
        const data = { ...updateTarget, image_url: metaImage };
        await updatePlatFormData(data as TablesInsert<'platform'>);
        const { platform } = await fetchPlatForm(store_id!);
        setFetchPlatFormData(platform);
        resetIsRegist();
        resetEditPlatForm();
        resetPrevData();
        toast('수정이 완료 되었습니다.', {
          type: 'info',
          position: 'top-center',
          showCloseButton: true,
          autoClose: 300,
        });
        return;
      }
      //기존 이미지가 없고 meta이미지만을 등록 할 때
      if (!prevData.image_url) {
        const { file, createdAt, metaImage, ...updateTarget } = comparedData;

        const data = { ...updateTarget, image_url: metaImage };
        await updatePlatFormData(data as TablesInsert<'platform'>);
        const { platform } = await fetchPlatForm(store_id!);
        setFetchPlatFormData(platform);
        resetIsRegist();
        resetEditPlatForm();
        resetPrevData();
        toast('수정이 완료 되었습니다.', {
          type: 'info',
          position: 'top-center',
          showCloseButton: true,
          autoClose: 300,
        });
        return;
      }
    }
    if (!meta) {
      console.log('!meta');
      // 기존이미지가 있고 이미지 변경 했을 때
      if (prevData.image_url && comparedData.file) {
        comparedData.createdAt = moment().toISOString();

        if (prevData.image_url.includes(SUPABASE_STORAGE_URL)) {
          //  opengraph 이미지가 아니면 삭제
          await removePlatFormImage(prevData);
        }

        // 새로운 이미지 업로드
        await uploadPlatFormImage(comparedData);
        const { publicUrl: image_url } = downloadPlatFormImageUrl(comparedData);
        comparedData = {
          ...comparedData,
          image_url,
        };

        const { file, createdAt, ...updateTarget } = comparedData;
        await updatePlatFormData(updateTarget as TablesInsert<'platform'>);
        const { platform } = await fetchPlatForm(store_id!);
        setFetchPlatFormData(platform);
        resetIsRegist();
        resetEditPlatForm();
        resetPrevData();
        toast('수정이 완료 되었습니다.', {
          type: 'info',
          position: 'top-center',
          showCloseButton: true,
          autoClose: 300,
        });
        return;
      }

      // 기존데이터에 이미지가 없을 때 이미지 등록을 할 때
      if (!prevData.image_url && comparedData.file) {
        console.log('여기에 오니?');
        comparedData.createdAt = moment().toISOString();
        await uploadPlatFormImage(comparedData);
        const { publicUrl: image_url } = downloadPlatFormImageUrl(comparedData);
        comparedData = {
          ...comparedData,
          image_url,
        };
        const { file, createdAt, ...updateTarget } = comparedData;
        await updatePlatFormData(updateTarget as TablesInsert<'platform'>);
      }

      // 수정할 때 이미지만 삭제 할 때 실행 되는 조건문
      if (!prevImg && !comparedData.link_url && !comparedData.name) {
        console.log('여기에 오니?');
        // 수정할 이미지가 meta이미지이면
        if (!prevData?.image_url?.includes(SUPABASE_STORAGE_URL)) {
          const { file, createdAt, ...updateTarget } = comparedData;
          console.log(updateTarget);
          await updatePlatFormData({ ...updateTarget, image_url: null } as TablesInsert<'platform'>);
          const { platform, error } = await fetchPlatForm(store_id!);
          setFetchPlatFormData(platform);
          resetIsRegist();
          resetEditPlatForm();
          resetPrevData();
          toast('수정이 완료 되었습니다.', {
            type: 'info',
            position: 'top-center',
            showCloseButton: true,
            autoClose: 300,
          });
          return;
        }
        // 수정할 이미지가 storage 이미지 이면
        if (prevData?.image_url!.includes(SUPABASE_STORAGE_URL)) {
          await removePlatFormImage(comparedData);
          const { file, createdAt, ...updateTarget } = comparedData;
          await updatePlatFormData({ ...updateTarget, image_url: null } as TablesInsert<'platform'>);
          const { platform, error } = await fetchPlatForm(store_id!);
          setFetchPlatFormData(platform);
          resetIsRegist();
          resetEditPlatForm();
          resetPrevData();
          toast('수정이 완료 되었습니다.', {
            type: 'info',
            position: 'top-center',
            showCloseButton: true,
            autoClose: 300,
          });
          return;
        }
      }
    }
    const { file, createdAt, ...updateTarget } = comparedData;
    await updatePlatFormData(updateTarget as TablesInsert<'platform'>);
    const { platform } = await fetchPlatForm(store_id!);
    setFetchPlatFormData(platform);
    resetIsRegist();
    resetEditPlatForm();
    resetPrevData();
    toast('수정이 완료 되었습니다.', {
      type: 'info',
      position: 'top-center',
      showCloseButton: true,
      autoClose: 300,
    });
  };

위 코드를 안 읽었다면 정말 다행이라 생각한다.

간단하게 무슨 함수이냐면, 카드 편집 후 클릭으로 db에 전송하기 전, 추출된 meta image로 수정 되어있는지를 확인 하는 로직을 추가한 코드이다.

위 코드를 보면 어떻게 압축 시킬수 있을까? 생각을 많이 했던것 같다.

역으로도 생각해보고, 공통된 코드가 있는지 확인도 해보았지만, 그 때 당시에는 도무지 어떻게 해야할 도리가 없었다.
그래서 다른 작업을 하다가 갑자기 생각난 것은

코드가 길어지는 가장 큰 원인은 image 올리는 것 때문이다.

라는 생각이 머릿속으로 스쳐지나가

image를 가지고 조건부로 처리하는 함수 하나를 만들면 위의 대단해 엄청난 함수 로직이 줄어 들것 같았다.

따라서 뭔가 반대로 생각하면 될것 같은 " 감 " 을 가지고 생각해본 결과

이미지를 업로드 하기 위해서는 file이 있는지 없는지를 알아야한다. -> file이 없다면 meta image가 있는지 없는지를 알아야 한다. 

간단한 문장이지만 이걸 위해 몇 일을 고민했는지 모르겠다.


이것을 함수로 표현 하자면

export const handleImageUpload = async (data: AddPlatFormType | EditPlatFormType) => {
  if (data.file) {
    data.createdAt = dayjs().toISOString();
    await uploadPlatFormImage(data);
    const { publicUrl } = downloadPlatFormImageUrl(data);
    data.image_url = publicUrl;
    return data;
  }
  data.image_url = data.metaImage ?? null;
  return data;
};
  
// if (meta) {
//   console.log('meta');
//   // 기존 이미지가 있고 이미지 변경 했을 때
//   if (prevData.image_url) {
//     if (prevData.image_url.includes(SUPABASE_STORAGE_URL)) {
//       //  opengraph 이미지가 아니면 삭제
//       await removePlatFormImage(prevData);
//     }
//     const { file, createdAt, metaImage, ...updateTarget } = comparedData;
//     const data = { ...updateTarget, image_url: metaImage };
//     await updatePlatFormData(data as TablesInsert<'platform'>);
//     const { platform } = await fetchPlatForm(store_id!);
//     setFetchPlatFormData(platform);
//     resetIsRegist();
//     resetEditPlatForm();
//     resetPrevData();
//     toast('수정이 완료 되었습니다.', {
//       type: 'info',
//       position: 'top-center',
//       showCloseButton: true,
//       autoClose: 300,
//     });
//     return;
//   }
//   //기존 이미지가 없고 meta이미지만을 등록 할 때
//   if (!prevData.image_url) {
//     const { file, createdAt, metaImage, ...updateTarget } = comparedData;

//     const data = { ...updateTarget, image_url: metaImage };
//     await updatePlatFormData(data as TablesInsert<'platform'>);
//     const { platform } = await fetchPlatForm(store_id!);
//     setFetchPlatFormData(platform);
//     resetIsRegist();
//     resetEditPlatForm();
//     resetPrevData();
//     toast('수정이 완료 되었습니다.', {
//       type: 'info',
//       position: 'top-center',
//       showCloseButton: true,
//       autoClose: 300,
//     });
//     return;
//   }
// }
// if (!meta) {
//   console.log('!meta');
//   // 기존이미지가 있고 이미지 변경 했을 때
//   if (prevData.image_url && comparedData.file) {
//     comparedData.createdAt = moment().toISOString();

//     if (prevData.image_url.includes(SUPABASE_STORAGE_URL)) {
//       //  opengraph 이미지가 아니면 삭제
//       await removePlatFormImage(prevData);
//     }

//     // 새로운 이미지 업로드
//     await uploadPlatFormImage(comparedData);
//     const { publicUrl: image_url } = downloadPlatFormImageUrl(comparedData);
//     comparedData = {
//       ...comparedData,
//       image_url,
//     };

//     const { file, createdAt, ...updateTarget } = comparedData;
//     await updatePlatFormData(updateTarget as TablesInsert<'platform'>);
//     const { platform } = await fetchPlatForm(store_id!);
//     setFetchPlatFormData(platform);
//     resetIsRegist();
//     resetEditPlatForm();
//     resetPrevData();
//     toast('수정이 완료 되었습니다.', {
//       type: 'info',
//       position: 'top-center',
//       showCloseButton: true,
//       autoClose: 300,
//     });
//     return;
//   }

//   // 기존데이터에 이미지가 없을 때 이미지 등록을 할 때
//   if (!prevData.image_url && comparedData.file) {
//     console.log('여기에 오니?');
//     comparedData.createdAt = moment().toISOString();
//     await uploadPlatFormImage(comparedData);
//     const { publicUrl: image_url } = downloadPlatFormImageUrl(comparedData);
//     comparedData = {
//       ...comparedData,
//       image_url,
//     };
//     const { file, createdAt, ...updateTarget } = comparedData;
//     await updatePlatFormData(updateTarget as TablesInsert<'platform'>);
//   }

//   // 수정할 때 이미지만 삭제 할 때 실행 되는 조건문
//   if (!prevImg && !comparedData.link_url && !comparedData.name) {
//     console.log('여기에 오니?');
//     // 수정할 이미지가 meta이미지이면
//     if (!prevData?.image_url?.includes(SUPABASE_STORAGE_URL)) {
//       const { file, createdAt, ...updateTarget } = comparedData;
//       console.log(updateTarget);
//       await updatePlatFormData({ ...updateTarget, image_url: null } as TablesInsert<'platform'>);
//       const { platform, error } = await fetchPlatForm(store_id!);
//       setFetchPlatFormData(platform);
//       resetIsRegist();
//       resetEditPlatForm();
//       resetPrevData();
//       toast('수정이 완료 되었습니다.', {
//         type: 'info',
//         position: 'top-center',
//         showCloseButton: true,
//         autoClose: 300,
//       });
//       return;
//     }
//     // 수정할 이미지가 storage 이미지 이면
//     if (prevData?.image_url!.includes(SUPABASE_STORAGE_URL)) {
//       await removePlatFormImage(comparedData);
//       const { file, createdAt, ...updateTarget } = comparedData;
//       await updatePlatFormData({ ...updateTarget, image_url: null } as TablesInsert<'platform'>);
//       const { platform, error } = await fetchPlatForm(store_id!);
//       setFetchPlatFormData(platform);
//       resetIsRegist();
//       resetEditPlatForm();
//       resetPrevData();
//       toast('수정이 완료 되었습니다.', {
//         type: 'info',
//         position: 'top-center',
//         showCloseButton: true,
//         autoClose: 300,
//       });
//       return;
//     }
//   }
// }

이렇게 비교하면 어마어마한 압축량이 보인다.

이것으로 위에 코드를 바꿔보면

refactoring

 const submitEditCard = useCallback(
    async (e: FormEvent<HTMLFormElement>) => {
      e.preventDefault();

      const comparedData = isPlatFormCardValueChange(prevData, editPlatForm);
      if (isEmptyObject(comparedData) && prevData.image_url === prevImg) {
        handleResetStateAfterAction(isEdit);
        return;
      }

      comparedData.id = editPlatForm.id;
      comparedData.store_id = editPlatForm.store_id;
      await prevImageRemove(prevData);
      const ensureHttpsUrlData = ensureHttpsUrl(comparedData);
	  
      // 여기가 바꾼 곳
      const form = await handleImageUpload(ensureHttpsUrlData);

      // react-query mutation
      editCardPlatForm(form as EditPlatFormType);
      setPending(true);
    },
    // eslint-disable-next-line react-hooks/exhaustive-deps
    [editPlatForm, prevData, prevImg],
  );

이렇게 126줄에서 -> 12줄로 바뀌었다.

1개의 댓글

comment-user-thumbnail
2024년 2월 21일

멋집니다

답글 달기