Google Summer of Code 2025 결과

Google Summer of Code 2025 결과

Google Summer of Code 2025에 참여한 Dart 기여자들의 결과예요.

Google Summer of Code(GSoC) 프로그램은 전 세계 신규 개발자들을 오픈소스 소프트웨어 개발에 참여시키는 데 초점을 맞춘 프로그램이에요. Google은 기여자들이 여름 동안 멘토링 오픈소스 조직과 함께 12주 프로그래밍 프로젝트를 진행하도록 후원해요. 지난 20년 동안 2만 명이 넘는 기여자들이 Google Summer of Code에 참여했어요. 2025년에 Dart는 6년 연속으로 Google Summer of Code의 멘토링 조직으로 참여했어요. 올해는 전 세계 예비 참가자들로부터 100건이 훨씬 넘는 프로젝트 제안을 받았어요. 오늘은 우리가 이번 여름에 멘토링한 프로젝트 중 일부를 소개할게요. 기여자들이 이 글에서 자신들의 프로젝트를 설명해요.

출처: Google Summer of Code 2025 Results

본문

사용자 지정 iOS 컨텍스트 메뉴 항목

작성자: Jing Shao

모바일 앱 개발의 핵심 목표 중 하나는 진정한 네이티브 경험을 제공하는 거예요. 이 프로젝트 전에는 iOS의 Flutter 앱에 큰 제약이 있었어요 — 개발자들이 네이티브 iOS 컨텍스트 메뉴에 사용자 지정 작업을 추가할 수 없었거든요. GSoC 2025 동안 저는 Flutter iOS용 사용자 지정 컨텍스트 메뉴 지원을 성공적으로 구현해서 Flutter 앱의 iOS 상호작용 기능을 크게 향상시켰어요. 이 프로젝트는 새로운 IOSSystemContextMenuItemCustom API를 만들었는데, TextFieldcontextMenuBuilder 속성을 통해 사용자 지정 제목과 콜백이 있는 메뉴 항목을 네이티브 메뉴에 쉽게 추가할 수 있게 해줘요. 구현은 Flutter를 네이티브 iOS UIMenu 시스템과 연결해서, 사용자 지정 항목이 표준 iOS 메뉴 옵션(복사, 붙여넣기)과 매끄럽게 통합되면서도 네이티브한 느낌과 모양을 유지하도록 보장해요. 이 개선 덕분에 Flutter 개발자는 이제 더 표현력 있고 기능이 풍부한 애플리케이션을 만들 수 있어요. 이 작업은 Flutter가 뛰어난 크로스플랫폼 네이티브 경험을 제공하는 데 중요한 진전을 나타내며, 개발자에게 뛰어난 앱을 만들 수 있는 강력한 도구를 제공해요. 자세한 내용은 GitHub에서 제 기술 블로그와 PR을 확인할 수 있어요. 궁금한 점이 있으면 언제든 연락 주세요! 이 프로젝트를 진행하는 내내 귀중한 지도와 지원을 아끼지 않은 멘토 JustinHuan에게 감사드려요. 아래 예시는 네이티브 컨텍스트 메뉴에서 표준 iOS 메뉴 항목과 함께 Clear Text, Add Heart ❤️, Uppercase 같은 사용자 지정 메뉴 항목을 보여줘요.

Dart TUI 프레임워크

작성자: Gedion Ezra

이 프로젝트 전에는 대화형 터미널 애플리케이션을 만들고 싶은 Dart 개발자들이 종종 Rust, Go, Python으로 전환해야 했어요. Dart에는 성숙한 텍스트 기반 사용자 인터페이스(TUI) 프레임워크가 없어서, GUI나 정적 CLI 도구로 제한됐거든요. GSoC 2025의 일환으로 우리는 Pixel Prompt를 만들었어요. Flutter의 선언적·컴포넌트 기반 접근 방식에서 영감을 받은 터미널 UI 프레임워크예요. Pixel Prompt는 개발자가 완전히 Dart로 동적 대화형 앱을 만들 수 있게 해줘요. Pixel Prompt는 Flutter의 계층형 아키텍처(위젯 레이어의 위젯 → 엘리먼트 레이어 → RenderObject 레이어로 매핑)에서 영감을 받은 Component에서 ComponentInstance 모델을 도입해요. Component는 UI를 선언적으로 설명하고, ComponentInstance는 상태 레이아웃과 렌더링을 관리해요. 아키텍처의 단순화된 버전을 확인해 보세요. 프레임워크는 상태 유무(stateful/stateless) 컴포넌트, 입력 처리, 이중 버퍼링과 ANSI diffing을 통한 최적화된 렌더링을 지원해요. 이는 터미널 다시 그리기(redraw)를 최소화해 성능을 개선하고, 가상 터미널 인터프리터로 안정적인 골든 테스트(golden testing)를 가능하게 해요. Pixel Prompt가 달성할 수 있는 것에 대한 시각적 감각을 위해 아래에 데모 스크린샷이 몇 개 있어요. 이들은 선언적 레이아웃, 대화형 컴포넌트, 실시간 업데이트를 보여줘서, Dart가 이제 생태계를 떠나지 않고도 완전히 대화형 터미널 애플리케이션을 구동할 수 있음을 입증해요. Pixel Prompt가 이미 핵심 터미널 애플리케이션 구축을 가능하게 하지만, 앞으로 더 많은 것이 있어요. TextAreaTable 같은 복잡한 컴포넌트 지원, flex 같은 레이아웃 시스템, 전용 애니메이션 API, 시각적 디버거가 향후 기여로 계획되어 있어요. 관심 있는 개발자는 공개 이슈를 탐색하고 pixel_prompt 저장소에 기여할 수 있어요.

