딥다이브

AI 시대, UI 엔지니어링은 어디로 가고 있나

AI 이전에는 Web 기반 크로스 플랫폼이 좋은 답이었다. 이제 코드 작성 비용은 내려갔지만 검증 비용은 그대로다. GPU UI와 플랫폼별 네이티브 앱 직접 생성 모두 기회를 얻었다. 프레임워크 10개를 직접 측정했다.

오리지널허가 없이 어떤 형태로도 전재 금지

Web, GPU 자체 렌더링, 네이티브를 뜻하는 세 창의 선이 빨간 검증 표시로 모이는 그림

2025년 12월 12일, Zed 엔지니어 mikayla-maki가 PR 하나를 닫았다. GPUI에 커스텀 shader를 추가하자는 제안이었다. 답변은 정중했다. 기여에 감사한 뒤 “we’re shifting focus to core product work at Zed, and without a Zed use case, I can’t validate this code”라고 설명했다. 끝에는 웃는 이모티콘도 붙었다.

GPUI는 Zed가 직접 만든 GPU 인터페이스 프레임워크다. Electron의 대안을 이야기할 때 자주 등장한다. 당시 Zed가 Sequoia가 주도한 투자로 32,000,000달러를 유치해 누적 투자액이 42,000,000달러를 넘었다고 발표한 지 넉 달도 지나지 않은 때였다.

아홉 달 남짓 지난 2026년 9월 26일, 개발자 egoist가 MyGo라는 저장소를 만들었다. 39일 뒤 커밋은 1,042개였고, 그중 890개에 Claude의 이름이 올라 있었다.

Claude는 Anthropic이 만든다. Anthropic의 데스크톱 앱은 Electron을 쓴다.

이 세 가지를 함께 놓으면 어딘가 어색하다. 우리는 이 분야가 어디까지 왔는지 알아보려고 컴퓨터 두 대에서 프레임워크 10개를 직접 측정했다.

01평가 배경

Claude, Codex 같은 데스크톱 앱은 여전히 Electron을 사용한다. Web 생태계는 성숙했고 하나의 코드로 여러 플랫폼을 지원할 수 있으며 모델도 익숙하다. AI가 개발 비용을 낮춰도 플랫폼 간 호환성과 유지보수에는 계속 투자가 필요하다.

GPU 자체 렌더링은 또 다른 선택지지만 GPUI는 여전히 Zed를 우선한다. 플랫폼별 렌더링과 위젯 생태계에는 오랜 축적이 필요하다. MyGo는 AI와 기존 구성요소로 초기 개발을 앞당길 수 있음을 보여줬지만, 실서비스의 성숙도와 장기 유지보수 능력은 아직 검증이 필요하다.

Flutter, Compose, Slint, egui, iced 등은 저마다 다른 절충을 한다. 우리는 10개 프레임워크를 같은 시나리오로 실측해 부드러움, CPU, 메모리, 디자인 재현도에서 각 방식의 실제 비용을 확인했다.

02로컬에서 직접 측정했다

Apple M4 Max와 ThinkPad T14 Gen6에서 같은 시나리오로 10개 프레임워크를 테스트했다. 두 플랫폼 모두 CPU와 메모리를 측정했고, Windows는 PresentMon으로 프레임을 외부 측정했다. Mac의 프레임 콜백은 프레임워크마다 기준이 달라 비교에 사용하지 않는다. 하드웨어와 메모리 지표도 다르므로 각 플랫폼 안에서만 비교한다.

애니메이션은 밀도가 높은 장면입니다. 96×64 논리 픽셀 카드 500개를 25열로 겹쳐 배치하고, 각 카드에 반경 12의 모서리, 135° 그라데이션, blur 16과 아래쪽 오프셋 4의 그림자를 적용했습니다. 모든 카드는 프레임마다 위치를 갱신하며 각 중심 주위를 반경 12, 주기 4초로 회전합니다. 30초씩 5회 실행한 중앙값입니다.

