
최종 업데이트: 2026년 5월 28일
Quire(Dart 53,992줄, 1,620 KB)는 2014년에 클라이언트와 서버 모두 Dart로 만들어졌습니다. 더 세밀한 DOM 제어를 위해 AngularDART나 Polymer.dart 대신 DQuery와 Bootjack을 사용했습니다. 전 계층의 강한 타입, 클라이언트와 서버가 공유하는 데이터 모델, 서버의 이벤트 루프, JS 출력의 트리 셰이킹이라는 핵심 결정은 2026년에도 유효합니다.
Quire는 Dart로 만든 첫 번째 웹 애플리케이션도, 마지막 애플리케이션도 아니겠지만, 클라이언트와 서버 양쪽에서 이렇게까지 Dart에 의존한 앱으로는 처음일 수 있습니다.

트리 구조를 핵심으로 삼은 재미있는 업무 관리 도구입니다. 이 프로젝트는 커뮤니티의 오픈소스 라이브러리 몇 가지를 활용해 만든 53,992줄, 1,620KB 분량의 Dart 코드로 이루어져 있습니다.
이 프로젝트를 시작하기 전부터 저희는 Rikulo 팀이라는 이름의 Dart 애호가였습니다. UI 프레임워크, UI 라이브러리, 웹 서버, 메시징 서버, 데이터베이스 클라이언트 등 여러 Dart 라이브러리를 공개해 왔습니다.
2011년 Dart가 처음 나왔을 때 그 미래 가치에 모두 들떴고, 곧바로 작은 프로젝트 일부에 Dart를 적용하기 시작했습니다. 그러다 결국 Dart가 대부분을 차지하는 완전한 애플리케이션을 만들기에 이르렀습니다. 저희의 경험을 겸손하게 나누어, Dart 개발에 참고가 되기를 바랍니다.
Dart를 선택할 이유는 아주 많습니다. 그중 저희에게 가장 중요했던 이유는 다음과 같습니다.
Dart를 선택했을 때의 단점도 있습니다.
강한 타입 지원 덕분에 Dart로 작성한 코드는 JavaScript보다 훨씬 믿을 수 있습니다. 또한 Dart는 Java보다 덜 장황하고, 경우에 따라(예: 함수 표현식) 순수 JavaScript보다도 덜 장황합니다. 전반적으로 Dart 작업은 쾌적하지만, 몇 가지는 아쉽습니다.
Dart VM이 Chrome에 탑재되기 전까지는 제품을 JavaScript로 컴파일해서 배포해야 합니다. JavaScript로 컴파일되는 언어는 많지만, Dart는 몇 가지 추가 장점으로 돋보입니다.
서버 측 Dart는 Dart 커뮤니티에서 뜨거운 주제였던 적이 없지만, 저희는 Dart가 서버 측 프로그래밍 언어의 유력한 후보라고 생각합니다. 이유는 다음과 같습니다.
관련 글: Quire, 데이터를 보호하는 ISO 인증 획득 — 서버 측 견고성과 보안을 중시하는 같은 태도는 수년 뒤 Quire의 공식 데이터 보호 인증으로 이어졌습니다.
Quire에는 약 30개의 라이브러리 import가 있으며, 그중 10개는 커뮤니티에서, 나머지는 Dart 팀에서 공개한 것입니다. Dart 전문가라면 AngularDART와 Polymer.dart가 있으리라 짐작하겠지만, 실제로는 둘 다 사용하지 않습니다.
AngularDART를 사용하지 않는 이유는 다음과 같습니다.
Polymer.dart도 사용하지 않는데, 이유는 다음과 같습니다.
저희 클라이언트 측 스택의 초석은 DQuery와 Bootjack입니다. 둘 다 Rikulo 팀이 공개한 오픈소스 프로젝트입니다.
이렇게 애플리케이션 스택을 구성해, JavaScript 세계에서 쌓은 지식과 기술을 그대로 활용했습니다.
Stream은 순수 Dart로 작성한 저희 웹 서버로, 라우팅, 필터, 서버 측 MVC 등의 기능을 갖추고 있습니다. Stream은 이벤트 루프 모델과 매끄럽게 동작합니다. 요청 핸들러를 작성하는 일은 논블로킹 루틴을 차례로 연결하는 것이 전부입니다.
기존 멀티스레딩 모델보다 생산성이 높을 뿐 아니라 작업하는 즐거움도 더 큽니다. 또한 nginx로 웹 서비스를 확장하고 HTTPS를 처리하며, 요청을 Stream에 전달합니다. 이 구조 덕분에 Dart VM을 개별적으로 띄우고 내릴 수 있고, 사용자 활동을 중단하지 않고 서버를 업그레이드할 수 있습니다.
Dart로 작업하는 경험은 즐거웠고, Dart 커뮤니티의 더 흥미로운 발전을 기대합니다. 마지막으로, Dart로 무엇을 만들 수 있는지 궁금하시다면 저희 앱 Quire를 직접 써 보세요. 무료입니다!
Quire가 이후 Mark II로 새롭게 구상되고 다시 만들어진 이야기를 더 읽어 보세요.

