최신 안정 버전 Flutter 3.44(2026년 5월)와 Dart 3.12 기준으로 본문을 손봤다. 핵심 변화는 다음과 같다.
Impeller가 기본 렌더러로 자리 잡았다. iOS는 Impeller만 지원하고 Skia 경로가 제거됐으며, Android는 Vulkan을 지원하는 API 29 이상에서 기본 활성화된다. Flutter 3.38부터는 Android에서 Impeller를 끄는 opt-out 플래그도 폐기됐다.
Flutter GPU(Dart로 커스텀 렌더러와 3D를 다루는 저수준 그래픽 API)와 WebAssembly(WasmGC) 컴파일이 정식 경로로 들어왔다. 또한 Material과 Cupertino를 코어 SDK에서 물리적으로 분리하는 작업이 2026년에 마무리 단계에 있고, Material 3가 기본 디자인 시스템이다.
Flutter와 Dart가 뭔가
Flutter는 Google이 2017년에 공개한 오픈소스 UI 프레임워크다. 핵심은 하나의 코드베이스로 여러 플랫폼을 동시에 대응할 수 있다는 점이다. iOS, Android는 물론이고 웹, Windows, macOS, Linux까지 지원하며, 데스크톱과 웹 타깃 모두 안정 채널에 올라와 프로덕션에서 쓰인다.
Dart는 Flutter의 프로그래밍 언어다. 2026년 6월 기준 최신 안정 버전은 Dart 3.12로, JavaScript와 Java의 장점을 조합한 느낌인데 타입 시스템이 탄탄하면서도 문법이 깔끔하다. 모든 변수가 기본적으로 null을 허용하지 않는 sound null safety가 표준이고, AOT(Ahead of Time) 컴파일로 네이티브 수준의 성능을 내며, JIT(Just in Time) 컴파일로 개발 중 Hot Reload를 지원한다.
React Native가 JavaScript 브릿지(현재는 JSI 기반 새 아키텍처)를 통해 네이티브 컴포넌트를 호출하는 방식이라면, Flutter는 자체 렌더링 엔진으로 화면을 직접 그린다. 과거에는 Skia를 썼지만, 지금은 새 렌더러인 Impeller가 기본이다. 셰이더를 미리 컴파일해 두기 때문에 첫 실행 시 화면이 끊기는 셰이더 컴파일 지터가 사라졌고, 고주사율 기기에서 120fps까지 안정적으로 뽑아낸다.
- Impeller 렌더링 엔진으로 플랫폼 간 동일한 UI와 안정적 고주사율
- Hot Reload로 코드 수정 즉시 반영
- Material 3 디자인과 Cupertino 위젯 기본 제공
- Dart의 sound null safety와 강력한 타입 시스템
환경 설정과 첫 프로젝트
Flutter 개발을 시작하려면 Flutter SDK를 설치해야 한다. 공식 사이트에서 운영체제에 맞는 버전을 받으면 된다.
Flutter SDK 설치
flutter.dev에서 SDK를 다운로드하고 환경 변수에 등록한다. flutter doctor 명령어로 설정 상태를 확인할 수 있다.
IDE 설정
VS Code 또는 Android Studio에 Flutter/Dart 플러그인을 설치한다. VS Code가 가볍고 빠르지만, Android Studio는 에뮬레이터 관리가 편하다.
첫 프로젝트 생성
flutter create my_app 명령어로 프로젝트를 만들고 flutter run으로 실행한다. 에뮬레이터나 실제 기기에서 카운터 앱이 바로 뜬다.
flutter doctor # 설치 상태 점검
flutter create my_app # 새 프로젝트 생성
cd my_app
flutter run # 연결된 기기/에뮬레이터에서 실행
flutter run -d chrome # 웹(WasmGC)으로 실행
flutter run -d windows # 데스크톱으로 실행
2026년 6월 기준 Impeller가 기본 렌더러다. iOS는 Impeller만 지원하고 Skia 경로가 제거됐으며, Android는 Vulkan을 지원하는 API 29 이상에서 자동으로 켜진다. Flutter 3.38부터 Android의 Impeller opt-out 플래그도 폐기됐으니, 별도 설정 없이 최신 SDK를 그대로 쓰면 된다.
Widget 기초와 레이아웃
Flutter에서 화면에 보이는 모든 것은 Widget이다. 텍스트, 버튼, 이미지, 레이아웃 전부 Widget으로 구성된다. Widget은 크게 StatelessWidget과 StatefulWidget으로 나뉜다.
StatelessWidget vs StatefulWidget
StatelessWidget은 상태가 없는 고정 UI다. 한 번 그려지면 변하지 않는다. StatefulWidget은 내부 상태를 가지고, setState()를 호출하면 화면이 다시 그려진다.
const CounterPage({super.key});
@override
State<CounterPage> createState() => _CounterPageState();
}
class _CounterPageState extends State<CounterPage> {
int _count = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Counter')),
body: Center(child: Text('$_count', style: const TextStyle(fontSize: 48))),
floatingActionButton: FloatingActionButton(
onPressed: () => setState(() => _count++),
child: const Icon(Icons.add),
),
);
}
}
레이아웃 기본: Row, Column, Stack
수평 배치는 Row, 수직 배치는 Column, 겹침 배치는 Stack을 쓴다. Expanded와 Flexible로 비율을 조절하고, Padding과 SizedBox로 여백을 넣는다. 이 세 가지만 잘 조합해도 대부분의 레이아웃을 만들 수 있다.
자주 쓰는 Widget 목록
| Widget | 용도 | 비고 |
|---|---|---|
| Container | 박스 모델 (크기, 배경, 테두리) | CSS의 div와 유사 |
| ListView | 스크롤 가능한 리스트 | builder로 지연 렌더링 |
| GridView | 그리드 레이아웃 | 상품 목록 등에 적합 |
| GestureDetector | 터치 이벤트 감지 | 탭, 스와이프, 드래그 |
| AnimatedContainer | 자동 애니메이션 전환 | 속성 변경 시 부드럽게 전환 |
상태 관리 전략
앱이 커질수록 상태 관리가 핵심이 된다. Flutter에서는 여러 가지 상태 관리 방식이 있는데, 프로젝트 규모에 맞게 선택하면 된다.
Provider
Flutter 팀이 공식 추천했던 상태 관리 도구다. ChangeNotifier 기반으로 동작하고, 학습 곡선이 낮아서 입문자에게 적합하다. 소규모 앱에서는 이것만으로도 충분하다.
Riverpod
Provider의 제작자가 단점을 보완해서 만든 차세대 상태 관리다. 컴파일 타임에 안전성을 보장하고, 전역 상태와 비동기 상태를 깔끔하게 처리한다. 2026년 기준으로 새 프로젝트라면 Riverpod을 권한다. 코드 생성(@riverpod 애너테이션) 방식이 표준으로 자리 잡아 보일러플레이트가 크게 줄었다.
class Counter extends _$Counter {
@override
int build() => 0;
void increment() => state++;
}
// 위젯에서 구독
class CounterText extends ConsumerWidget {
const CounterText({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final count = ref.watch(counterProvider);
return Text('$count');
}
}
BLoC
비즈니스 로직을 UI와 완전히 분리하는 패턴이다. 스트림 기반이라 이벤트 주도 아키텍처에 적합하다. 대규모 팀 프로젝트에서 코드 일관성을 유지하기 좋다. 다만 보일러플레이트 코드가 많은 편이다.
| 방식 | 복잡도 | 추천 규모 |
|---|---|---|
| setState | 최소 | 단일 화면 내 |
| Provider | 낮음 | 소규모 앱 |
| Riverpod | 중간 | 중규모 이상 |
| BLoC | 높음 | 대규모 팀 프로젝트 |
HTTP API 연동
대부분의 앱은 서버와 데이터를 주고받아야 한다. Flutter에서 HTTP 통신은 http 패키지로 기본 처리가 되지만, 실전에서는 Dio를 쓰는 게 편하다.
Dio 라이브러리
인터셉터, 타임아웃, 파일 업로드/다운로드, 취소 토큰 등 실무에서 필요한 기능을 전부 지원한다. 인터셉터로 토큰 자동 갱신이나 에러 처리를 공통화하면 코드 중복이 크게 줄어든다.
JSON 파싱과 모델 클래스
서버에서 받은 JSON 데이터를 Dart 객체로 변환해야 한다. json_serializable과 freezed 패키지를 조합하면 모델 클래스를 자동 생성할 수 있다. dart run build_runner build 한 번이면 불변 모델과 copyWith, 직렬화 코드까지 만들어진다. 타입 안전성이 확보되고, 직렬화/역직렬화 코드를 수동으로 작성할 필요가 없다.
앱 스토어 배포
개발이 끝나면 실제 스토어에 올려야 한다. Android와 iOS 배포 과정은 다르지만, Flutter에서 빌드 자체는 간단하다.
Android 배포
flutter build appbundle로 AAB 파일을 생성하고, Google Play Console에 업로드한다. 서명 키 관리와 버전 코드 관리에 신경 쓰자.
iOS 배포
flutter build ipa로 빌드하고, Xcode나 Transporter로 App Store Connect에 업로드한다. Apple Developer 계정이 필요하고, 첫 심사에 3~7일 정도 걸린다.
Fastlane이나 Codemagic 같은 CI/CD 도구를 연동하면 빌드부터 배포까지 자동화할 수 있다. 반복되는 수동 작업을 줄이고 실수를 방지하는 데 효과적이다.
마무리
Flutter는 크로스플랫폼 앱 개발에서 가장 균형 잡힌 선택지다. Dart 3.12의 생산성, Impeller 렌더러의 일관성, 풍부한 위젯 라이브러리가 결합되어 실제 프로덕션 수준의 앱을 빠르게 만들 수 있다. 2026년에는 모바일을 넘어 WasmGC 기반 웹과 데스크톱까지 같은 코드로 묶는 흐름이 자리 잡았고, Flutter GPU로 3D와 커스텀 렌더링까지 영역을 넓히고 있다.
물론 Dart라는 새로운 언어를 배워야 하고, 네이티브 코드가 필요한 고급 기능에서는 추가 작업이 생긴다. 하지만 하나의 코드베이스로 여러 플랫폼을 대응할 수 있다는 이점은 개발 비용과 유지보수 측면에서 압도적이다.
이미 JavaScript에 익숙하다면 React Native도 좋은 선택이지만, 처음부터 새로 배우는 거라면 Flutter를 추천한다. 공식 문서가 잘 되어 있고, 커뮤니티도 활발하다. 일단 flutter create부터 실행해보자.