사전 Flutter
구현체

Flutter

gabury1고친 사람 github-actions[bot]

Flutter 는 코드 한 벌로 Android 앱과 iPhone 앱의 화면을 함께 짜게 해 주는 Google 의 도구입니다. 화면은 작은 부품을 겹겹이 끼워 맞추는 코드로 적습니다. 그 화면을 그리는 일도 운영체제에 맡기지 않고 Flutter 가 직접 합니다.

쉽고 빠른 이해

Flutter 는 앱 화면을 한 번 짜서 Android 폰과 iPhone 에 같이 띄우게 합니다. 「안녕, 유미」 한 줄을 띄우는 화면 조각을 한 번 적으면 두 기기에서 똑같이 뜨는 식입니다.

이게 없으면 같은 화면을 Android 용과 iPhone 용으로 두 번 짜야 합니다. 로그인 화면 하나를 고쳐도 두 곳을 고칩니다. 한쪽을 빠뜨리면 두 앱의 동작이 어긋납니다.

어떻게 도는가:

  1. 화면을 작은 부품으로 쪼개 겹겹이 끼워 맞추는 코드로 적습니다
  2. 화면이 기대는 값이 바뀌면 다시 그려 달라고 Flutter 에 알립니다
  3. Flutter 가 달라진 곳을 찾아 화면에 직접 그립니다

대가도 있습니다. 그리는 프로그램을 앱 안에 싣고 다니므로 설치 파일이 커집니다. Flutter 는 운영체제 부품을 흉내 내어 직접 그리므로, 운영체제가 부품의 생김새를 바꾸면 Flutter 가 따라 그릴 때까지 옛 모양이 보입니다. 카메라 같은 기기 기능은 Kotlin 이나 Swift 로 짠 코드를 따로 거쳐 씁니다.

두 기기에 같은 앱을 낼 때 Flutter 를 고릅니다. 한 운영체제에만 낼 앱은 그 운영체제의 도구로 짭니다.

상세

Flutter 는 앱의 UI(User Interface, 사용자 인터페이스)를 짜는 프레임워크입니다. UI 는 사용자가 보고 누르는 화면 전체를 말합니다. Google 이 만들었습니다. 누구나 코드를 보고 고칠 수 있는 오픈 소스로 내놓았습니다.

코드 한 벌이 Android 와 iOS(iPhone 의 운영체제)에서 함께 돕니다. 웹 브라우저와 Windows · macOS · Linux 데스크톱도 같은 코드로 겨냥합니다. 이렇게 여러 운영체제를 한 코드로 겨냥하는 도구를 크로스플랫폼 프레임워크라고 부릅니다.

코드는 Dart 로 적습니다. Dart 는 Google 이 만든 프로그래밍 언어입니다. 클래스와 정적 타입이 있어서 Java 를 쓰던 사람에게 낯설지 않습니다.

두 벌로 짜던 모바일 앱

Android 앱과 iPhone 앱은 원래 서로 다른 도구로 짭니다. Android 는 Kotlin 으로, iPhone 은 Swift 로 짜는 일이 많습니다. 화면에 놓는 버튼과 글자 칸 같은 부품도 운영체제가 저마다 따로 내놓습니다.

그래서 같은 앱을 두 운영체제에 내려면 코드를 두 벌 짭니다. 대개 팀도 둘로 나뉩니다. 로그인 화면 하나를 고쳐도 두 곳을 고칩니다. 한쪽을 빠뜨리면 두 앱의 동작이 어긋납니다.

운영체제마다 그 운영체제의 전용 도구로 짠 앱을 네이티브 앱이라고 부릅니다. Flutter 는 이 두 벌을 한 벌로 줄이려고 나왔습니다.

화면을 직접 그린다

한 코드로 두 운영체제를 겨냥하는 길은 크게 둘입니다. 하나는 운영체제가 주는 화면 부품을 빌려 쓰는 길입니다. React Native 가 이 길을 갑니다. 버튼을 달라고 하면 Android 에서는 Android 버튼이, iPhone 에서는 iPhone 버튼이 뜹니다.

