개발/Dart, Flutter

왜 Flutter는 Dart를 사용하는가?

공티스토리 2021. 5. 4. 11:05

본문은 이 글( https://hackernoon.com/why-flutter-uses-dart-dd635a054ebf) 을 번역한 것으로, 저자에게 게시 동의를 얻었습니다. 다만 글 작성 후 시간이 꽤 지났고 그 사이에 몇가지 Dart의 새로운 기능들이 추가되었다는 것을 감안해서 보시기 바란다는 말을 전해주었습니다.

 

개인적으로 Dart와 Flutter에 관심을 갖게 되어 번역해 보았습니다. 오역이 있다면 주저없이 알려주세요 :)

 

---

 

    많은 언어학자들은 언어가 그 언어를 사용하는 사람들의 사고방식에도 영향을 미친다고 주장합니다. 과연 프로그래밍 언어에도 같은 주장이 적용될까요? 각기 다른 언어를 사용하는 프로그래머들은 주어진 어떤 문제에 대해 근본적으로 다른 해결책을 만들어냅니다. 더욱 극단적인 예를 들자면, 어떤 컴퓨터 과학자들은 더욱 구조적인 프로그램을 장려하기 위해 goto 문을 제거하기도 했습니다(사상 범죄를 제거하기 위해 자연어에서 이단적인 단어를 말소하는 전체주의 지도자가 등장하는 소설 1984에서 아이디어를 얻었답니다.)

    대관절 이것이 Dart, 그리고 Flutter와는 무슨 상관이 있는 걸까요? 사실 꽤나 관계가 있답니다. 초기 Flutter 팀은 십수개의 언어를 평가했고, 그 중 그들이 UI를 구현하는 방식과 궁합이 맞다는 이유로 Dart를 선택했습니다.

 

    이 글에서 우리는 Flutter에게 최고의 언어인 Dart의 특징에 대해 더욱 깊게 다루어 볼 것입니다.

컴파일과 실행

[이미 static vs dynamic language, AOT, JIT에 대해 알고있다면 이 섹션을 지나쳐도 좋습니다.]

 

    역사적으로 프로그래밍 언어는 정적 언어와 동적 언어, 두 그룹으로 나뉘어왔습니다. 정적 언어에는 Fortran, C와 같이 컴파일 시점에 타입이 정적으로 결정되어 있는 언어들이 있고, 동적 언어에는 Smalltalk나 Javascript와 같이 변수의 타입이 런타임에 변할 수도 있는 언어들이 있습니다. 정적 언어들은 보통 컴파일 과정을 거쳐 실행 환경에 알맞은 기계어 또는 어셈블리 코드를 만들어냅니다. 반면 동적 언어들은 인터프리터에 의해 실행되며, 기계어를 따로 만들지 않습니다.

 

    여기서 끝이 아닙니다. 모든 것은 계속해서 복잡해지기 마련이니까요. 하드웨어를 소프트웨어 기술로서 흉내내는, 진일보된 인터프리터인 Virtual Machine(이하 VM) 개념이 유행하게 된 것입니다. VM은 언어를 어느 새로운 하드웨어 플랫폼에서든 쉽게 실행할 수 있도록 해주었습니다. 이 경우, VM의 입력값이 되는 언어를 intermediate language라 합니다. 예를 들어 Java는 bytecode로 컴파일된 뒤, JVM이라는 VM 위에서 실행됩니다.

 

    게다가, 이제는 just-in-time (JIT) 컴파일러가 등장했습니다. JIT 컴파일러는 프로그램의 실행 도중에 컴파일을 실행합니다. 따라서 지금까지의 컴파일러와 같이 프로그램의 실행 시점 이전에 컴파일 하는 것을 ahead-of-time (AOT) 컴파일러라고 부르게 되었습니다. 일반적으로 기계어는 데이터 타입을 알아야하는데, 동적 언어들은 컴파일 시점 이전에 타입을 고정할 수 없기 때문에 정적 언어들만이 AOT 컴파일을 할 수 있었습니다. 결과적으로 동적 언어들은 일반적으로 인터프리트 되거나 JIT 컴파일을 사용할 수 밖에 없습니다.

 

    AOT 컴파일 방식은 필연적으로 개발 사이클을 느리게 합니다(프로그램이 바뀔 때마다 결과를 확인하기 위해서는 컴파일을 통해 실행 가능한 프로그램을 만들어야 하기 때문입니다.). 이러한 단점에도 불구하고 AOT 컴파일 방식은 런타임 시점에 프로그램의 동작 예측이 가능하고, 런타임 시점에 분석이나 컴파일을 위해 프로그램을 멈출 필요가 없습니다. 물론 실행 속도 또한 더 빠릅니다(이미 컴파일되었기 때문이죠).

 

    반대로, JIT 컴파일 방식은 훨씬 빠른 개발 속도를 제공하지만, 실행 속도가 더 느려집니다. 특히 JIT 컴파일러는 코드를 실행하기 위해서는 코드 분석과 컴파일을 해야하기 때문에 초기 실행 속도를 느리게 합니다. 많은 연구들은 어플리케이션 첫 실행을 위해 수 초 이상 걸리는 경우 앱을 그냥 닫아버린다는 것을 밝혀내기도 했습니다.

 

    여기까지가 배경 지식입니다. AOT와 JIT 컴파일 방식의 장점만을 취할 수 있다면 굉장할 것 같지 않으신가요?

