(위의 귀여운 친구들은 플러터 마스코트 대시랍니다!)
안녕하세요! 제가 이때까지 플러터 프레임워크를 사용한지 1년이란 시간이 훌쩍 넘어가게 되었는데요.
학생이란 신분에 회사를 재직하면서 이런저런 고난과 많은 실패를 거듭해 큰 프로젝트들을 성공적으로
완수시키고 이제 퇴사를 하게 되는데 그랬던 과정속에서 혼자 플러터 공부를 하다보니 많은 역경을
겪었답니다. 그리고 이제 제 후배들에게 플러터 스터디를 해주는 좋은 기회를 얻게 되어서 이렇게 플러터
스터디 시리즈를 작성해보려 합니다. 이를 통해 저도 기본기부터 다시 다지면서 더 깊게 공부하고 아직 많이
부족하지만 최대한 제 경험을 녹여 잘 써볼게요 !
플러터 스터디를 함에 앞서 플러터가 무엇인지부터 알아야겠죠?
플러터는 구글에서 개발한 크로스 플랫폼 프레임워크입니다. 구글에서 개발했기에 언어 역시 구글에서 개발한 다트언어를 사용합니다. 플러터 1.0은 2018년에 처음 출시되었으며, 2021년과 2022년 각각 2.0, 3.0 버전이 발표되었습니다.
플러터 3.0 발표 이후 윈도우, 맥 운영체제, 리눅스, iOS, Android, 웹의 6개 플랫폼을 공식으로 지원하는 프레임워크로 자리잡고 있습니다. 이외에도 임베디드 시스템, 웨어러블 디바이스 , iOT 개발등 다양한 플랫폼에서의 개발을 할 수 있는 프레임워크로 자리잡고 있습니다.
플러터는 2020년에 들어서 구글 트렌드, 깃허브 스타등 다양한 지표에서 대표적인 경쟁자인 리액트 네이티브를 추월했습니다. 현재는 플러터의 친정인 구글을 비롯해서 네이버 지식iN, 카카오브레인, 라인등 유수의 기업들이 플러터를 활용해서 자사의 앱을 개발하고 있습니다.
플러터는 대부분의 개발자와 초심자들에게 문턱이 낮은편에 속합니다.
다트언어는 C-패밀리 문법을 사용하기 때문에, C,C++,자바,자바스크립트를 기존에 다루던 개발자들에게 사실상 부담이 거의 없는 수준입니다. 또한 기존 프로그래밍 언어에 비해 유연한 코딩스타일을 보유하고 있습니다. 때에 따라 자바나 자바스크립트처럼 코드를 작성할 수 있습니다.
UI를 작성하는 방식도 위젯을 조합하여 만들어 내거나 선언형 UI를 사용하는 등 똑같이 UI 작업이 포함된 웹 프론트엔와 iOS의 최신 트렌드를 잘 따르고 있습니다.
Dart는 모든 플랫폼에서 빠른 앱을 개발하기 위해 클라이언트에 최적화된 언어입니다.
클라이언트에 최적화된 다트에 대해서 알아봅시다~!
🤩 JIT (Just in Time)
컴파일, 인터프리트 방식을 섞어 놓은 방식으로 프로그램 실행 중 컴파일 가능한 방법.
캐싱을 사용하여 자주사용되는 코드를 어딘가에 저장해두고(컴파일 언어의 특성)
실행시점에 인터프리터 방식인 한 줄씩 읽기를 하면서 실행된다.
😎 AOT (Ahead of Time)
프로그램 작성 중 컴파일을 실행하는 방법.
인터프리터 방식처럼 런타임에 들어서기 전에 모든 컴파일을 완료시키고 프로그램이 동작된다. 런타임 시(실행 중 일때) 속도가 빠르지만 개발 시에는 무조건 재실행 되기에 개발속도가 느리다.
JIT을 지원하기에 핫 리로드 기능을 원활히 수행해서 개발중에 개발자가 변화하는 것을 바로 캐치가 가능하고, 배포할 때는 AOT 컴파일을 통해 런타임에서 바로 동작하는 코드를 만들 수 있답니다!
네이티브에 준하는 성능
Flutter는 자체 엔진을 통해 프레임워크가 UI를 직접 그려주기 때문에
React-Native 처럼 브릿지를 통해 작성된 코드를 네이티브로 변환하는 과정을 거치지 않아 정말 빠릅니다!
🤬 Null Safety
bool isEmpty(String value) => value.length == 0;
void main() {
String value;
isEmpty(value);
}
이 코드의 문제점은 어디에 있을까요? 바로 value가 초기화되지 않았는데 value의 length를 확인한다는 점입니다. 그래서 여기서 null 참조 오류가 발생하는데요.
여기서 비효율적인것이 코드 자체는 실행 되지만 참조 오류가 발생하게 됩니다. 이때 해결책으로 value가 null인지 아닌지 체크 해주는 코드를 작성해서 막을수는 있겠지만 코드의 양이 많아지게 되면 엄청 비효율적인 코드가 작성되게 됩니다.
이를 해결하기 위해서 Data type 자체에 null을 허용하는 것과 허용하지 않는 것으로 분리합니다. 위의 코드에서 null safety를 적용하면 문법오류를 발생시킴으로써 실행조차 하지 못하게 합니다.
null safety를 적용하면 null을 허용하는 타입과 아닌 타입으로 타입자체가 달라지기 때문이죠.
그래서 null safety는 실행 단계의 null 참조오류를 코딩단의 문법오류로 바꾸는 효과로 달라져 결과적으로 null 참조오류의 가능성을 상당히 낮추는 기대효과가 있습니다.
bool isEmpty(String value) => value.length == 0;
void main() {
String? value;
isEmpty(value);
}
이렇게 String 타입 뒤에 ?를 붙여줌으로써 문법단의 오류로 바꿔주는 효과를 지니게 됨으로 실행 자체를 막아버립니다.
이외에도 엄청 다양하고 최근 records, patterns, class modifiers등 새롭고 개발자 친화적인 기능이 계속해서 나오고 진화중인 언어입니다!
Flutter app은 위젯을 기반으로 구성되며, 위젯은 앱의 UI 요소를 구축하는 데 필요한 기본 단위입니다.
플러터에서는 크게 두 가지 종류의 위젯을 사용합니다. StatelessWidget과 StatefulWidget.
플러터 앱은 위젯의 계층 구조로 이루어져 있습니다.
각 위젯은 부모 위젯과 자식 위젯을 가질 수 있으며, 이를 통해 복잡합 UI를 구성할 수 있습니다.
부모 위젯은 자식 위젯을 가지고 있으며, 자식 위젯은 다시 자신의 부모가 될 수 있습니다.
위젯은 다양한 속성을 가지고 있어서 해당 위젯의 모양, 크기, 색상 등을 조절할 수 있습니다.
플러터에서는 위젯의 속성을 변경하여 레이아웃을 조정하거나 스타일을 적용할 수 있습니다.
플러터는 위젯 트리를 사용하여 화면을 그립니다.
참고로, 위젯 트리는 부모 위젯과 자식 위젯들이 계층 구조로 연결된 구조를 말합니다.
앱의 시작점은 최상위 위젯인 MaterialApp입니다.
MaterialApp은 앱의 전반적인 구성을 정의하고, 화면 라우팅, 테마 설정등의 다양한 기능을 제공합니다.
MaterialApp의 자식 위젯은 주로 Scaffold 위젯이 사용되며, Scaffold는 앱의 기본 레이아웃을 정의합니다.
Scaffold 위젯 내부에는 AppBar 위젯과 Body 위젯이 포함됩니다.
AppBar 위젯은 상단에 앱의 타이틀이나 액션 버튼을 표시하는 데 사용되며, Body 위젯은 앱의 실제 콘텐츠를 표시하는 데 사용됩니다.
Body 위젯은 다양한 위젯으로 구성될 수 있으며, 예를 들어 Column, ListView, Container 등을 사용하여 콘텐츠를 배치하고 스크롤 가능한 영역을 만들 수 있습니다.
또한, 위젯은 특정 이벤트에 반응하거나 사용자 입력을 처리하기 위해 사용될 수도 있습니다.
예를 들어, ElevatedButton 위젯은 사용자가 버튼을 클릭할 때 특정 동작을 수행하도록 할 수 있습니다.
플러터는 위젯의 상태 변화를 감지하고 자동으로 UI를 업데이트하는 "핫 리로딩" 기능을 제공하여 개발자가 쉽게 UI를 수정하고 확인할 수 있도록 합니다.
참고로, 위젯은 다양한 속성과 메서드를 가지고 있어 개발자가 원하는 대로 UI를 구성하고 조작할 수 있습니다.
또한, 플러터는 다양한 내장 위젯을 제공하며, 필요에 따라 사용자 정의 위젯을 만들 수도 있습니다.
플러터는 위젯 트리로 구축된다는 이야기는 잘 알려져 있지만 단순히 Widget 트리 구조만으로 플러터의 화면이나 요소가 만들어지는 건 아닙니다. 위젯 트리 외에도 Element 트리, RenderObject 트리가 존재합니다. 이 세 개의 트리가 어떤 관계가 있는지 알아보겠습니다.
Widget 트리는 immutable(불변)인 오브젝트로 구성되어 있습니다. 위젯 트리는 생성 및 파기 비용이 매우 작도록 설계 되었습니다. 즉, 자주 바꿀 수 있는 Widget 트리의 업데이트에 순간적으로 대응할 수 있도록 설계되어 있습니다.
Element 트리는 mutable(가변)인 오브젝트로 구성되어 있습니다. Element 트리는 두 가지 역할을 하는데, 위젯 트리의 상태를 관리하고, RenderObject 트리의 라이프사이클을 관리합니다. 위젯 트리가 불변이기 때문에 Element는 위젯 트리를 대신해서 상태를 관리해 주는 역할을 대신해 줍니다. 즉 Element 트리는 위젯 트리와 RenderObject 트리의 중재 역할을 해준다고 볼 수 있습니다.
RenderObject의 역할은 화면 렌더링과 그리기입니다. RenderObject 트리는 mutable(가변) 객체로 구성됩니다. 따라서 Flutter가 실제로 화면에 표시할 때 참조하는 것은 Widget 트리가 아닌 RenderObject 트리가 됩니다.
제가 개인적으로 생각하는 플러터의 장점은 기능적인 측면도 무시못하지만 무엇보다 제가 만들기 원하는 것을
플러터 하나를 통해 빠르게 개발할 수 있다는 점이라고 생각합니다! 아직 웹이나 데스크탑 앱은 앱에 비해
초기단계라고 할 수 있겠지만 2017년에 출시된 프레임워크가 정말 빠르게 시장을 지배하고 있습니다.
무엇보다 구글에서 언어와 프레임워크를 개발하고 전격적으로 지원하고 있기에 현재 시장을 점차 장악하고
있다고 판단되는데요. 시간이 가면 갈수록 플러터는 선택이 아닌 필수인 세상이 오지않을까? 라는 생각도 저는
하고 있습니다.
이렇게 플러터와 다트에 대해 알아보는 첫시간을 간단하게 가졌습니다!
그리고 다음시간에는 Dartpad를 활용해 Dart가 가지고 있는 장점을 알려주는 문법을 공부하고 간단하게 UI에 적용을 해서 실습해보는 시간을 가져보겠습니다!
그러기 위해서는 UI를 어떻게 그리는지도 알아야겠죠? 그래서 기본 위젯들과 UI를 어떻게 그리는지 알아보고
Dart의 문법을 활용해서 코딩을 하는 시간을 가져보려고 합니다!
모두들 즐겁게 개발합시다!
학생 신분에 회사까지 다니면서 힘드셨겠네요 ㅠㅠ