티스토리 뷰

728x90
반응형

사용자의 앨범에 접근하거나 카메라 촬영을 하여 이미지를 등록하는 등의 기능은 거의 대부분의 앱에서 사용된다. React Native에서 사용자의 앨범과 카메라에 접근하여 이미지 파일을 불러오는 라이브러리는 다양하며, 라이브러리마다 해당 기능을 사용하는 방법이 다르지만 보통 함수 내에서 Promise를 호출하여 사용자 동작에 따른 callback으로 처리하는 방법이 대다수이다.

컴포넌트 내에서 카메라 기능을 호출하는 함수, 사용자의 앨범에 접근하는 기능을 하는 함수, 이에 따른 처리 로직 등을 선언해야 하고 이러한 기능을 하는 컴포넌트가 다수개 있다면 일일이 컴포넌트 내에 선언하는 것보다 전역으로 사용 가능한 공통 모듈을 작성하는 편이 유지 보수와 확장성 측면에서 훨씬 더 유리할 것이다.

만약 함수가 컴포넌트의 특정 상태나 props에 강하게 의존하고 있다면, 공통 함수로 분리했을 때 해당 컴포넌트에 매개변수로 해당 상태나 값을 전달해야 하는데 이 경우 오히려 코드가 더 복잡해질 수 있으니 반복적인 로직이나 여러 컴포넌트에서 공통적으로 사용되고 있을 때 공통 함수로 분리하도록 하자.

📚 사용 라이브러리

https://github.com/ivpusic/react-native-image-crop-picker

image crop picker는 openCamera(카메라 기능), openPicker(앨범 가져오기) 를 했을 경우 권한 체크를 자동으로 해주고, 필요에 따라 이미지의 비율도 설정할 수 있도록 cropper 또한 제공해주고 있어 사용하였다.

공통 모듈 작성하기

위에서 언급한 openCamera, openPicker, openCropper 를 전역적으로 사용하기 위한 imgHandlers.ts 파일을 생성해준다.

onCameraHandler & onImageHandler

export const onCameraHandler = (
  callback: Function,
  isCrop: boolean = false,
) => {
  ImageCropPicker.openCamera({
    cropping: isCrop,
  })
    .then(image => {
      callback(image);
    })
    .catch(e => {
      console.log('onCameraHandler', e);
    });
};

export const onImageHandler = (callback: Function) => {
  ImageCropPicker.openPicker({
    cropping: false,
  })
    .then(image => {
      callback(image);
    })
    .catch(e => {
      console.log('onImageHandler', e);
    });
};

기본적인 형태는 위 코드와 같다.

onCameraHandler를 호출할 때 특정 컴포넌트에서 crop 기능을 사용하기 위해 props로 받도록 했다. (image-crop-picker 라이브러리에서 단일 이미지를 cropping : true 할 경우 크롭 기능이 활성화 된다.)

onImageCropHandler

export const onImageCropHandler = async (
  callback: (croppedImage: ImageOrVideo | ImageOrVideo[]) => void,
  isMultiple: boolean = false,
  pickerOptions?: Options,
) => {
  try {
    // 이미지를 선택하고 크롭까지 처리
    const images: ImageOrVideo | ImageOrVideo[] =
      await ImageCropPicker.openPicker({
        cropping: !isMultiple, // 단일 이미지일 때만 크로핑
        multiple: isMultiple,
        mediaType: 'photo',
        ...pickerOptions,
      });

    // 크롭 작업이 필요한 경우
    if (isMultiple && Array.isArray(images)) {
      const arr: ImageOrVideo[] = [];
      for await (const _img of images) {
        const img = await ImageCropPicker.openCropper({
          mediaType: 'photo',
          path: _img.path,
        });
        arr.push(img);
      }
      callback(arr);
    } else if (!isMultiple && !Array.isArray(images)) {
      // 단일 이미지 크롭 작업
      callback(images);
    } else {
      throw new Error('Unexpected image format');
    }
  } catch (error) {
    console.log(`onImageCropHandler Error: ${error}`);
  }
};

Cropper 기능을 사용하기 위한 onImageCropHandler이다. openPikcer에서 단일 이미지에서만 cropping을 true로, multiple이 true일 경우에는 cropping을 false로 하고 openCropper를 사용하는데, 여러 이미지를 사용할 때는 이미지를 한장 한장 크롭 처리하기 위해 Cropper를 동기적으로 처리해야 하기 때문이다.

공통 모듈 사용하기

이제 이미지를 사용할 컴포넌트에서 해당 함수를 호출해주고, 불러온 이미지를 처리할 로직만 callback으로 넘겨주기만 하면 된다.

이전보다 훨씬 가독성도 좋아지고 처리 로직 쪽에 문제가 발생했을 때 하나하나 수정하는 번거로움도 없어졌다.

728x90
반응형
반응형
250x250
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
글 보관함