컴파일과 실행 in Dart

    Dart 개발에 뛰어들기 전에, Dart 팀의 구성원들은 동적 언어(Javascript를 위한 V8 engine)와 정적 언어(Java의 Hotspot Compiler)에 사용된 진일보된 컴파일러와 VM에 대해 엄청난 경험을 가지고 있었습니다. 구성원들은 이 경험을 토대로 Dart가 컴파일되고 실행되는 방식을 비정상적으로 유연하게 만들 수 있었습니다.

 

    Dart는 AOT와 JIT 방식으로 컴파일 할 수 있는 몇 안되는 "주류" 언어 중 하나입니다. 두 가지 방식의 컴파일을 지원하는 것은 Dart의 엄청난 장점 중 하나입니다 (특히 Flutter에게 더!). 특히 빠른 JIT 컴파일을 개발 중에 사용하고, 앱의 출시 준비가 완료되면 AOT 컴파일을 이용합니다. 이러한 진일보된 도구와 컴파일을 이용해 Dart는 극단적으로 빠른 개발 주기와 빠른 시작 시간이라는 두 마리 토끼를 성공적으로 잡아낼 수 있게된 것입니다.

 

    컴파일과 실행에 있어 Dart의 유연성은 여기서 그치지 않습니다. 예를 들어, Dart는 Javascript로 컴파일 되어 브라우저에서 실행할 수 있습니다. 이를 통해 모바일 앱과 웹 앱에서 코드를 재사용할 수 있게 됩니다. 많게는 70%의 개발자들이 모바일 앱과 웹 앱에서 코드를 재사용한다고 합니다. 또한 native code로 컴파일 되거나 Javascript로 컴파일 되어 node.js에서 사용할 수 있기 때문에 서버 사이드에서도 사용할 수 있습니다. 마지막으로 Dart 자체를 intermediate language로 사용할 수 있는 standalone VM 또한 제공합니다.

 

    Dart는 AOT 또는 JIT 방식으로 효율적으로 컴파일되고, 인터프리트 되고 또 다른 언어로 번역 될 수 있습니다. Dart 컴파일 및 실행은 매우 유연 할뿐만 아니라 특히 빠릅니다.

 

    다음 섹션에서는 Dart의 컴파일 속도가 어떻게 게임 체인저(game changer)가 될 수 있는지 예시를 통해 알아보겠습니다.

