Medium - Why Flutter Uses Dart
in Trend
Trend 파악을 Medium 기고문 요약 포스팅 - 플러터가 다트를 사용하는 이유에 대해.
Flutter loves Dart
많은 언어학자들은 사람이 사용하는 언어가 그들의 사고방식에 영향을 준다고 생각합니다. 같은 개념이 컴퓨터 언어에도 적용될까요? 다른 종류의 언어를 사용하는 프로그래머들은 문제를 해결하는 데 있어서 종종 근본적인 차이를 보이곤 합니다. 극단적인 예를 들자면 컴퓨터 과학자들은 더욱 구조적인 프로그램을 위해 goto 구문을 제거합니다. (소설 1984의 빅브라더가 사상범죄를 제거하기 위해 이단적인 단어를 삭제한 것과 비슷한건 아니지만 무슨 의미인지 아셨을 겁니다.)
이런 것이 다트와 플러터에서는 어떨꽈요? 꽤 많은 영향을 미칩니다. 초기 플러터 팀은 수십개의 언어를 평가하고 다트를 선택했습니다. 왜냐하면 다트가 사용자 인터페이스를 구성하는 방식이 일치했기 때문입니다.
다트는 개발자들이 플러터를 사랑하는 큰 이유입니다. 어떤 사람은 이런 트윗을 남기기도 했습니다.
@flutterio got me to look at @dart, and I’m glad I took it for a spin. #Dart is an awesome language, and #flutterio takes it even further, to mobile devices <3— Jordy (@Jordy_vD_) 2018년 1월 8일
아래는 플러터에게 없어서는 안될 다트의 특징을 간략히 오약한 리스트 입니다.
- 다트는 사전컴파일이기 때문에 빠르고 예측가능하며 네이티브 코드라서 플러터의 거의 모든 것을 다트로 작성할 수 있게 합니다. 이것은 플러터를 빠르게 할 뿐만 아니라 위젯을 포함하여 모든 것이 수정될 수 있게 합니다.
- 다트는 빠른 개발 사이클을 위한 JIT 컴파일과 게임 체인징 워크플로우(플러터의 인기있는 상태저장 핫리로드)가 가능합니다.
- 다트는 초당 60프레임에 해당하는 자연스러운 애니메이션과 움직임을 쉽게 만들 수 있습니다. 다트는 lock이 없이도 모든 객체들의 할당과 가비지 컬렉션을 할 수 있습니다. 자바스크립트와 같이 자바스크립트는 선점 스케줄링과 메모리 공유를 피합니다. 플러터의 앱이 네이티브 코드로 컴파일 되므로 자바스크립트와 달리 느려지게 만드는 브릿지가 필요한 영역이 없습니다. 또 한 시작시간이 더욱 빠릅니다.
- 다트는 플러타가 JSX나 XML과 같은 선언적 레이아웃 언어나 레이아웃 빌더가 필요하지 않습니다. 다트는 선언적이고 프로그래밍 가능한 레이아웃이 시각화 되어 준비돼 있습니다. 그리고 모든 레이아웃이 하나의 언어에 하나의 공간에 있어서 플러터가 레이아웃을 쉽고 빠르게 만들 수 있게 합니다.
- 개발자들은 다트가 사용자에게 동적언어와 정적언어의 특정을 가지고 있으므로 특히나 더 학습하기 쉬운 언어라는 것을 알아냈습니다.
위의 특징들이 다트에만 있는 것은 아니지만 위의 특징을 모두 갖고 있기 때문에 다트는 플러터를 구현하는데 특별히 더 강력합니다. 그렇기 때문에 다트 없는 플러터의 강력함은 상상하기 어렵습니다.
나머지 이 기사에서는 플러터를 구현하는데 최적의 언어인 다트의(표준 라이브러리를 포함해서) 많은 특징에 대해 좀 더 깊게 다뤄보겠습니다.
Compilation and execution
역사적으로 컴퓨터 언어는 두 그룹으로 분류됩니다: 정적 언어와(포트란이나 C와 같이 변수들이 컴파일 때 고정되는 타입) 동적언어(Smalltalk이나 자바스크립트와 같이 변수들이 실행시간에 변할 수 있는 언어)입니다. 정적언어는 관습적으로 하드웨어에 의해 직접적으로 실행될 수 있는 기계언어나 어셈블리 코드를 만들어 내기 위해 컴파일 됩니다. 동적언어는 기계어를 만들어내지 않고 인터프리터에 의해 실행됩니다.
물론 어떤 것이든 더욱 복잡해지기 마련이죠. 가상 머신의 컨셉이 대세가 되면서 인터프리터는 소프트웨어에서 하드웨어 장치처럼 동작하는 장점이 있었습니다. 가상 머신은 하나의 언어가 새로운 하드웨어 플랫폼으로 가기 쉬운 항구가 되었습니다. 이 경우에 가상머신에 사용되는 언어는 중간언어 였습니다. 예를 들어 자바와같은 프로그래밍 언어는 bytecode 중간언어로 번역되어 JVM에서 실행됩니다.
게다가 이제는 JIT컴파일러 까지 등장했습니다. JIT 컴파일러는 프로그램이 실행되는 동안 컴파일을 합니다. 프로그램이 만들어지는 동안에 실행되었던 원래의 컴파일러는 이제 AOT 컴파일러라고 불리게 되었습니다.
일반적으로 오직 정적언어만 AOT 컴파일로 기계어 코드가 됩니다. 왜냐하면 기계어는 일반적으로 데이터의 타입을 알아야 하고 동적 언어의 타입은 사전에 타입이 고정되지 않기 때문입니다. 그러므로 동적언어는 인터프리터가 JIT로 컴파일 됩니다.
AOT 컴파일이 개발 중에 완료되는 것은 개발 사이클을 좀 더 느리게 합니다.(프로그램을 수정하고 프로그램을 실행하여 변화된 결과를 확인하는 시간) 그러나 프로그램에서 AOT 컴파일의 결과는 좀 더 예측가능하며 실행 중에 컴파일을 멈추지 않고 분석할 수 있습니다. AOT로 컴파일된 프로그램은 실행 시간 또한 빠릅니다.(왜냐면 이미 컴파일 되어있기 때문이죠)
반대로 JIT 컴파일은 빠른 개발 사이클을 가져갈 수 있ㅋ지만 실행에는 느립니다. 특별히 JIT 컴파일러는 시작이 느린데 왜냐하면 JIT 컴파일러는 코드가 실행 될 수 있는지 분석하고 컴파일을 하기 때문입니다. 한 연구에서는 많은 사람들이 실행 시간이 몇 초 이상 걸리면 앱을 지울 것이라고 말했습니다.
이것이 배경지식에 관한 정보 들입니다. AOT와 JIT 컴파일의 장점만 모으면 정말 굉장하지 않을까요? 계속 읽어봅시다.
Compiling and executing Dart
다트를 작업하기 전에 다트 팀의 멤버들은 동적언어(자바스크립트의 V8엔진과 Smalltalk의 Strongtalk)와 정적언어(자바의 Hotspot compiler)를 사용한 향상된 컴파일러와 가상 머신 분야의 개척자 들이었습니다. 그들은 이 경험으로 다트가 매우 유연하게 컴파일되고 실행될 수 있게 만들었습니다.
다트는 매우 희귀한(아마 주류 언어 중에는 딱 하나있는) AOT와 JIT 컴파일에 모두 적합한 언어입니다. 다트와 특별히 플러터에게는 양 쪽의 컴파일을 지원한다는 것이 매우 큰 장점이 됩니다.
JIT 컴파일은 개발 도중에 사용됩니다. 그리고 나서 앱이 릴리즈될 준비가 되면 AOT로 컴파일 되죠. 결론적으로 발전된 도구와 컴파일러의 도움으로 다트는 양 쪽의 장점만 전달할 수 있습니다: 매우 빠른 개발 사이클, 빠른 실행과 실행 시간.
다트의 실행, 컴파일 유연성은 이게 다가 아닙니다. 예를 들면 다트는 자바스크립트로 컴파일되어 브라우저에서 실행될 수도 있습니다. 이것은 모바일 앱의 코드를 웹에서도 사용할 수 있는 것이죠. 개발자들은 모바일과 웹페이지의 코드가 70% 정도 재사용된다고 보고했습니다. 다트는 네이티브 코드나 node.js를 사용하는 자바스크립트로 변환되어 서버에 사용될 수도 있습니다.
결정적으로 다트는 독립적인 가상머신을 제공하여 다트 언어자체가 중간언어가 되도록 합니다.
다트는 AOT 혹은 JIT, 인터프리터 방식으로 효과적이게 컴파일 될 수 있으며 다른 언어로 변환될 수 있습니다. 다트는 실행과 컴파일의 유연성 뿐만아니라 매우 빠릅니다.
다음 섹션에서는 예제를 통해 다트의 컴파일 속도가 어떻게 판도를 뒤집었는지 알아보겠습니다.
Stateful got reload
플러터의 가장 유명한 특징 중 하나는 엄청나게 빠른 핫리로드 입니다. 개발 중에 플러터는 JIT 컴파일러를 이용하기 때문에 실시간으로 코드를 계속해서 실행시킬 수 있습니다. 앱의 상태는 가능할 때마다 계속해서 리로드 되기 때문에 앱을 종료하지 않는 이상 계속 유지됩니다.
Flutter’s sub-second stateful hot reload
플러터의 핫리로드를 써보지 않는 이상 그 기능이 개발 중에 얼마나 빠른지 예상하기 어려우실 겁니다. 개발자들은 마치 앱을 그리는 것 같다고 표현하면서 그들이 앱을 만드는 작업방식이 바뀌었다고 말했습니다.
아래는 플러터의 핫리로드를 사용해본 개발자의 말입니다.
저는 핫리로드를 테스트하고 싶어했죠. 색을 바꾸고 수정사항을 저장하고 그리고.. 사랑에 빠졌답니다❤️!
이기능은 정말 놀랍습니다. 비주얼스튜디오의 Edit & Continue도 좋았다고 생각하지만 이것은 정말 놀랍십니다. 핫리로드 만으로 개발자들의 생산력은 두 배가 넘게 향상될 것입니다.
이 것은 저에게 정말 혁신적이었습니다. 코드를 배포하는데 오랜시간이 걸렸고 저는 집중이 흐트려지고 제가 테스트하려고 했던게 무엇인지 잊어버리기도 했죠. 고작 2px을 수정하기 위해서 5분을 기다려야 하는 것보다 실망스러운게 있을까요? 플러터와 함께라면 이런 것은 모두 안녕입니다.
플러터의 핫리로드는 새로운 생각이나 테스트들을 쉽게 적용해 볼 수 있기 때문에 창의적인 활동에 엄청난 촉매가 됩니다.
지금까지 우리는 다트가 개발자들에게 얼마나 도움이 됬는지 알아봤습니다. 다음 섹션은 다트가 얼마나 손쉽게 유저를 사로잡는 부드러운 앱을 만드는지 알아보겠습니다.
Avoiding jank
빠른 앱도 대단하지만 부드러운 앱은 더 엄청나죠. 매우 빠른 애니매이션도 툭툭 끊긴다면 보기에 좋지 않을 것입니다. 그러나 jank를 유발하는 이유가 너무나도 많기 때문에 방지하는 것이 매우 어렵습니다. 다트는 jank를 일으키는 일반적인 요소들을 피할 수 있는 많은 특징이 있습니다.
물론 다른 언어와 마찬가지로 플러터의 앱도 janky할 수 있습니다만 단언컨데 다트는 개발자들이 더욱 예측하기 쉽고 앱의 부드러움을 완벽히 컨트롤할 수 있고 가능한한 쉽게 최상의 UX를 전달할 수 있게합니다.
플러터에서 만들어진 60프레임으로 동작하는 사용자 인터페이스는 다른 크로스플랫폼 개발 프레임워크에서 만들어진 인터페이스 보다 매우 뛰어납니다.
그리고 크로스플랫폼 뿐만아니라 네이티브 앱만큼 뛰어나죠.
그 UI는 버터처럼 부드러워요.. 이렇게 부드러운 안드로이드 앱을 본적이 없습니다.
AOT compilation and the “bridge”
우리는 이미 다트의 AOT 컴파일 기능이 앱을 부드럽게 유지하는데 도움이 되는 특징이라고 알고 있습니다. 사전에 컴파일된 AOT 코드는 JIT 분석이나 컴파일을 수행하기 위해 런타임중에 멈추지 않기 때문에 JIT 보다 더욱 예측가능합니다.
그러나 AOT의 더욱 큰 장점은 자바스크립트 브릿지를 피할 수 있다는 것입니다. 자바스크립트 같은 동적언어는 플랫폼의 네이티브 언어와 통신을 해야할 필요가 있습니다. 이럴 때 브릿지를 이용하는데 컨텍스트 스위치를 일으켜서 상태에 관한 정보를 저장해야 합니다. 이런 컨텍스트 스위치는 느려지게 할 뿐만아니라 심각한 jank까지 유발합니다.
“The Bridge”
Note: 컴파일된 코드라고 해도 플랫폼 코드와 통신하기 위해서 인터페이스가 필요할 수 있습니다. 이것 또한 브릿지를 요청하지만 동적언어에서 브릿지를 요청하는 것보다 훨씬 빠릅니다. 추가적으로 다트는 위젯과 같은 요소가 앱의 안으로 이동하기 때문에 브릿지가 필요한 일이 줄어듭니다.
Preemptive scheduling, time slicing, and shared resources
많은 컴퓨터 언어(Java, Kotlin, Object-C, Swift)는 스레드의 선점을 바꿔서 다수의 동시성 처리 스레드를 지원합니다. 각 쓰레드는 “짧은” 실행 시간을 할당받고 할당받은 시간을 초과하게 되면 스레드는 컨텍스트 스위치를 사용하여 선점됩니다. 그러나 선점이 메모리와 같이 스레드간에 공유 자원을 업데이트 해야할 때 발생하면 이것은 race condition을 발생합니다.
Race condition은 앱의 비정상 종료, 데이터 손실과 같은 심각한 버그를 유발할 수 있고 독립된 스레드들의 흐름과 연관이 되기 때문에 발견 및 수정이 매우 힘듭니다. 디버거에서 앱을 실행시켰을 때 메니페스트가 중단되는 것은 종속성 문제와 관련해서는 일반적인 일입니다.
관습적으로 종속성 문제를 해결하기 위해 공유자원은 다른 스레드가 실행할 수 없기 때문에 lock을 사용합니다. 그러나 lock은 jank를 일으키거나 deadlock, starvation과 같은 심각한 문제를 일으킬 수 있습니다.
다트는 다른 접근법으로 이 문제를 대합니다. isolate라고 불리는 다트의 쓰레드는 가장 많은 Lock이 필요한 메모리를 공유하지 않습니다. Isolate들은 채널을 통해 메시지를 주고받으며 Erlang의 actor나 자바스크립트의 웹 워커와 비슷합니다.
자바스크립트처럼 다트는 단일 스레드이기 떄문에 선점을 전혀 허용하지 않습니다. 대신에 스레드는 명시적으로 async/await/Futres/Steams들을 이용하여 양보합니다. 개발자에게 실행을 더욱 통제할 수 있게 합니다. 단일 스레드는 개발자가 중요한 함수들이 선점없이 완벽히 실행되었는지 확신하는데 도움이 됩니다. 이것은 유저인터페이스의 장점일 뿐만 아니라 클라이언트-서버 코드에서도 마찬가지 입니다.
물론 개발자가 컨트롤을 양보한 것을 까먹었다면 코드가 실행되는데 딜레이 될 수가 있습니다. 그러나 락을 걸어놓은 것을 까먹은 것보다는 훨씬 쉽게 찾고 고칠 수 있습니다. (왜냐하면 종속성 문제는 찾는 것이 힘드니까요)
Allocation and garbage collection
Jank를 일으키는 또 다른 것은 가비지 컬렉션입니다. 사실 이것은 많은 언어에서는 락을 사용하도록 요구하는, 특별한 케이스의 공유자원 접근입니다. 그러나 락은 남는 자원을 수집하는 와중에 앱 전체를 중단시킬 수 있습니다. 그러나 다트는 가비지 컬력센을 거의 락 없이 수행할 수 있습니다.
다트는 아주 짧게 살아있는 객체들을 할당하는데 매우 빠른 차세대 가비지컬렉션과 할당 스킴을 사용합니다. 이것은 플러터가 변하지 않는 뷰트리를 매 프레임 재빌드 하는 것처럼 동적 사용자 인터페이스에 매우 적합합니다. 다트는 객체 할당을 단일 포인터 한방에 할 수 있습니다. 다시 말하지만 이 결과가 jank 없는 부드러운 스크롤링과 애니메이션 입니다.
Unified layout
new Center(child:
new Column(children: [
new Text('Hello, World!'),
new Icon(Icons.star, color: Colors.green),
])
)
A view in Dart and what it produces
다트를 써보지 않았더라도 얼마나 쉽게 코드가 시각적 결과물을 만들어내는지 알아채셨을 겁니다. 이제 플러터는 다트2를 쓰기 때문에 new 키워드가 옵셔널이 되었습니다. 때문에 정적 레이아웃은 더욱 명시적인 레이아웃은 언어처럼 보이게 되었고 간단해 졌습니다.
return new ListView.builder(itemBuilder: (context, i) {
if (i.isOdd) return new Divider();
// rest of function
});
아마 당신은 이렇게 생각하고 있겠군요 - 특별한 레이아웃 언어가 없는게 어떻게 장점이 되지? 그러나 그것은 실제로 장점입니다. 다음은 “네이티브 앱 개발자들이 플러터를 심각하게 봐야하는 이유” 기사에 개발자들이 쓴 내용입니다.
플러터에서는 레이아웃이 다트 코드로만 작성됩니다. XML/템플릿 언어가 없죠. 스토리보드 도구나 시각 디자이너가 없습니다.
제 직감에 여기까지 들으면서 많은 분들이 실증나셨을 것 같군요. 명백히 제 반응도 그랬습니다. 비주얼 툴로 레이아웃을 구성하는 게 더 쉽지 않나? 코드로 모든 제약조건을 만들면 더 복잡해지지 않나? 그러나 제 대답은 NO로 바뀌었습니다. 여러분 눈을 더 크게 뜨세요!
플러터에서는 코드기반 레이아웃이나 정적 레이아웃 모두 한 곳에 존재합니다. 그리고 플러터 인스펙터와 아웃라인 뷰를 포함하여 다트의 새로운 도구들은 복잡하고 아름다운 레이아웃을 훨씬 쉽게 만들 수 있습니다.
Is Dart a proprietary language?
아닙니다. 플러터와 마찬가지로 다트는 ECMA 표준을 따르는 완벽한 오픈소스 라이센스입니다. 다트는 구글 내외로 유명합니다. 구글 내부에서는 Adwords, 플러터, Fuchsia 등등에 쓰이는 가장 빠르게 성장하는 언어중 하나입니다. 외부적으로 다트 저장소는 100명의 외부 커미터들이 있습니다.
다트의 개방성에 대한 더욱 좋은 지표는 구글 외부의 커뮤니티 성장입니다. 예를 들면 외부에서 작성한 다트에 관한 기사나 영상이 꾸준하게 볼 수 있다는 것이죠.
추가적으로 다트 자체의 외부 커미터들은 3000개가 넘는 다트 패키지 저장소가 있습니다. 거기에는 Firebase, Redux, RxDart, 국제화, 암호, 데이터베이스, 라우팅, 콜렉션 등등이 있습니다.
Will Dart programmers be easy to find?
많은 개발자들이 다트를 아는 것이아니라면 능력있는 개발자를 찾는 것이 어렵지 않을까요? 아이러니하게도 다트는 매우 배우기 쉬운 언어기 때문에 개발자를 쉽게 찾을 수 있습니다. 자바, 자바스크립트, 코틀린, C#, 스위프트 언어를 이미 아는 개발자들은 다트로 프로그래밍을 거의 바로 할 수 있습니다. 게다가 핫리로드로 사용자들이 다트로 새로운 것을 시도하도록 장려하기 때문에 다트를 더욱 빠르고 만족스럽게 배울 수 있습니다.
Conclusion
다트를 사용하기 매우 좋은 때 입니다. 다트를 사용해본 적이 없다면 이 기사를 통해 다트의 무엇이 다르고 어떤 것이 새로운 점인지에 대한 가치있는 정보를 얻으셨길 바랍니다.
Summary
- 플러터에서 다트를 사용하는 이유에 대해서