7 min read

[Flutter] Architecture 살펴보기

Flutter Architecture 살펴보기
[Flutter] Architecture 살펴보기
Photo by Danil Shostak / Unsplash

서론

최근에 Flutter를 잘 쓰고 있는데 Architecture를 자세히 살펴보지 않았다. 상용 서비스도 내고, 내부에서도 적극적으로 사용하고 있는데 디테일하게는 모른다. 그래도 개발자로서 어떻게 동작하는지 알면 언젠간 도움이 되겠지 하면서 공부한걸 끄적여 본다.

Flutter

Flutter는 Google에서 만든 UI툴킷으로 하나의 코드 베이스에서 임베딩 된다. 웹, 모바일 데스크탑 등에서 사용할 수 있다.

특정방식으로 UI를 만들 필요 없이 코드로 빌드할 수 있도록 해준다. Flutter 아키텍쳐를 학습하면서 얻을 수 있는 이점은 상태 업데이트, 위젯 또는 화면 빌드, 앱 유지 관리 시 프로그램의 구조화에 도움이 된다.

Flutter Architecture Layer

네이티브 프로그램과 마찬가지로 3가지의 레이어로 구성되어있다. Framework, Engine, Embedder

flutter_layers

Embedder(Platform Specific)

플랫폼 임베더에 의해 제공되며, 운영체제와 연관되어있다. 렌더링된 화면과 입력과 같은 서비스에 액세스 된다. 각 플랫폼별 언어로 작성된다.
Android(Java/Kotlin) / iOS,Mac(Objective-C/Swift) / WIndows, Linux(C++) 등

기존 응용 프로그램에 모듈 혹은 응용프로그램으로 임베드될 수 있다.

Engine(C/C++)

엔진은 C++로 작성이 되어있다. 입력, 출력, 네트워크 요청을 처리하고, 프레임을 렌더링 할 때 변환을 처리하는 역할을 수행한다. Dart클래스에서 C++코드를 랩핑을통해 Flutter Framework에 제공된다.

Framework(Dart)

일반적으로 개발자가 상호작용하는 부분이다. Dart로 작성된 반응적이고 현대적인 프레임워크를 제공한다. 기본적으로 Rendering(렌더링), Widget(위젯), Material/Cupertino(Android/iOS 사용되는 디자인) 이 포함되어있고, 애니메이션과 제스처와 같은 서비스도 블록으로 제공된다.

Flutter Widget

Flutter에서는 모든것이 Widget이다. Flutter UI의 기본 구성요소이며 화면에서 현재 구성과 상태가 어떻게 표시되어야 하는지 나타낼 수 있다.

위젯은 다양한 형태인데 버튼, 이미지, 아이콘, 레이아웃의 형식을 띌 수 있다. 위젯을 사용하게 되면 위젯 트리(Widget Tree)가 생성된다.

Widget Tree

flutter_screen_detail

트리

flutter_rendering

시각화된 위젯 트리, 렌더링되는 순서와 각 위젯이 포함하고 있는 자식 요소들을 확인할 수 있다.

Root → Material → Scaffold

보기에는 어려워보이기도 하는데 실제 코드를 보면 훨씬 간편하게 파악할 수 있다.

코드상으로 볼 때

실제 코드는 생략된 부분이 있지만 어떻게 구성되어 표현되는지 보도록 하자

Scaffold(
	body: Container(
		child: Column(
			children: [
				Text(),
				Text(),
				// ... Expanded(BoxedSize) 등이 있는데 생략
					Center(
						child: Column(
							children: [
								TextField(),
								TextField(),
								Button()
							]
						)
					),
				Button()
			]
		)
	)
)

레이아웃 위젯, 플랫폼별 위젯, 플랙폼 독립적 위젯 및 상태유지 등 그룹화할 수 있다. 위젯을 조립하는 과정을 구성이라 하고, 각각의 작업을 수행하는 여러개의 인터페이스를 통해 화면을 그릴 수 있다. 각 위젯을 쪼개는 방식은 Atomic Pattern을 참고하면 도움이 될 수 있다.