TestGen — LLM 기반 테스트 생성 도구

작성자: Amr Ahmed

TestGen은 Dart용 단위 테스트 생성을 자동화하는 실험적 프로젝트로, 핵심 목표는 코드베이스에서 커버되지 않은 줄을 구체적으로 대상으로 하는 테스트 케이스를 생성해 테스트 커버리지를 개선하는 거예요. 대규모 언어 모델(LLM)을 활용해 의미 있는 테스트를 생성함으로써, TestGen은 테스트를 작성하는 데 필요한 수동 노력을 줄여 개발자가 더 높은 커버리지를 달성하고 코드 품질을 개선하도록 돕는답니다. 테스트 자동 생성에 LLM을 사용할 때 주요 과제 중 하나는 모델에 얼마나 많은 코드 컨텍스트를 줄지 결정하는 거예요. 예를 들어 함수를 테스트해야 하는데 전체 파일을 컨텍스트로 제공하면, LLM이 압도당해 관련 없거나 부정확한 테스트를 생성할 수 있어요. 함수 자체만 제공하면 모델이 함수 내부의 중요한 의존성을 놓쳐서 불완전하거나 깨진 테스트로 이어질 수 있어요. 이 문제를 해결하기 위해 TestGen은 Dart 분석기를 사용해 전체 코드베이스를 Declarations으로 구문 분석해요. Declarations은 함수, 변수, 클래스, mixin 같은 코드 구조를 나타내는 클래스예요. 구문 분석 후에는 이러한 선언들을 가로지르는 의존성 그래프를 구성하는데, 이는 주어진 선언이 정확히 어떤 코드 조각에 의존하는지 보여줘요. 이는 주어진 선언의 **추상 구문 트리(AST)**를 순회하며 방문 중에 의존성을 기록하는 방식으로 이루어져요. 이 그래프를 사용해 TestGen은 구성 가능한 깊이에서 LLM에 **관련 컨텍스트만 제공할 수 있어서(context-aware prompting), 불필요한 노이즈 없이 정확하고 집중된 테스트를 생성하도록 도와줘요.

  • 그림은 주어진 Dart 파일에 대해 생성된 의존성 그래프를 보여줘요. toBeTestedFunction을 테스트할 때 그래프는 프롬프트에 포함할 모든 관련 컨텍스트를 쉽게 검색할 수 있게 해줘요. LLM은 이제 함수와 주변을 더 잘 이해할 수 있어서 더 효과적이고 정확한 테스트 생성 과정으로 이어져요.

테스트 생성을 효과적으로 하기 위해 TestGen은 **package:coverage**와 통합해 아직 테스트되지 않은 코드 부분을 자동 감지하고 그 부분을 대상으로 해요. 이 도구는 Gemini 모델에 연결해(gemini-2.5-pro, gemini-2.5-flash, gemini-2.5-flash-lite 같은 변형 사용) 테스트 케이스를 생성하며 package:google_generative_ai를 통해 연결돼요. 이 테스트들은 검증 및 피드백 루프를 거치는데, 실행되고 오류가 있는지 확인돼요. 문제가 발견되면 오류가 LLM에 다시 피드백되어 출력을 개선해서 최종 테스트가 더 정확하고 안정적이게 돼요. 이 패키지에는 앞으로 더 많은 것이 있어요. 새로운 기능, 개선된 테스팅, Flutter 프로젝트 지원 추가 등이요. 현재 이슈 목록은 dart_testgen 저장소에서 확인할 수 있어요. 생성된 프롬프트가 어떻게 생겼는지 샘플은 default-prompt 예시를 참고하세요. 프로젝트의 자세한 내용은 전체 GSoC 보고서에서 확인할 수 있어요.

JNIgen 바인딩을 사용해 Android(Java/Kotlin) 문서를 Dart로 LLM 기반 번역

작성자: Marshelino Maged