Stateful hot reload

    엄청나게 빠른 hot reload는 Flutter의 가장 잘 알려진 특징 중 하나일 것입니다. Flutter는 개발 과정에서 코드 리로드와 실행을 수 초 이내에 가능하게 하는 JIT 컴파일러를 이용합니다. 리로드가 되어도 앱의 state는 유지되기 때문에 앱이 중단된 시점부터 다시 개발을 시작할 수 있습니다.

 

    여러분이 직접 경험해보지 않았다면 빠르고 안정적인 hot reload가 얼마나 중요한 것인지 이해하기 어려울지도 모릅니다. 어떤 개발자들은 이를 앱에 생명을 불어넣는 것 같다고 말하며 그들이 앱을 만드는 방식마저 바꾸었다고 말합니다.

    여기 모바일 앱 개발자들이 Flutter의 Hot reload에 대해 얘기하는 것을 보시죠.

hot reloading을 맛보고 싶어서 색을 바꾸고 저장해 보았지. 그리고 난.. 사랑에 빠지지 않을 수 없었어 ❤️!

이건 정말 쩔어. 지금까지 난 VS의 Edit & Continue 도 좋다고 생각했는데, 이건 그냥 개쩔어. 이것만 가지고도 모바일 개발자들은 생산성이 두 배 이상 좋아질거야.

나한텐 이게 game changer야. 내 코드를 배포하는 동안 집중력을 잃고 다른 일을 하는 바람에 내가 뭘 테스트하려고 했는지조차 잊어버리곤 했어. 더 짜증나는 건 2px 정도 변경을 확인하기 위해 5분 이상을 기다리곤 해야 했다는 거지. 근데 Flutter를 쓰면 더 이상 그럴 일이 없어.

    Flutter의 hot reload를 통해 창조성을 크게 향상시키는 것은 물론 훨씬 쉽게 여러가지 새로운 아이디어를 시도하거나 대안을 실험할 수 있게 되었습니다.

    지금까지는 어떻게 Dart가 개발자들에게 더 나은 경험을 주었는지 이야기했다면, 다음 섹션에서는 Dart를 이용해 어떻게 유저를 기쁘게 하는 부드러운 앱을 만들 수 있게 되었는지 알아보겠습니다.

Avoiding jank

    그저 빠르기만한 앱도 나쁘지 않지만 부드럽게 동작하는 앱은 훨씬 훌륭합니다. 초고속 애니메이션도 이상하게 버벅인다면 썩 좋아보이진 않을 것입니다. 하지만 jank를 미연에 방지하는 것은 그 발생 원인이 너무 많아 쉽지 않습니다. Dart에는 이런 jank를 유발한다고 알려진 문제들을 피할 수 있는 특징들이 존재합니다.

    물론, 다른 언어들처럼 Flutter를 사용하더라도 janky app이 만들어질 수 있습니다. 하지만 Dart를 사용함으로서 결과가 조금 더 예측 가능해지고 개발자들이 앱의 부드러움에 대한 더 많은 제어권을 갖게 되기 때문에 개발자들은 더 쉽게 최고의 유저 경험을 창조할 수 있게 됩니다. 그리고 그 결과는,

60 fps로 실행해보면, Flutter로 만든 UI가 다른 어떤 cross platform 개발 프레임워크를 이용해 개발한 것 보다 훨씬 나아.

이는 단지 cross-platform 앱에만 국한되는 이야기는 아닙니다. 네이티브 앱에도 통하는 이야기죠.

UI가 훨씬 부드러워.. 이런 건 안드로이드 앱에서는 한 번도 본 적 없어.

AOT 컴파일과 "Bridge"

    애플리케이션을 부드럽게 만들어주는 Dart의 특징 중 하나인 AOT에 대해 이야기를 해 보았습니다. 미리 AOT 컴파일된 기계어 코드는 런타임에 JIT 분석이나 컴파일을 위해 때때로 실행을 중단해야 하는 JIT 컴파일에 비해 훨씬 예측 가능했습니다.

 

    하지만 AOT 컴파일에는 이보다 훨씬 큰 장점이 존재하는데, 이는 "Javascript Bridge"를 피할 수 있다는 것입니다. Javascript와 같은 동적 언어는 native code와 플랫폼 사이에서 상호작용 하게 되는데, 이 때 마치 다리를 건너는 것처럼 많은 양의 상태를 저장하는 등의 문맥 교환(Context Switching)이 발생합니다. 이러한 문맥 교환은 심각한 비단 앱의 속도를 저하시킬 뿐만아니라 jank를 유발할 수도 있습니다.

