드디어 학기가 어찌 되었든 끝났기 때문에 일전에 쓰려고 한 프로그래밍 언어에 관한 글을 쓰려고 했으나,

이걸 쓰기 이전에 프로그래밍 언어에 대한 접근을 고민하다 보니 개발 그 자체에 대한 글을 먼저 쓰는 것이 맞겠다는 생각이 들었습니다.

제가 이렇게 생각하는 이유는 간단합니다.


현업에서 주로 쓰이는 프로그래밍 언어는, 개발시의 수요를 충족해주는 언어를 중심으로 발전


한다고 생각하기 때문입니다. 대표적으로 대규모 시스템 프로그래밍에서 C++의 언어 자체의 레거시 성질을 극복하기 위해 Rust가 등장했고, JVM이라는 환경의 매력은 그대로 쓰지만 언어의 생산성을 높이고(특히 NPE problem을 해결하기 위해)Kotlin이 등장했죠. 대량의 데이터가 오고가는 서버에서의 동시성 제어를 위해 Go가 등장했고, 대규모 Javascript 어플리케이션에서의 구조적 프로그래밍을 위해 TypeScript가 등장했구요. 적어도 저는 프로그래밍 언어의 발전을 이런 관점에서 바라봅니다.


따라서 현업 감각 중심으로 프로그래밍 언어에 대한 이야기를 하려면, 우선 개발에 대한 수요를 이해해야 한다고 생각했고, 이를 위해서는 개발 그 자체에 대한 이해를 우선 하는 것이 맞다고 판단했습니다. 이에 따라 많은 사람들이 요즘 관심있어 할 만한 주제가 무엇인지에 대해 생각해 보았고, 그 중 첫 번째로 고른 것이 바로 모바일 앱 프로그래밍입니다.



자주 듣는 단어, Swift, Kotlin, React Native, Flutter


모바일 앱 프로그래밍에 입문하시기 위해 검색하시면 저 단어들을 어딘가에서 한 번 쯤은 보셨을 겁니다. iOS의 공식 프로그래밍 언어가 Swift, Android의 공식 프로그래밍 언어로 Kotlin이 채택되었다는 건 이 글을 읽으실 정도 된다면 이미 아실 거라고 생각해요. 그리고 React Native가 Javascript, Flutter가 Dart라는 언어를 사용한다는 것도 이미 많은 검색을 해 보신 분들이라면 아실 수 있습니다. 그리고 스타트업에서 특히 더 React Native를 많이 사용한다는 것도, 어떤 분들은 이미 아실 수 있습니다. 그렇다면 왜 React Native는 현재 스타트업 씬에서 주목받고 있고, Flutter는 왜 새로이 등장했을까요?


자, 오늘 이야기는 양 플랫폼의 네이티브 프로그래밍에서부터 출발합니다.


Swift나 Kotlin이란 언어가 구려서는 절대 아닙니다


솔직히 말해서, 예전의 Java나 Objective C는 정말 구리다고 생각합니다(Objective C가 살짝...아니 매우 더 싫긴 합니다). 극단적으로 예전의 코드에서 지금의 코드가 얼마나 진일보했는지 설명해드리기 위해서, Objective C로 짠 예시 코드를 한번 보여드리겠습니다. 원문은 여기서 가져왔습니다.


#import "CollectionCache.h"

@implementation CollectionCache

+ (instancetype)sharedCache {

  static CollectionCache *sharedInstance = nil;

  static dispatch_once_t dispatchToken;

  dispatch_once(&dispatchToken, ^{
    sharedInstance = [[self alloc] init];
  });

  return sharedInstance;
}

@end


정말... Objective C는 다시 봐도 소름돋게 생겼네요. 이걸 새로이 바뀐 언어인 Swift로 표현하면 다음과 같습니다.

class CollectionCache {

  static let sharedCacheSharedInstance: CollectionCache? = {
    var sharedInstance = self.init()
    return sharedInstance
  }()

  class func shared() -> Self {
    return sharedCacheSharedInstance!
  }

}


