본문으로 건너뛰기
뒤로가기

[Unity] UI Toolkit 도입기: UGUI에서 UITK으로의 전환

TL;DR — UGUI 기반 UI를 LLM으로 편집하기 어렵다는 문제에서 출발해 UI Toolkit(UITK) 도입을 결정했습니다. USS 기반 스타일 시스템과 Flexbox 레이아웃 덕분에 디자인 시스템 구축과 빠른 UI 구현이 가능했지만, 스프라이트 중심의 게임 UI와 동적 연출에서는 추가적인 설계가 필요했습니다. 텍스트 기반 UI 정의라는 UITK의 특성은 LLM 활용과 디자인 시스템 확장에 큰 가능성을 보여주었습니다.

Table of contents

Open Table of contents

들어가며

게임 프로젝트에서 UI 작업을 진행하던 중, 기존 UGUI 프리팹 기반 워크플로의 한계를 체감했습니다. 특히 LLM을 활용한 UI 편집이 어렵다는 점이 결정적이었습니다. UITK이 HTML/CSS와 유사한 구조를 가지고 있다는 점에서 영감을 받아, 게임 UI 작업에 UITK을 도입해 보기로 했습니다.

이 글은 UITK 도입 과정에서 UGUI와의 차이를 체감하고, 디자인 시스템을 구축하며 겪은 경험을 정리한 기록입니다.

이 글에서 다루는 내용:

사전 지식: Unity의 기본 UI 시스템(UGUI)과 Canvas, RectTransform 등의 개념에 대한 기본 이해를 전제로 합니다.


1. UGUI의 구조적 한계

UITK 도입을 검토하게 된 배경을 이해하려면, 먼저 UGUI가 가진 구조적 특성을 짚어볼 필요가 있습니다.

1.1 렌더링: GameObject + Canvas 기반

UGUI에서 모든 UI 요소는 GameObject입니다. UI는 유니티 컴포넌트의 집합이며, 배치 단위는 Canvas입니다. 이 구조에서는 Canvas 내 하나의 요소만 변경되어도 해당 Canvas 전체의 메시가 리빌드됩니다. Sub-Canvas로 분리하면 dirty 전파를 차단할 수 있지만, 그만큼 드로우 콜이 증가하는 트레이드오프가 있어 최적화 설계가 까다롭습니다.

1.2 스타일: 인라인 하드코딩

UGUI에서 색상, 크기, 폰트 등의 스타일 속성은 각 컴포넌트의 Inspector에 직접 설정됩니다. 프로젝트 전체의 폰트 사이즈를 12에서 14로 변경하려면 수백 개의 프리팹을 하나씩 수정하거나, 런타임 스크립트를 작성해야 합니다. 일괄 변경이 구조적으로 어렵습니다.

1.3 레이아웃: 앵커와 레이아웃 그룹

RectTransform의 앵커/피벗/오프셋으로 위치를 지정하고, 자동 정렬이 필요하면 HorizontalLayoutGroup, VerticalLayoutGroup, GridLayoutGroup을 추가합니다. 레이아웃 그룹을 중첩하면 매 프레임 재계산이 발생하여 성능이 저하됩니다.

1.4 데이터 바인딩: 수동 연결

GetComponent<Text>().text = value 형태로 직접 값을 할당하고, Button.onClick.AddListener()로 이벤트를 연결합니다. 프리팹과 스크립트 간 SerializeField 참조 관리가 필수적이며, UI 요소가 늘어날수록 연결 관리 부담이 커집니다.

이러한 특성들은 UGUI가 비주얼 에디터 중심의 WYSIWYG 방식에 최적화되어 있기 때문입니다. 디자이너가 Scene 에디터에서 드래그 앤 드롭으로 UI를 조립하는 데는 직관적이지만, 코드 기반 자동화나 일괄 스타일 관리에는 근본적인 한계가 있습니다.


2. UITK이 제안하는 다른 구조

UI Toolkit(UITK)은 UGUI와 근본적으로 다른 설계 철학을 가지고 있습니다. 웹 기술(HTML/CSS)의 구조를 Unity 환경에 도입한 UI 시스템입니다.

2.1 렌더링: 경량 C# 객체 트리

UITK은 VisualElement 트리 기반으로 동작합니다. GameObject가 아닌 경량 C# 객체이며, retained-mode 렌더링을 사용합니다. 변경이 발생한 요소를 MarkDirtyRepaint로 마킹하여 효율적으로 갱신하는 구조입니다. GameObject 기반이 아니므로 계층 구조에 따른 오버헤드가 UGUI보다 적을 것으로 기대됩니다.

2.2 스타일: USS 스타일시트