참고: 컴파일된 코드 또한 플랫폼과 상호작용해야 할 수 있고, 이 또한 일종의 다리를 건너는 것과 같다고 볼 수 있다. 하지만 이러한 상호작용은 일반적으로 동적 언어에 필요한 시간보다 훨씬 짧다. 더욱이 Dart에서는 위젯과 같은 것들을 앱 안으로 이동시킬 수 있게 해주기 때문에 다리를 건널 필요가 훨씬 줄어든다.

선점 스케줄링, 시분할 그리고 공유 자원

    Java, Kotlin, Objective-C 그리고 Swift와 같이 병렬 처리 스레드를 지원하는 프로그래밍 언어들은 스레드간 전환을 위해 선점 알고리즘을 사용합니다. 각각의 스레드들은 일정 실행 시간을 부여받고, 그 시간을 모두 소진하면 문맥교환에 의해 다른 스레드가 자원을 점유하게 됩니다. 하지만 공유자원에 대해 선점이 발생하는 경우 경쟁 상태를 유발할 수 있습니다.

 

    경쟁 상태는 데이터 유실이나 크래시와 같은 심각한 버그들을 초래할 뿐만아니라, 문제 상황 발견 및 수정 모두가 어렵기 때문에 매우 위험합니다. 경쟁 상태를 디버깅으로 찾아내기란 불가능에 가깝다는 것은 이미 널리 알려진 사실이기도 합니다.

 

    이러한 경쟁 상태를 제거하는 가장 보편적인 방법은 lock을 이용해 공유 자원을 보호하는 것입니다. 하지만 lock 자체로도 jank를 유발할 수 있고, deadlock이나 starvation과 같은 더 심각한 문제를 일으킬 수도 있습니다.

 

    Dart는 이런 문제에 조금 다른 방법으로 접근합니다. isolates라 불리는 Dart의 스레드는 메모리를 공유하지 않아 lock이 필요하지 않습니다. isolate들은 channel을 통해 메세지를 주고받는 것으로 의사소통 하며, 이는 Erlang의 actors나 Javascript의 web worker와 비슷한 개념이라고 볼 수 있습니다.

 

    Dart는 Javascript와 마찬가지로 싱글 스레드 기반이며, 이는 곧 선점을 허용하지 않는다는 것을 의미합니다. 대신 스레드들은 async/await, Futures, Streams를 이용해 명시적으로 서로에게 제어권을 양도합니다. 이는 개발자들이 코드 실행에 대한 제어권을 갖도록 합니다. 덕분에 개발자들은 싱글 스레드 환경에서도 애니메이션이나 트랜지션과 같은 중요한 기능들이 실행되면 선점으로 인해 취소되는 일 없이 완료될 것이라고 예상할 수 있습니다. 이는 UI 뿐만이나 클라이언트-서버 코드에서도 큰 이점이 됩니다.

 

    물론, 개발자가 제어권을 양도하는 것을 잊는다면 다른 코드가 실행되는 것이 지연될 수도 있습니다. 하지만 양도하는 것을 잊어버려서 생기는 일들은 lock을 잊어버려 발생하는 문제에 비해 훨씬 쉽게 찾아내고 수정할 수 있습니다.

할당과 가비지 컬렉션

    Jank를 유발하는 다른 심각한 원인중에 하나는 가비지 컬렉션입니다. 사실 이는 다른 많은 언어들이 Lock을 통해 접근을 제어하는, 메모리와 같은 공유자원에 접근하는 때에 발생합니다. Lock은 더 이상 사용하지 않는 메모리 공간을 수집할 때 앱 전체를 중지시키기도 합니다. 하지만 Dart는 Lock을 거의 사용하지 않고 가비지 컬렉션을 수행할 수 있습니다.

 

    Dart는 모든 프레임마다 view tree를 재생성해야하는 반응형 UI를 사용하는 Flutter처럼, 수명주기가 짧은 오브젝트들을 수집하는 것에 진일보된 가비지 컬렉션과 수집 스킴을 이용합니다. Dart는 Lock이 필요 없는 single pointer bump를 이용해 오브젝트들을 생성할 수 있습니다. 결과적으로 부드러운 스크롤 애니메이션을 구현할 수 있게 되는 것입니다.