Flutter 는 다른 길을 갑니다. 운영체제의 화면 부품을 쓰지 않습니다. 버튼의 테두리와 글자까지 Flutter 가 픽셀 단위로 직접 그립니다. 운영체제에게서 받는 것은 그림을 그릴 빈 화면 한 장과 터치 입력뿐입니다.

직접 그리는 까닭은 두 운영체제에서 같은 화면을 얻기 위해서입니다. 빌려 쓰는 부품은 운영체제마다 생김새와 동작이 조금씩 다릅니다. 직접 그리면 두 기기에 같은 픽셀이 찍힙니다.

이 일을 Flutter 는 세 계층으로 나눠 합니다. 맨 위의 프레임워크 계층은 Dart 로 짠 라이브러리입니다. 개발자가 쓰는 화면 부품이 여기 들어 있습니다.

이 계층 이름의 「프레임워크」는 Flutter 전체가 아니라 그 안의 맨 위 계층 하나를 가리킵니다. 앞에서 Flutter 를 프레임워크라고 부른 것과는 다른 쓰임입니다.

그 아래 엔진 계층은 C++ 로 짰습니다. 프레임워크가 넘긴 그림을 픽셀로 바꿉니다. 화면을 그리는 이 프로그램을 렌더링 엔진이라고 부릅니다.

맨 아래 임베더 계층은 운영체제마다 따로 있습니다. 임베더는 운영체제 안에서 앱 창을 열고 터치 입력을 받아 엔진에 넘기는 코드입니다.

flowchart TD
    A["앱 코드 · Dart"] --> F["프레임워크 계층 · 화면 부품을 담은 Dart 라이브러리"]
    F --> E["엔진 계층 · C++ · 그림을 픽셀로 바꾼다"]
    E --> M["임베더 계층 · 창과 터치 입력을 운영체제에서 받아 온다"]
    M --> O["Android · iOS · 웹 · 데스크톱"]

운영체제마다 따로 짜는 것은 주로 맨 아래 임베더 계층입니다. 그 위의 앱 코드와 프레임워크 계층은 어느 기기에서나 같습니다.

모든 것이 위젯이다

Flutter 에서는 화면 부품을 위젯이라고 부릅니다. 글자 한 줄도, 버튼도, 여백도 위젯입니다. 화면 한 장은 위젯 안에 위젯을 끼워 넣은 나무 모양이 됩니다. 이것을 위젯 트리라고 부릅니다.

위젯은 화면이 어떻게 생겨야 하는지를 적은 설정값입니다. 한 번 만들면 안의 값을 바꾸지 않는 불변 객체입니다. 화면이 달라져야 하면 위젯을 고치지 않고 새로 만듭니다.

백엔드 개발자에게는 Thymeleaf 같은 템플릿 엔진이 가까운 예입니다. 템플릿은 모델 데이터를 받아 웹 페이지 한 장을 만듭니다. 데이터가 바뀌면 이미 보낸 페이지를 고치지 않고 페이지를 새로 만듭니다. Flutter 의 위젯도 값을 받아 화면 모습을 새로 내놓습니다.

이렇게 결과의 모양만 적고 거기까지 가는 절차는 도구에 맡기는 방식을 선언형이라고 부릅니다. 반대로 화면 부품을 찾아 값을 하나씩 바꾸라고 시키는 방식은 명령형입니다.

아래는 이름을 받아 인사말 한 줄을 띄우는 위젯입니다. 주석은 이름으로 「유미」를 넘겼을 때 화면에 뜨는 글자입니다.

dart
class Greeting extends StatelessWidget {
  Greeting(this.name);
  final String name;

  @override
  Widget build(BuildContext context) =>
      Text('안녕, $name'); // 안녕, 유미
}

StatelessWidget 은 스스로 바뀌는 값이 없는 위젯이 상속하는 클래스입니다. 이 위젯이 어떻게 생겼는지는 build 메서드가 돌려줍니다. Flutter 는 화면을 그려야 할 때 이 메서드를 부릅니다.