어렵게 생각하실 것 없습니다. 언어상으로 많은 발전이 있었다는 걸 전달하기 위해서 코드를 보여드렸을 뿐입니다. 지금 당장 위의 코드가 이해가 안 되시는 분들도, Objective C 의 코드는 아니더라도 Swift의 코드 정도는 금방 보고 이해하실 날이 올 거라고 믿습니다(혹시 Objective C가 얼마나 극혐인지 조금이라도 느끼고 싶으신 분은, 저기서 +의 의미가 무엇인지 찾아보시면 됩니다. 아마 기절초풍하실 겁니다). 중요한 것은, 두 개 플랫폼이 모두 초반에는 상당히 프로그래밍하기 거지같은 면이 있었던 게 사실이지만, 지금 와서는 굉장히 많이 개선되었다는 사실이죠. 이 점을 설명드리는 이유는, 인터넷의 몇몇 글들이 각 모바일 플랫폼의 공식 네이티브 프로그래밍 언어와 툴킷을 사용한 개발이 지나치게 난해하다는 주장을 하고 있고, 개인적으로 여기에 동의하지 않기 떄문입니다. 뒤에서 설명하겠지만, 결국 React Native나 Flutter를 사용한다 하더라도 사실상 위의 글들이 이들 개발 플랫폼이 네이티브보다 쉽다고 주장한 근거들을 반박하는 행위들을 해야 하거든요.


자, 그렇다면 React Native와 Flutter가 스타트업 씬에서 네이티브 개발 플랫폼보다 주목받는 이유는 무엇일까요?



스타트업의 핵심은 경량화입니다.


여러분이 스타트업 팀을 꾸린다고 생각해 봅시다. 그래도 서비스를 만들어야 할 테니 디자이너가 필요할 테고, 개발자도 최소한 한 명은 필요하겠죠. 기획자가 별도로 있으면 좋겠지만 스타트업은 기획의 중요성을 무시하는 경우가 많기 때문에(으아악) 기획은 팀원들의 수-평적인 대화와 데이터 어널리틱스로 어느 정도 대체한다고 가정할게요. 그리고 마케팅과 영업과 같은 프로덕 개발과 무관한(하지만 중요한) 업무를 남은 한명이 담당한다고 해 볼게요. 자, 인원 3명짜리 스타트업이 창설되었습니다.


이런 인력 구성이 충격적이실지 모르겠지만, 실제로 스타트업에서 이 또한 비일비재하게 일어나는 게 현실입니다. 자, 중요한 건 이겁니다. 프로그래밍 가능한 인력 한 명, 최소한 백엔드 필요, 사용자를 위한 프론트엔드도 필요. 당연히 누가 봐도 정신나간 업무량이란 걸 알 수 있지만 아무튼 선택지는 없습니다. 그럼 기간이라도 길게 줄까요? 절대 아니죠. 제가 실제로 겪은 일을 중심으로 스타트업의 '환상적인 일처리'를 보여드리겠습니다. 당시의 슬랙 대화를 중심으로 재구성한 내용입니다.


???: 결제 서비스 구현 완료되었나요?

나: 네, 말씀해신 대로 XX XXXX를 통한 카드 결제와 XXX페이, XXX페이로 결제까지는 가능하게 만들었습니다. 저희가 PG 연계 서비스인 XXXX를 쓰고 있으니 추후에 다른 PG들 계약되는 것 봐 가면서 앱만 수정하면 됩니다.

???: 네 빨리 구현해 주셨네요

나: 감사합니다.

???: 그런데, 저희가 이번에 XX XXXX PG와 투자 조건으로 계약이 되어서, 중간에 연계 서비스를 걷고 해당 PG 중심으로 서비스를 재설계해야 할 것 같은데, 혹시 언제까지 가능할까요?

나: ...? 갑자기요?

???: 저희가 아직까지 수익이 잘 안 나오는 입장이다 보니 투자가 필요해서요 ㅜㅜ... 힘드시겠지만 가능한 빠르게 부탁 드릴게요. 혹시 2주일 정도면 가능할까요?

나: ??????