효과가 적용된 많은 요소가 계속 움직일 때 UI 갱신, 그리기 준비, 렌더링 제출에 드는 CPU 비용과 안정적인 프레임 출력을 주로 봅니다. CPU는 앱 프로세스 트리 전체의 사용률이며 GPU 사용률이나 단계별 소요 시간은 아닙니다. 프레임 간격과 함께 봐야 합니다. 프레임을 적게 출력해도 CPU 사용률이 낮아질 수 있습니다. 500은 장면의 카드 수이며, 겹침과 창의 클리핑 때문에 매 프레임 500개 전체가 완전히 그려지는 것은 아닙니다.

그라데이션과 그림자가 있는 청보라색 둥근 카드 500개가 겹쳐 있는 모습
그림 1애니메이션 부하 테스트: 그라데이션과 그림자가 있는 카드 500개. Electron / macOS 테스트 앱을 시작 위치에 고정한 스크린샷.

Windows

표 1Windows 실측, 5회 중앙값. 프레임은 p95 표시 간격(ms)이며 8.3이면 120Hz를 온전히 채운다. CPU는 논리 코어 하나를 100%로 계산한다. 메모리는 private commit(MiB)이다.
프레임워크목록 간격모션 간격스트림 CPU편집 CPU모션 CPU모션 메모리
WPF(네이티브)8.668473%13%49%2,425
Electron8.810831%92%138%947
Tauri무효9254%105%148%913
GPUI8.616.724%4%22%142
MyGo8.48.611%6%33%115
egui8.88.512%20%49%388
iced8.98.520%3%25%215
Slint8.58.527%99%67%61
Flutter8.48022%105%91%4,934
Compose8.816034%106%102%2,422

목록 스크롤은 모두 따라왔다. 차이는 모션에서 드러났다. 그림자와 그라데이션이 있는 카드 500개에서 Rust와 Go의 자체 렌더링 프레임워크는 대체로 120Hz를 지켰다. Flutter, Electron, Tauri, Compose는 프레임 간격이 80~160ms에 달했다. WPF의 684ms는 독립된 그림자 효과 500개 때문이었다. 끄면 8.3ms로 돌아오므로 일반적인 문제로 볼 수는 없다.

텍스트 편집도 문턱이다. 5,000줄 문서에 초당 10자를 삽입하자 Flutter, Compose, Slint는 모두 코어 하나를 가득 썼다. Windows의 Flutter는 입력의 30%가 빠지기도 했다.

Mac

표 2Mac 실측, 5회 중앙값. CPU는 논리 코어 하나를 100%로 표시하며 메모리는 phys_footprint(MiB)다. 테스트 중 컴퓨터는 유휴 상태가 아니었다. 프레임워크 간 비교 가능한 프레임률은 제공하지 않는다.
프레임워크스트림 CPU편집 CPU모션 CPU목록 메모리모션 메모리
SwiftUI87.5%8.9%99.1%4037
Electron16.1%62.0%102.2%536698
Tauri42.1%86.9%78.7%753555
GPUI22.5%2.9%17.0%341335
MyGo8.2%2.8%16.3%368371
egui8.6%7.2%20.4%803839
iced18.2%7.5%15.0%489491
Slint18.4%52.1%26.7%423416
Flutter18.3%101.9%237.4%468994
Compose31.3%105.1%107.5%7101,295

Mac에서 애니메이션 CPU는 GPUI, MyGo, egui, iced가 약 15%–20%, Flutter가 237%, Electron과 Compose가 약 100%였다. 텍스트 편집에서 Flutter와 Compose는 여전히 코어 하나에 가까운 CPU를 사용했다. Slint는 52%로 Windows의 99%보다 낮았다.

목록 장면의 SwiftUI 약 40 MiB, GPUI 약 340 MiB, egui 약 800 MiB는 우선 앱 프로세스의 메모리 풋프린트입니다. 네이티브 UI는 시스템의 프로세스 외부 렌더링 서비스를 사용할 수 있습니다. Apple은 AppKit이 보통 레이어 트리를 프로세스 밖에서 렌더링한다고 설명합니다. 따라서 그리기와 합성의 일부는 앱 밖에서 수행됩니다. 자체 렌더러도 시스템 합성을 거치지만, 앱 수치만으로 두 경로의 역할 분담을 비교할 수는 없습니다. M 시리즈의 통합 메모리는 CPU와 GPU의 물리 메모리 공유를 뜻하며, 모든 관련 비용이 앱의 phys_footprint에 귀속된다는 뜻은 아닙니다.