Text 는 글자 한 줄을 화면에 놓는 위젯입니다. Flutter 가 기본으로 내놓는 위젯입니다. 버튼과 그림과 입력 칸도 이렇게 위젯으로 들어 있습니다.

build 가 받는 context 는 이 위젯이 트리 어디에 붙어 있는지 알려 주는 값입니다. 이 예에서는 쓰지 않습니다.

코드에는 Java 와 모양이 다른 Dart 문법이 셋 나옵니다.

Dart 문법 뜻
Greeting(this.name); 인자로 받은 값을 name 필드에 바로 넣는 생성자
=> 식 하나만 돌려주는 메서드를 짧게 적는 법
'안녕, $name' 문자열 안에 변수 값을 끼워 넣는 법

위젯 뒤에 남는 객체

위젯을 자주 새로 만들어도 괜찮은 까닭은 Flutter 가 위젯 뒤에 객체를 두 가지 더 두기 때문입니다. 하나는 트리 안의 위치를 기억하는 엘리먼트입니다. 다른 하나는 크기를 재고 화면에 그리는 렌더 객체입니다.

하는 일 얼마나 사나
위젯 화면이 어떻게 생겨야 하는지 적는다 build 가 불릴 때마다 새로 만든다
엘리먼트 트리 안의 위치를 기억한다. 위젯과 렌더 객체를 잇는다 그 위치에 같은 종류의 위젯이 오는 동안
렌더 객체 크기와 위치를 재고 화면에 그린다 엘리먼트가 붙잡고 있는 동안

새 위젯이 오면 엘리먼트가 바로 전 위젯과 견줍니다. 종류가 같으면 렌더 객체를 버리지 않습니다. 바뀐 값만 렌더 객체에 넘깁니다. 싸게 새로 만드는 것은 위젯뿐입니다. 만들기 비싼 렌더 객체는 뒤에 남아 다시 쓰입니다.

상태와 setState

값이 바뀌면 화면도 따라 바뀌어야 하는 값을 상태라고 부릅니다. 좋아요 수나 입력 칸에 친 글자가 상태입니다.

위젯은 불변이라 상태를 품지 못합니다. 그래서 상태가 있는 화면 부품은 클래스 둘로 짭니다. StatefulWidget 을 상속한 위젯 클래스와, 상태를 쥐는 State 클래스입니다. 위젯은 자주 새로 만들어집니다. State 객체는 엘리먼트에 붙어 오래 남습니다.

아래는 누를 때마다 숫자가 하나씩 오르는 좋아요 버튼입니다. 주석은 버튼 글자가 누를 때마다 바뀌는 모습입니다.

dart
class LikeButton extends StatefulWidget {
  @override
  State<LikeButton> createState() =>
      _LikeState();
}

class _LikeState extends State<LikeButton> {
  int likes = 0;

  @override
  Widget build(BuildContext context) {
    return TextButton(
      onPressed: () => setState(() => likes++),
      child: Text('$likes'), // 0 → 1 → 2
    );
  }
}

createState 는 Flutter 가 이 위젯의 State 객체를 처음 한 번 만들 때 부르는 메서드입니다.

_LikeState 이름 앞의 _ 는 이 파일 밖에서 못 보게 하는 Dart 의 표시입니다. Java 의 private 과 같은 구실을 합니다.

TextButton 은 글자를 담은 버튼 위젯입니다. onPressed 에는 눌렸을 때 돌 함수를 넘깁니다. child 에는 버튼 안에 보일 위젯을 넘깁니다. () => ... 는 이름 없는 함수입니다. Java 의 람다와 같은 구실을 합니다.

setState 가 이 코드의 핵심입니다. setState 는 넘겨받은 함수를 돌려 likes 를 1 올립니다. 그리고 이 State 가 맡은 화면 부품을 다시 그려야 한다고 Flutter 에 표시합니다. Flutter 는 다음 화면을 그릴 때 build 를 다시 불러 새 위젯을 얻습니다.