Gesture

Flutter의 위젯과 상호작용은 GestureDetector 를 통해 수행된다. 탭및 드래그 등 사용자의 이벤트를 받을 수 있는 투명한 위젯이다. GestureDetector 페이지를 통해 실제 동작을 볼 수 있다.

6_45

Widget State

말 그대로 위젯의 상태(동작)을 의미한다. 위젯의 속성을 위젯을 만들 때 생성되는데 이 상태는 위젯이 살아있는 동안 병경할 수 있다.

Flutter에서 위젯의 상태는 아래 두가지 타입이 있다.

  • Stateless Widget
  • Stateful Widget

Stateless Widget

단어 그대로 상태가 없는 위젯이다. 초기화 이후에는 변경하지 않는다는것을 의미한다. 실시간 정보를 유지하지 않고, 관리할 상태가 없으며 앱과 직접적인 상호작용이 없을 때 사용합니다.

Icons, IconButton, Text 등이 그 예가될 수 있다.

import 'package:flutter/material.dart';

void main() => runApp(OurApp());

class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Text("바뀌지 않는 화면");
  }
}

위의 코드처럼 빌드 함수가 override되고, BuildContext를 매개변수로 사용하여 위젯을 반환한다.

Stateful Widget

상태에 따라 동적으로 변경될 수 있는 위젯, 실시간 데이터를 저장할 수 있고 그에따라 사용자 인터페이스를 변경할 수 있다. TextField, Slider, Form 등이 그 예다.

상태는 createState() 메서드를 통해 상태 저장 위젯을 생성하고, 사용한다. 상태 클래스의 경우 템플릿으로 입력되어 확장된다. 상태가 저장되는 위젯이기 때문에 메소드가 여러번 호출되고, 이 메서드는 화면의 위젯을 다시 그리도록 호출된다.

상태 객체 내에서 setState() 호출 시 Flutter Framework에게 위젯을 다시 그리라고 명령한다.

void main() => runApp(OurApp());

class App extends StatefulWidget {
  @override
  _AppState createState() => _AppState();
}

class _AppState extends State<App> {
  @override
  Widget build(BuildContext context) {
    return Text("바뀔 수 있는 화면");
  }
}

Rendering Process

Flutter의 렌더링 프로세스는 위젯 → 픽셀로 변환한다.

Flutter의 다중 렌더링 파이프라인은 입력 → 애니메이션 실행 → 위젯 트리 빌드 → 렌더링 객체 배치 → 렌더링 객체 페인팅 → 단일 이미지 컴파일.

위젯 트리의 일부가 사용자 입력, 애니메이션 또는 기타 변경 사항을 수신하면 Flutter 내부에서는 빌드단계로 전환된다. 이 단계에서 프레임워크는 필요한 빌드 메서드를 호출하여 위젯 트리를 재구성한다. 재구성으로는 요소 트리 업데이트, 렌더 객체 트리 업데이트를 수행한다. 렌더 객체는 레이아웃과 페인팅을 담당하는데. 레이아웃 단계에서는 제약조건(Constants)을 전달하고, 페인팅 단계에서는 지정된 위치에 색상을 입힌다.


다른 코드와 동작하는 방식

Flutter 내에서 상호운용이 가능한 프로토콜을 제공한다. Flutter는 플랫폼 채널(Platform Channel)을 통해 사용자 지정코드를 모바일/데스크탑 앱에 통합할 수 있고, Dart와 Native 언어간의 통신을 수행할 수 있다.

플랫폼 채널(Platform Channel)을 통해서 데이터 전달 시. 데이터는 Dart에서 표준형식으로 직렬화 된 다음 Kotlin/Swift 데이터 타입으로 변환된다.