Building user interfaces with Flutter
Introduction to user interface development in Flutter.
docs.flutter.dev
위 Flutter의 공식 문서 내용을 보면 Flutter의 UI 철학은 React에서 영감을 받았다고 하는 내용이 있다.
이에 대해서 Gemini에게 물어보니 아래와 같은 답변을 얻을 수 있었는데
Flutter가 React에서 영감을 받았다고 하는 핵심적인 이유는
"선언적(Declarative) UI 패러다임과 '컴포넌트 기반 구조 때문" 이라는 것이다.
1. 선언적 UI (Declarative UI)
- React: State가 변경되면 React가 UI를 다시 그리는데 개발자는 "상태가 이럴 때 UI는 이렇게 보여야 한다"라고 선언만 하면됨.
- Flutter: Flutter 역시 State가 변경되면 build() 메서드가 호출되어 UI를 다시 그림.
공식 문서에서도 "UI는 상태의 함수다" 라는 개념을 강조하는데, 이는 React 핵심철학과 동일하다.

2. 컴포넌트(Widget) 기반 구조
- React: 모든 UI를 소형 컴포넌트 단위로 쪼개고 이를 조립해서 만듭니다.
- Flutter: "Everything is a Widget"이라는 말처럼, 아주 작은 단위부터 전체 화면까지 모두 위젯(Widget)으로 구성된다. React의 Component와 Flutter의 Widget은 개념적으로 거의 동일하다고 볼 수 있다.
3. 효율적인 업데이트 (Diffing Algorithm)
- React: 'Virtual DOM'을 사용하여 이전 상태와 새 상태를 비교(Diffing)하고, 바뀐 부분만 실제 브라우저 DOM에 반영한다.
- Flutter: 위젯 트리(Widget Tree)가 재빌드될 때, Flutter 프레임워크는 이전 위젯 트리와 새 위젯 트리를 비교하여 실제 렌더링 객체(RenderObject) 중 최소한의 변경 사항만 업데이트하는데 이 메커니즘이 React의 조정(Reconciliation) 과정과
매우 흡사함.
4. 단방향 데이터 흐름
- 부모가 자식에게 데이터를 전달하고, 상태 변화에 따라 UI가 아래로 흐르며 갱신되는 방식 또한
React가 대중화시킨 패턴이며 Flutter가 이를 적극적으로 수용하였다.
결국은 Flutter 팀은 기존의 명령형(Imperative) 방식 (ex:Android의 XML, iOS의 UIkit) 보다
React가증명한 현대적인 선언적 UI 프로그래밍 방식이 더 효율적이라고 판단한 것이다.
5. 모든 플랫폼에서 '선언적 UI'로 패러다임의 변환
현재 개발 생태계는 웹, 모바일, 데스크톱을 가리지 않고 선언적(Declarative) UI를 표준으로 채택하고 있다.
이는 단순한 유행이 아니라, 기존 명령형 방식이 가졌던 고질적인 한계를 극복하기 위한 진화의 결과라고 볼 수 있다.
(1) 플랫폼별 선언적 전환 현황
각 진영의 메이저 프레임워크들은 이미 명령형(Imperative)에서 선언적으로 그 중심축을 완전히 옮겼다.
- Web : React의 성공 이후 Vue, Angular, Svelte 등 모든 현대적 프레임워크가 선언적 방식을 기본 모델로 사용함
- Android : 기존 XML 기반의 명령형 방식에서 Jetpack Compose로 전환됨.
- iOS : UIKit의 복잡한 제어 대신 SwiftUI가 공식 표준으로 자리 잡음.
- Cross-platform : Flutter는 탄생부터 React의 선언적 철학을 모바일 환경에 최적화하여 설계됨.
- Desktop (Classic) : WPF는 WinForms라는 명령형 프레임워크처럼 컨트롤의 속성을 일일이 코드로 지정하고, 이벤트 발생 시마다 UI 요소를 수동으로 찾아가서 갱신하다보니 발생하는 상태 불일치 버그 등의 고질적인 문제를 해결하기 위해서
선언적 개념을 도입한 프레임워크이다.
- Desktop (Modern): Microsoft의 WinUI 3나 Kotlin 진영의 Compose for Desktop 역시 선언적 패턴을 지향함.
(2) 선언적 방식이 '증명된 효율성'을 갖는 이유
개발자들이 기존 명령형(Imperative) 방식에서 겪었던 가장 큰 고통은 "UI의 상태(State)와 화면(View) 사이의 동기화"문제였다.
선언적 UI는 이를 다음과 같은 방식으로 해결하여 생산성을 혁신했다.
A. 상태 관리의 단순화 (Single Source of Truth)
- 명령형: 데이터가 바뀔 때마다 label.setText(), button.setColor() 등 UI의 각 요소를 직접 수정해야 했다.
코드가 복잡해지면 하나를 빼먹어 데이터는 '성공'인데 화면은 '로딩 중'인 상태 불일치(Inconsistency) 버그가 빈번했다. - 선언적: 개발자는 "데이터가 A일 때 UI는 B여야 한다"라고 최종 결과물만 정의한다.
데이터(State)가 변하면 프레임워크가 바뀐 부분을 알아서 계산해 화면을 갈아 끼우므로, 데이터와 UI가 항상 일치한다.
B. 가독성과 유지보수성 (What vs How)
- 명령형: 화면을 "어떻게(How) 조작할 것인가"에 집중하다보니 로직이 길어지면 UI 구조를 파악하기 위해 수많은 조작 코드를 역추적해야 하는 문제가 발생한다.
- 선언적: 화면에 "무엇(What)이 보여야 하는가"에 집중한다. 코드 구조 자체가 UI 계층 구조와 일치하므로, 코드만 보고도 화면 설계를 직관적으로 이해할 수 있어 협업과 유지보수에 압도적으로 유리하다.
C. 복잡한 인터랙션의 체계적 대응
현대적인 앱은 다크모드, 애니메이션, 기기별 반응형 레이아웃 등 실시간으로 변하는 요소가 매우 많은데 명령형으로 이 모든 경우의 수를 제어하면 조건문이 꼬여 '스파게티 코드'가 되기 십상이지만, 선언적 방식은 상태 변화에 따른 레이아웃의 규칙만 세워두면 프레임워크가 복잡한 처리를 대신 수행한다.
'Flutter' 카테고리의 다른 글
| Flutter 프로젝트 생성하기. (1) | 2026.03.08 |
|---|