setState 없이 likes++ 만 하면 값은 오르지만 화면은 그대로입니다. Flutter 가 값이 바뀐 줄 모르기 때문입니다.

버튼 한 번이 화면까지 가는 길을 그리면 아래와 같습니다.

sequenceDiagram
    participant 사용자
    participant S as _LikeState
    participant F as Flutter
    participant 화면
    사용자->>S: 버튼을 누른다
    S->>S: setState 안에서 likes 를 1 올린다
    S->>F: 다시 그려야 한다고 표시한다
    F->>S: 다음 화면 때 build 를 다시 부른다
    S-->>F: 새 위젯
    Note over F: 엘리먼트가 전 위젯과 견준다
    F->>화면: 달라진 글자를 다시 그린다

여러 화면이 함께 쓰는 상태

setState 는 위젯 하나가 쥐는 작은 값에 씁니다. 로그인한 사용자나 장바구니처럼 여러 화면이 함께 쓰는 값은 트리 위쪽에 두고 아래로 내려 줍니다.

Flutter 는 이 일을 맡는 InheritedWidget 을 둡니다. 트리 위쪽에 이 위젯을 놓으면 그 아래 어느 위젯이든 값을 꺼내 읽습니다. 값이 바뀌면 그 값을 꺼내 읽은 위젯만 다시 그려집니다.

실무에서는 이 일을 더 편하게 해 주는 상태 관리 패키지를 따로 골라 쓰는 일이 많습니다. 어느 패키지를 쓸지는 팀마다 갈립니다. 흔히 쓰는 패키지 이름은 아래 관련 항목에 모아 두었습니다.

배치도 위젯이다

위젯을 어떻게 늘어놓을지도 위젯으로 적습니다. 배치를 맡는 위젯은 안에 든 위젯들을 어떤 방향으로 늘어놓을지 적습니다. 실제 크기와 위치를 재는 일은 그 뒤의 렌더 객체가 합니다.

위젯 안의 것을 놓는 방향
Column 위에서 아래로 쌓는다
Row 왼쪽에서 오른쪽으로 늘어놓는다
Stack 한곳에 겹쳐 놓는다

여백과 가운데 맞춤 같은 꾸밈도 위젯입니다. 글자에 여백을 두르려면 Padding 위젯으로 Text 를 감쌉니다.

dart
Padding(
  padding: EdgeInsets.all(16), // 사방 16
  child: Text('주문'),
)

EdgeInsets.all(16) 은 위아래와 좌우에 같은 여백을 줍니다. 꾸밈을 하나 더할 때마다 감싸는 위젯이 한 겹 늘어납니다. 그래서 Flutter 코드는 괄호가 깊게 겹칩니다. 겹이 깊어지면 한 덩이를 떼어 따로 위젯 클래스로 만듭니다.

이렇게 겹친 위젯이 곧 위젯 트리입니다. Column 안에 여백을 두른 글자와 버튼을 쌓은 화면이면 트리는 아래 모양입니다.

flowchart TD
    C["Column"] --> P["Padding"]
    C --> B["TextButton"]
    P --> T1["Text('주문')"]
    B --> T2["Text('0')"]

렌더 객체가 크기와 위치를 재는 순서는 이렇습니다. 부모 렌더 객체는 자식에게 쓸 수 있는 크기의 범위를 내려 줍니다. 이 범위를 제약이라고 부릅니다.

자식은 그 범위 안에서 자기 크기를 정해 올려 보냅니다. 부모는 받은 크기를 보고 자식의 위치를 정합니다.

sequenceDiagram
    participant 부모
    participant 자식
    부모->>자식: 제약 · 폭은 0~300 사이
    자식-->>부모: 크기 · 폭 120
    Note over 부모: 받은 크기로 자식의 위치를 정한다

자식은 부모가 준 범위를 넘는 크기를 고르지 못합니다. 제약이 한 번 내려가고 크기가 한 번 올라오면 배치가 끝납니다. 트리 전체를 위에서 아래로 한 번 훑고 돌아오면 모든 렌더 객체의 크기와 위치가 정해집니다.