Unified layout

    Dart를 이용하는 것의 또다른 이점 중 하나는 Flutter가 Layout을 프로그램과 부가적인 템플릿이나 JSX나 XML과 같은 Layout 언어로 분리하지 않는다는 것과, 독립된 Layout 시각화 툴을 필요로하지 않는다는 것입니다. 여기 Dart로 작성된 Flutter의 View 샘플을 보시죠.

new Center(child:
  new Column(children: [
    new Text('Hello, World!'),
    new Icon(Icons.star, color: Colors.green),
  ])
)

(결과물)

    이 코드가 얼마나 쉽게 결과를 시각화 하는지 보세요(심지어 여러분이 Dart의 경험이 없다고 가정해도 말이죠).

    지금 Flutter가 사용하는 Dart 2에서는 new 키워드가 optional이 되면서 레이아웃을 생성하는 일이 훨씬 쉽고 깔끔해졌는데요, 정적 레이아웃을 생성하는 코드가 마치 레이아웃 언어로 작성된 것 처럼 훨씬 자연스러워 보이게 되었답니다.

// new 키워드가 사라진 것이 보이시나요? 
Center(child:
  Column(children: [
    Text('Hello, World!'), 
    Icon(Icons.star, color: Colors.green), 
  ] 
))

   하지만, 저는 지금 여러분이 어떤 생각을 하고 있을지 알고 있답니다. '어떻게 레이아웃 생성에 특화된 언어를 사용하지 않아도 된다는 게 장점이라는 걸까?' 하지만 이 또한 game changer 입니다. 여기 어떤 개발자가 쓴 블로그의 내용의 일부를 보시죠.

Flutter에서 레이아웃은 오직 Dart 코드를 사용해서만 작성된다. XML이나 템플릿 언어는 존재하지 않는다. 시각 디자이너나 스토리보딩 툴 또한 존재하지 않는다.

내 생각에 이 말을 들은 여러분은 흠칫 놀랐을 것입니다. 저 또한 그랬으니까요. 시각화 툴 을 이용해서 레이아웃을 만드는게 더 쉽지 않나? 모든 조건을 코드로만 만드는건 너무 복잡한 일 아닌가? 하고 말이죠.

그 질문에 대한 답은 no 였습니다. 되려 눈을 번쩍 뜨게 해 주었죠.

이 대답의 첫 파트는 위에서 언급했던 hot reload 였습니다.

저는 우선 Hot reload가 안드로이드의 Instanr Run 이나 그와 비슷한 솔루션보다 몇 광년이나 앞서있음을 강조하지 않을 수 없습니다. 규모가 큰 앱에서도 그냥 잘 동작합니다. 그리고 미친듯이 빠르죠. 그것이 바로 여러분에게 주어지는 Dart의 힘입니다.

실제로 그것이 비주얼 에디터 인터페이스가 더 이상 필요없게 만듭니다. 저는 더이상 XCode를 그리워하지 않게 되었습니다.

    Dart는 미친듯이 빠른 hot reload와 동시에 간단명료하고 이해하기 쉬운 레이아웃을 만들어 여러분에게 즉각적으로 내보입니다. 이는 비정적 레이아웃에도 동일하게 적용됩니다.

결과적으로 저는 Android/Xcode를 이용했던 것보다 훨씬 생산적인 방법으로 레이아웃을 생성할 수 있었습니다. 여러분이 한 번이라도 사용해 보신다면(적어도 몇 주 정도는 말이죠.) 컨텍스트 스위칭이 발생하지 않기때문에 잠재적으로 꽤나 많은 오버헤드가 줄어든다는 것을 느낄 수 있을겁니다. 디자인 모드로 변경해서 마우스를 몇번 딸깍거리는 등의 일을 할 필요가 없기 때문입니다. 코드로 더 해 주어야 하는게 없는지 생각하면서 말이죠. 모든 것이 프로그래밍-친화적 입니다. API들 또한 잘 디자인되어 있습니다. 레이아웃을 생성하는 데에 자동 레이아웃이나 레이아웃 XML을 사용하는 것보다 훨씬 직관적이고 강력하다는 것을 알 수 있을 것입니다.

    예를 들어, 아래는 코드로 구현된 모든 아이템 사이에 수평 구분선을 집어넣는 간단한 리스트 레이아웃입니다.

