Flutter에서 이미지를 다룰 때 iOS의 경로 문제 (Stored image is missing)

Posted by , August 14, 2024
FlutteriOSTroubleshooting
Series ofFlutter

thumbnail

이미지를 다루다가...

전에 마와셀 1.0 버전대 개발을 하다 겪은 일이다.
마와셀에는 와인 사진 및 셀러, 시음 노트에 이미지를 첨부하는 기능이 있다.

img01

안드로이드에서는 잘 되어서 문제없이 넘어갔다가,
iOS도 실제 디바이스에서 테스트를 진행하면서 문제가 없음을 확인했었다.

하지만 iPad용 스크린샷이 필요해서 시뮬레이터에서 구동하다가 문제가 생겼다.


이미지를 못 가져옴

시뮬레이터를 끈 다음 빌드 후 다시 접근하는데 이미지가 없어서 앱 크래시가 발생했다.
물론 2.0에서는 이미지가 없을 때 기본 이미지 표시로 바꾸긴 했다.

마와셀의 이미지는 파일명만 가져와서 저장을 하게 된다.
경로의 경우 조립해서 사용하는 방식을 사용했다.

로직에는 문제가 없었고,
뭔가 이상함을 느낀 나는 몇 가지 로그를 남기며 테스트를 했다.
그 결과 시뮬레이터의 이미지 경로가 계속 변경함을 찾을 수 있었다.

  • 첫 번째 테스트 빌드 하였을 때 경로

/Users/testMan/Library/Developer/CoreSimulator/Devices/73169529-CF2Z-20FT-U1A1-O23DBE772DCA/data/Containers/Data/Application/2DQ07F26-AB29-968D-00FA-DOQE96A35B27/Documents/tmp_img/2233-FF00-img001.png

  • 두 번째 테스트 빌드 하였을 때 경로

/Users/testMan/Library/Developer/CoreSimulator/Devices/73169529-CF2Z-20FT-U1A1-O23DBE772DCA/data/Containers/Data/Application/576G7D01-Z3K0-D2K1-6FFQ-J6YF3ME8A02B/Documents/tmp_img/O1DV-W991-img001.png


iOS는 별도 구현이 필요

위 로그를 보면 알겠지만, 어플리케이션 ID가 계속 변함을 알 수 있다.

저 앱 ID의 경우 path_providergetApplicationDocumentsDirectory를 통해서 가져오게 된다.

class DirectoryManager {
  late final Directory appDir;
  late final Directory tmpDir;

  DirectoryManager();

  Future<void> init() async {
    appDir = await getApplicationDocumentsDirectory();
    tmpDir = Directory('${appDir.path}/tmpRes');

    await _createDirectories();
  }
}

난 디렉토리랑 파일을 다루는 별도의 클래스를 두고,
get_it을 통해서 Injection 해서 사용한다.

해당 문제를 수정하려면 결국 경로를 플랫폼마다 조정해서 써야 한다.
아래의 코드를 참고하자.

try {
      String imgPath;

      ///Android
      if (Platform.isAndroid) {
        imgPath = _getAttachImageFullPath(attachImageEnum);
      }

      ///iOS
      else if (Platform.isIOS) {
        imgPath =
            "${dirManager.appDir.path}/${attachImageEnum.getAttachPath()}";
      }
      // 웹이나 다른 플랫폼의 경우 임시 디렉토리 사용
      else {
        imgPath = (await getTemporaryDirectory()).path;
      }
    } catch (e) {
      logger.d('[cloneFile] Error: $e');
    }

/// 다른 함수
String _getAttachImageCategoryFullPath(AttachImageEnum imgEnum) {
  final directoryManager = getIt.get<DirectoryManager>();
  if (imgEnum == AttachImageEnum.wine) {
    return directoryManager.wine.path;
  }
  return directoryManager.tmpDir.path;
}

내가 사용하는 코드를 잘라서 주요 로직은 잘라낸 예제 코드다.

핵심은 iOS의 경우 getApplicationDocumentsDirectory이거를 직접 가져와서
뒤에 사용자 경로를 붙이면 되고, 그 외 플랫폼은 그냥 고정된 값을 사용해도 된다.


정리

이걸 처음엔 GPT한테 물어봤는데 내가 프롬프트를 이상하게 줘서 스택에서 찾게 되었다.

Flutter-iOS when apps update / recompile stored image is missing

Flutter는 이런 플랫폼 간 몇 가지 설정을 해줘야 하는 부분이 있다.
문제가 생길 땐 Claude나 GPT에게 물어보자.