UITK은 CSS와 유사한 USS(Unity Style Sheet)를 사용합니다. 변수(토큰)를 정의하고 전체에서 참조하는 방식(var(--color-text-primary))이 가능하며, 선택자 기반으로 스타일을 일괄 적용할 수 있습니다. 스타일 상속과 클래스 조합도 지원됩니다.

:root {
  --color-primary: #3a7bff;
  --font-size-base: 14px;
}

.button {
  font-size: var(--font-size-base);
  background-color: var(--color-primary);
}

프로젝트 전체 폰트 사이즈 변경이 변수 하나의 수정으로 끝납니다. UGUI에서 수백 개 프리팹을 수정해야 했던 작업과 근본적으로 다릅니다. 단, USS의 var()는 CSS와 달리 calc() 등 함수 내부에서 사용하거나 변수 간 수학 연산을 수행할 수 없으므로, 토큰 설계 시 이 제약을 고려해야 합니다.

2.3 레이아웃: Flexbox

UITK에서 모든 요소는 기본적으로 Flex 컨테이너입니다. flex-direction, flex-grow, justify-content, align-items로 선언적 배치가 가능하며, 레이아웃 재계산이 내부적으로 최적화되어 있습니다. UGUI의 레이아웃 그룹 중첩 문제에서 자유롭습니다.

2.4 데이터 바인딩: 쿼리와 이벤트 버블링

root.Q<Label>("player-name").text = value처럼 이름이나 클래스로 요소를 쿼리하고, W3C DOM 이벤트 모델에 기반한 이벤트 전파를 지원합니다. Unity에서는 Capture 단계를 Trickle-Down, Bubbling 단계를 Bubble-Up이라 부릅니다. Unity 6부터는 SerializedObject뿐 아니라 임의의 C# 객체에 대한 런타임 데이터 바인딩도 공식 지원됩니다.


3. 도입을 결정한 계기

UGUI로 만들어진 프리팹들은 바이너리 형태의 에셋이기 때문에 LLM으로 편집하기가 쉽지 않습니다. 반면 UITK은 UXML(마크업)과 USS(스타일시트)라는 텍스트 기반 포맷으로 UI를 정의합니다. LLM이 웹 디자인(HTML/CSS)을 곧잘 다루는 것을 보고, 같은 구조적 유사성을 가진 UITK에서도 유사한 생산성을 기대할 수 있다고 판단했습니다.

게임의 전반적인 톤 & 매너는 이미 정해져 있었기 때문에, 이를 기반으로 디자인 시스템을 구현하고 실제 인게임 UI까지 적용하는 것을 목표로 설정했습니다.

도입 로드맵:

  1. 토큰화 — 색상, 타이포그래피, 간격 등 디자인 토큰을 USS 변수로 정의
  2. 컴포넌트화 — 버튼, 카드, 리스트 아이템 등 재사용 가능한 UI 컴포넌트 제작
  3. Storybook — 컴포넌트를 독립적으로 확인할 수 있는 카탈로그 구성
  4. 인게임 적용 — 실제 게임 화면에 디자인 시스템 기반 UI 적용

4. 도입 과정에서 만난 과제

작업을 진행하면서 몇 가지 예상치 못한 문제를 만났습니다.

4.1 USS와 CSS 문법의 차이

UITK에 대한 레퍼런스가 부족하다 보니, LLM이 USS가 아닌 CSS 문법을 생성하는 경우가 종종 발생했습니다. USS는 CSS의 서브셋이기 때문에 지원하지 않는 속성이나 문법이 있고, 이를 검증하는 별도의 작업이 필요했습니다.

구분CSSUSS
단위rem, em, vw 등 다양px, % 위주
선택자의사 클래스·의사 요소 다수 지원:hover, :active, :focus, :disabled, :checked 등 제한적 지원. ::before/::after, :nth-child() 미지원
레이아웃Grid, Flexbox 모두 지원Flexbox만 지원
미디어 쿼리@media 지원미지원

4.2 스프라이트 중심 게임 UI와의 간극

게임 UI는 웹/앱 UI와 달리 이미지(스프라이트)를 다층적으로 사용하는 경우가 많습니다. 여러 스프라이트 이미지가 겹쳐져 있고, 애니메이션이나 VFX 등 시각적 요소가 혼재되어 있는 화면에서는 UITK만으로 구현하기 어려운 부분이 있었습니다. UGUI의 Scene 에디터에서 스프라이트를 드래그 앤 드롭으로 배치하고 9-slice를 Inspector에서 바로 확인하는 워크플로와 비교하면, UITK은 코드에서 경로를 지정하고 USS에서 9-slice 수치를 직접 입력해야 하는 차이가 있습니다.

