콘텐츠로 이동

@gj-kit/expo-media 핵심 개념

Expo 미디어 업로드의 위험한 기본값을 사고가 아니라 컴파일 에러로 만듭니다.

Expo 미디어 파이프라인의 사고는 대부분 실패처럼 보이지 않습니다. iOS 26에서 FileSystem.uploadAsync는 업로드를 시작하는 도중 프로세스를 그대로 종료시켜, promise가 reject될 기회도 재시도 로직이 발화할 기회도 없습니다. iOS MediaLibrary가 돌려주는 localUri는 앱 컨테이너가 아니라 사진 보관함 안을 가리키는 경우가 많아 stat은 성공하지만 업로더에 넘기는 순간 네이티브 URLSession을 종료시킵니다. Android는 quality<1 재인코딩 뒤에도 원본 fileSize를 보고해, presign 크기와 스토리지가 실제로 받은 바이트가 어긋납니다.

선택한 asset이 항상 업로드 가능한 것은 아닙니다

섹션 제목: “선택한 asset이 항상 업로드 가능한 것은 아닙니다”

기기 라이브러리 URI는 업로더가 끝날 때까지 유지되지 않을 수 있습니다. adapter 경계는 지속 staging과 정리를 명시적인 앱 결정으로 만듭니다.

업로드 복구는 불확실한 상태에 이름을 붙입니다

섹션 제목: “업로드 복구는 불확실한 상태에 이름을 붙입니다”

네트워크 실패는 업로드됐거나, 업로드됐을 수 있거나, 저장소에 도달하지 못했다는 뜻일 수 있습니다. 공개 recovery metadata는 URL을 노출하지 않고 그 차이를 보존합니다.

  • 무제한 업로드는 명시해야 합니다 — createMediaKit({ api })는 컴파일되지 않습니다. limits는 필수이고 Number.POSITIVE_INFINITY 탈출구도 없어, 무제한은 'server-enforced'라고 적어야 합니다.
  • duplicate는 빠뜨릴 수 없습니다 — UploadResult.duplicate는 옵셔널이 아니라 필수입니다. 값이 빠지면 “새로 생성”으로 오독되고, 그 뒤 중복 취소 경로가 사용자의 예전 사진을 지우기 때문입니다.
  • 사본을 만든 쪽이 정리까지 책임집니다 — createDeviceLibrary는 staging 없이는 컴파일되지 않습니다. 기기 사진을 캐시로 실체화하는 팩토리가 그 사본을 지우는 StagingCache.cleanup을 반드시 함께 갖습니다.
  • iCloud 다운로드는 기본으로 켜지지 않습니다 — adapter.getAssetInfo('id')처럼 인자 하나로 부르면 컴파일 에러입니다. downloadFromNetwork를 담은 두 번째 인자가 필수라 매 호출에서 호출부가 결정하고, 무단 셀룰러 전송을 시작하던 레거시 기본값 true를 adapter가 조용히 물려받을 수 없습니다.
  • peer 격리는 CI가 검증합니다 — dist-peer-graph 가드가 빌드 산출물에서 엔트리별 외부 지정자를 다시 뽑아 browser·node·네이티브 × ESM·CJS로 대조합니다. ./core·./image/pure·./web·./testing은 peer 0으로 확인됩니다.

presigned URL이나 native URI 세부 정보를 공개 오류에 노출하지 말고, 정리 권한과 attachment 트랜잭션은 소비 앱에 둡니다.

다음은 검증된 레시피 두 개입니다.