@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 트랜잭션은 소비 앱에 둡니다.
다음은 검증된 레시피 두 개입니다.