라티의 작은 일기장

패스트캠퍼스 환급챌린지 10일차 미션(2월 10일): 15개 프로젝트로 실무까지 끝내는 Dart & Flutter 앱 개발 강의 후기 본문

Flutter & Dart

패스트캠퍼스 환급챌린지 10일차 미션(2월 10일): 15개 프로젝트로 실무까지 끝내는 Dart & Flutter 앱 개발 강의 후기

코드라티 2024. 2. 10. 23:53

벌써 Part 2 중반까지 왔다...

오늘 다뤄볼 내용은 Flutter 위젯의 Lifecycle(생명주기)과 아키텍처이다.

위젯은 웹 개발에서 컴포넌트에 해당하는 개념이라고 얘기했었는데, 그렇다보니 생명주기 또한 존재한다.

여기서 생명주기란, 위젯이 생성되고 동작을 수행한 뒤에 프로그램 내에서 정리되는 과정을 의미한다.

우선 Stateless 위젯의 생명주기는 단순하게 아래의 순서로 흘러간다.

- Create

- build()

- dispose

한번 빌드되면 변화할 필요가 없는 위젯이다보니 이렇게 단순한 생명주기를 갖는다.

그래서 많이 사용해도 메모리 사용 최적화를 위한 별도의 노력을 요구하지 않는다. 그럼 Stateful 위젯은 어떨까?

Stateful 위젯의 생명주기는 그림으로 도식화해서 나타내보았다.

처음 보면 조금 복잡해보일 수 있지만 중요한 단계들에 집중해서 보면 또 그렇게 복잡하지도 않다.

일단 중요한 부분은 내부적으로 상태를 관리하고 있어서 initState()과정과 build() 과정이 분리되어있는 점, 상태가 변경되면 build()를 다시 수행하는 점, 마지막으로 더이상 활성화 상태가 아니라면 deactivate에 들어서서 dispose()되어 메모리에서 정리되는 점이다.

깊게 생각해봐야하는 부분은 상태 변경에 의한 build()의 호출이 철저히 개발자의 의도에 의해 이루어져야한다는 점인데, 위젯이 몇 개 없는 단순한 앱의 경우는 그나마 이런 case에 대한 예측이 어느 정도 가능하지만, 위젯 간의 상호작용이 많은데 개수도 많은 복잡한 앱의 경우는 상태 관리에 대한 복잡성이 매우 높아진다. (웹 개발 때 Prop 드릴링 생각하면 될듯) 그래서 Flutter도 전역 상태 관리 도구들이 존재한다.

잘 알려진 것들에는 Riverpod / BLoC / GetX / Provider / Redux 등이 있다고 한다. (Redux 반갑고)

 

다음은 Flutter 앱의 아키텍처에 관한 내용을 다뤄보겠다. 이 내용은 공식문서에서 이미 다루고 있는 내용 중 일부에 대한 요약이 주를 이룬다. (https://docs.flutter.dev/resources/architectural-overview)

일단 중요도가 높은 내용 중 하나는, 아키텍처 중 계층에 관한 것이다.

Architectural layers - 출처: docs.flutter.dev

 

위에서 아래로 내려올 수록 로우레벨에 가까워지고, 우리가 사용하는 Flutter의 경우 Framerwork 계층에 해당한다고 볼 수 있다.

엥? 이게 무슨 말이지? 이게 Flutter 내부 구조 아닌가? 하시는 분들이 계실 수 있는데, 엄밀히 말하면 Flutter의 역할은 Framework로서 Dart를 기반으로 작성된 앱이 Engine 계층으로 전달되도록하는 역할이라는 것이다.

그럼 Engine 계층은 왜 필요한걸까? Flutter에서 Dart를 네이티브 코드로 번역한 뒤에 바로 Embedder 계층으로 내려보내지 않는 이유는 뭘까?

사실 Flutter와 같은 크로스 플랫폼 개발 도구로 React Native라는 것이 있다. (JS로 네이티브 앱을 개발할 때 사용)

React Native는 Flutter에 비해 느리다는 의견이 있는데 이것은 React Native가 JS를 네이티브 코드로 변환하고 이것을 토대로 앱을 렌더링하는 구조에 기인한다. Flutter는 Engine 계층에서 기계어에 가깝게 한번 컴파일 되어 로우레벨 단으로 전달되기 때문에 React Native에 비해 빠르다고 한다.

 

그러면 Flutter는 어떤 Engine을 사용하고 있을까? 3.10 버전이 나오기 전에는 AOS / IOS 모두 Skia라는 엔진을 사용했고, 3.10버전 부터는 IOS 앱을 렌더링할 때 Impeller라는 엔진을 사용한다고 한다.(AOS도 Impeller를 활용하도록 현재 변경 작업에 있다고 한다.)

그리고 이 렌더링 엔진이 안드로이드 앱을 렌더링 하는 경우 Canvas라는 컴포넌트에서 앱의 화면을 렌더링한다고 한다.

Skia -> Impeller로 건너오면서 얻은 이점은 무엇일까? 가장 두드러진 변화는 3D 렌더링이 가능해졌다는 것이고, 부수적으로 렌더링 속도에서 개선이 이루어졌다고 한다.

 

아래 내용은 우리가 위젯을 트리 구조로 조립하며 앱을 만들 때 Element Tree라는 것이 생성된다는 내용에 관한 것이다.

나는 이거 보고 바로 DOM 트리 생각했다.

Build: from Widget to Element - 출처: docs.flutter.dev

우리가 사용하는 위젯은 모두 Element라는 것으로 변환이 되어 별도의 Tree를 구성하고, 실제 렌더링 시 생성된다.

 

그리고 각 플랫폼의 네이티브 코드를 실행하기 위해 사용하는 Platform channel이 있고, FFI(Foreign Function Interface)라는 임베디드 기기와 통신하기 위한 기능도 지원한다고 한다.

 

본 포스팅은 패스트캠퍼스 환급 챌린지 참여를 위해 작성하였습니다.

https://bit.ly/48sS29N