Dart 3.4 발표

Dart 3.4 발표 (Announcing Dart 3.4)

Dart 3.4가 오늘 출시됐어요. 이번 릴리스는 Dart와 Flutter가 함께 만든 결과물이라, 세부 내용은 Flutter 3.22 / Dart 3.4 / IO24 글에서 살펴볼 수 있어요. 이 글에서는 Dart가 WebAssembly를 지원하게 된 소식과, 올해 Dart 언어 로드맵의 핵심 과제 중 하나인 **매크로(macros)**에 대해 자세히 설명할게요.

출처: Announcing Dart 3.4

본문

오늘, 최신 Flutter 3.22 안정 버전에서 Flutter Web 앱의 WebAssembly(Wasm)를 완전히 지원하게 됐다는 소식을 전하게 되어 기뻐요.

이건 Dart와 Flutter가 여러 해에 걸쳐 투자해 온 작업이에요. 그동안의 개발 과정을 따라가 보면 점진적인 진전을 볼 수 있어요.

  • WasmGC 제안을 표준화하고,
  • WasmGC 코드를 생성하는 새로운 Dart 컴파일러 백엔드를 추가하고,
  • Wasm을 가장 잘 지원하도록 웹 및 JavaScript 상호운용(interop) 구성을 개편했어요.

앞으로도 WebAssembly에 계속 투자할 거예요. 다음 작업은 순수 Dart 앱에서 Wasm을 완전히 지원하고, 아직 빠진 몇 가지 기능(예: 지연 로딩)을 마무리하는 거예요. Dart에서 Wasm 컴파일을 위한 end-to-end 도구는 아직 개발 중이지만, 임시 단계를 거쳐 지금 stable에서 프리뷰를 써볼 수 있어요. 나중에는 JS 환경 밖에서도 Wasm을 지원하고 싶은데, 예를 들어 wasmtime이나 wasmer 같은 표준 Wasm 런타임에서도 돌아가게 하는 거죠.

Dart 매크로: 개발 추상화 수준을 높이다

Dart 매크로 시스템을 설계하는 데 수년을 투자해 왔어요. 매크로는 코드 생성과 같은 메타프로그래밍 해법을 제공해서 Dart의 개발 경험을 개선하려는 거예요. 이 해법이 Dart 언어에 내장되어 있어서 개발자에게 최고의 성능, 효율, 생산성을 제공하죠. 이제 그 경험을 프리뷰로 공개할 준비가 됐어요!

Dart 개발자에게 오래된 골칫거리가 하나 있었는데, 바로 JSON 데이터를 직렬화·역직렬화하는 지루하면서도 반복적인 패턴이에요. Dart는 성능상의 이유로 런타임 리플렉션을 지원하지 않아서, 재사용 가능하면서도 충분히 강력한 해법을 만들기가 어려워요. 그래서 대안으로 JsonSerializable 같은 코드 생성 해법에 의존해 왔죠. 그런데 이건 코드 실행 전에 돌아가는 외부 도구에 의존해서 개발 경험을 복잡하게 만들어요.

오늘 우리는 JSON 직렬화·역직렬화를 위한 아주 새로운 접근의 프리뷰를 발표해요. 바로 JsonCodable 매크로예요.

매크로는 컴파일 타임에 다른 코드를 들여다봐서 더 많은 코드를 생성하는 일종의 코드예요. 예를 들어, 아래는 새로운 JsonCodable 매크로를 적용한 Dart 클래스 Vehicle이에요.

@JsonCodable()
class Vehicle {
  final String description;
  final int wheels;
  Vehicle(this.description, this.wheels);
}
void main() {
  final jsonString = Vehicle('bicycle', 2).toJson();
  print('Vehicle serialized: $jsonString');
}

