| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | |
| 7 | 8 | 9 | 10 | 11 | 12 | 13 |
| 14 | 15 | 16 | 17 | 18 | 19 | 20 |
| 21 | 22 | 23 | 24 | 25 | 26 | 27 |
| 28 | 29 | 30 | 31 |
- Clean Architecture
- 자바 포맷 출력
- Flutter
- scss
- develop
- riverpod
- LLM
- lifecycle
- nodejs
- 자바 출력 방식
- DART
- 엡
- react
- abap
- UI/UX
- firebase
- 단축키
- 앱심사
- printf
- ListView
- 자바스크립트
- JQ
- java 출력
- npm
- unity
- java
- 배포
- java 콘솔 출력 차이
- JS
- println
- Today
- Total
guricode
[Flutter] 네이티브 코드와 연동하는 방법 본문
1) 플랫폼 채널 (Platform Channels)
Flutter(Dart)와 Android(Kotlin)/iOS(Swift) 사이에 문자열 메서드 호출 + 직렬화된 메시지로 통신한다.
단발 호출은 MethodChannel, 스트림 이벤트는 EventChannel, raw 메시지는 BasicMessageChannel을 쓴다.
흐름
Dart가 invokeMethod("getBattery") → 네이티브가 같은 채널 이름으로 핸들러 등록 → 결과 반환.
예시: 배터리 잔량 조회 (MethodChannel)
Dart
import 'package:flutter/services.dart';
class NativeBridge {
static const _ch = MethodChannel('app/native');
static Future<int> getBatteryLevel() async {
final level = await _ch.invokeMethod<int>('getBattery');
return level ?? -1;
}
}
Android (Kotlin)
class MainActivity : FlutterActivity() {
override fun configureFlutterEngine(engine: FlutterEngine) {
super.configureFlutterEngine(engine)
MethodChannel(engine.dartExecutor.binaryMessenger, "app/native")
.setMethodCallHandler { call, result ->
if (call.method == "getBattery") {
val level = getBatteryLevel() // 구현
result.success(level)
} else result.notImplemented()
}
}
}
iOS (Swift)
@UIApplicationMain
class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
let controller = window?.rootViewController as! FlutterViewController
let ch = FlutterMethodChannel(name: "app/native", binaryMessenger: controller.binaryMessenger)
ch.setMethodCallHandler { call, result in
if call.method == "getBattery" {
result(Int(UIDevice.current.batteryLevel * 100))
} else { result(FlutterMethodNotImplemented) }
}
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
2) 플러그인 (Plugin)
위 채널 코드를 재사용 가능한 패키지로 캡슐화한다.
flutter create -t plugin my_plugin으로 스캐폴드 생성. 퍼블리시 가능하고 모듈 경계가 명확해진다.
3) Pigeon (타입 안전 RPC 코드 생성)
문자열 키와 맵 직렬화의 취약점을 피하기 위해, Dart 인터페이스 정의 → Dart/Swift/Kotlin 스텁 자동 생성.
런타임 오타·직렬화 실수를 줄인다.
pigeon/dart_api.dart (예시 정의)
import 'package:pigeon/pigeon.dart';
class BatteryLevel {
int? value;
}
@HostApi()
abstract class DeviceApi {
BatteryLevel getBattery();
}
이 파일을 기준으로 Pigeon 실행 → 각 플랫폼 스텁 생성 → 네이티브에서 DeviceApi 구현, Dart에서는 타입 안전 호출.
4) FFI (Foreign Function Interface)
C/C++ 라이브러리를 Dart에서 직접 호출한다. JNI/Obj-C 브리지가 없고 성능이 좋다.
다만 메모리 안전과 포인터 수명 관리를 개발자가 책임진다.
예시: C 합계 함수 호출
C (sum.c)
#include <stdint.h>
int64_t sum_to(int64_t n){ int64_t s=0; for(int64_t i=0;i<n;i++) s+=i; return s; }
Dart (dart:ffi 바인딩)
import 'dart:ffi' as ffi;
import 'dart:io';
typedef c_sum_to = ffi.Int64 Function(ffi.Int64);
typedef d_sum_to = int Function(int);
final lib = ffi.DynamicLibrary.open(
Platform.isAndroid ? 'libsum.so' : 'libsum.dylib'
);
final sumTo = lib.lookupFunction<c_sum_to, d_sum_to>('sum_to');
void main() {
print(sumTo(1000000)); // 네이티브 C 실행
}
5) PlatformView (네이티브 UI 임베딩)
WebView, 지도 같은 네이티브 뷰 자체를 Flutter 위젯 트리에 삽입한다.
스크롤/오버레이/성능 이슈를 고려해야 한다.
예시: Android 네이티브 뷰 삽입
class NativeBanner extends StatelessWidget {
const NativeBanner({super.key});
@override
Widget build(BuildContext context) {
return AndroidView(
viewType: 'native/banner',
layoutDirection: TextDirection.ltr,
creationParams: {'text': 'Hello from Android'},
creationParamsCodec: const StandardMessageCodec(),
);
}
}
Android 쪽에서 PlatformViewFactory를 등록해 viewType: 'native/banner'를 생성한다.
Flutter 네이티브 연동의 기본값은 플랫폼 채널, 타입 안전이 필요하면 Pigeon, 고성능 네이티브 라이브러리는 FFI, 네이티브 UI가 필요하면 PlatformView를 쓴다.
'앱 > Flutter&Dart' 카테고리의 다른 글
| [Flutter] 안드로이드,ios ,버전과 버전코드 (0) | 2025.10.27 |
|---|---|
| 애플 긴급심사 관련 링크 (0) | 2025.10.22 |
| [Flutter]AOT와 JIT 컴파일러 (0) | 2025.10.20 |
| [Flutter] 비동기 처리하는 여러가지 방법 (0) | 2025.10.20 |
| [Flutter] Clean Architecture란? (0) | 2025.10.20 |