네, 눈물겹지만 이런 일은 한 두번 겪은게 아닙니다(4일만에 서비스 모델 교체하란 요청 받은적도 있었습니다). 결국 여러 이유로 초기 작업 인력을 확보하기는 힘들고, 제품 자체의 문제나 서비스 개선을 위해서 만이 아닌 수많은 이유로 프로덕을 굉장히 잦고, 빠르게 수정을 해야 한다는 사실이죠. 그래서 스타트업에서는 컴퓨터 공학에서 배운 내용을 '너무 어기지는 않는'수준 안에서, 최대한 빠르게 구현해야 합니다. 그리고 또 다른 중요한 사실은, 개별 구현 코드에 큰 정성을 들여봤자 소용이 없다는 겁니다. 왜냐하면,


결국 여러분이 힘들게 구현해도, 대개는 사업적 판단 실수로 결론나 버려질 테니까요


스타트업 현실편에 오신 걸 환영합니다.



빠른 배포를 위해, 웹을 사용하다.


혹시 iOS 앱을 배포해 보신 적 있나요? 그렇지 않더라도 App Store에 앱을 배포하기 위해서는 검수 절차를 거쳐야 한다는 것은 잘 아실 겁니다. 정말... 별에 별 이유로 다 퇴짜를 맞게 됩니다. Apple이 만든 로고와 같은 에셋이 자사 가이드라인에 맞지 않다는 이유, 인터페이스 구성이 자사의 가이드라인에 맞지 않다는 이유, 충분히 빠른 시간 이내에 최초 동작을 하지 않거나, 컨텐츠가 없어서 로드하지 않았는데 아무 것도 로딩이 되지 않았다는 이유... 특히 최초 배포시에는 다른 때 보다도 훨씬 많은 시간을 들여서 배포를 하게 되죠. 가장 짧게 끊어본 최초 배포조차도 2주는 넘겼던 것 같습니다. 안드로이드는 자동화된 검수를 하기 때문에 이보다는 낫지만, 여전히 최초 배포시에는 상당히 많은 시간을 필요로 합니다.


그럼 추후 검수는 좀 나을까요? 아니죠. Play Store가 그나마 좀 나아서 평균적으로 6~8시간 정도면 전체 배포가 되고, iOS는 일단 검수 받아야 하기 때문에 하루 이틀 정도 시간이 걸리면 그나마 다행이죠.


거기다 개발자가 한 명인데, 서로 다른 운영체제의 프로그래밍 언어를 모두 습득하는 것을 기대하기도 힘들 뿐더러, 어찌어찌 언어와 개발 툴은 통달했다고 해도 새로운 기능을 출시하거나 버그픽스를 할 때마다 서로 다른 플랫폼으로 모두 적용하는 것은... 너무나도 힘들겠죠.


물론 각 플랫폼이 검수를 하는 이유 자체는 이해를 합니다. 어떤 플랫폼주라도 서드파티가 깽판쳐서 자신들의 이미지가 망하는 걸 원하진 않을 테니까요. 그리고 개발 언어와 툴이 다른 것도, 서로 다른 회사니 어쩔 수 없는 노릇이죠. 하지만 그렇다고 해서 자신들의 생존 자체가 더 급한 스타트업 쪽에서 이런 플랫폼주의 욕심과 사정을 100퍼센트 양해해주긴 힘듭니다. 그래서 플랫폼 주의 허가 없이도 앱을 배포하고, 최대한 서로 다른 플랫폼에서 코드를 공유해 쓸 수 있는 방법을 찾기 시작했죠.


그 중 최초로 등장한 것이 바로 웹뷰를 사용한 앱 구현입니다. 결국 어떤 운영체제 플랫폼이던 앱에서 광고나 공지사항 처럼 잦은 변경이 필요한 부분을 네이티브로 구성하는 것이 비효율적이죠. 그래서 당연히 데스크톱부터 모바일 운영체제까지 대개의 경우 운영체제는 웹뷰를 허용합니다. 이 웹뷰를 용도를 간단한 구현에서 조금 벗어나서 운용하면(?) 웹뷰 앱이 탄생합니다.