return new ListView.builder(itemBuilder: (context, i) { 
   if (i.isOdd) return new Divider(); // rest of function 
 });

    Flutter에서는 정적 레이아웃이든 programmatic 레이아웃이든 모든 레이아웃은 한 곳에 존재합니다. 그리고 Flutter Inspector와 아웃라인 뷰(모든 레이아웃이 한 곳에 있는 이점을 이용하는)가 포함된 새로운 Dart 도구를 이용해 더욱 복잡하고 아름다운 레이아웃들을 훨씬 쉽게 만들 수 있습니다.

Dart는 소유권이 있는 언어인가요?

    아닙니다. Dart는 (Flutter와 같이) 명확한 라이센스를 가진 오픈소스이며, ECMA Standard를 따릅니다. Dart는 구글 내/외부에서 유행입니다. 구글 내부에서는 Adwords, Flutter, Fuchsia 및 기타 서비스 개발에 사용됨으로써 가장 빠르게 성장중인 언어들 중 하나이며, 외부에서 Dart 저장소는 100명 이상의 커미터를 보유하고 있습니다.

 

    개방성 지표가 훨씬 개선되었다는 지표는 구글 외부에 커뮤니티들의 성장입니다. 예를 들어, 우리는 Flutter와 AngularDart를 포함한 Dart 관련된 글이나 영상등이 써드파티들로부터 계속해서 증가하는 것을 확인했고, 그 중 몇가지는 제가 인용하기도 했습니다.

 

    Dart의 외부 커미터들 뿐만아니라, Firebase, Redux, RxDart, internationalization, encryption, databases, routing, collections 에 관한 3000개가 넘는 공식 Dart 패키지 저장소들 또한 있습니다.

Dart 프로그래머들을 찾기 쉬울까요?

    만약 Dart를 아는 프로그래머가 많지 않다면, 시장에서 뛰어난 Dart 프로그래머들을 찾기 어렵지 않을까요? 아이러니하게도 Dart는 프로그래머들이 배우기에 놀라울정도로 쉽습니다. Java, JavaScript, Kotlin, C# 혹은 Swift에 익숙한 프로그래머들은 Dart를 거의 순식간에 배울 수 있습니다. 이에 더해 프로그래머들은 hot reload를 이용해 Dart를 가지고 놀며 새로운 것을 시도해보며 빠르고 즐겁게 Dart를 배울 수 있습니다.

 

여기 어떤 프로그래머가 작성한 글 "왜 2018년 Flutter가 뜰 수 밖에 없나." 을 보시죠.

Flutter 앱을 개발하기 위해 사용하는 Dart는 열라 배우기 쉽다. 구글은 Go 언어처럼 심플하고 잘 문서화된 언어를 만드는 데 일가견이 있는 것 같다. 지금까지 나는 Dart를 배우며 Ruby를 배울 때의 즐거움이 떠올랐다. 모바일 뿐만아니라 웹에서도 말이다.

다른 어떤 글도 한 번 보시죠. “Why Flutter? and not framework X? or better yet why i’m Going Flutter all in.