이 글을 쓴 이후 Dart 언어와 Quire 코드베이스는 모두 크게 발전했습니다. 2018년에는 Dart 2.0(사운드 타입 시스템)이, 2023년에는 Dart 3.0(null safety, 레코드, 패턴)이 나왔고, Flutter는 크로스 플랫폼 UI 환경을 바꿔 놓았습니다.
(Quire의 모바일 팀도 Flutter로 전환했습니다.) 하지만 위에서 다룬 아키텍처 결정들은 예상보다 훨씬 잘 버티고 있습니다.
전 계층의 강한 타입은 여전히 값어치를 합니다. 강한 타입 시스템이 빌드 단계에서 잡아내는 런타임 오류는 지금도 똑같은 오류입니다.
JavaScript는 TypeScript를 통해 타입 쪽으로 어느 정도 다가갔지만, 처음부터 끝까지 타입이 갖춰진 스택은 여전히 드뭅니다. Simon이 짚은 버그의 부류(수많은 사소한 실수)는 타입 없는 스택이 지금도 운영 환경까지 끌고 가는 바로 그 부류입니다.
클라이언트와 서버의 공유 데이터 모델은 여전히 작업을 줄여 줍니다. 데이터 모델 사본 생성하기 문제(JS에 하나, Python에 하나를 두고 조용히 어긋나는 상황)는 2026년에도 2014년과 같습니다. 해법(처음부터 끝까지 한 언어)도 같습니다. Node 기반 TypeScript 팀들이 Quire와 같은 구조를 만드는 것도 바로 이 때문입니다.
웹 서버에서는 멀티스레딩보다 이벤트 루프가 여전히 우세합니다. Node, Deno, Bun, 그리고 Dart 자체의 Stream 패턴 모두 같은 결론입니다. 몇 해마다 논쟁이 되풀이되지만 결론은 늘 같은 곳에 닿습니다.
트리 셰이킹은 더 중요해졌습니다. 2014년에 Dart의 트리 셰이킹 컴파일러는 차별화 요소였습니다. 2026년에는 JS를 대상으로 하는 모든 빌드 파이프라인의 기본 요건입니다. Webpack, Rollup, esbuild, Vite 모두 지원합니다. 교훈은 그대로이고, 도구가 따라잡았습니다.
2014년의 ShadowDOM 우려는 대부분 해소되었습니다. Polymer.dart는 지원이 중단되었고, Web Components는 성숙했습니다.
Simon이 Polymer를 피한 이유(스타일 주입, 프레임워크와의 협업)는 결국 플랫폼 차원에서 해결되었습니다. 운영 앱의 핵심에는 최신 프레임워크를 피하라는 일반 원칙은 지금 "가장 주목받는" 프레임워크가 무엇이든 2026년에도 그대로 적용됩니다.
관련 글: 제작 이야기: Flutter 기반 모바일 타임라인 — Quire의 모바일 팀이 Flutter로 타임라인 뷰를 만든 과정을 살펴봅니다.
수년간 운영할 애플리케이션의 언어 스택을 고르는 일은 되돌리는 데 큰 비용이 드는 몇 안 되는 엔지니어링 결정입니다. 팀이 잘못 고를 때는 네 가지 패턴이 반복됩니다.
1. 커뮤니티가 가장 크다는 이유로 기본 선택하기. JavaScript의 커뮤니티가 가장 크지만, "가장 크다"는 것이 "내 문제에 가장 잘 맞는다"는 뜻은 아닙니다. 강한 타입 시스템과 좋은 도구를 갖춘 작은 커뮤니티의 언어가, 보장이 약한 방대한 생태계보다 나은 성과를 낼 수 있습니다. 커뮤니티 규모는 중요하지만 유일하게 중요한 것은 아닙니다.
2. 클라이언트와 서버의 언어가 갈라지는 스택 고르기. 중복된 데이터 모델은 모두 터질 날을 기다리는 버그입니다. 서버는 Ruby, 클라이언트는 JS로 출시하는 팀은 그 비용을 영원히 치릅니다. 두 영역에서 한 언어(Dart, TypeScript, Kotlin)를 공유하는 팀은 버그의 한 부류를 통째로 피합니다.
3. 안정되기 전에 최신 기술 도입하기. Quire 팀은 2014년에 AngularDART와 Polymer.dart를 피했습니다. 둘 다 아키텍처상의 미해결 문제가 있었기 때문입니다.
AngularDART는 크게 방향을 틀었고 Polymer는 지원이 중단되었습니다. 앱의 핵심을 걸기 전에 프레임워크가 대규모 운영 환경에서 검증되기를 기다리라는 일반 원칙은 지금 "가장 주목받는" 프레임워크가 무엇이든 2026년에도 그대로 적용됩니다.
4. 단기 속도를 위해 타입 시스템 건너뛰기. 타입 없는 언어는 첫 주에는 더 빠르게 느껴집니다. 하지만 여섯 달쯤 지나면 아낀 시간은 디버깅 시간으로 모두 돌려주고도 남습니다. 타입 없는 스택과 타입 있는 스택을 대규모로 모두 겪어 본 엔지니어링 팀은 자발적으로 되돌아가는 일이 거의 없습니다.
Quire 팀의 2014년 Dart 선택이 돌이켜 보아 합리적인 것은 Dart가 주류가 되어서(그렇지 않았습니다)가 아닙니다. 그 근거였던 기준(타입, 클라이언트와 서버의 공유, 이벤트 루프, 트리 셰이킹)이 이후 10년 동안 업계의 공감대가 되었기 때문입니다.
세월이 지나도 빛이 바래지 않은 것은 특정 도구가 아니라 그 밑에 깔린 엔지니어링 원칙이었습니다. 불확실한 상황에서 내리는 언어 선택은 대개 마찬가지입니다. 오늘 측정할 수 있는 인기보다, 10년 뒤에도 옹호할 수 있는 원칙을 기준으로 고르세요.
클라이언트와 서버 모두 Dart입니다. 애플리케이션은 약 54,000줄의 Dart 코드이며 라이브러리 import는 약 30개입니다.
강한 타입, 클래스 기반 상속 모델, 그리고 클라이언트와 서버에서 쓰는 하나의 언어 때문입니다. 또한 Dart는 JavaScript가 널리 지원하기 전부터 몇 가지 최신 기능을 제공했습니다.
팀은 AngularDART의 바인딩이 허용하는 것보다 더 세밀한 DOM 제어를 원했고, Quire의 아키텍처 패턴도 Angular의 논리와 맞지 않았습니다. Polymer.dart는 당시 ShadowDOM이 Bootstrap 방식의 셀렉터와 충돌해서 사용하지 않았습니다. 이후 Polymer가 지원 중단되면서 그 결정이 옳았음이 확인되었습니다.
Rikulo 팀(Quire의 엔지니어링 팀)이 공개한 오픈소스 라이브러리입니다. DQuery는 이벤트 위임에 초점을 맞춰 jQuery를 Dart로 부분 포팅한 것입니다. Bootjack은 거의 동일한 CSS와 API를 갖춘 Bootstrap 3의 완전한 포팅입니다.
순수 Dart로 작성되어 이벤트 루프 모델을 사용하는 Quire의 웹 서버입니다. 라우팅, 필터, 서버 측 MVC가 기본으로 들어 있습니다. Quire는 nginx 뒤에서 Stream을 운영하며, nginx가 확장과 HTTPS를 처리합니다.