사실 생각해 보면 그다지 이상한 것도 아닙니다. 웹의 기능성은 이미 지속적으로 향상되어 왔고, 서버와 통신하며, 유저에게 상황에 맞는 뷰를 보여주고 상호작용한다는 기본 기능은 오래 전에 가능했습니다. 거기다 구세대의 웹에서 불가능했던 수준 높은 시각화도 이미 가능하고, 아예 단순한 정보 표시의 기능을 넘어서는 기능들도 많이 탑재했습니다. 또한 이미 기존에 웹으로 서비스 로직을 거대하게 구현한 조직이 전체 기능성을 모바일로 옮기는 것은 매우 어렵죠. 이것은 네이버나 구글과 같은 대기업도 마찬가지입니다(구글의 검색 서비스 전체를 모바일 네이티브 앱으로 몽땅 다 옮긴다고 생각해 보세요). 앞의 두 기업의 서비스는 자체가 웹 브라우저의 성격을 갖기 때문에 더욱 더 그렇겠죠. 그래서 실제로 웹뷰를 사용해서 자사의 앱들을 구현한 기업이 초기에 굉장히 많았습니다. 실제로 이런 방법으로 앱을 구현하면, 기능성을 전환하기 위해서는 웹 서버의 로직만 변경하면 될 테니, 이전에 비해 훨씬 빠른 배포가 가능해집니다. 애플이나 구글이 아무리 대기업이라고 하더라도, 내가 굴리는 내 웹 서버를 좌지우지할 권한 따위는 없으니, 내 마음대로 내 웹 서버에 배포하면 그만입니다. 거기다 웹 기술 자체는 근본적으로는 특정 플랫폼에서만 지원되는 것이 아니니까 개발 비용도 아낄 수 있습니다. 하지만 다음과 같은 고민이 생겨났습니다.


결국 웹이 네이티브와 동등한 수준의 사용자 만족도를 주기는 힘듭니다.


저 사용자 만족도라는 단어는 정의하기 상당히 힘듭니다. 결국 앱을 쓸 때 느껴지는 미묘한 성능의 차이, 섬세하면서도 빠른 애니메이션, 각 플랫폼의 특수 기능과 플랫폼과의 통합도와 같은 개념을 통합해 사용자에게 얼마나 큰 만족도를 주는가인데, 기본적으로 웹이라는 플랫폼은 성능보다는 범용성에 중점을 두고 있고, 플랫폼별 특수 기능을 지원해주려니 웹의 플랫폼 중립성이라는 특성을 위반하게 될 테니 이것도 쉽지 않습니다. 그래서 등장하게 된 것이 React Native입니다.



React Native: Facebook답게 꼼수에 꼼수를 거듭한


이 시점에서 솔직하게 하나 말씀드리겠습니다. 저는 Facebook을 별로 좋아하지 않습니다. 그들이 개인정보와 광고를 기반으로 사업을 하는 방식이 싫으며, 그들이 앱을 배포하는 플랫폼의 개인정보 보호 규정을 어떻게든 우회하려는 태도를 싫어합니다. 하지만 이들이 이런 태도를 갖고 있기 때문에 React Native가 등장했다는 건 부정하기가 힘드네요.


React Native에 대해서 몇 가지 요약을 해 드리겠습니다.

1. 웹앱 아님.

2. 자바스크립트 사용함

3. Facebook이 이미 자사의 앱(Facebook, Instagram)을 구현함.


사람들이 React Native와 웹뷰 앱을 많이 혼동합니다. 아마도 위에서 본 웹뷰 앱을 이미 경험해보기도 했고, 둘 다 JavaScript라는 생태계와 연관이 있으니까요. 하지만 다음과 같은 결정적인 차이가 있습니다:


웹뷰는 웹 브라우저 렌더러가 인터페이스를 Draw 하고, React Native는 각 플랫폼의 네이티브 인터페이스 렌더러에 의해 화면에 Draw 됩니다.


물론 조금 잘 아시는 분께서는 이것이 결정적인 차이가 아니라 웹 환경이 앱이 구현되는 근간인지, Native 환경이 앱이 구현되는 근간인지가 기준이라고 하시겠으나, 잘 모르시는 분이 명확히 이해하기도 쉬운 설명이 아니고 Cordova나 Capacitor 같은 사례가 있어 그런 설명을 채택하지 않았습니다.