Android 라이브러리와 유틸리티는 일반적으로 Java/Kotlin 코드 스니펫으로 문서화돼요. JNIgen은 이러한 라이브러리에 대한 Dart 바인딩을 생성하는 것을 가능하게 하지만, 바인딩에 대해 Dart 코드를 작성하는 것은 두 언어 간의 구문적·구조적 차이 때문에 어려울 수 있어요. 이는 개발자가 공식 Android 문서와 튜토리얼에서 찾을 수 있는 많은 Java/Kotlin 예시를 직접 재사용할 수 없다는 뜻이에요. native_doc_dartifier 프로젝트는 Android 문서의 Java 및 Kotlin 스니펫을 Dart 버전으로 자동 변환하여 이 격차를 해결하기 위해 만들어졌어요. (Java 스니펫 예시. 스니펫 번역 예시.) 이 프로젝트는 외부 함수 인터페이스(FFI)를 통해 Java 및 Kotlin API용 Dart 바인딩을 생성하는 JNIgen을 기반으로 해요. Java와 Dart는 구문과 의미론 모두에서 다르기 때문에 직접 변환만으로는 충분하지 않아요. 예를 들어 Java는 메서드 오버로딩을 지원하지만 Dart는 지원하지 않아서, JNIgen은 add$1, add$2 같은 이름이 바뀐 메서드로 바인딩을 구분해요. 정확한 Dart 코드를 생성하려면 번역 모델이 표면 수준 변환에 의존하기보다는 이러한 바인딩 규칙을 고려해야 해요.

주요 기술적 과제는 규모였어요. Android 라이브러리의 바인딩은 종종 수십만 줄의 보일러플레이트 코드를 포함해서, 가장 큰 언어 모델(현재 1M 토큰)의 입력 한도를 훨씬 초과해요. 이를 해결하기 위해 프로젝트는 추상 구문 트리(AST) 추출을 도입했는데, 이는 바인딩을 공개 API 표면으로 줄여 원래 크기의 약 6% 로 만들면서도 중요한 정보는 보존해요. 이는 **검색 증강 생성(RAG)**과 결합됐는데, 각 클래스의 AST를 따로 저장하고 번역되는 스니펫을 기준으로 가장 관련 있는 클래스만 검색해요. AST 추출과 검색 기반 컨텍스트 선택을 결합함으로써 native_doc_dartifier는 LLM 컨텍스트 제약 내에서 효율적으로 유지하면서, 생성된 바인딩과 정확히 일치하는 정확한 Dart 번역을 생성할 수 있어요. 결과는 Android 문서로 작업하는 Dart 개발자의 마찰을 줄이고 Java/Kotlin과 Flutter 생태계 간의 상호운용성을 강화하는 실용적인 솔루션이에요. 번역이 LLM에 의해 생성되기 때문에 생성된 Dart 코드를 컴파일할 때 가끔 오류가 발생할 수 있어요. 신뢰성을 높이기 위해 시스템은 피드백 루프를 통합했는데, 컴파일 오류가 LLM에 여러 번 반환되어 작업 버전이 나올 때까지 번역을 개선하게 해요. 이 반복적 접근 방식은 생성된 예시의 견고성을 더욱 높여요. 자세한 내용은 native_doc_dartifier 저장소를 방문해 주세요.

TS 선언을 Dart JS Interop 인터페이스로 변환

작성자: Nikechukwu Okoronkwo

Dart는 dart:js_interop을 통해 JavaScript와 강력한 상호운용성을 제공하며, 이는 JavaScript로 작성된 코드와 인터페이스하는 데 사용할 수 있어요. 하지만 크고 큰 라이브러리와 패키지에 대한 바인딩을 작성하는 것은 시간이 많이 걸리고 오류가 발생하기 쉬워요. 이 문제를 해결하기 위해 우리는 JS Interop Generator를 만들었어요. 이 도구는 TypeScript 선언 파일(.d.ts)에서 Dart 래퍼를 자동 생성해요. 이는 웹에서 Dart의 채택을 돕고 Dart 및 Flutter 개발자가 NPM 등의 방대한 JS 라이브러리 생태계를 더 쉽게 활용할 수 있게 해줘요. 제너레이터는 .d.ts 파일을 구문 분석하고 TypeScript 선언을 Dart 버전으로 변환해 동작해요. 선언은 Dart가 JS와 상호운용하는 방식에 기반해 생성되어, TS 선언 코드가 나타내는 JS 코드와의 상호운용 구현 측면에서의 정확성과, 가능한 경우 TS 선언의 코드 표현에 대한 근접성을 모두 보장해요. 변수, 함수, enum, 클래스, 인터페이스, 네임스페이스, 타입 별칭을 포함한 광범위한 TS 기능을 지원해요. 제너레이터는 TS 타입의 동등한 Dart 표현을 생성하고 가능하면 dart:js_interoppackage:web의 기존 타입을 활용해요. 익명 객체, 익명 클로저, 유니온, 병합된 타입, typeof/keyof 같은 고급 TypeScript 기능 지원도 포함돼요. 통합 테스트 스위트에서 많은 예시를 볼 수 있어요. 우리는 이미 이 제너레이터를 nanoiduuid 같은 인기 패키지의 바인딩을 성공적으로 만드는 데 사용했어요. 자세한 내용은 제너레이터 테스트 결과를 참고하세요. 이 프로젝트는 web 저장소web_generator 패키지에서 사용할 수 있어요. bin/gen_interop_bindings.dart 스크립트를 실행해 직접 시도해 볼 수 있어요. 문제나 버그를 발견하면 자유롭게 이슈를 제기하거나 기여해 주세요!

더 알아보기