본문 바로가기
공부낙서장

부트캠프 프론트엔드 및 백엔드 협업 과제 진행 ing (cloudinary 연결 회고)

by 곰인간 2023. 8. 8.

코로나 후유증 대단해..

하루 짧으면 4시간 길면 7시간 정도 자던 나!

하루 14시간씩 자게 만들었음..


현재 협업 과제 진행 사항은 기능 구현 완료

금일 오후에 다같이 모여서 배포하고, 1차 통합 테스트 거칠 예정

그전에 진행 중에 에러 사항있던 부분 되짚어 보기

먼저 내가 맡은 부분은 회원가입, 메인 페이지에 이벤트가 렌더링될 달력, 마이페이지 나의 일정 관리

회원가입 부분 진행 중에 에러 사항 중 하나는 프로필 이미지 부분,

서버측과 협의하에 프로필이미지 부분을 url로 데이터를 받는 부분이었는데,

이미지 업로드하고 저장되는 부분을 cloudinary를 이용해서 저장된 이미지의 url을 받아왔다.

처음에 cloudinary를 사용할 때 ant design에 있는 upload와 같이 사용하기로 기획하고 작업에 들어갔는데,

cloudinary를 연결하는 부분에서 어려움을 겪었다.

const cloudinaryName = import.meta.env.VITE_CLOUD_NAME;

export const handleUpload = async (file: string | Blob) => {
  const formData = new FormData();
  formData.append('file', file);
  formData.append('upload_preset', '자신의 cloudinary preset');

  if (!file) {
    return null;
  }

  const response = await axios.post(
    `https://api.cloudinary.com/v1_1/${cloudinaryName}/image/upload/`,
    formData,
  );

  return response;
};

일단 api통신하는 곳에서 에러 처리를 하지않고, 

api를 사용하는 컴포넌트에서 에러 처리를 하였다.

프로필 이미지를 업로드 하지않는 경우 null을 반환한다.

서버 측의 스키마 상에도 null을 받게 되어있다.

  const normFile = (e: any) => {
    if (Array.isArray(e)) {
      return e;
    }
    return e?.fileList;
  };
        
  <Form.Item
    label="프로필"
    name="profileThumbUrl"
    valuePropName="fileList"
    getValueFromEvent={normFile}
  >
    <Upload beforeUpload={() => false}>
      <Button>
        <PlusOutlined /> Click to Upload
       </Button>
    </Upload>
  </Form.Item>

ant design을 사용했고, 업로드 버튼을 누르면 프로필 이미지가 업로드 되게 하였다.

  // cloudinary를 이용해서 이미지url이 없으면 null, 있으면 이미지url을 반환
  const getImageUrl = async (values: valuseType) => {
    let imageUrl = null;

    try {
      if (values.profileThumbUrl && values.profileThumbUrl.length > 0) {
        const response = await handleUpload(
          values.profileThumbUrl[0].originFileObj,
        );
        // response가 null일 수도 있기 때문에 옵셔널 체이닝을 이용해서 
        // null이나 undefined일 때도 코드가 동작하게
        if (response?.status === 200) {
          const data = response.data;
          imageUrl = data.url; // 이미지 URL을 받아옴
        } else {
          throw new Error('이미지 업로드에 실패하였습니다.');
        }
      }
    } catch (error) {
      console.error('오류 발생:', error);
      imageUrl = null; // 오류가 발생했으므로 imageUrl을 null로 설정
    }

    return imageUrl;
  };

values는 ant design의 Form에서,

originFileObj는 ant design의 Upload에서 

  const onFinish = async (values: valuseType) => {
    // 클라우디너리로 전송한 이미지 url 가져옴
    const imageUrl = await getImageUrl(values);

    // 가져온 이미지 url만 profileThumbUrl에 전달하기 위해서
    // values객체를 전개연산자를 이용해서 newValues에 모든 속성을 복사하고,
    // profileThumbUrl: imageUrl을 마지막에 사용해서 덮어 씌움
    const newValues = {
      ...values,
      profileThumbUrl: imageUrl,
    };
    .
    .
    .
    생략
    };

위의 코드 블럭엔 밑에 부분을 생략했다.

onFinish이 부분도 ant design의 Form 제출 부분이랑 연관되어있다.

getImageUrl을 통해서 imageUrl을 가져와서

Form values에서 필요없는 부분을 제거하기 위해서 

newValues 변수를 선언하고 values객체를 전개연산자를 이용해서 모든 속성을 복사한다.

그리고 profileThumbUrl: imageUrl을 마지막에 사용해서 덮어 씌운다.

이렇게 하면 profileThumbUrl에 필요없는 속성 부분 위에 imageUrl이 덮어 씌워져서 내가 원하는대로 url만 출력된다.

댓글