React Native에 대한 설명을 더 이어 갈게요. React Native는 기본적으로 다음과 같이 동작합니다:

1. JavaScript 코드는 각 운영체제가 기본으로 사용하는 JavaScript 엔진을 사용함. 이는 브라우저 밖에서 구동됨.

2. React Native 자체가 JavaScript 함수와 네이티브 바이너리 간에 소통하는 Channel을 가짐

3. 최근의 JavaScript 엔진들은 어마어마한 성능 개선을 이뤄냈고, 네이티브 바이너리로 구현이 이어지기 때문에 스크립트 언어의 성능손실을 최소화

와 같은 이유로, React Native는 JavaScript로 로직이 구동되는 구간에서는 물론 네이티브에 비해 성능 손실을 어느정도 가질 수 있지만, 사실상 네이티브 앱이라고 보는 것이 타당합니다. 그리고 순수 네이티브 앱에 비해 성능을 희생한 댓가로 다음과 같은 장점을 갖습니다. React Native가 웹과 공유하는 몇 안되는 특성이기도 하죠:


JavaScript 파일은 운영체제 입장에서는 앱에서 쓰는 Image와 같은 Asset이기 때문에, 검수 없이 실시간으로 교체 가능


네, 실제로 저게 됩니다. 당장에 Facebook부터가 이 저 특징을 굉장히 잘 써먹었고, 아예 Microsoft는 자사의 서비스 Appcenter에서 이와 같은 배포를 빠르고 안전하게 해 주는 CodePush라는 서비스를 운영중입니다. 그렇다면 여러분은 다음과 같은 합리적 의문을 가지실 겁니다.


왜 Apple과 Google은 이런 행위를 막지 않는 것이지? 이건 검수를 사실상 무력화하는 행위가 아닌가?


실제로 애플이 React Native를 엄청 싫어합니다. 당장 애플이 최근에 어마어마하게 페이스북을 견제하고 있기도 하고, 개별 앱의 기능성을 자신들의 통제 하에 두고 싶어하는데 이를 우회하는데 써먹는 회사들도 상당히 많으니까요. 하지만 Facebook이 만든 기술이라는 이유로 차단을 할 수 없으니 기술적으로 여기에 태클을 걸 수 있어야 원하는 대로 React Native를 사용하는 앱들을 시장에서 차단할 수 있을 텐데, 이것이 불가능합니다. 왜냐구요? 당장  애플부터가 JavaScript를 어마어마하게 응용하고 있으니까요.


애플은 GNU진영과의 갈등 이후에 기본 컴파일러를 GCC에서 LLVM/Clang으로 전환했습니다. 이후 빠른 운영체제 및 프로세서 전환에 대응하기 위해서 LLVM에서 사용하는 IR(중간 기계어)으로 앱을 업로드할 것을 요구했는데, 이 때 검수조건 중 하나가 이것입니다: 서드파티 런타임 사용 불가. 모든 바이너리는 bitcode(애플이 LLVM 바이트코드에 붙인 이름)으로 컴파일된 형태여야 함. 단, JavaScript예외.


이것은 물론 애플이 갖는 하드웨어 플랫폼의 특수성에서 기인합니다. 애플은 소프트웨어 동작을 최대한 통제함으로서 하드웨어 구현을 단순화해왔고(정확히는 본인들이 해결해야 하는 문제가 너무 많으니 이를 단순화하고 마진을 최대화하기 위해서), 따라서 본인들이 가정하지 않는 방식으로 하드웨어가 구동되는 것을 방지하기 위해서 바이너리 단에서 확실하게 통제하기 위해 이와 같은 제약사항을 넣은 것입니다.


