Dart 2.8 발표

Dart 2.8 발표

오늘 Dart SDK의 새 릴리스, 버전 2.8을 발표해요. Dart 커뮤니티는 계속해서 놀라운 성장을 보여주고 있어요. 이제 수백만 명의 Flutter 개발자가 Dart를 어떤 플랫폼에서든 빠른 앱을 만들기 위한 클라이언트 최적화 언어로 사용하고 있죠. 우리는 여전히 곧 출시할 null safety 기능을 완성해서 Dart를 빠르고 안정적인 사용자 인터페이스를 만들기 위한 더욱 최적화된 언어로 만들기 위해 열심히 작업하고 있어요. 그와 함께, 개발자가 의존성(dependency)을 관리할 때 훨씬 더 생산적이게 해주는 흥미로운 새 기능 몇 가지도 준비했어요.

Dart 플랫폼은 pub 클라이언트 도구와 pub.dev 패키지 저장소를 통한 패키지 관리를 기본으로 지원해요. pub.dev는 지난 1년 동안 200% 성장해서 이제 거의 10,000개의 패키지를 담고 있어요. Dart 생태계를 개선하기 위한 지속적인 작업의 일환으로, Dart 2.8 SDK는 pub 클라이언트 도구에 두 가지 개선을 가져와요. pub get의 훨씬 더 나은 성능과, 패키지 의존성을 최신 상태로 유지하는 데 도움을 주는 새 도구예요.

Dart 2.8은 또한 Dart 언어와 라이브러리에 몇 가지 작은 breaking changes를 가져와요. 이 변경들은 우리 첫 번째 버전의 null safety 기능을 위한 기반을 마련해요.

출처: Announcing Dart 2.8

본문

null safety를 위한 길을 여는 breaking changes

앱 크래시의 흔한 원인은 우연히 null인 변수를 사용하려는 코드예요. 1965년 ALGOL 프로그래밍 언어에 null 참조를 도입한 Tony Hoare 경은 2009년 QCon 강연에서 그걸 유명하게 "10억 달러짜리 실수(billion-dollar mistake)"라고 불렀죠. 어떤 경우에는 null 값이 유용해요. 문제는 유용한 경우와 그렇지 않은 경우를 구분하는 거예요. 지난 1년 동안 우리는 Dart에서 사운드(sound) null safety를 지원하는 작업을 바빠서 진행해 왔어요. 이 지원은 항상 non-nullable인 변수를 표현하도록 타입 시스템을 확장하고, 게다가 타입 시스템이 완전히 사운드하도록 만들 거예요. Dart 컴파일러와 런타임이 그 타입들을 신뢰하고, 타입 시스템이 변수가 null이 아님을 보장할 때 최적화된 코드를 생성할 수 있게 되는 거죠.

짐작하시겠지만 이건 움직이는 부품이 많은 큰 작업이에요. null safety를 깔끔한 의미(semantics)로 만들 수 있도록, 우리는 Dart 언어와 라이브러리에 몇 가지 작은 breaking changes를 만들기로 결정했어요. 이 breaking changes는 Dart 타입 시스템의 모서리 경우와 몇몇 Dart 핵심 라이브러리를 약간 조정해서 훌륭한 nullability 관련 사용성과 성능을 보장해요. Dart 공지 목록에서 사전 공지된 이 breaking changes가 일반적인 앱 코드에 미치는 실제 영향은 미미할 거라고 기대해요. Dart 2.8에서 문제가 생기면 breaking changes와 그 설명·완화 단계를 검토해 보시길 권해요. 그래도 해결되지 않으면 우리 이슈 트래커에 이슈를 등록해 주세요. null safety 경험을 미리 보려면 null safety 플레이그라운드를 사용해 보세요.

더 높은 품질의 패키지 생태계

pub 패키지 매니저와 pub.dev 사이트는 계속 성장하는 Dart와 Flutter 생태계를 뒷받침해요. pub.dev에는 거의 10,000개의 패키지가 있고, 공유되는 흥미로운 패키지가 많아서 우리는 계속 놀라고 있어요. 패키지 작성자가 고품질 패키지를 만들도록 돕고 앱 개발자가 그런 패키지를 찾도록 돕는 것이 우리의 핵심 사명이에요 — 예를 들어 개선된 pub.dev 발견(discovery), 검증된 게시자(verified publishers), Flutter Favorites 등을 추가했죠.

오늘 우리는 pub.dev 저장소에서 패키지를 가져올 때 훨씬 더 빠른 성능과, 모든 패키지 의존성을 최신 상태로 유지하도록 돕는 새 도구를 발표해요. 현대 앱의 복잡성 때문에, 여러분의 앱은 아마 수십 개의 패키지에 의존할 거예요. 그런데 이 모든 것을 최신 버전으로 — 버그 수정과 성능 개선이 모두 담긴 가장 최근 의존성으로 — 어떻게 유지할 수 있을까요? Dart 2.8부터는 **pub outdated**를 사용할 수 있어요. 어떤 의존성을 최신 버전으로 업데이트해야 하는지 자동으로 판단해 주는 새 도구예요.

Dart 2.8 pub 도구 성능 개선

우리는 pub get을 실행할 때 패키지 병렬 가져오기를 지원하고, pub run 프리컴파일을 지연시켜서 pub 도구의 성능을 최적화했어요.

