본문 바로가기
리액트(React)

[React Native] 이미지 위치정보 가져오기 (EXIF 포맷)

by 즐거운코딩 2025. 4. 18.
반응형

이전 블로그에서 갤러리 & 앨범에서 이미지 가져오는 방법에 대해 알아 보았습니다.

2024.09.21 - [리액트(React)] - [React Native] 갤러리&앨범 이미지 가져오기

 

이번에는 좀 더 나아가서 이미지에서 위치정보를 가져오는 방법에 대해 알아보고자 합니다. 

핸드폰(삼성 기준) 갤러리앱에서 이미지를 선택하고 상세보기를 보면 사진관련 다양한 정보들을 확인할 수 있습니다.

 

아래 이미지는 광화문에서 찍은 사진인데 촬영한 날짜, 시간, 핸드폰 기종, 해상도, 카메라 셋팅값, 파일용량, 저장위치, 파일명 등 다양한 정보를 확인 가능합니다. 여기에 위치정보도 같이 있어서 주소지 정보와 지도상 위치도 확인 가능합니다.

갤러리 이미지 상세정보

 

이러한 정보의 기준 포맷은  무엇일까요?

 

혹시 Exif 라는 이미지 파일포맷을 들어 보신적 있나요?

 

  • Exif 란 ?
    • EXchangable Image File format 의 약자
    • 디지털 카메라에서 이용되는 이미지 파일 포맷으로  JPEG, TIFF 6.0과 RIFF, WAV 파일 포맷에서 이용되며 사진에 대한 정보를 포함하는 메타데이터를 추가로 가지고 있음
  • Exif Viewer
    • Exif 파일 포맷의 이미지의 상세 정보를 확인할 수 있는 뷰어로 아래 사이트 참고
    • https://exif.tools/
 

EXIF / File Metadata Viewer

 

exif.tools

EXIF tools

 

위의 Exif tools를 사용하여 제가 샘플로 올린 광화문 사진의 정보를 보면 다음과 같습니다.

 

EXIF Format

 

많은 Metadata중에서 GPS 관련 정보도 포함되어 있습니다.

 

앱 개발시 이미지를 가져오는 React-native 패키지 종류는 다음과 같습니다.

  • react-native-image-picker
  • expo-image-picker

그럼 두 패키지의 차이점에 대해 좀 더 상세히 알아보겠습니다. 

 

  • 차이점 비교
항목 react-native-image-picker expo-image-picker
설치 및 설정 네이티브 모듈 설정 필요
 (iOS: `Info.plist`, Android: `Manifest`)
Expo 프로젝트에서 간단히 설치 가능, 
추가 설정 불필요
플랫폼 호환성 React Native CLI 기반 프로젝트 (iOS, Android) Expo 기반 프로젝트 (iOS, Android)
사용자 인터페이스 커스터마이징 가능, 기본 UI 없음 기본 UI 제공, Expo 디자인 가이드라인 준수
기능 이미지/비디오 선택, 카메라 촬영, 
크롭/리사이즈 등 고급 기능 지원
이미지/비디오 선택, 크기 조정 및 품질 설정 가능
커뮤니티 및 지원 널리 사용되지만 업데이트가 느릴 수 있음 활발한 커뮤니티와 공식 문서 제공
성능 네이티브 최적화 가능하지만 설정 복잡 Expo 환경에 최적화되어 성능 우수

 

  • react-native-image-picker 사용법
    • 패키지설치 : yarn add react-native-image-picker
    • iOS는 추가 설치 :  npx pod-install ios  
    • 코드 예제
import React, { useState } from 'react';
import { View, Button, Image, StyleSheet } from 'react-native';
import { launchImageLibrary } from 'react-native-image-picker';

export default function App() {
  const [imageUri, setImageUri] = useState(null);

  const pickImage = () => {
    const options = {
      mediaType: 'photo',
      quality: 1,
    };
    launchImageLibrary(options, (response) => {
      if (!response.didCancel && !response.errorCode) {
        setImageUri(response.assets[0].uri);
      }
    });
  };

  return (
    
      
      {imageUri && }
    
  );
}

const styles = StyleSheet.create({
  container: { flex: 1, justifyContent: 'center', alignItems: 'center' },
  image: { width: 200, height: 200 },
});

 

  • expo-image-picker 사용법
    • 패키지 설치 : npx expo install expo-image-picker
    • 코드예시
import React, { useState } from 'react';
import { View, Button, Image, StyleSheet } from 'react-native';
import * as ImagePicker from 'expo-image-picker';

