프로필 사진, 게시글 이미지 등 카메라와 갤러리는 대부분의 앱에서 필수 기능입니다.


expo-image-picker (Expo)

BASH
npx expo install expo-image-picker
TSX
import * as ImagePicker from 'expo-image-picker';

// 갤러리에서 이미지 선택
async function pickImage() {
  const permission = await ImagePicker.requestMediaLibraryPermissionsAsync();
  if (!permission.granted) {
    Alert.alert('갤러리 접근 권한이 필요합니다');
    return;
  }

  const result = await ImagePicker.launchImageLibraryAsync({
    mediaTypes: ['images'],
    allowsEditing: true,     // 크롭 허용
    aspect: [1, 1],          // 크롭 비율 (정사각형)
    quality: 0.8,            // 이미지 품질 (0-1)
  });

  if (!result.canceled) {
    return result.assets[0].uri;
  }
}

// 카메라로 촬영
async function takePhoto() {
  const permission = await ImagePicker.requestCameraPermissionsAsync();
  if (!permission.granted) {
    Alert.alert('카메라 접근 권한이 필요합니다');
    return;
  }

  const result = await ImagePicker.launchCameraAsync({
    allowsEditing: true,
    aspect: [4, 3],
    quality: 0.8,
  });

  if (!result.canceled) {
    return result.assets[0].uri;
  }
}

프로필 이미지 컴포넌트

TSX
function ProfileImagePicker() {
  const [imageUri, setImageUri] = useState<string | null>(null);

  const showOptions = () => {
    Alert.alert('프로필 사진', '사진을 선택하세요', [
      { text: '카메라', onPress: async () => {
        const uri = await takePhoto();
        if (uri) setImageUri(uri);
      }},
      { text: '갤러리', onPress: async () => {
        const uri = await pickImage();
        if (uri) setImageUri(uri);
      }},
      { text: '취소', style: 'cancel' },
    ]);
  };

  return (
    <Pressable onPress={showOptions} style={styles.avatarContainer}>
      {imageUri ? (
        <Image source={{ uri: imageUri }} style={styles.avatar} />
      ) : (
        <View style={[styles.avatar, styles.placeholder]}>
          <Text style={styles.placeholderText}>+</Text>
        </View>
      )}
    </Pressable>
  );
}

const styles = StyleSheet.create({
  avatarContainer: { alignItems: 'center', marginBottom: 20 },
  avatar: { width: 120, height: 120, borderRadius: 60 },
  placeholder: { backgroundColor: '#e0e0e0', justifyContent: 'center', alignItems: 'center' },
  placeholderText: { fontSize: 40, color: '#999' },
});

react-native-vision-camera (고급)

실시간 카메라 프리뷰, QR 코드 스캔, ML 처리 등 고급 카메라 기능이 필요할 때 사용합니다.

BASH
npm install react-native-vision-camera
TSX
import { Camera, useCameraDevice, useCameraPermission } from 'react-native-vision-camera';

function CameraScreen() {
  const device = useCameraDevice('back');
  const { hasPermission, requestPermission } = useCameraPermission();
  const cameraRef = useRef<Camera>(null);

  if (!hasPermission) {
    return (
      <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
        <Text>카메라 권한이 필요합니다</Text>
        <Pressable onPress={requestPermission}><Text>권한 요청</Text></Pressable>
      </View>
    );
  }

  if (!device) return <Text>카메라를 찾을 수 없습니다</Text>;

  const takePhoto = async () => {
    const photo = await cameraRef.current?.takePhoto({ flash: 'auto' });
    if (photo) {
      console.log('촬영 완료:', photo.path);
    }
  };

  return (
    <View style={{ flex: 1 }}>
      <Camera
        ref={cameraRef}
        style={{ flex: 1 }}
        device={device}
        isActive={true}
        photo={true}
      />
      <Pressable onPress={takePhoto} style={styles.captureButton}>
        <View style={styles.captureInner} />
      </Pressable>
    </View>
  );
}

정리

  • 간단한 이미지 선택에는 expo-image-picker 가 충분합니다
  • 실시간 카메라 프리뷰, QR 스캔 등에는 react-native-vision-camera 를 사용하세요
  • ** 권한 요청 **은 반드시 사용 전에 처리하고, 거부 시 안내 메시지를 보여주세요
  • 이미지 업로드 시에는 quality를 0.7~0.8 로 설정하여 용량을 줄이세요
댓글 로딩 중...