SwiftUI 목록과 애니메이션의 짧은 GPU trace 각 5회에서 앱 PID의 GPU 실행 이벤트는 관측되지 않았고, 같은 기간 WindowServer에는 GPU 활동이 있었습니다. 이는 SwiftUI가 GPU를 쓰지 않는다는 뜻도, 데스크톱 전체 활동이 이 앱 때문이라는 뜻도 아닙니다. WindowServer 메모리 기준값은 약 205 MiB 변동했습니다. 스냅샷에 큰 공유 객체가 없더라도 기존 시스템 자원의 재사용을 배제할 수 없습니다. 이 결과는 SwiftUI 앱 프로세스의 점유가 더 낮다는 것만 보여주며, 전체 렌더링 비용이 더 낮다거나 차액 전부를 시스템이 부담한다는 증거는 아닙니다.

이 수치는 두 컴퓨터, 해당 버전, 우리가 작성한 테스트 프로그램의 결과만 나타낸다. 방법과 전체 데이터는 05절에 있다.

03처음부터 하나만 고르는 문제가 아니다

편집기, 개발 도구, 업무용 앱은 텍스트 입력, 애니메이션, 메모리, 크로스플랫폼 배포, 위젯 생태계에 대한 요구가 다르다. 각자 쓰이는 상황이 있으며, 어떤 절충을 받아들일 수 있는지에 따라 프레임워크를 골라야 한다.

많은 프레임워크가 유지, 캐싱, 부분 업데이트로 반복되는 레이아웃과 그리기를 줄이고 있다. GPUI는 즉시 모드와 유지 모드를 결합한 설계다. 어떤 모드를 쓰는지, 어떤 작업을 재사용하는지, 한 프레임을 얼마나 빨리 그리는지는 서로 다른 문제다.

MyGo, iced, GPUI, Slint, egui는 모두 애니메이션을 무리 없이 처리하며 CPU 사용률도 낮다. Slint는 메모리 사용량이 가장 적고 egui는 많은 편이며, GPUI의 편집 컨트롤은 직접 마련해야 한다. MyGo는 현재 주로 저자 자신의 앱에서 사용되며 아직 대규모 프로덕션 환경에서 검증되지 않았다.

Flutter, Electron, Compose 모두 이번 애니메이션 부하 테스트의 프레임 간격과 자원 사용량도 좋지 않았습니다. Tauri의 패키지는 11 MB에 불과하지만 실행 중 메모리 사용량은 Electron과 비슷하다.

04병목은 검증이다

현재 우리는 렌더링보다 검증이 더 중요하다고 본다.

코드 작성 비용은 낮아졌지만 코드가 올바른지 확인하는 데는 여전히 시간이 든다. Stack Overflow 2025 개발자 설문에서 66%는 AI 해법이 “almost right, but not quite”인 경험을 했고, 45.2%는 AI 코드 디버깅에 시간이 더 든다고 답했다. Sonar가 올해 1월 발표한 설문에서는 개발자 96%가 AI 생성 코드의 기능적 정확성을 완전히 믿지 않았으며, 커밋 전 항상 확인한다는 응답은 48%뿐이었다. Sonar가 코드 검사 도구를 파는 회사라는 점은 감안해야 하지만, 앞선 조사와도 맞아떨어진다.

Slint와 egui의 두 릴리스는 큰 주목을 받지 못했다. 우리는 렌더링 개선보다 더 중요하다고 본다. agent가 입력을 주입하고 스크린샷을 찍을 수 있어야 수정하고, 보고, 다시 고칠 수 있다. 예전에는 사람이 컴퓨터 앞에서 하나씩 눌러 가며 화면을 검증했다. 이제 그 일을 기계에 맡길 수 있기 시작했다.

현재 세 가지 방법이 있다. Web 기반 크로스 플랫폼은 가진 자산이 가장 많다. GPU 자체 렌더링은 브라우저를 함께 가져갈 필요가 없고 만드는 문턱도 전보다 낮아졌다. 플랫폼별 네이티브 개발은 가장 오래된 방법이다. 예전에는 대기업만 여러 팀을 유지할 수 있었다. 지금 어려운 것은 Breunig가 말한 세 배의 bug와 지원 범위다. 검증 비용이 내려가고 품질이 올라가면 플랫폼마다 네이티브 앱을 직접 생성하는 방식도 가능할 수 있다.