목록

주문 목록처럼 같은 모양이 여러 줄 되풀이되는 화면은 ListView.builder 로 짭니다. 줄 번호를 받아 그 줄의 위젯을 돌려주는 함수를 넘깁니다.

dart
ListView.builder(
  itemCount: orders.length,
  itemBuilder: (context, i) =>
      OrderRow(orders[i]),
)

OrderRow 는 주문 한 건을 그리도록 개발자가 짠 위젯입니다. ListView.builder 는 화면에 보이는 줄의 위젯만 그때그때 만듭니다. 주문이 천 건이어도 보이는 열 줄 남짓만 만듭니다.

줄이 지워지거나 순서가 바뀌면 문제가 하나 생깁니다. 엘리먼트는 새 위젯을 트리 안의 순서대로 전 위젯과 짝짓습니다.

주문 A 줄과 B 줄이 있고 A 줄을 지운다고 해 봅시다. 순서대로 짝지으므로 첫째 엘리먼트에 B 줄 위젯이 옵니다. State 는 엘리먼트에 붙어 남으므로(앞의 「상태와 setState」), B 줄이 A 줄의 State 를 쥐게 됩니다. 상태가 엉뚱한 줄에 붙은 것입니다.

이럴 때 위젯마다 주문 번호 같은 키를 답니다. 그러면 엘리먼트가 순서가 아니라 키로 짝을 찾습니다.

flowchart TD
    subgraph S1["지우기 전"]
        WA["주문 A 위젯"] --> E1["엘리먼트 1 · A 의 State"]
        WB["주문 B 위젯"] --> E2["엘리먼트 2 · B 의 State"]
    end
    subgraph S2["A 를 지운 뒤 · 키 없음"]
        WB2["주문 B 위젯"] --> E1b["엘리먼트 1 · A 의 State"]
    end
    subgraph S3["A 를 지운 뒤 · 키 있음"]
        WB3["주문 B 위젯 · 키 B"] --> E2c["엘리먼트 2 · B 의 State"]
    end
    S1 ~~~ S2 ~~~ S3

키가 없으면 B 줄이 순서를 따라 엘리먼트 1 에 붙어 A 의 상태를 보입니다. 키가 있으면 B 줄이 제 상태를 쥔 엘리먼트 2 를 찾아갑니다.

직접 그리는 대가

화면을 직접 그리는 선택에는 값이 따릅니다. 첫째는 설치 파일 크기입니다. Flutter 엔진이 앱 안에 함께 실립니다. 그래서 같은 화면을 운영체제 부품으로 짠 앱보다 설치 파일이 큽니다.

둘째는 운영체제의 생김새를 따라가는 일입니다. Flutter 는 운영체제마다 그 생김새를 본뜬 위젯 묶음을 따로 내놓습니다.

Android 풍 묶음은 Material 위젯입니다. Material 은 Google 이 정한 화면 디자인 규칙입니다. iPhone 풍 묶음은 Cupertino 위젯입니다. iPhone 화면 부품의 생김새를 본떴습니다.

두 묶음 모두 Flutter 가 운영체제 부품을 흉내 내어 그린 것입니다. 운영체제가 부품의 생김새를 바꾸면 Flutter 가 따라 그릴 때까지 앱은 옛 모양을 보입니다.

셋째는 기기 기능입니다. 카메라나 블루투스 같은 기능은 운영체제가 주는 API(Application Programming Interface, 응용 프로그램 인터페이스)로 씁니다. Dart 코드가 이 API 를 쓰려면 대개 Kotlin 이나 Swift 로 짠 코드를 거칩니다. 그 길은 아래 「맞물림」 절에서 봅니다.

Flutter 를 고르는 경우

코드 한 벌로 Android 와 iPhone 에 같은 앱을 내려면 Flutter 를 고릅니다. 두 기기에서 화면이 같게 보여야 하는 앱도 Flutter 를 고릅니다.

