본문 바로가기

모바일 개발/React Native-이론

갤러리 앱 클론코딩 - 갤러리에 사진 추가하기

1. Device 내장 갤러리 접속 : expo의 imagePicker라는 로직이용

(1) 로직

(2) 코드리뷰

내부 코드들인데 async 함수, await 등 pickImage를 구현하는 내부 로직들 중 모르는 keyWord들이 많다. 

해당 내용들을 알려면 promise 라는 키워드 부터 공부해야 한다. 이는 시간이 많이 걸리므로, 먼저 이번 강의 전 내용을 빠르게 정리한 후 돌아와서 공부하도록 하겠다.

(3) 새롭게 알게 된 것 - image Picker 로직 분해를 통하여

https://docs.expo.dev/versions/latest/sdk/imagepicker/

2. imagePicker가 하나의 사진 뿐만 아니라 여러 개의 사진을 가지고 있을 수 있도록 커스터마이징

+ imagePicker가 받은 여러 사진들을 화면에 띄우기 (flatList 이용)

(1) 로직

(2) 코드리뷰

setImage에서 기존 image 배열의 원소들을 넣기 위해 전개 연산자 사용, 그 후 result (현재 찝은 거 ) 넣음.

(3) 새롭게 알게 된 것 

없음

3. 한 줄에 화면 3개 뜨도록 커스터마이징

(1) 로직

(2) 코드리뷰

renderItem 내부

(3) 새롭게 알게 된 것 

Dimensions는 윈도우 창이나 스크린의 크기 높이를 알아내는 API 이다. 

같은 방식으로 height도 얻을 수 있다. 

const windowWidth = Dimensions.get('window').width;
const windowHeight = Dimensions.get('window').height;



const ScreenWidth = Dimensions.get('screen').width;
const ScreenHeight = Dimensions.get('screen').height;

4. 삭제 로직 

(1) 로직

a. 먼저 커스텀 훅 useGallery 내의 상태변수 image를 String 배열에서 객체들의 배열로 바꾸어줘야 한다. 

삭제를 위해서 필요한 사진들만의 고유 번호 id를 설정해줘야 해서 구조체 형태로 원소를 바꾸어 주어야 하기 때문이다.

 

why? 왜 id가 따로 필요한가? uri 값으로 특정해서 사진을 지우면 되지 않나?

갤러리에 똑같은 사진을 2개 올리는 경우를 생각해보자. 만약 uri를 기준으로 사진 삭제 로직이 가동 된다면 둘 중 하나의 사진을 삭제해도 둘 다 삭제될 것이다. 둘은 uri가 같기 때문이다. 

 

그래서 id라는 변수를 객체 내부에 새로 만들어준다. 

Lastid를 만들어 배열 마지막 원소인 객체의 id를 알아낸다. 

Lastid+1 해서 새로운 사진이 배열에 들어올 때마다 교부한다. 

그러면 사진별로 고유한 id가 생긴다.  

(2) 코드리뷰

export const useGallery = () => {
  const [images, setImages] = useState([]);

  const pickImage = async () => {
    // No permissions request is necessary for launching the image library
    let result = await ImagePicker.launchImageLibraryAsync({
      mediaTypes: ImagePicker.MediaTypeOptions.All,
      allowsEditing: true,
      aspect: [4, 3],
      quality: 1,
    });

    console.log(result);

    // 만약에 취소를 누른게 아니라면
    if (!result.canceled) {
      const lastId = images.length === 0 ? 0 : images[images.length - 1].id;
      //id는 1부터 시작하고 배열의 index는 0부터 시작한다. 헷갈리지 말자.
      // 여기서는 images[최대길이-1]의 id를 구해 사용한다. index는 따로 사용하지 않는다.
      const newImage = {
        id: lastId + 1,
        uri: result.assets[0].uri,
      };

      setImages([...images, newImage]); // result의 assets의 첫번째 원소값의 uri를 image 값으로 설정 해달라.
    }
  };

  const deleteImage = (imageId) => {
    Alert.alert("이미지를 삭제하시겠습니까?", "", [
      {
        style: "cancel",
        text: "아니요!",
      },

      {
        text: "네!",
        onPress: () => {
          const newImages = images.filter((image) => image.id !== imageId);
          setImages(newImages);
        },
      },
    ]);
  };


  return {
    images,
    pickImage,
    deleteImage,
  };
};
 const onLongPressImage = (imageId) => {
    deleteImage(imageId);
  };

  const renderItem = ({ item: { id, uri }, idex }) => {
    return (
      <TouchableOpacity onLongPress={() => onLongPressImage(id)}>
        <Image
          source={{ uri: uri }}
          style={{ width: columnSize, height: columnSize }}
        />
      </TouchableOpacity>
    );
  };

(3) 새롭게 알게 된 것 

없음.

5. + 버튼을 따로 만들어서 해당 버튼을 누를 시 내장 갤러리로 접속 가능하도록 만들기 

(1) 로직

(2) 코드리뷰

return === -1 일 때는 + 버튼 만들고 

나머지는 원래 그대로 사진 uri 받아서 사진 구현

(3) 새롭게 알게 된 것 

없음 

총 설계도