dioxus-compose 가이드

시작하기

받아 온 저장소에서 창이 뜰 때까지

지금 이 경로는 macOS 전용입니다. 렌더러는 미리 공유 라이브러리로 컴파일해 두고 Rust 바이너리가 그것을 링크하는 구조라서, 렌더러를 먼저 빌드해야 어떤 Rust 예제든 실행됩니다.

준비물

무엇보다 먼저 ./scripts/setup-check.sh를 돌리세요. 빌드와 품질 게이트가 쓰는 도구를 전부 점검하고, 빠진 것이 있으면 그것을 설치하는 명령을 그대로 알려 줍니다. 아래 표의 항목은 모두 이 스크립트의 점검 목록에 들어 있습니다.

무엇
macOS (Apple Silicon 또는 Intel)네이티브 빌드 스크립트는 Darwin이 아니면 바로 종료합니다.
Xcode 커맨드라인 도구C와 Objective-C 파일 몇 개를 컴파일하고 라이브러리를 링크합니다.
Rust 툴체인 (stable)Host 크레이트를 빌드합니다. 보통 rustup으로 설치합니다.
Liberica NIK 25 Fullnative-image로 렌더러를 빌드합니다. 일반 GraalVM으로는 안 됩니다. 아래 설명을 보세요.
upstream GraalVM이 아니라 Liberica NIK입니다

upstream GraalVM은 Darwin에서 AWT 지원을 건너뜁니다 (oracle/graal#13272, 2026-09 기준 여전히 open). Compose Desktop은 AWT를 거쳐 그리기 때문에, upstream으로 만든 이미지는 띄울 창 자체가 없습니다. Liberica NIK Full은 AWT를 정적으로 링크하므로, macOS에서는 이쪽이 필수 툴체인입니다.

빌드 스크립트는 기본 설치 위치에서 NIK를 찾고, 없으면 GRAALVM_HOME을 봅니다.

shell
# 여기에 설치돼 있으면 자동으로 찾습니다:
~/Library/Java/JavaVirtualMachines/bellsoft-liberica-vm-full-openjdk25*/Contents/Home

# 아니면 직접 알려 줍니다:
export GRAALVM_HOME=/path/to/bellsoft-liberica-vm-full-openjdk25/Contents/Home

NIK 자체가 없다면 ./scripts/install-nik.sh가 설치해 줍니다. 버전으로 주소를 잡기 때문에 캐시가 따뜻하면 두 번째 실행은 아무 일도 하지 않습니다. 내려받기는 호출할 때마다가 아니라 NIK 버전마다 한 번입니다. 빌드 스크립트는 lib/static/darwin-*/libawt_lwawt.a가 없는 설치를 거부합니다. 순정 GraalVM을 긴 빌드 끝의 링크 실패가 아니라 시작 전에 잡아내려는 장치입니다.

Kotlin은 따로 설치할 필요가 없습니다. 렌더러 프로젝트에 들어 있는 ./kotlin 래퍼가 처음 실행될 때 고정된 버전의 Kotlin Toolchain을 내려받습니다.

렌더러 빌드

스크립트 하나가 전부를 합니다. NIK JVM에서 렌더러를 잠깐 띄워 실제 런타임 클래스패스를 확보하고, C 진입점을 컴파일한 다음 공유 라이브러리를 만듭니다.

shell
./dioxus-compose-renderer/desktop/scripts/build-native.sh

결과물은 그 자체로 완결된 런타임 디렉터리입니다.

dioxus-compose-renderer/build/native-image/dist/lib/
libdioxus_compose_renderer.dylib   # 렌더러: AWT, Skiko JNI, Compose, 우리 코드
libskiko-macos-<arch>.dylib        # Skiko가 경로로 로드하는 Skia
libjawt.dylib                      # JAWT_GetAWT를 렌더러 안으로 넘기는 포워더
libawt_lwawt.dylib                 # libawt가 경로로 찾는 자리 채우기

곁에 있는 작은 라이브러리 셋은 군더더기가 아닙니다. macOS에서 정적으로 링크된 AWT도 일부 항목은 런타임에 파일 경로로 찾기 때문에, 그 자리를 메우는 것입니다. 자세한 내용은 아키텍처에 있고, 요점은 배포 레이아웃이 lib/ 디렉터리 하나이며 그 부모가 렌더러가 보고하는 java.home이라는 점입니다.

렌더러를 다른 곳에 두고 쓴다면(내려받은 아티팩트나 벤더링한 사본 등) DIOXUS_COMPOSE_RENDERER_DIR을 그 lib 디렉터리로 지정하면 워크스페이스 빌드 대신 그쪽을 씁니다(NFR-10).

첫 빌드는 느립니다. native-image가 Compose, Skiko, AWT를 통째로 AOT 컴파일하기 때문입니다. 다시 빌드할 일은 Kotlin 쪽이 바뀔 때뿐이고, 평소 Rust 작업은 이미 만들어 둔 라이브러리를 그대로 씁니다.

라이브러리 스모크 테스트

Rust를 끌어들이기 전에, 라이브러리만으로 창이 뜨는지 먼저 봅니다. 아주 작은 C 호스트를 링크해 dioxus_compose_renderer_run을 부릅니다.

shell
./dioxus-compose-renderer/desktop/scripts/smoke-test.sh

창이 떠야 합니다. 창을 닫으면 run0을 반환하고 프로세스가 정상 종료됩니다. 이것이 macOS 런타임 요건(SPEC PR-8)의 수용 기준이며, 2026-09-20에 통과했습니다.

데모 실행

데스크톱 예제는 native-renderer 기능 뒤에 있습니다. 이 기능이 켜져야 Rust 빌드가 방금 만든 라이브러리를 링크합니다.

shell
cargo run -p dioxus-compose --features native-renderer --example desktop_demo

메시지를 입력하고 Enter를 누르면 전송되고, Shift+Enter는 줄바꿈입니다. 한글 IME를 쓴다면 글자를 조합하는 도중에 Enter를 눌러 보세요. 조합만 확정되고 메시지는 전송되지 않아야 합니다. 이 구분이 설계 전체의 이유이고, UI 작성하기에서 다룹니다.

기능 플래그 없이 빌드하면

native-renderer 없이 빌드하면 렌더러가 아무 일도 하지 않는 Host가 만들어집니다. launch가 곧바로 반환하고 창은 뜨지 않습니다. 이 빌드는 단위 테스트와 벤치마크가 쓰는 구성이라 쓸모가 있습니다. 다만 눈으로 볼 것이 없을 뿐입니다.

검사 돌리기

저장소의 품질 게이트는 스크립트 하나입니다. 포맷 검사, 경고를 오류로 취급하는 Clippy, 테스트, Criterion quick 모드 벤치마크, 그리고 Kotlin 빌드와 테스트까지 돌립니다.

shell
./scripts/check.sh              # 프리서브밋용 빠른 벤치마크 샘플링
./scripts/check.sh --full       # 전체 샘플링
./scripts/check.sh --no-kotlin  # Rust만. DXC_SKIP_KOTLIN=1도 같습니다

이 중 한 테스트는 Rust 스키마가 만들어 내는 Kotlin 코드와 저장소에 들어 있는 파일을 비교합니다. 스키마를 고치고 재생성하지 않으면 테스트가 실패합니다. 불편이 아니라 의도된 동작입니다.