블로그 목록
apps

expo-sharing으로 파일 공유하기 — 네이티브 공유 시트 띄우기

앱에서 CSV 리포트를 하나 뽑아서 사용자가 메일이나 카카오톡으로 보낼 수 있게 하고 싶었다. 웹이면 navigator.share로 끝날 일인데, React Native에는 그게 없다. 파일을 만든 다음 그걸 다른 앱으로 넘기는 통로가 필요했다.

찾아보니 방법이 둘로 갈렸다. 텍스트나 URL을 공유하는 건 React Native 내장 Share API로 되고, 로컬 파일을 넘기는 건 expo-sharing을 써야 한다. 이걸 처음에 헷갈려서, Share.share({ url: 파일경로 })를 iOS에서 억지로 굴리다가 Android에서 안 돼서 한참 헤맸다.

설치

npx expo install expo-sharing

파일 만들고 공유하기

expo-sharing은 이름 그대로 "이미 존재하는 로컬 파일"을 공유 시트에 태우는 역할만 한다. 그래서 보통 expo-file-system으로 파일을 먼저 쓴 다음 그 경로를 넘긴다.

import * as Sharing from 'expo-sharing';
import { File, Paths } from 'expo-file-system';

async function exportCsv(rows: string[][]) {
  // 공유 가능한 환경인지 먼저 확인 (시뮬레이터·일부 기기는 false)
  if (!(await Sharing.isAvailableAsync())) {
    alert('이 기기에서는 공유를 사용할 수 없어요.');
    return;
  }

  const csv = rows.map((r) => r.join(',')).join('\n');
  const file = new File(Paths.cache, 'report.csv');
  file.write(csv);

  await Sharing.shareAsync(file.uri, {
    mimeType: 'text/csv',           // Android가 어떤 앱을 띄울지 판단하는 기준
    UTI: 'public.comma-separated-values-text', // iOS 쪽 타입 힌트
    dialogTitle: '리포트 공유하기',
  });
}

포인트가 두 개다. 하나는 isAvailableAsync()를 꼭 먼저 부르는 것. 시뮬레이터에서는 false가 나오는 경우가 많아서, 이 체크 없이 바로 shareAsync를 부르면 조용히 아무 일도 안 일어나서 디버깅이 괴롭다.

다른 하나는 mimeType과 UTI를 넣어주는 것. 안 넣어도 동작은 하는데, Android에서 공유 시트에 엉뚱한 앱까지 다 뜨거나 정작 필요한 앱이 안 뜨는 일이 생긴다. 파일 타입을 명시해주면 OS가 알맞은 앱만 추려서 보여준다.

텍스트·URL은 다른 API

다시 강조하면, expo-sharing으로 순수 텍스트나 링크를 넘기려고 하면 안 된다. 그건 내장 API가 담당이다.

import { Share } from 'react-native';

await Share.share({ message: '이 글 좋더라: https://example.com' });

정리

  • 파일(이미지, CSV, PDF 등) → expo-sharing + expo-file-system
  • 텍스트·URL → React Native 내장 Share
  • shareAsync 전에 항상 isAvailableAsync()로 가드
  • mimeType/UTI를 넣어야 공유 시트가 깔끔하게 뜬다

파일 하나 내보내는 데 별도 화면이나 라이브러리를 만들 필요 없이, 몇 줄로 OS 공유 시트를 그대로 빌려 쓸 수 있다는 게 제일 마음에 들었다.