한 운영체제에만 낼 앱은 그 운영체제의 도구로 짜는 일이 많습니다. Android 에는 Jetpack Compose, iPhone 에는 SwiftUI 가 같은 선언형 방식을 씁니다. 운영체제가 새로 내놓은 화면 부품을 바로 써야 하는 앱도 그쪽 도구로 짭니다.

맞물림

Flutter 는 혼자 앱을 이루지 않습니다. 같은 Google 이 만든 Dart 가 Flutter 코드를 기계어로 바꿉니다. 운영체제 쪽 코드와는 메시지를 주고받습니다. 이 절은 Flutter 를 쓰면 거의 반드시 만나는 세 가지 붙는 방식을 봅니다.

Dart 가 Flutter 코드를 두 가지로 컴파일한다

개발하는 동안 Flutter 앱은 Dart 의 가상 머신 위에서 돕니다. 가상 머신은 코드를 받아 실행해 주는 프로그램입니다. Java 의 JVM(Java Virtual Machine) 과 같은 구실을 합니다.

이때 Dart 는 코드를 실행하는 도중에 그때그때 기계어로 바꿉니다. 이 방식을 JIT(Just-In-Time) 컴파일이라고 부릅니다. 필요한 때에 맞춰 컴파일한다는 뜻입니다.

JIT 덕분에 핫 리로드가 됩니다. 코드를 고쳐 저장하면 바뀐 코드만 실행 중인 앱에 넣습니다. 앱을 껐다 켜지 않으니 보던 화면과 상태가 남은 채로 새 모습이 뜹니다.

출시할 앱은 다르게 만듭니다. Dart 가 코드를 미리 기계어로 바꿔 앱에 담습니다. 이 방식이 AOT(Ahead-Of-Time) 컴파일입니다. 실행 전에 미리 컴파일한다는 뜻입니다. 실행 도중에 컴파일하지 않으니 앱이 빨리 뜹니다.

대가는 둘입니다. 핫 리로드는 앱을 다시 시작하지 않습니다. 그래서 main 함수나 State 필드의 첫 값처럼 처음 한 번만 도는 코드를 고치면 반영되지 않습니다. 그때는 앱을 처음부터 다시 띄우는 핫 리스타트를 씁니다.

그리고 개발용 빌드는 JIT 로 돌아서 출시용보다 느립니다. 화면이 버벅이는지는 출시용과 같은 방식으로 만든 빌드에서 재야 합니다.

Flutter 가 운영체제 쪽 코드를 부른다

카메라 같은 기기 기능은 Kotlin 이나 Swift 쪽에 있습니다. Flutter 는 플랫폼 채널로 그 코드를 부릅니다. 플랫폼 채널은 Dart 코드와 운영체제 쪽 코드가 메시지를 주고받는 통로입니다.

Dart 쪽이 채널 이름과 메서드 이름, 인자를 담아 메시지를 보냅니다. 운영체제 쪽 코드는 같은 이름의 채널에서 메시지를 받아 기기 기능을 부릅니다. 그리고 결과를 메시지로 돌려보냅니다. 서버에 요청을 보내고 응답을 받는 것과 같은 모양입니다.

아래는 운영체제 쪽에 배터리 잔량을 묻는 Dart 코드입니다. 주석은 돌아온 값의 한 예입니다.

dart
const channel = MethodChannel('app/battery');

final level = await channel
    .invokeMethod<int>('getLevel'); // 87

MethodChannel 이 앞에서 말한 플랫폼 채널 하나입니다. invokeMethod 는 메서드 이름을 담아 운영체제 쪽에 메시지를 보내는 호출입니다.

sequenceDiagram
    participant D as Dart 코드
    participant O as 운영체제 쪽 코드 · Kotlin · Swift
    participant K as 기기 기능
    D->>O: 채널 app/battery · 메서드 getLevel
    Note over D,O: 값은 바이트로 바뀌어 오간다
    O->>K: 배터리 잔량을 묻는다
    K-->>O: 87
    O-->>D: 결과 87

