📱 Flutter란?
✅목 차
1. 완전 기초 개념 설명
2. 좀 더 깊은 기본 개념
3. 심화 개념
4. 좀 더 깊은 심화 개념
5. 연관된 이론 및 개념들
6. 구조 설명 + 도식화
7. 실무에서의 활용 맥락
8. 코드 예제
구글에서 만든 오픈소스 UI 프레임워크로, 하나의 코드베이스로 iOS, Android, 웹, 데스크탑 앱을 동시에 개발할 수 있는 도구.
✅ 1. "구글에서 만든"
Flutter는 구글 내부 프로젝트 ‘Sky’에서 시작 (초기 목표: 120fps UI 렌더링)
구글이 적극적으로 유지/개발 중이며, Flutter 1.0은 2018년 정식 출시
현재는 Google Fuchsia OS의 공식 UI 프레임워크로 채택되어 있음
기업 신뢰도와 생존 가능성 측면에서 매우 높은 평가를 받음
✅ 2. "오픈소스 UI 프레임워크"
즉, Dart로 작성한 한 프로젝트가
→ iOS, Android, Web, Windows, macOS, Linux까지 모두 커버 가능
✅ Flutter는 코드베이스가 하나면서도, UI까지 직접 렌더링하는 방식이 특징
→ 디바이스별 편차 적음, 디자인 완전 통일 가능
✅ 4. "iOS, Android, 웹, 데스크탑 앱을 동시에 개발"
플랫폼 | 지원 여부 | 빌드 방법 |
---|---|---|
Android | ✅ 정식 지원 | Gradle |
iOS | ✅ 정식 지원 | Xcode |
Web | ✅ 정식 지원 | WASM + CanvasKit or HTML |
Windows | ✅ 정식 지원 | Win32 API |
macOS | ✅ 정식 지원 | Cocoa API |
Linux | ✅ 정식 지원 | GTK |
각 플랫폼은 Embedder라는 하위 시스템을 통해 렌더링 엔진과 연결됨
즉, 플랫폼마다 실제 앱을 띄워주는 런타임 환경은 다르지만, Flutter 엔진은 동일하게 작동
🟨 Dart는 어떤 언어인가?
속성 | 설명 |
---|---|
개발사 | |
패러다임 | OOP + FP 지원 |
컴파일 | JIT (개발) / AOT (배포) |
특성 | 정적 타입, null safety, async/await 지원 |
📌 Dart는 Flutter와는 뗄 수 없는 관계.
→ 거의 독점적인 관계이며, Dart를 이해하지 않고는 Flutter를 제대로 못 다룸.
✅ 6. "위젯 기반 UI 구성"
Flutter의 모든 UI는 '위젯의 조합으로 구성'됨.
📦 예시: 계층 구조
MaterialApp
└── Scaffold
└── AppBar
└── Body
└── Center
└── Column
└── Text
└── Button
```
위젯은 HTML의 div 같은 구조가 아니라, 실제 '로직과 렌더링을 동시에 담당'
StatelessWidget, StatefulWidget, InheritedWidget, RenderObjectWidget 등 다양한 계층 존재
'Hot Reload'는 Flutter 개발 생산성을 폭발적으로 끌어올린 핵심 기능
항목 | Hot Reload | Hot Restart |
---|---|---|
상태 유지 | ✅ | ❌ 앱 초기화됨 |
속도 | 매우 빠름 | 조금 느림 |
대상 | UI 변경 중심 | 로직 변경 포함 |
✅ 8. "📌 직접 UI를 그린다는 점에서 독보적"
💥 이게 Flutter의 핵심 철학
React Native / Xamarin은 OS의 네이티브 UI 요소를 호출
→ 그래서 성능과 디자인 차이가 발생
Flutter는 Skia/Impeller 엔진을 통해 픽셀 단위로 직접 그린다
즉, Flutter는 iOS/Android의 UI 위젯을 "빌려 쓰는" 게 아니라,
직접 그려서 보여주는 것
그래서 디자인 완전 통일, 모든 플랫폼에서 UI 일관성 보장
📌 이 구조 덕분에:
📌 Flutter는 React Native, Xamarin과 같은 크로스플랫폼 프레임워크 중 하나지만,
직접 UI를 그린다는 점에서 독보적.
항목 | 설명 | 심화 해설 |
---|---|---|
단일 코드베이스 | iOS, Android, Web, Desktop을 하나의 프로젝트/코드로 개발 | 실제로는 플랫폼별 Embedder 가 존재하며, 같은 위젯 트리가 모든 플랫폼에서 작동하도록 플랫폼 추상화 가 잘 되어 있음 |
위젯 기반 구조 | UI 구성 요소가 모두 위젯 형태. 버튼, 텍스트, 레이아웃 전부 위젯으로 표현 | React처럼 함수형 UI 구조. 위젯은 immutable , 상태는 State 객체로 분리하여 관리 |
자체 렌더링 엔진 | Skia(기본) 또는 Impeller(신엔진)로 UI를 직접 그림 | 네이티브 UI 위젯을 "호출"하는 게 아니라 픽셀 단위로 그려 → 디자인 완전 통일 + GPU 최적화된 렌더링 가능 |
고성능 | 네이티브 수준의 빠른 UI 반응성과 애니메이션 제공 | JS 브릿지가 없기 때문에 React Native보다 오버헤드 적음. 특히 Jank-Free Animation 에 강함 |
Hot Reload | 코드 수정 → 화면 즉시 갱신 | JIT 컴파일 기반으로 메모리 상태 유지. UI만 빠르게 교체 → 매우 빠른 테스트/디버깅 사이클 제공 |
장점 | 설명 | 실무 맥락 |
---|---|---|
빠른 개발 사이클 (Hot Reload) | 저장만 해도 앱이 바로 갱신됨 | 디자인 반복, 프로토타입 제작에 탁월. 디자이너와 페어 작업에 매우 효율적 |
뛰어난 UI 커스터마이징 | 위젯 기반 + 직접 렌더링 구조로 모든 UI 요소 완전 제어 가능 | 브랜드/스타일 통일, 테마 시스템, 애니메이션 커스터마이징에 강함 |
코드 재사용성 극대화 | 하나의 코드로 모든 플랫폼에서 동작 | 유지보수 비용 절감. 기능 추가시 수정 범위도 작음 |
성능 우수 (JS Bridge 없음) | 통신 브릿지 없이 Dart → Native로 AOT 컴파일됨 | React Native보다 CPU/GPU 효율성이 높고, 애니메이션이나 제스처 처리도 더 부드럽게 가능 |
단점 | 설명 | 해결 전략 |
---|---|---|
앱 크기 큼 | 아무것도 안 해도 최소 4~5MB | 초기 런타임, 엔진, 폰트 등 포함되기 때문. 리소스 분리/트리 쉐이킹으로 줄이기 가능 |
네이티브 연동 복잡 | 카메라, 백그라운드 서비스, 알림 등은 직접 네이티브 코드 필요 | 플랫폼 채널(MethodChannel) 사용 or 플러그인 활용. 안드로이드/Swift 연동 이해 필수 |
Web/Windows 성능 제한 | Web에서는 DOM 대신 Canvas로 렌더링됨 → DOM 조작 어려움 | Web 특화된 UX 설계 필요. SEO, 접근성 문제 있음 |
커뮤니티/에코시스템 제한 | React Native보다 라이브러리 생태계가 작음 | 패키지 pub.dev 활용 + 직접 플러그인 작성 가능 능력 요구됨 |
항목 | 설명 |
---|---|
Skia | 기존 Flutter 렌더링 엔진. OpenGL 기반 |
Impeller | Flutter 3.10부터 도입된 새로운 엔진. Metal(iOS)/Vulkan(Android) 기반으로 더 안정적 |
차이점 | Skia는 렌더링 최적화 어려움 → Impeller는 Shader 컴파일 사전 처리로 첫 실행 시 렉(Jank) 방지 |
현황 | Flutter 3.13+부터 iOS 기본 활성화, Android는 opt-in 단계 |
항목 | Native | Flutter |
---|---|---|
언어 | Kotlin/Swift/Java | Dart |
UI 구성 | Native UI 컴포넌트 | Flutter 자체 위젯 |
렌더링 | 시스템 뷰 계층 사용 | 자체 엔진 (Skia/Impeller) |
성능 | 최고 성능 | Native에 근접한 성능 |
코드 베이스 | 플랫폼별 별도 | 단일 코드로 모든 플랫폼 |
항목 | Native | Flutter | 심화 설명 |
---|---|---|---|
Android | Kotlin / Java | Dart | Kotlin은 코루틴, Java는 레거시. 둘 다 JVM 기반 |
iOS | Swift / Objective-C | Dart | Swift는 모던하나 iOS 전용 |
공통점 | 각 플랫폼 전용 언어 | Dart 단일 언어 | Dart는 AOT + JIT 모두 지원, async 지원 우수 |
학습 곡선 | 2개 이상 언어 학습 필요 | Dart만 알면 전체 커버 | Dart는 Java/C# 계열 경험자에게 익숙함 |
✅ Flutter는 한 명의 개발자가 전체 플랫폼을 다룰 수 있음
반면 Native는 플랫폼별 팀/개발자 구성이 필요
항목 | Native | Flutter | 심화 설명 |
---|---|---|---|
Android | XML + View 클래스로 구성 | Dart 코드로 직접 위젯 구성 | Flutter는 선언형 UI (React와 유사) |
iOS | Storyboard / SwiftUI | Dart 위젯 시스템 | 위젯은 immutable, 상태는 별도 관리 |
렌더링 | 시스템 뷰 계층 사용 (Android: ViewGroup 등) | Skia로 직접 GPU에 그림 | 플랫폼 UI를 호출하지 않고 직접 그림 |
커스터마이징 | 플랫폼 한계 존재 (커스텀 뷰 필요) | 위젯 조합/커스텀으로 유연함 | CustomPaint로 완전한 UI도 가능 |
✅ Flutter는 디자인 시스템 통일, 커스터마이징 UI에 강력
Native는 기본 컴포넌트 사용에 익숙한 환경
항목 | Native | Flutter |
---|---|---|
렌더링 경로 | 시스템 뷰 계층 → OS → GPU | Dart → Skia/Impeller → GPU |
UI 컨트롤 | OS가 제공하는 UI 컴포넌트 | Flutter 엔진이 직접 픽셀 렌더링 |
오버헤드 | 플랫폼 의존 + 다양한 경로 | 단일 파이프라인, 성능 일관 |
애니메이션 | 프레임워크 제한 있음 | 60fps 이상 애니메이션도 가능 (CustomPainter 등) |
✅ Flutter는 UI 일관성 보장과 GPU 직접 접근이 가능
반면, Native는 OS 버전/디바이스마다 UI 달라질 수 있음
항목 | Native | Flutter |
---|---|---|
컴파일 | AOT (C/Swift/Java) | JIT(개발) / AOT(릴리즈) |
성능 | 최적화된 최고 성능 | 90~95% 수준 (거의 차이 없음) |
프레임 드랍 | 거의 없음 | 초기엔 Skia shader warm-up으로 약간의 jank 있음 |
메모리 관리 | OS가 직접 관리 | Dart VM이 GC 수행 |
✅ Flutter는 이제 Impeller로 Jank 문제 해결 중
Native는 OS와 1:1 최적화 가능성이 있음
항목 | Native | Flutter |
---|---|---|
구조 | 플랫폼별 프로젝트 분리 | 단일 프로젝트 |
재사용성 | 없음 (로직도 분리 필요) | UI + 로직 모두 공유 |
유지보수 | 플랫폼별 이슈 대응 | 하나의 코드로 전체 패치 |
빌드관리 | Android Studio / Xcode 각각 설정 | Flutter CLI로 전체 관리 가능 |
✅ Flutter는 MVP, 스타트업, 빠른 프로토타이핑에 매우 적합
Native는 플랫폼 특화 앱에 적합 (ARKit, BLE 등)
하나의 Dart 코드로 Android, iOS, 웹, 윈도우, macOS 앱까지 동시에 빌드할 수 있는 구조
✅ 개발 속도 극대화
✅ 유지보수 비용 절감
⚠️ 플랫폼별 세부 대응은 여전히 필요 (예: 권한, 파일 경로 등)
항목 | Skia | Impeller |
---|---|---|
GPU API | OpenGL 기반 | Metal (iOS), Vulkan (Android) |
Frame Drop | 있음 (iOS에서 특히) | 매우 적음 |
예측 렌더링 | ❌ 없음 | ✅ 있음 (레이턴시 감소) |
Flutter 버전 적용 | 기본 적용 아님 | Flutter 3.10+부터 iOS 기본 탑재 |
📌 Flutter 3.13부터는 iOS에서 Impeller가 기본 활성화, Android는 추후 적용 확산 중
Flutter에서 도입한 새로운 렌더링 엔진으로, 기존 Skia의 한계를 극복하기 위해 만들어짐.
특히 iOS에서 Skia 기반 Flutter 앱이 프레임 드랍(Jank)을 유발하는 문제가 심각했기 때문.
Flutter에서 작성한 위젯 → GPU에 그릴 수 있는 데이터로 변환 → 화면에 출력
즉, UI를 실제로 “그리는” 부분을 담당.
구분 | Skia | Impeller |
---|---|---|
렌더링 API | OpenGL 기반 | Metal (iOS), Vulkan (Android) |
Shader 실행 | 런타임 컴파일 (느림) | 미리 컴파일 (빠름) |
퍼포먼스 | 예측 불가능한 jank 발생 | 예측 가능하고 부드러움 |
Flutter 적용 시점 | 기본 내장 아님 (옵션 활성화) | Flutter 3.10부터 iOS에서 기본 적용됨 |
flowchart TD
A[Dart UI 코드] --> B[Skia Engine]
B --> C[OpenGL API 호출]
C --> D[GPU]
flowchart TD
A[Dart UI 코드] --> B[Impeller Engine]
B --> C[Metal/Vulkan API 호출]
C --> D[GPU]
기능 | 설명 |
---|---|
Shader pre-compilation | 빌드 시점에 GPU shader를 미리 생성하여 runtime jank 제거 |
Predictable pipeline | 렌더링 파이프라인이 고정되어 있어 성능 예측 용이 |
Metal/Vulkan 최적화 | 각 플랫폼에서 권장하는 최신 GPU API 사용 |
타임라인 안정성 | 애니메이션과 프레임 동기화가 정밀해짐 (특히 iOS에서 중요) |
🔹 프레임 드랍 원인 (기존 Skia)
🔹 Impeller 개선 사항
Dart는 Flutter 앱을 작성하는 언어.
Google이 만든 언어로, JavaScript 대체를 목표로 시작됐지만 Flutter와 함께 부상.
Flutter의 공식 언어이며 필수.
항목 | 설명 |
---|---|
언어 유형 | 객체지향 언어 (Java/C# 계열 느낌) |
주요 특징 | 명확한 문법, 클래스 기반, null safety, async/await |
쓰임새 | Flutter UI/비즈니스 로직, 서버 개발 (Dart Frog 등), CLI 등 |
실행 방식 | JIT(개발 시), AOT(릴리즈 빌드 시) 모두 지원 |
✅ Dart는 Hot Reload와 성능 최적화를 모두 가능하게 만드는 유일한 언어 중 하나
구분 | JIT (Just-In-Time) | AOT (Ahead-Of-Time) |
---|---|---|
시점 | 앱 실행 중 | 앱 빌드 시점 |
용도 | 개발 중 빠른 피드백용 (Hot Reload) | 릴리즈용 최적화된 바이너리 |
장점 | 빠른 반영, 디버깅 용이 | 성능 우수, 앱 실행 속도 빠름 |
단점 | 느린 시작, 최적화 부족 | 디버깅 어려움, 빌드 느림 |
🔹 Flutter의 사용 예:
flutter run → JIT 모드로 실행
flutter build apk/ipa → AOT 컴파일되어 최적화된 앱 생성
String? name; // null 허용
String name = "다미로"; // null 불가
Isolate.spawn(myFunction, "data");
Future<void> fetchData() async {
final res = await http.get(Uri.parse("..."));
print(res.body);
}
Future<String> fetchName() async {
await Future.delayed(Duration(seconds: 1));
return "Damiro";
}
Flutter UI의 근간이 되는 개념. 모든 화면은 위젯 트리로 구성.
Flutter에서는 UI의 모든 요소가 ‘위젯’(Widget).
텍스트, 버튼, 레이아웃, 앱바 등 전부 위젯.
위젯들은 트리 형태로 중첩되어 구조화.
→ 이를 위젯 트리(widget tree) 라고 부름.
📌 React의 Virtual DOM 구조와 매우 유사함.
차이점은 DOM이 아닌 "렌더 객체로 직접 그리기".
종류 | 예시 | 설명 |
---|---|---|
StatelessWidget | Text() , Icon() | 상태 변경 없음 |
StatefulWidget | TextField() , Checkbox() | 상태 변경 있음 |
Layout Widget | Column() , Row() , Padding() | 위치/구성 담당 |
Functional Widget | GestureDetector() | 기능 부여용 (이벤트 등) |
위젯 빌드 순서와 렌더링 파이프라인.
📌 "위젯 트리 → 엘리먼트 트리 → 렌더 트리" 로 연결됨.
개념 | 설명 |
---|---|
BuildContext | 위젯 트리 내 위치 정보 전달 |
Element Tree | 위젯의 인스턴스가 실제로 존재하는 구조 |
RenderObject Tree | 실제 UI를 그리는 구조 |
InheritedWidget | 부모 → 자식 위젯에 데이터 전달 |
Keys | 동일한 위젯을 구분하기 위한 식별자 |
class MyText extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Text("변경되지 않음");
}
}
class MyCounter extends StatefulWidget {
@override
State<MyCounter> createState() => _MyCounterState();
}
class _MyCounterState extends State<MyCounter> {
int count = 0;
@override
Widget build(BuildContext context) {
return Text("Count: $count");
}
}
StatelessWidget: 상태 유지 불가. 생성될 때 한 번 빌드.
StatefulWidget: setState()로 내부 상태 변경 → 다시 빌드됨.
Flutter의 UI가 네이티브 컴포넌트를 쓰지 않고도 직접 그려질 수 있는 핵심 기술 요소
Flutter는 Android/iOS의 네이티브 UI 컴포넌트를 직접 사용하지 않음.
대신, 자체 렌더링 엔진을 사용해 화면의 픽셀을 그림.
이 렌더링 엔진은 주로 Skia였고, 최근에는 Impeller로 점차 전환 중.
📌 즉, Flutter는 "내가 직접 UI를 그린다"는 구조입니다.
Skia란?
Google이 개발한 2D 그래픽 엔진
Chrome, Android, Firefox 등에도 사용됨
Flutter는 Skia를 통해 위젯 트리 → 실제 픽셀로 렌더링
Impeller란?
Skia를 대체하기 위한 Flutter 전용 렌더링 엔진
Metal (iOS), Vulkan (Android) 기반으로 설계
프레임 드롭과 예측 불가능한 레이턴시 문제를 개선
Widget Tree
↓
Element Tree
↓
RenderObject Tree
↓
Layer Tree (Painting)
↓
Scene (Composited Frame)
↓
Engine (Skia or Impeller)
↓
GPU (Metal/OpenGL/Vulkan)
↓
Screen
RenderObject는 위치/크기/layout 정보를 관리
Layer Tree는 실제로 그림을 그리는 역할
최종적으로 Skia/Impeller가 GPU를 통해 화면에 그립니다
항목 | Skia (기존) | Impeller (신규) |
---|---|---|
기반 API | OpenGL | Metal (iOS), Vulkan (Android) |
성능 일관성 | 낮음 (iOS에서 문제) | 높음 (프레임 드롭 거의 없음) |
Shader Precompile | ❌ 없음 | ✅ 있음 (시작 속도 ↑) |
예측 렌더링 | ❌ 불가능 | ✅ 가능 (vsync 미리 처리) |
지원 현황 | 기본 (모든 플랫폼) | Flutter 3.10+ iOS 기본, Android opt-in |
📌 Impeller는 성능과 예측 가능성을 위해 설계된 Flutter 전용 엔진
Flutter는 Dart로 UI를 구성하지만,OS의 고유 기능(카메라, 센서, Bluetooth 등)은 네이티브(Android/iOS) API로 접근해야 합니다.
이때 사용하는 것이 바로 플랫폼 채널 (Platform Channel) 입니다.
Dart ↔ Android(Java/Kotlin), iOS(Swift/Objective-C) 간의 브리지 역할을 합니다.
📌 마치 Flutter가 네이티브에 요청하고, 네이티브가 응답하는 통신 구조
구성 요소 | 설명 |
---|---|
MethodChannel | Dart 측에서 네이티브 함수 호출 |
setMethodCallHandler | 네이티브 측에서 Dart의 요청을 받아 처리 |
invokeMethod() | 네이티브 함수를 Dart에서 호출할 때 사용 |
채널 이름 | "samples.flutter.dev/battery" 같은 string 식별자 |
// Dart
const platform = MethodChannel('samples.flutter.dev/battery');
final batteryLevel = await platform.invokeMethod('getBatteryLevel');
// Android (Kotlin)
methodChannel.setMethodCallHandler { call, result ->
if (call.method == "getBatteryLevel") {
val level = getBatteryLevel()
result.success(level)
}
}
채널 종류 | 설명 |
---|---|
MethodChannel | 함수 호출 기반 (가장 일반적) |
EventChannel | 이벤트 스트림 (센서 등 연속값 전달) |
BasicMessageChannel | 단순 메시지 송수신 (양방향 대화) |
graph LR
Dart[Flutter (Dart)]
--> |MethodChannel| Native[iOS/Android Code]
Native --> |결과 반환| Dart
✅ 실무에서는 플랫폼 기능 연동(카메라, 공유, 알림 등)에 반드시 사용.
구분 | 하이브리드 앱 | 크로스 플랫폼 앱 |
---|---|---|
대표 기술 | Cordova, Ionic | Flutter, React Native |
UI 구성 방식 | WebView 기반 (HTML/CSS/JS) | 실제 네이티브처럼 렌더링 |
성능 | 낮음 (웹처럼 느려짐) | 높음 (Native에 근접) |
앱 크기 | 작음 | 큼 (엔진 포함) |
📌 하이브리드는 "앱 안에 웹 브라우저", 크로스 플랫폼은 "직접 화면을 그림"
하이브리드 앱
내부적으로 WebView를 렌더링
네이티브 기능은 JS → 브리지 → 네이티브 호출
UI/UX는 웹 기준, 느린 인터랙션과 뚜렷한 '웹 느낌'
크로스 플랫폼 앱
Dart/JS로 작성 → 실제 UI를 직접 그림 (Flutter는 Skia)
React Native는 네이티브 컴포넌트 + JS Bridge
Flutter는 네이티브 컴포넌트조차 사용하지 않고 직접 렌더링
항목 | 하이브리드 | React Native | Flutter |
---|---|---|---|
렌더링 방식 | WebView | Native Components + JS Bridge | 직접 그림 (Skia/Impeller) |
브리지 구조 | JS → Native (WebView 내) | JS ↔ Native (Bridge) | 없음 (Dart → 엔진 직접 호출) |
성능 | 낮음 | 중간 | 높음 |
일관된 UI | 브라우저마다 다름 | 플랫폼 별 UI | 동일한 UI |
App Shell
└── WebView
└── HTML/CSS/JS
└── Cordova Plugin → Native API
느리고 일관되지 않음.
JS-Native 간 호출 지연 존재.
Flutter 구조
Dart Framework
└── 위젯 트리 구성
└── 렌더링 트리
└── Engine(Skia/Impeller)
└── GPU로 직접 그림