flutter create로 만든 새 프로젝트에서 flutter pub get을 실행하는 비공식 벤치마크에서, 총 실행 시간이 Flutter 1.12(Dart 2.7 사용)의 약 6.5초에서 Flutter 1.17(Dart 2.8)의 단 2.5초로 줄었어요. Flutter gallery 같은 더 큰 앱에서는 약 15초에서 약 3초로 줄어요!

pub outdated로 의존성 관리하기

Dart 코드의 의존성은 pubspec 파일에 담겨요. pub get 명령으로 pub.dev에서 패키지를 가져오면, pub 버전 솔버(족 PubGrub 알고리즘을 사용해요)가 여러분의 pubspec에 나열된 제약 조건을 만족하는 모든 의존성 버전의 최신 가능한 조합을 결정하는 과정을 실행해요. pub은 각 패키지가 앱에 단일 버전으로만 포함되는 single-version 방식을 사용한다는 점을 참고하세요. 이는 앱 크기를 가능한 한 작게 유지하기 위한 중요한 최적화예요.

항상 최신 안정 패키지 버전을 사용하는 것이 모범 사례이지만, 그렇게 하는 건 꽤 번거로울 수 있어요. Dart는 pub upgrade를 사용해 의미적으로 호환되는 최신 버전으로 업그레이드하는 것을 지원하지만, pubspec을 업데이트하지 않고서는 패키지의 새 메이저 버전을 포함할 수 없어요. pub outdated 명령은 현재 사용 중인 버전을 pub.dev에서 사용 가능한 최신 버전과 비교해서, 마이너·메이저 버전이 언제 사용 가능한지 이해하도록 도와줘요.

구체적인 예시를 생각해 볼게요. 앱을 만들고 있고 pubspec.yaml에 다음이 들어 있다고 상상해 보세요.

dependencies:
  foo: ^1.3.0
  bar: ^2.0.0

pub get을 실행하면, 도구가 다음 버전을 담은 pubspec.lock 파일을 만들어요.

packages:
  foo:
    version: "1.3.0"
  bar:
    version: "2.0.1"

몇 달이 지나서 pub.dev에 이제 foo(1.3.1)와 bar(2.1.0, 3.0.3)의 새 버전이 있다고 해볼게요. 이 새 버전을 어떻게 발견할 수 있을까요? 마이너 버전 업그레이드(foo 1.4.0과 bar 2.1.0)는 pub upgrade를 실행하면 되지만, 그건 bar 3.0.0을 주지 않아요. 그 새 버전을 발견하려면 pub.dev에서 각 패키지를 방문해서 최신 버전을 확인해야 해요. 또는 Paulina Szklarska의 version checker나 Jeroen Meijer의 pubspec assist 같은 커뮤니티 솔루션을 사용할 수도 있어요.

pub outdated로 이제 Dart SDK가 버전 발견(version discovery)을 지원해요. Dart나 Flutter 지원이 있는 IDE를 쓰고 있다면, pubspec.yaml 파일이 열려 있을 때 표시되는 Pub outdated 액션을 사용해요. 아니면 터미널에서 pub outdated(또는 flutter pub outdated)를 실행하면 돼요.

$ pub outdated

Dependencies            Current  Upgradable  Resolvable  Latest
foo                     1.3.0    1.3.1       1.3.1       1.3.1
bar                     2.0.1    2.1.0       3.0.3       3.0.3

1 upgradable dependency is locked (in pubspec.lock) to an older version.

To update it, use `pub upgrade`.

1 dependency is constrained to a version that is older than a resolvable version.

이 출력은 pub upgrade로 자동으로 foo 1.3.1로 업그레이드할 수 있다는 걸 알려줘요. 그러면 foo의 사용 가능한 최신 버전에 도달하게 되죠. 하지만 동시에 bar 2.1.0으로는 자동 업그레이드할 수 있지만 3.0.3 버전이 사용 가능하다는 것도 알려줘요. bar 3.0.3으로의 업그레이드는 메이저 버전 업그레이드이기 때문에, pubspec.yaml 파일을 편집해서 그 업그레이드를 선택해야 해요.

dependencies:
  foo: ^1.3.0
  bar: ^3.0.3

그 편집을 하고 pub upgrade를 실행하면, pub outdated가 이제 모든 의존성이 최신 상태라고 보고해요.

$ pub outdated

Dependencies            Current   Upgradable  Resolvable  Latest

all up-to-date

성공, 최신 상태가 됐어요! 새 메이저 버전을 포함한 새 버전을 방금 받았으니, 그 버전들의 잠재적 breaking changes를 검토하고 모든 테스트를 실행해서 앱이 여전히 예상대로 동작하는지 확인해야 해요.

다음 단계

성능 개선, breaking changes, 새 pub outdated 명령은 오늘 안정적인 Dart 2.8 SDK와 안정적인 Flutter 1.17 SDK에서 사용할 수 있어요. 지금 pub outdated를 실행해서 의존성의 상태를 확인해 보시길 권해요!

문제를 발견하면 pub 이슈 트래커 또는 일반 이슈는 SDK 이슈 트래커에 보고해 주세요. pub outdated에 대한 여러분의 경험을 듣고 싶어요. 아래에 댓글을 남기거나 @dart_lang으로 트윗해 주세요.

더 알아보기