guricode

[Flutter] 네이티브 기능과 연결하기 위한 패키지 사용 경험 본문

앱/Flutter&Dart

[Flutter] 네이티브 기능과 연결하기 위한 패키지 사용 경험

agentrakugaki 2025. 10. 20. 02:19

1. 이미지 처리 관련 네이티브 기능

image_picker 패키지를 사용하여 갤러리에서 이미지를 선택하는 기능을 구현

// lib/data/datasources/image_picker_datasource_impl.dart
class ImagePickerDataSourceImpl implements ImagePickerDataSource {
  final ImagePicker _picker;

  @override
  Future<List<XFile>> pickMultiImage() async {
    final pickedFiles = await _picker.pickMultiImage(
      imageQuality: 80,  // 이미지 품질 설정
    );
    return pickedFiles;
  }
}

이 패키지는 Android의 갤러리 앱과 iOS의 Photos 앱에 직접 접근하여 네이티브 이미지 선택 UI를 제공

2. 디바이스 정보 접근

device_info_plus 패키지를 사용하여 플랫폼별 디바이스 정보를 가져오는 기능:

// lib/presentation/device_info.dart
Future<void> _getDeviceModel() async {
  final deviceInfo = DeviceInfoPlugin();

  String? model;
  if (Platform.isAndroid) {
    final androidInfo = await deviceInfo.androidInfo;
    model = androidInfo.model; // 예: "SM-G991B"
  } else if (Platform.isIOS) {
    final iosInfo = await deviceInfo.iosInfo;
    model = iosInfo.utsname.machine; // 예: "iPhone15,3"
  }
}

3. 웹뷰를 통한 네이티브 브라우저 기능

webview_flutter 패키지를 사용하여 개인정보처리방침 페이지에서 웹 콘텐츠를 표시:

// lib/presentation/screens/auth/page/privacy_policy_page.dart
final controller = WebViewController()
  ..setJavaScriptMode(JavaScriptMode.unrestricted)
  ..loadRequest(
    Uri.parse("https://www.notion.so/278e795aec4c8002bca1df539c27f6cd"),
  );

4. 로컬 데이터 저장

shared_preferences 패키지를 사용하여 사용자 동의 정보를 로컬에 저장:

Future<void> _setConsent(bool consent, BuildContext context) async {
  final prefs = await SharedPreferences.getInstance();
  await prefs.setBool('privacy_consent', consent);
}

5. 소셜 로그인 네이티브 연동

google_sign_insign_in_with_apple 패키지를 사용하여 네이티브 소셜 로그인:

// lib/data/datasources/auth_datasource.dart
final GoogleSignIn _googleSignIn = GoogleSignIn(
  clientId: Platform.isIOS
      ? '932235207263-ls86slhic1mfi5big5h46hv35r83egtb.apps.googleusercontent.com'
      : null,
);

6. 이미지 압축

flutter_image_compress 패키지를 사용하여 네이티브 이미지 압축 기능을 활용

7. 권한 관리

permission_handler 패키지를 사용하여 카메라, 갤러리 접근 권한을 관리

8. 지역화 및 시간대

timezone 패키지를 사용하여 네이티브 시간대 정보를 활용:

// lib/main.dart
tz.initializeTimeZones();

 

 

 

 

가장 복잡했던 네이티브 기능 연동

소셜 로그인 (Google Sign-In + Apple Sign-In)이 가장 복잡했던 네이티브 기능 연동이었다.

1. 플랫폼별 설정의 복잡성

Firebase 설정의 플랫폼별 차이점:

// lib/firebase_options.dart
static FirebaseOptions get currentPlatform {
  switch (defaultTargetPlatform) {
    case TargetPlatform.android:
      return android;  // Android 전용 설정
    case TargetPlatform.iOS:
      return ios;      // iOS 전용 설정
  }
}

Google Sign-In의 플랫폼별 clientId 처리:

// lib/data/datasources/auth_datasource.dart
final GoogleSignIn _googleSignIn = GoogleSignIn(
  clientId: Platform.isIOS
      ? '932235207263-ls86slhic1mfi5big5h46hv35r83egtb.apps.googleusercontent.com'
      : null,  // Android는 null (자동 감지)
);

2. Apple Sign-In의 iOS 전용 제약

@override
Future<AuthModel?> signInWithApple() async {
  // iOS에서만 Apple 로그인 허용
  if (!Platform.isIOS) {
    throw Exception('Apple 로그인은 iOS에서만 지원됩니다.');
  }

  // Apple 전용 nonce 생성 및 처리
  final rawNonce = _generateNonce();
  final hashedNonce = _sha256ofString(rawNonce);
}

3. 네이티브 설정 파일의 복잡성

iOS Info.plist 설정:

<!-- Google Sign-In URL Scheme -->
<key>CFBundleURLSchemes</key>
<array>
  <string>com.googleusercontent.apps.932235207263-ls86slhic1mfi5big5h46hv35r83egtb</string>
</array>

<!-- Apple Sign In URL Scheme -->
<key>CFBundleURLSchemes</key>
<array>
  <string>com.example.jaChwi</string>
</array>

iOS Entitlements 설정:

<!-- ios/Runner/Runner.entitlements -->
<key>com.apple.developer.applesignin</key>
<array>
  <string>Default</string>
</array>

플랫폼별 차이점 해결 방법

1. 조건부 컴파일을 통한 플랫폼 분기

// 디바이스 정보 처리
Future<String> _getDeviceName() async {
  if (Platform.isAndroid) return 'Android';
  if (Platform.isIOS) return 'iOS';
  return 'unknown';
}

// 디바이스 모델 정보 처리
if (Platform.isAndroid) {
  final androidInfo = await deviceInfo.androidInfo;
  model = androidInfo.model; // "SM-G991B"
} else if (Platform.isIOS) {
  final iosInfo = await deviceInfo.iosInfo;
  model = iosInfo.utsname.machine; // "iPhone15,3"
}

2. Firebase 설정의 자동 플랫폼 감지

// lib/main.dart
await Firebase.initializeApp(
  options: DefaultFirebaseOptions.currentPlatform
);

3. UI 레벨에서의 플랫폼별 처리

// Apple 로그인 버튼 표시 조건
// if (!Platform.isIOS) {
//   return SizedBox.shrink(); // Android에서는 버튼 숨김
// }

4. 빌드 설정의 플랫폼별 차이

Android (build.gradle.kts):

plugins {
    id("com.google.gms.google-services")
    id("com.google.firebase.crashlytics")
}

iOS (Podfile):

# iOS 전용 Firebase 설정

가장 어려웠던 점과 해결 방법

  1. Google Sign-In의 clientId 차이: iOS는 명시적 설정, Android는 자동 감지
  2. URL Scheme 설정: 각 플랫폼별로 다른 URL scheme 설정
  3. Firebase 프로젝트 설정: Android와 iOS용 별도 앱 등록