우리도 자체 GPU UI를 시도한다. 차이는 Web 개발의 DX를 많이 가져온다는 점이다. JSX와 비슷한 컴포넌트, CSS와 비슷한 스타일, flexbox 레이아웃, 반응형 상태, 브라우저 같은 DevTools를 제공하고 최종적으로 네이티브 코드로 컴파일한다. 아직 초기 단계다.

어느 답이 이길지는 모른다. 여러 방식이 오래 공존할 수도 있다. 처음의 세 가지 사실은 지금도 그대로다. PR은 여전히 닫혀 있고 MyGo는 성장하며 Claude 데스크톱은 여전히 Electron이다. 무척 흥미로운 시기다.

05실험 보고서

테스트는 2026년 11월 4일부터 6일까지 진행했다. 각 프레임워크에서 같은 시나리오를 권장 방식과 기본 설정으로 구현한 뒤 릴리스 빌드를 사용했다. Compose의 흐림 효과를 수정한 뒤 디자인 페이지와 해당 구현을 공유하는 정지 시나리오를 다시 측정했다.

표 3테스트 환경. 두 컴퓨터는 하드웨어, 창, 메모리 지표가 달라 같은 플랫폼 안에서만 비교했다. 플랫폼 간 절대값은 비교하지 않는다.
항목MacWindows
컴퓨터Apple M4 Max, 16코어, 64 GBThinkPad T14 Gen6, Core Ultra 7 255H, Arc 140T 내장 GPU, 32 GB
OSmacOS 26.4Windows 11 Pro 10.0.26300
디스플레이Studio Display,60Hz,2x2880×1800,120Hz,200%
창1440×900 논리 픽셀1280×720 논리 픽셀, 디자인 페이지는 1440×900 테두리 없음
메모리 지표phys_footprintprivate commit(커밋된 전용 메모리, 물리 사용량과 다름)
프레임 지표앱 콜백. 프레임워크마다 의미가 달라 비교에 쓰지 않음PresentMon 2.6.0 표시 간격, 외부 측정
컴퓨터 상태유휴 상태 아님, 테스트 중 다른 개발 작업 실행다른 사용자 조작 없음
표 4테스트한 프레임워크와 버전. 렌더링 경로는 런타임 로그나 프레임워크 API의 실제 반환값에서 확인했다. “미검증”은 이번에 런타임 증거를 얻지 못했다는 뜻이다.
프레임워크버전Mac 렌더링 경로Windows 렌더링 경로
SwiftUI / WPFmacOS 26.4 SDK / .NET Framework 4.8.1시스템 합성WPF 기본 D3D9 파이프라인
Electron45.2.2미검증Chromium,ANGLE D3D11
Tauri2.12.5WKWebViewWebView2 156,ANGLE D3D11
GPUIZed c4273271Metal, 기본 설정미검증
MyGo86ec3b30미검증미검증
eguieframe 0.37.0MetalVulkan
iced0.14.0MetalVulkan
Slint1.18.1FemtoVG,OpenGLFemtoVG,OpenGL ES
Flutter3.47.9Impeller,MetalImpeller,ANGLE D3D11
Compose1.12.2Skiko,MetalSkiko,D3D12
표 5테스트 시나리오. 앱 내부 타이머로 구동하며 수동 조작은 없다. 테스트 데이터는 고정 시드로 생성한다.
시나리오작업 내용
정지디자인 페이지를 표시한 뒤 그대로 두어 유휴 비용 측정
목록10,000행 가상화 목록, 행 높이 64, 2,000 px/s로 일정하게 스크롤
스트리밍이전 메시지 200개를 불러온 뒤 마지막 메시지에 초당 40단어 추가, 항상 하단 유지
편집5,000줄 문서, 커서 위치에 초당 10자 삽입
모션96×64 카드 500개, 모서리 반경 12, 그라데이션과 그림자, 동일한 공식으로 원운동
디자인 페이지디자인 사양 11개: 글꼴, 그림자, 가는 선, 그라데이션, P3, 배경 흐림, 둥근 모서리, emoji, OpenType, 중국어·영어 혼합 조판