그럼 이게 어떻게 동작할까요? toJson() 메서드(그리고 짝이 되는 fromJson() 생성자)는 어디서 나온 걸까요? 이건 우리의 새로운 매크로 시스템을 단순화한 실험적 구현이에요. Dart 컴파일러가 @JsonCodable() 애노테이션을 보면 즉시 JsonCodable 매크로의 정의를 찾아가서 실행하기 시작해요. 그러면 매크로는:

  • 기존 클래스에 새로운 선언을 추가할 수 있게 해주는 새 언어 구조인 "augmentation class"를 만들고,
  • 개발자가 정의한 Vehicle 클래스를 읽어 필드가 descriptionwheels 두 개라는 걸 파악하며,
  • augmentation class에 새로운 toJson 메서드 시그니처를 추가하고,
  • descriptionwheels 필드의 직렬화를 처리하도록 toJson 메서드 본문을 채워요.

이 모든 과정은 지연 없이 일어나요. 통합된 경험은 핫 리로드 같은 기존 개발 워크플로우를 지원해요. 이 스크린캐스트를 보면, 처음에는 toJson 코드 완성이 없지만, 클래스에 @JsonCodable을 추가하자마자 toJson 완성이 바로 나타나는 걸 확인할 수 있어요.

장기 매크로 목표

궁극적인 목표는 커뮤니티가 스스로 매크로를 만들 수 있게 하는 거예요. 그러면 Dart 프로그래밍의 추상화 수준이 올라가요. 가장 많은 투표를 받은 Dart 언어 기능인 데이터 클래스를 예로 들어 볼게요. Dart에 데이터 클래스에 대한 내장 지원을 추가하는 걸 검토해 봤지만, 그런 구조가 무엇을 지원해야 하는지에 대한 의견이 크게 갈렸어요. 필드는 immutable이어야 할까? equals를 지원해야 할까? hashCode는? toString도? 결국 매크로 시스템을 지원하는 게 더 나은 접근이라고 결론을 내렸어요. 커뮤니티가 스스로의 추상화를 만들어 낼 수 있으니, 더 확장 가능한 실험과 다양성이 가능해지죠.

이렇게 강력한 매크로 시스템을 설계하고 구현하는 건 상당히 큰 작업이에요. 코드 지원이나 완성, 코드 분석, 핫 리로드 같은 핵심 Dart 개발 사용 사례에 해로운 성능 영향이 없도록 하는 게 우리 목표예요. 그래서 단계적으로 접근하고 있어요.

  • 이번 릴리스에서는 JsonCodable 매크로 하나의 프리뷰를 공개해서, 사용자가 매크로를 쓰는 개발 경험에 익숙해질 수 있게 해요.
  • 이 매크로의 배포가 잘 진행되면, 나중 릴리스에서 JSON 매크로를 stable로 승격시키고 싶어요.
  • 그와 동시에 근본이 되는 매크로 시스템의 설계와 구현을 마무리하고 있어요. 성능과 안정성에 자신이 생기면, 궁극적으로는 Dart 개발자 커뮤니티가 스스로 매크로를 정의할 수 있게 하는 게 목표예요.

이 단계들을 완성하려면 아직 할 일이 많아요. 그동안 문서에서 Dart 매크로 시스템에 대해 더 배울 수 있고, 오늘 JsonCodable 매크로의 프리뷰를 직접 써볼 수 있어요.

기타 개선 사항

늘 그렇듯이, 이 릴리스에는 최고의 Dart를 제공하기 위한 모든 지속적인 개발이 담겨 있어요. 이번 릴리스에서 이렇게 개선했어요.

  • analyzer 코드 완성 버그의 50% 이상을 해결했어요. (계속 이슈를 제보해 주세요!)
  • 조건식, if-null 식, switch 식의 타입 분석을 언어 명세에 더 잘 맞췄어요 (changelog).
  • Dart VM의 기술 부채를 줄이기 위해 dart:cli 라이브러리에서 불완전하고 일관성 없는 도구를 제거했어요.
  • 새로운 **dart:js_interop 라이브러리를 개선하기 위한 여러 부족한 점을 보완했어요.

전체 내용은 Changelog에서 확인할 수 있어요. 이번 릴리스에서 Dart와 Flutter가 함께 만든 내용을 전부 보고 싶다면 Dart와 Flutter 공동 블로그 글도 놓치지 마세요.

더 알아보기