그런데 왜 JavaScript만 예외일까요? 그것은 애플 스스로도 어느정도 앱에 유동성이 필요함을 인정할 수 밖에 없었기 때문입니다. 당장해 애플 뮤직이나 앱스토어 광고를 매번 각 소프트웨어를 업데이트해서 배포한다고 생각해 보세요. 결국 Google이나 Apple모두 어느 정도 앱에 유동성을 넣을 수 밖에 없고, 그 중 웹의 시장성 확대와 운영체제 자체에 기본으로 브라우저라는 스크립트 언어 실행환경은 탑재할 수 밖에 없으니까요. 실제로 요즈음의 운영체제에서 JavaScript런타임은 종전에 비해 상당히 운영체제의 하부 구조와 밀접한 수준에서 구동되고, 엔진 자체의 언어 처리속도도 범용성 있는 스크립트 언어 중에서는 수요를 충족하기 위해 상당히 빠른 편입니다.


React Native는 바로 이런 점을 파고들어 탄생한 플랫폼입니다. Facebook은 이전부터 광고/트렌트 중심의 비즈니스 모델을 구축해 왔기 때문에 빠른 기능 배포가 필수적이었고, 이를 위해 자신들에게 가장 맞는 환경을 조성한 것이죠(또 애플이나 구글과 싸울때 일단 원하는 기능 최대한 앱에 밀어넣으면서 시간도 벌고요). 이것이 스타트업의 수요와 맞아떨어져 아주 빠르게 거대한 규모로 성장한 것이구요. 이것이 요즈음 스타트업에서(그리고 상당수의 대기업에서도) React Native의 수요가 거대한 이유입니다.



Flutter: 구글 스스로 만들어낸 똥떵어리를 해결하기 위한


솔직히 말하겠습니다. 저는 Android도 좋아하지 않습니다. iOS식 통제를 좋아하냐고 물으면 그렇지는 않습니다. 윈도우도 굉장히 좋아하거든요. 애플의 통제는 일상생활을 영위하는 사용자 입장에서는 편하다고 생각하고, 이 플랫폼을 바탕으로 소프트웨어를 구현해야 하는 입장에서는 상당히 귀찮아합니다. 하지만 Google이 만들어낸 API 구현체는 재앙이라고 생각합니다. 당장에 제조사별로 구현이 상이하고, 자바 생태계 자체의 파편화를 해결하지 못하고 패키지 매니저 위에 패키지 매니저가 겹겹이 올라가는 복잡한 구조를 택했으며, 런타임에서 본인들이 만들어낸 Firebase와 같은 서비스의 구현체 조차도 난독화인 Proguard를 상당부분 비활성화 하지 않고서는 돌릴 수 없습니다(이 말은 곧 상당수 기능들이 정적 링크가 안 된 상태로 구동된다는 말과 거의 비슷합니다). 어떤 운영체제든 대규모 소프트웨어인 만큼 버그는 피할 수 없죠, 하지만 버그와는 별개의 이유로 안드로이드의 여러 의미에서의 파편화를 무척 싫어합니다.


그렇지만 솔직히 말해서, Flutter는 구글이 무책임하게 버려댄 수많은 프로젝트 중에서 생존한, 최고의 역작 중 하나라고 생각합니다. 지금까지 Android에서 시도한 수많은 시행착오 중 유의미한 정책만을 남겨두었고(혹은 과오를 해결했고), Dart라고 하는 언어의 장벽만 뛰어넘으면 설계 자체는 상당히 명료한 편이며, 결정적으로 React Native의 문제 중 하나를 해결했으니까요.


Flutter와 React native는 얼핏 보기에 상당히 비슷해 보입니다. 동일한 코드베이스로 iOS와 Android 전체에서 구동 가능한 응용을 구현할 수 있고, 그럼에도 네이티브와 동등한 속도를 보장합니다. 하지만 Flutter는 React Native와 결정적인 차이가 있는데, 바로 이것입니다: 사이드채널 업데이트 불가. 즉, 앱 스토어를 통해 ‘설치’하는 형태로만 바이너리 로직을 전환할 수 있음.


이 말을 듣고 나면, 제가 굉장히 이상한 사람이란 생각이 드실 수도 있습니다. React Native의 가장 큰 장점을 Flutter가 달성하지 못하는데, 도대체 왜 역작이라고 하는 것이지?