4.3 생태계 성숙도

UITK은 에디터 UI 도구로 시작한 후 런타임 지원이 추가된 이력이 있어, 게임 런타임에서의 레퍼런스와 커뮤니티 사례가 UGUI 대비 적습니다. UI Builder는 Unity 6.x에서 production-ready 수준에 도달했고, world-space UI와 커스텀 셰이더, SVG 지원 등이 추가되었습니다. 다만 비프로그래머를 위한 직관적 편집 워크플로에서는 UGUI의 Scene 에디터가 여전히 접근성이 높습니다.


5. 도입 후 체감한 장점

과제가 있었음에도 불구하고, UITK 도입이 가져온 이점은 분명했습니다.

5.1 해상도 대응의 용이함

CSS 기반의 Flexbox 레이아웃 덕분에 다양한 해상도와 윈도우 크기 변화에 유연하게 대응할 수 있었습니다. UGUI에서는 앵커 설정과 레이아웃 그룹 조합으로 해결해야 했던 반응형 배치가, UITK에서는 flex-grow, flex-shrink 등의 선언적 속성으로 간결하게 처리됩니다.

5.2 디자인 시스템 기반의 빠른 구현

디자인 시스템을 구축한 이후에는 UI 구현 속도가 크게 향상되었습니다. 토큰과 컴포넌트가 정의되어 있으면, 새로운 화면을 만들 때 조합만으로 빠르게 완성할 수 있었습니다. 이 부분은 UGUI와 근본적으로 다른 생산성을 보여줍니다.

5.3 LLM 활용 가능성

코드(텍스트)를 기반으로 UI를 정의하기 때문에 LLM을 활용하기에 매우 적합합니다. UXML 구조와 USS 스타일을 프롬프트로 설명하면 LLM이 생성하고, 결과를 바로 적용하여 확인할 수 있습니다. 바이너리 프리팹을 다뤄야 하는 UGUI에서는 불가능한 워크플로입니다.

5.4 관심사 분리의 강제

동적인 연출이 필요한 경우, UITK만으로 처리하기 어렵기 때문에 별도 레이어를 두고 애니메이션이나 VFX 재생을 담당하게 됩니다. 처음에는 제약으로 느껴졌지만, 이 구조가 오히려 UI의 역할 구분을 명확하게 해주었습니다. View(화면 구조)와 연출(이펙트)이 분리되면서, 각각의 변경이 서로에게 영향을 주지 않는 구조가 자연스럽게 만들어졌습니다.


6. UITK은 어디까지 갈 수 있을까

UITK 도입 경험을 바탕으로, 앞으로의 활용 방향을 정리합니다.

6.1 적합한 영역과 그렇지 않은 영역

현재 시점에서 UITK과 UGUI는 상호 배타적이 아닌 상호 보완적 관계입니다.

상황추천
에디터 도구, 디버그 UIUITK
데이터 중심 리스트, 테이블UITK
디자인 시스템, 토큰 관리UITK
신규 프로젝트, 웹/앱 스타일 UIUITK
스프라이트 기반 게임 UIUGUI
복잡한 애니메이션/이펙트 연출UGUI
디자이너가 직접 수정하는 UIUGUI

6.2 LLM 기반 UI 자동화

UITK의 텍스트 기반 정의 방식은 LLM 기반 UI 자동화의 기반이 됩니다. 디자인 시스템의 토큰과 컴포넌트 규칙을 LLM에 컨텍스트로 제공하면, 새로운 화면 생성이나 기존 화면 수정을 자연어 지시만으로 처리할 수 있습니다. 디자인 시스템이 체계적으로 구축될수록 LLM의 출력 품질도 함께 높아지는 선순환 구조가 가능합니다.

6.3 하이브리드 접근

게임 UI에서는 UITK과 UGUI의 하이브리드 접근이 현실적입니다. 데이터 표시, 설정 화면, 인벤토리 목록 등 정보 전달 중심의 UI는 UITK으로 구현하고, 스프라이트 연출이 핵심인 전투 HUD나 이펙트가 많은 화면은 UGUI로 유지하는 방식입니다. 두 시스템이 공존하는 구조에서 디자인 토큰(색상, 타이포그래피, 간격)을 양쪽에서 일관되게 관리하는 것이 핵심 과제가 됩니다.


정리하며

핵심 요약:

참고 자료


이 게시물은 학습한 내용을 바탕으로 초안을 작성한 뒤, LLM의 도움을 받아 내용을 검수하고 다듬어 완성되었습니다.


공유하기:

다음 글
[Unity] UseCase Pattern: EditMode 테스트 가능한 비즈니스 로직 분리