Flutter는 구글에서 개발한 Dart라는 언어를 사용해. 솔직히 난 C#이나 자바처럼 강타입 언어들을 좋아하진 않아. 하지만 Dart에서 코드를 작성하는 방식은 왠지 조금 다른것 같아. 코드를 작성할 때 어쩐지 편하거든. 아마 배우기 정말 쉽고 아주 직관적이라서 그렇게 느껴지는 것 같아.

    Dart는 UX 연구와 테스팅을 거쳐 근본적으로 배우기 쉽게 디자인되었습니다. 예를 들어, 2017년의 첫 6개월 동안 Flutter 팀은 8명의 개발자들과 함께 UX 연구를 했습니다. 우리는 그들에게 Flutter에 대한 간략한 개요를 전달하고, 한시간 정도 간단한 뷰를 만들도록 했습니다. 참여한 모든 개발자들은 그 때까지 Dart 개발 경험이 없었음에도 불구하고 바로 개발을 시작할 수 있었습니다. 그들은 언어가 아니라 그저 반응형 뷰를 개발하는 데 집중했고, Dart는 예상대로 동작했습니다. Dart just worked.

 

    끝으로, 주어진 작업보다 훨씬 많은 것을 구현해 낸 어떤 참가자는 언어에 대해 어떤 언급도 하지 않았는데, 개발팀에서 그에게 어떤 언어가 사용되었는 지 알아챘는 지 물었을 때 그는 알지 못한다고 대답했습니다. 언어는 중요하지 않았고, 그들은 단지 몇 분만에 Dart를 이용해 프로그래밍 했습니다.

 

    새로운 시스템을 배우는 것의 가장 어려운 부분은 언어 그 자체라기 보다는 라이브러리, 프레임워크, 툴, 패턴 그리고 좋은 코드 작성을 위한 best practice를 배우는 것입니다. 그리고 Dart 라이브러리와 툴들은 비정상적으로 훌륭하고 잘 문서화되어 있습니다. 어떤 글에서는 "보너스로, 그들은 코드베이스를 엄청나게 관리하고 내가 본 것 중 최고의 문서화 작업을 해 두었습니다." Dart를 배우는 데 약간의 노력을 기울이면 나머지를 배우는 시간을 절약 할 수 있습니다.

 

    직접적인 증거로, 구글의 한 내부 프로젝트가 모바일 앱을 iOS로 포팅하려고 한 일이 있었습니다. 처음에는 iOS 프로그래머들을 개발하려고 했으나, Flutter를 시도해보기로 했습니다. 그들은 개발자들이 Flutter를 사용했을 때 Flutter에 익숙해지기까지 얼마나 걸리는 지 모니터링 했습니다. 그리고 약 3주 안에 Dart를 배우고 Flutter를 통해 충분한 생산성을 발휘하는 것을 확인할 수 있었습니다. 이것은 안드로이드 개발자들이 5주에 걸쳐 보여주었던 퍼포먼스와 비슷한 것이었습니다.

 

    마지막으로, 거대한 엔터프라이즈 어플리케이션을 Dart로 마이그레이션한 어떤 회사에서 작성한 이 글에서의 결론은 다음과 같았습니다.

채용이 훨씬 쉬워졌다. 이제 우리는 플랫폼에 관계없이 최고의 지원자를 찾을 수 있게 되었다.

모든 팀이 하나의 코드 베이스에 집중할 수 있게 되며 3배의 Bandwith를 얻을 수 있었다.

지식의 공유가 활발히 이루어진다.

    그들은 Dart와 Flutter를 사용함으로서 생산성을 3배로 증가시킬 수 있었습니다. 이전 상태를 생각해보면 그리 놀랍기만한 결과는 아닙니다. 왜냐하면 지금까지는 다른 회사들과 마찬가지로 각각의 플랫폼마다 앱을 만들었고, 다른 툴을 썼고 다른 개발자들을 고용했왔으니까요. Dart로의 전환은 더 이상 서로 다른 프로그래머들을 고용할 필요가 없다는 것을 의미하는 것이었습니다. 그리고 기존의 개발자들이 Dart를 사용하게 하는 것 또한 어렵지 않았습니다.

 

    또한 그들은 개발자들이 한 번 Flutter를 사용하기 시작하면, 종종 Dart에 푹 빠져버리는 것을 발견했습니다. 그들은 Dart가 가진 간결함과 비격식을 좋아했습니다. Dart 언어의 특성들인 cascades, named parameters, async/await 그리고 streams 또한 좋아하지 않을 수 없었습니다. 무엇보다도, Dart 덕분에 실현 가능했던 Flutter의 특성들과 아름답고 뛰어난 성능을 가진 앱들 또한 사랑하게 되었습니다.