엔지니어링은 장점과 단점 사이에서의 최적점을 찾는 것이죠. 당연히 포기한 만큼 이득이 있습니다. 그것은 바로 런타임에 인터프리터가 동작 자체를 하지 않는, 완벽한 형태의 기계어로 번역되기 때문에 한결 더 성능이 높단 것이죠.


이 외에도 한 가지 이점이 더 있습니다. React Native는 인터페이스 드로잉을 각 운영체제의 인터페이스 구성요소를 사용한다고 말씀드렸습니다. 하지만 Flutter는 Google이 이미지 렌더링 등을 위해 만든 Skia라고 하는 렌더러를 통해서 인터페이스를 렌더링 합니다. 이 말은 Flutter의 인터페이스 렌더링은 사실 대학에서 한번쯤 해 보셨을 OpenGL과 같은 GPU컨텍스트에서 직접 드로잉을 하는 것과 비슷하단 말입니다. 따라서 React Native가 생각만큼 픽셀 단위로 인터페이스를 다듬기 힘든 데 반해서, Flutter는 상당히 정교하고 깔끔하게 인터페이스를 렌더링하기 좋음을 뜻합니다. 실제로 Flutter에서 가장 빛을 발하는 부분이 애니메이션 구현이기도 하구요.


그런데 오늘은 성능의 관점이나 결과물의 우수성보다 개발 편의성 측면에서 Flutter의 장점을 바라보고자 합니다. 결국 웹뷰와는 두 플랫폼 모두 넘사벽의 성능 격차가 있는 만큼, 속도 면에서 소비자가 차이점을 특정하기가 힘드니까요. 개발 편의성 면에서 Flutter가 가장 잘 결정한 것은 정적 타입 언어를 채택한 것이라고 생각합니다(개인적으로 Dart 말고 다른 언어였으면 더 좋았겠지만...)


자바스크립트는 동적인 언어입니다. 그런데 대개의 경우 운영체제는 인터페이스의 동작을 바이너리 수준에서 정의합니다. 운영체제가 이러는 이유는 당연합니다. 연산장치와 거의 맞닿은 수준에서 동작하고 있고, 빠른 동작을 보장하기 위해서는 이미 프로세서에 내장된 처리장치에 가장 최적화된 연산을 요구하는 것이 합리적이죠. 이 두 가지 환경의 격차에서 수많은 문제가 발생합니다. 그리고 이미 제거할 수 있는 방법이 수없이 많이 개발되었음에도 놓치는 문제가 생깁니다. 그것이 바로 Type의 문제입니다.


컴퓨터 프로그래밍 언어는 여러 방면으로 증가해 왔지만, 시장에서 생산되는 로직의 평균적 복잡도가 상승해 갈수록 오류를 미연에 방지하기 위한 기술에 대한 수요가 커져 왔습니다. 하지만 대개의 경우에는 해결할 수 없거나 근사해서 해결하는 정도의 수준에 그칩니다(너무 많은 컴퓨터과학 개념을 설명해야 하기 떄문에 생략하겠습니다). 하지만 그럼에도 불구하고 타입에서만큼은 상당히 높은 수준의 문제 해결을 했습니다. 실제로 컴파일러들이 논리적 오류는 찾아내지 못하는 경우가 많지만, 많은 경우에 타입 추론으로 Integer, String, 혹은 다양한 Class들의 타입을 정확히 추론하고 문제를 지적하죠. 또 암묵적 형 변환에서 발생할 수 있는 수많은 문제들도 이미 완전에 가까운 수준으로 지적하고 있구요. 따라서 수많은 발생가능한 예외 중에서도 타입 오류는 상당히 피해갈 수 있습니다(여전히 논리 오류들의 문제는 남지만…). 단, 정적 타입 언어에서만요.


결국 문제는 여기서 발생합니다. JavaScript의 타입이 동적이라는 문제죠. 동적 타입은 작은 단위의 소프트웨어에서는 중간 변수의 지나친 남발을 피하고 로직의 동작을 명료히 하는 효과가 있지만, 로직이 거대해질수록 의도하지 않은 동작을 유발합니다. 결국 웹이 최초 설계 의도를 벗어나 거대한 응용을 설계하면서 맞닥뜨린 문제에서 React Native도 자유롭지 않다는 말입니다. 아니, 어쩌면 더 심각합니다. 웹은 동작 자체가 정지하진 않겠지만 네이티브에서 저러면 당연히 Crash가 발생할 확률이 아주 높아질 테니까요.