프레임워크별 각 시나리오를 5회씩, 회당 30초 동안 순서를 섞어 순차 실행했다. 아래 표는 모두 중앙값이다. 5회 사이 범위의 중앙값은 약 3%였고, 90%는 24% 이내였다. 목록과 모션은 사양을 통일한 뒤 다시 측정했으므로 열마다 수집 시점이 다르다. CPU는 논리 코어 하나를 100%로 본다. 멀티프로세스 앱은 모든 자식 프로세스를 포함한다. Mac의 Tauri는 시스템이 띄운 WebKit 프로세스도 포함했다. Windows 프레임 데이터는 swapchain 하나에 고유하게 귀속되고 기록 누락이 없는 회차만 사용했다.

스트리밍과 편집은 실제 처리량도 확인했다. Windows에서 Flutter의 편집 완료율은 68%에 그쳤고 나머지는 모두 99% 이상이었다.

표 6Windows CPU, 단위 %.
프레임워크정지목록스트리밍편집모션
WPF2.637.272.713.549.3
Electron6.142.830.692.1137.8
Tauri31.658.253.7104.9147.8
GPUI1.510.624.33.621.5
MyGo0.017.910.66.332.8
egui0.315.912.219.648.9
iced0.321.320.23.024.5
Slint0.362.726.999.166.8
Flutter0.631.221.8104.690.6
Compose0.535.934.4106.4101.8
표 7Windows 메모리, private commit, 단위 MiB.
프레임워크정지목록스트리밍편집모션
WPF1571932502062,425
Electron280397392556947
Tauri260313346536913
GPUI135142160138142
MyGo132135133132115
egui379386396460388
iced212224274321215
Slint79877220261
Flutter6363963746674,934
Compose4215445743,3722,422
표 8Windows 표시 간격, 단위 ms. 120Hz에서 8.33이면 최대 프레임 속도다. 횟수는 유효한 프레임 데이터를 얻은 회차 수다.
프레임워크목록 p95목록 p99횟수모션 p95모션 p99횟수
WPF8.68.75684.3719.35
Electron8.88.94108.3115.92
Tauri——091.7100.05
GPUI8.68.8516.725.15
MyGo8.48.758.616.75
egui8.88.958.58.75
iced8.98.958.58.65
Slint8.58.858.58.75
Flutter8.48.6580.588.65
Compose8.88.95160.3211.85
표 9Mac CPU, 단위 %. 컴퓨터는 유휴 상태가 아님.
프레임워크정지목록스트리밍편집모션
SwiftUI1.016.987.58.999.1
Electron2.516.716.162.0102.2
Tauri6.332.042.186.978.7
GPUI0.49.722.52.917.0
MyGo0.113.28.22.816.3
egui0.19.08.67.220.4
iced0.124.218.27.515.0
Slint0.113.118.452.126.7
Flutter0.211.018.3101.9237.4
Compose0.423.331.3105.1107.5
표 10Mac 메모리, phys_footprint, 단위 MiB.
프레임워크정지목록스트리밍편집모션
SwiftUI324013629337
Electron205536567707698
Tauri101753601570555
GPUI74341358320335
MyGo75368361356371
egui414803817862839
iced75489541598491
Slint151423386434416
Flutter156468455663994
Compose3507107091,4261,295
표 11시작 시간은 프로세스 실행부터 첫 프레임 콜백까지(ms)다. 콜드 캐시의 첫 화면 시간이 아니다. 용량은 배포 디렉터리(MB)이며 시스템 WebView와 .NET은 제외한다.
프레임워크Mac 시작Windows 시작Mac 용량Windows 용량
네이티브(SwiftUI / WPF)2284493.0<0.1
Electron295818267.0376.4
Tauri56562212.511.2
GPUI25527711.913.4
MyGo74212613.111.5
egui30927717.417.4
iced25759014.414.2
Slint26127218.517.0
Flutter2441,04343.930.0
Compose5501,074123.1113.8

디자인 재현