Dart 2

    이 글은 Dart 2가 공식 발표된 후에 작성되었습니다. Dart 2는 클라이언트 어플리케이션 개발 경험과 개발 속도, 을 개선하고 향상된 개발자 도구 제공과 type safety 구현에 집중했습니다. 예를 들어 Dart 2의 기능 중에는 sound type system과 타입 추론이 있습니다.

    Dart 2는 또한 new 키워드를 선택형으로 만들었습니다. 이는 많은 Flutter 뷰를 키워드 없이 생성할 수 있게 됨으로써 덜 혼란스럽고 읽기에는 더 쉽게 만들었습니다. 아래는 그 예시입니다.

Widget build(BuildContext context) => Center(child: 
  Column(children: [ Text('Hello, World!'), Icon(Icons.star, color: Colors.green), ]) 
)

    Dart 2는 타입 추론을 통해 const 키워드가 const 문맥 안에서 중복으로 정의되지 않도록 옵셔널하게 변경했습니다. 예를 들어, 아래 코드는

const breakfast = { const Doughnuts(): const [const Cruller(), const BostonCream()], };

    이렇게 새롭게 작성할 수 있습니다.

const breakfast = { Doughnuts(): [Cruller(), BostonCream()], };

    왜냐하면 breakfast가 const이므로, 리스트에 속한 모든 아이템 또한 const로 추론할 수 있기 때문입니다.

비밀은 바로 집중입니다.

    Dart 2의 개선사항들은 모두 client side 개발을 최적화하는 것에 목적을 두고 있습니다. 하지만 우리는 여전히 서버, 데스크탑, 임베디드 시스템 그리고 다른 프로그램에서도 Dart를 멋지게 사용할 수 있습니다.

집중이란 좋은 것이죠. 우리가 알고있는 많은 언어들도 무엇인가에 집중함으로서 명성을 얻을 수 있었습니다. 예를 들어,

  • C는 시스템 콜과 컴파일러 작성을 위한 시스템 프로그래밍
  • Java는 임베디드 시스템
  • Javascript는 웹 브라우저용 스크립트
  • PHP는 개인용 홈 페이지 (Personal Home Page!)

    한편, 범용 언어가 되기 위해 대외적으로 많은 시도를 한 언어들도 있습니다. PL/1이나 Ada와 같은 언어들이죠. 하지만 가장 공통적인 문제는 집중이 없었던 이런 언어들이 그냥 싱크대가 되어버렸다는 것이죠.

 

    Dart를 훌륭한 클라이언트 사이드 언어로 만들어주는 기능들 덕분에 Dart는 서버 사이드 언어로서도 훌륭하게 사용될 수 있 습니다. 예를 들어, Dart가 선점형 멀티 태스킹을 사용하지 않는 것은 서버에도 같은, 혹은 훨씬 안전한 개발을 가능하게 합니다. 마찬가지로 임베디드 시스템을 구현할 때 Dart의 동시에 여러 입력을 안전하게 처리하는 능력이 빛을 발합니다.

 

    결과적으로, 클라이언트 사이드에서 Dart의 성공은 필연적으로 서버 사이드에서도 Javascript와 Node가 그랬듯이 흥미로운 일들을 만들어 낼 것입니다. 굳이 사람들에게 클라이언트-서버 소프트웨어를 만들 때 서로 다른 언어를 사용하게 강제할 이유는 없으니까요!

마침내, 결론

    지금까지 Dart를 위한 흥미로운 시간이었습니다. 지금은 Dart를 사용하는 유저분들 또한 흥미로우셨기를, 그리고 Dart 2의 새로운 기능들이 여러분의 코딩 무기고를 더욱 든든하게 만들어 만들어주었길 바랍니다. 그리고 만약 여러분이 Dart를 한 번도 사용해보지 않았다면, 이 글이 여러분에게 Dart와 Flutter를 시도해 볼 마음이 들게 하는 유익한 정보가 되었길 바랍니다.