이 문제를 해결하기 위해 JavaScript에 타입을 도입한 TypeScript가 등장했습니다. 마이크로소프트가 개발한 언어고, 현재 대규모 웹 응용이나 React Native 프로젝트에서 아주 활발하게 활용되고 있습니다. 하지만 이 언어는 JavaScript엔진들에서 표준으로 채택하고 있지는 않기 때문에 자바스크립트에 타입을 기껏 붙여 놓고 자바스크립트로 다시 변환을 하는 비직관적인 일을 해야 합니다. 여전히 인터프리터 언어에 의존하기 때문에 성능 저하를 완전히 피할 수 없다는 문제점도 있구요.


이런 면에서 Flutter는 정적 타입 언어를 채택하는 상당히 영리한 선택을 했습니다. 또 코드를 수정하면 개발 환경에서 이를 바로 테스트할 수 있는 React Native의 가장 큰 장점 중 하나, 핫 리로딩도 지원합니다. 아마 이것이 구글이 Dart를 사용한 이유일 텐데, Dart가 핫 리로딩 가능한 스크립트 형태로도, 완전한 네이티브 바이너리 형태로도 컴파일이 가능하다는 것이죠. 따라서 Flutter는 빠른 개발 iteration과 고성능이라는 목표를 모두 달성합니다(그래서 사이드채널 업데이트가 안 되지만…).


그리고 또 하나 눈여겨봐야 할 것은 구글이 퓨시아라는 차세대 프로젝트를 준비하고 있다는 사실입니다. 아마도 Android를 대체할 프로젝트의 주된 앱 개발환경은 Flutter를 채택할 것 같습니다. 구글이 안드로이드를 버리고 싶은 이유는 다양할 것입니다. 그 중 하나는 아마도 Linux에 기반한 오픈소스 생태계를 기반으로 빠르게 성장해 반 iOS에서 독점적 포지셔닝을 확실히 했으니 이런저런 집단에 휘둘리지 않고 자신들의 정책을 강력한 권력으로 시장에 밀어붙이고 싶다는 마음일 것이고, 다른 하나는 빠르게 발전하면서 안드로이드에 어마어마하게 쌓아올린 레거시도 프로젝트를 리부트해서 일소하고 싶은 마음일 것이고, 자바에 기반한 생태계에서 오라클과의 법적 분쟁과 런타임 파편화 문제도 피하고 싶겠죠.


Flutter는 안드로이드 특유의 뷰 라이프사이클과 인터페이스 구현에 대한 자유도 높은 특성은 상속받았지만, 그에 비해서 모듈 관리 전략이나 언어의 구현체 자체는 훨씬 정돈되어 있습니다. 거기에 구글의 차세대 모바일 운영체제의 기본 개발도구가 될 것이라면, Flutter를 배워두는 것도 미래를 위해서는 상당히 괜찮은 선택이 될 수 있습니다. 물론 구글이 이 프로젝트를 안 버려야 하겠지만요. 어쩌면 자신들의 플랫폼을 중심으로 개발하면 타사 플랫폼을 위한 구현체도 만들수 있게 한다면, 다른 플랫폼조차도 자신들의 플랫폼 일부로 편입할 수 있다는 마이크로소프트의 이상은 구글이 먼저 실현할지도 모르겠네요.


이번 글은 여기까지 써 보려고 합니다. 방학 시작 이후 본격적으로 회사 일을 다시 본격적으로 시작하기까지의 여유 기간이 짧아 글을 쓸 시간도 별로 없다 보니 상당히 두서가 없습니다. 여러 편에 나눠서 언급할 내용을 한편의 글에 욱여넣어서 그렇기도 합니다. 당연히 글에 많은 오류도 있을 거고, 궁금해하실만한 부분을 속 시원히 다 적지 못한 부분도 많습니다. 이런 부분은 댓글로 남겨드리면 최대한 답변해 드리겠습니다. 감사합니다!