export default function App() {
  const [imageUri, setImageUri] = useState(null);

  const pickImage = async () => {
    const result = await ImagePicker.launchImageLibraryAsync({
      mediaTypes: ImagePicker.MediaTypeOptions.Images,
      allowsEditing: true,
      quality: 1,
    });

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

  return (
    
      
      {imageUri && }
    
  );
}

const styles = StyleSheet.create({
  container: { flex: 1, justifyContent: 'center', alignItems: 'center' },
  image: { width: 200, height: 200 },
});

 

그럼 이렇게만 하면 위치정보를 가져올 수 있을까요??

 

아닙니다. 이렇게 하면 위치정보를 가져오지 않습니다. 그럼 어떻게 해야할까요??

이부분에 있어서 많은 웹서핑과 github 까지 확인했는데 결국 답은 EXIF 포맷에 있었습니다.

그렇기에 앞에서 EXIF 에 대해 먼저 언급을 한 것 입니다.

 

Expo의 공식 문서에 나오는 이미지 정보는 다음과 같습니다.

어디에도 위치정보는 없습니다. 즉, exif 값이 null 로 보입니다.

{
  "assets": [
    {
      "assetId": "C166F9F5-B5FE-4501-9531",
      "base64": null,
      "duration": null,
      "exif": null,
      "fileName": "IMG.HEIC",
      "fileSize": 6018901,
      "height": 3025,
      "type": "image",
      "uri": "file:///data/user/0/host.exp.exponent/cache/cropped1814158652.jpg"
      "width": 3024
    }
  ],
  "canceled": false
}

 

그럼 여기서 exif 값이 보이게 셋팅하는 방법입니다. 알고 보면 간단하지만 찾는데 고생(?) 좀 했습니다.

 

ImagePicker 에서 속성으로 exif 를 추가해주면 됩니다.

 

  👉   exif: true

const result = await ImagePicker.launchImageLibraryAsync({
        mediaTypes: ['images'],
        allowsEditing: false,
        quality: 1,
        exif: true,
        legacy: true,
      });

 

exif 추가 정보 : 속성 데이터중  location 정보 추출 가능

"Asset info":{
   "albumId":"-2075821635",
   "creationTime":1741401508375,
   "duration":0,
   "exif":{
      "ApertureValue":1.69,
      "BrightnessValue":6.37,
      "ColorSpace":1,
      "Compression":6,
      "DateTime":"2025:03:08 11:38:28",
      "DateTimeDigitized":"2025:03:08 11:38:28",
      "DateTimeOriginal":"2025:03:08 11:38:28",
      "DigitalZoomRatio":1,
      "ExifVersion":"0220",
      "ExposureBiasValue":0,
      "ExposureMode":0,
      "ExposureProgram":2,
      "ExposureTime":0.005555555555555556,
      "FNumber":1.8,
      "Flash":0,
      "FlashpixVersion":"0100",
      "FocalLength":6.4,
      "FocalLengthIn35mmFilm":23,
      "GPSLatitudeRef":"N",
      "GPSLongitudeRef":"E",
      "ISOSpeedRatings":20,
      "ImageLength":3000,
      "ImageUniqueID":"L40XLOD00NM",
      "ImageWidth":4000,
      "JPEGInterchangeFormat":996,
      "JPEGInterchangeFormatLength":42910,
      "LightSource":0,
      "Make":"samsung",
      "MaxApertureValue":1.69,
      "MeteringMode":3,
      "Model":"SM-S908N",
      "Orientation":6,
      "PixelXDimension":4000,
      "PixelYDimension":3000,
      "ResolutionUnit":2,
      "SceneCaptureType":0,
      "ShutterSpeedValue":0.005555555555555556,
      "Software":"S908NKSS6EYB1",
      "SubSecTime":"375",
      "SubSecTimeDigitized":"375",
      "SubSecTimeOriginal":"375",
      "ThumbnailImageLength":384,
      "ThumbnailImageWidth":512,
      "WhiteBalance":0,
      "XResolution":72,
      "YCbCrPositioning":1,
      "YResolution":72
   },
   "filename":"24047e24-8db0-4bb3-8845-c001747fdd93.jpeg",
   "height":4000,
   "id":"1000010460",
   "localUri":"file:///storage/emulated/0/DCIM/24047e24-8db0-4bb3-8845-c001747fdd93.jpeg",
   "location":{
      "latitude":35.8273183,
      "longitude":128.6223007
   },
   "mediaType":"photo",
   "modificationTime":1741516879000,
   "uri":"file:///storage/emulated/0/DCIM/24047e24-8db0-4bb3-8845-c001747fdd93.jpeg",
   "width":3000
}

 

이렇게 원하는 위치정보를 얻었는데 나머지 한가지 문제는 GPS 위치를 그대로 서비스 할 수 없다는데 있습니다.

물론 지도서비스를 제공하는데는 GPS정보만 있으면 되지만 '주소' 정보가 필요한 경우는 다른 지도 API 를 사용해야 합니다. 

 

이와 같이 하나의 서비스를 제공하는데 있어서 어려움이 많구나를 느끼게 됩니다.

 

저는 구글 Geocoding API를 추가로 적용하여 주소정보를 가져와서 서비스를 제공했습니다.

다른 분들도 다양한 지도 API를 활용하여 서비스에 적용해보시면 될 것 같습니다.

 

저희 다소 험난한 과정을 정리해 보았는데 도움이 되셨기를 바랍니다.

반응형