await 는 결과가 올 때까지 이 함수를 멈추고 기다리는 Dart 문법입니다. 기다리는 동안 화면은 멈추지 않습니다. 이렇게 결과를 나중에 받는 방식이 비동기입니다.

대가는 경계를 넘는 비용입니다. 메시지는 값을 바이트로 바꾸는 직렬화를 거쳐 오갑니다. 호출마다 이 변환 비용이 듭니다. 그리고 기능 하나를 Dart, Kotlin, Swift 세 언어로 짜게 됩니다.

실무에서는 이 코드를 직접 짜기보다 플러그인을 받아 씁니다. 플러그인은 Dart 코드와 운영체제별 코드를 한 묶음으로 담은 패키지입니다. Dart 패키지 저장소 pub.dev 에서 받습니다. 받은 플러그인 안에서도 같은 채널이 돕니다.

네이티브 앱이 Flutter 화면을 품는다

이미 Kotlin 이나 Swift 로 짠 앱에 Flutter 화면 몇 장만 넣을 수도 있습니다. 이 방식을 add-to-app 이라고 부릅니다. 큰 앱이 한 번에 옮기지 않고 화면 하나씩 Flutter 로 바꿔 갈 때 씁니다.

Android 에서 화면 한 장을 맡는 객체는 액티비티입니다. iPhone 에서는 뷰 컨트롤러가 같은 일을 맡습니다. 운영체제 쪽 코드는 화면을 이 객체 단위로 엽니다.

Flutter 는 이 객체에 대응하는 것을 운영체제마다 내놓습니다. Android 에는 FlutterActivity, iPhone 에는 FlutterViewController 입니다. 운영체제 쪽 코드가 보기에는 평범한 화면 한 장입니다. 그 안에서 Flutter 엔진이 돌며 Dart 로 짠 화면을 그립니다.

대가는 엔진을 띄우는 비용입니다. 엔진을 처음 띄울 때 시간과 메모리가 듭니다. 그래서 Flutter 화면을 처음 열 때 잠깐 늦습니다. 이를 줄이려고 앱이 켜질 때 엔진을 미리 띄워 두고 화면을 열 때 가져다 씁니다. 네이티브 쪽과 Flutter 쪽이 값을 나눌 때는 앞의 플랫폼 채널을 다시 씁니다.

관련 항목

Flutter 가 속하는 상위 분류

프레임워크 · UI 툴킷 · 크로스플랫폼 프레임워크 · 모바일 개발 · 사용자 인터페이스

Flutter 앱이 도는 플랫폼

Android · iOS · 웹 브라우저 · Windows · macOS · Linux

Flutter 를 짜고 빌드하는 언어와 도구

Dart · 가상 머신 · JIT 컴파일 · AOT 컴파일 · 핫 리로드 · 핫 리스타트 · pub.dev · Flutter DevTools · Android Studio

Flutter 화면을 이루는 구성 요소

위젯 · 위젯 트리 · 엘리먼트 · 렌더 객체 · 렌더링 엔진 · 위젯 키 · 레이아웃 · Material Design · Cupertino

Flutter 상태를 다루는 위젯과 패키지

UI 상태 · setState · InheritedWidget · Provider · Riverpod · BLoC

Flutter 위젯 방식이 기대는 프로그래밍 개념

선언형 프로그래밍 · 명령형 프로그래밍 · 불변 객체 · 템플릿 엔진 · 단방향 데이터 흐름 · 단일 진실 공급원

Flutter 와 운영체제 코드를 잇는 수단

플랫폼 채널 · 플러그인 · add-to-app · Kotlin · Swift · 액티비티 · 뷰 컨트롤러 · 직렬화 · 비동기

Flutter 와 같은 일을 두고 겨루는 UI 도구

React Native · Jetpack Compose · SwiftUI · Compose Multiplatform · Kotlin Multiplatform · Xamarin · .NET MAUI · 네이티브 앱

다른 이름: 플러터