배경 흐림 항목은 창 안의 지정된 패널에서 색 줄무늬의 경계를 부드럽게 만드는 것이다. Compose 1.12.2에서 줄무늬 레이어에 24 dp의 Modifier.blur를 적용하자 Mac과 Windows의 네이티브 창 캡처 모두에서 부드러운 경계가 나타났다. SwiftUI도 같은 방식으로 미리 정의된 줄무늬 레이어를 흐리게 한 뒤 반투명한 흰색을 덧씌운다. 두 방식 모두 이 레이어를 대상으로 검증했다. Compose Desktop API

10개 프레임워크의 줄무늬 패널 비교. Compose, SwiftUI, Electron, Tauri, MyGo, Flutter는 색 경계가 부드럽고, 나머지 네 개는 경계가 뚜렷하다.
그림 2Mac 네이티브 창의 2× 캡처에서 같은 줄무늬 패널을 잘라 동일한 비율로 축소했다.

GPUI, iced, egui, Slint의 테스트 구현은 줄무늬에 반투명 레이어를 덧씌웠으며, 재시험에서도 색 경계가 뚜렷했다. GPUI의 Blurred와 iced의 window::Settings::blur는 창 뒤의 콘텐츠에 적용된다. 테스트 버전의 내장 그리기 API에서는 국소 배경 흐림 기능을 찾지 못했다. iced에서는 사용자 지정 그리기로 국소 효과를 구현할 수 있고, egui에서는 PaintCallback으로 렌더링 백엔드를 호출할 수 있다. GPUI · iced 창 설정 · egui 그리기 콜백

Slint는 1.18.1과 FemtoVG 조합으로 테스트했다. 이 버전에는 요소 단위의 backdrop-blur 속성이 없었고, 이후 업스트림에서 Skia 렌더러에 이 속성을 추가했다. 캡처는 1.18.1의 FemtoVG 경로를 보여 준다. Slint 업스트림 이슈

디자인 페이지는 11개 항목입니다. 이번 Mac 출력에서는 GPUI, egui, iced, Slint, Compose의 P3 색상 블록이 재현되지 않았습니다. Windows 캡처에는 색상 프로필이 없어 P3를 판정하지 않았으며 국기 이모지는 모두 문자로 표시됐습니다.

표 12핵심 모듈의 기술 선택. 각 프레임워크의 고정 버전 소스와 공식 문서를 기준으로 했다.
프레임워크레이아웃텍스트접근성
GPUITaffymacOS는 CoreText 사용AccessKit
egui즉시 모드 레이아웃epaint + harfrustAccessKit
iced자체 flex 레이아웃cosmic-text시스템 브리지 확인 못 함
Slint컴파일 시 lowering + 런타임 레이아웃ParleyAccessKit
FlutterRenderBox 제약SkParagraphSemantics 트리 브리지
ComposeMeasurePolicySkiko의 SkParagraphSemantics, Windows는 Java Access Bridge 필요
ElectronBlinkChromium 텍스트 파이프라인Chromium 접근성 트리
Tauri시스템 WebView시스템 WebViewWebView를 통해 노출
SwiftUIStack / LayoutTextKit,Core Text시스템 내장

레이아웃은 비슷해지고 있지만 텍스트의 차이는 크다. iced에서 macOS에 PingFang 700을 요청하자 라틴 문자는 Menlo Bold로 폴백됐다.

한계:

  • 플랫폼마다 컴퓨터가 한 대뿐이다. 모션 결과는 Intel 내장 GPU에서 나왔으므로 외장 GPU에는 적용되지 않을 수 있다.
  • Mac은 테스트 중 유휴 상태가 아니었다. 프레임 데이터는 앱 콜백뿐이라 프레임워크 간 비교에 쓰지 않는다.
  • 그림자 blur의 의미가 제각각이며 egui, iced, GPUI는 근사 구현이다. 편집 컨트롤도 동등하지 않다. GPUI는 수정한 예제 에디터를 썼다.
  • CPU와 메모리 표는 앱과 집계에 포함된 보조 프로세스만 다룹니다. WindowServer 및 드라이버 비용의 창별 분담과 시스템 공유 자원의 재사용 효과를 정량화하지 않았으므로 전체 시스템 렌더링 비용의 순위를 매길 수 없습니다.
  • 입력기 후보 창, Mac 접근성 트리, 전력 소비는 유효한 측정 결과를 얻지 못했다.
U

ui.surf 편집부

ui.surf 편집부 · 1편