---
title: "uGUI 는 NGUI 에서 시작했다"
description: "유니티에 런타임 UI 가 없던 시절에 그 자리를 채운 것이 NGUI 입니다. 2025년 10월에 MIT 로 풀린 저장소를 열어 보면서, 무엇이 한 상자에 들어 있었는지와 유니티 UI 와 크게 갈리는 지점을 정리했습니다."
author: "유니얼"
pubDate: 2026-09-20
category: "game-dev/unity/ui"
tags: ["Unity", "UI", "NGUI", "라이브러리"]
canonical: https://blog.unialgames.com/posts/ngui-history/
---
<x-repo>
<script type="application/json">
{"repo":"tasharen/ngui","text":"2011년에 나온 유니티용 UI 시스템. 2025년 10월부터 MIT 오픈소스입니다.","chips":["MIT","2011~2025","Tasharen Entertainment"],"links":[{"text":"License.txt","path":"License.txt"},{"text":"Assets/NGUI/Scripts","path":"Assets/NGUI/Scripts"}]}
</script>
</x-repo>

[UI Toolkit 시리즈](/series/unity-ui-toolkit/)에서 유니티 UI 의 두 체계를 봤습니다. 하나가 더 있습니다. 오래된 유니티 프로젝트를 열었는데 하이어라키에 `UIRoot` 와 `UIPanel` 이 있고 캔버스가 안 보인다면 NGUI 입니다.

새 프로젝트에 쓸 일은 거의 없습니다. 그런데 이어받는 프로젝트에서 만나는 일은 아직 있고, 그때 **왜 이렇게 생겼는지** 를 모르면 손대기가 무섭습니다. 2025년 10월부터 저장소가 MIT 로 열려 있어서 이제는 코드를 직접 보면서 이야기할 수 있습니다.

## 2011년에는 유니티에 런타임 UI 가 없었습니다

<figure class="diagram">
<svg viewBox="0 0 680 196" role="img" aria-label="2011년 NGUI 첫 릴리스부터 2025년 10월 MIT 공개까지의 연표">
<text x="24" y="24" font-size="13" fill="var(--text)">유니티 UI 의 순서</text>
<line x1="50" y1="110" x2="634" y2="110" stroke="var(--border)" stroke-width="1.2"></line>
<polygon points="642,110 630,105 630,115" fill="var(--border)"></polygon>
<circle cx="100" cy="110" r="5" fill="var(--accent2)"></circle>
<line x1="100" y1="105" x2="100" y2="96" stroke="var(--accent2)" stroke-width="1"></line>
<text x="100" y="90" font-size="11.5" fill="var(--accent2)" text-anchor="middle">2011</text>
<text x="100" y="72" font-size="10.5" fill="var(--text-muted)" text-anchor="middle">NGUI 첫 릴리스</text>
<circle cx="270" cy="110" r="5" fill="var(--accent)"></circle>
<line x1="270" y1="115" x2="270" y2="124" stroke="var(--accent)" stroke-width="1"></line>
<text x="270" y="140" font-size="11.5" fill="var(--accent)" text-anchor="middle">2014</text>
<text x="270" y="158" font-size="10.5" fill="var(--text-muted)" text-anchor="middle">유니티 4.6 의 uGUI</text>
<circle cx="440" cy="110" r="5" fill="var(--accent)"></circle>
<line x1="440" y1="105" x2="440" y2="96" stroke="var(--accent)" stroke-width="1"></line>
<text x="440" y="90" font-size="11.5" fill="var(--accent)" text-anchor="middle">그 뒤</text>
<text x="440" y="72" font-size="10.5" fill="var(--text-muted)" text-anchor="middle">UI Toolkit</text>
<circle cx="600" cy="110" r="5" fill="var(--accent2)"></circle>
<line x1="600" y1="115" x2="600" y2="124" stroke="var(--accent2)" stroke-width="1"></line>
<text x="600" y="140" font-size="11.5" fill="var(--accent2)" text-anchor="middle">2025.10</text>
<text x="600" y="158" font-size="10.5" fill="var(--text-muted)" text-anchor="middle">NGUI, MIT 공개</text>
<text x="24" y="188" font-size="11" fill="var(--text-muted)">유니티가 자체 UI 를 내놓기까지 3년 가까이 걸렸습니다</text>
</svg>
<figcaption>그 3년 동안 유니티로 만든 게임의 UI 상당수가 NGUI 였습니다.</figcaption>
</figure>

지금은 Canvas 가 기본이지만 그때는 아니었습니다. 게임 화면에 버튼 하나를 띄우려면 `OnGUI` 안에서 IMGUI 를 부르거나, 쿼드 메시를 직접 만들어 텍스처를 붙여야 했습니다. `OnGUI` 는 에디터 도구에는 쓸 만해도 게임 UI 로는 매 프레임 비용이 컸습니다.

그 자리를 채운 것이 NGUI 입니다. README 첫 줄이 그 시점을 그대로 적어 뒀습니다. "a UI system for the Unity Engine, first released back in 2011, long before Unity created their own UI system."

유니티가 자체 UI 를 내놓은 것은 **2014년, 유니티 4.6** 입니다. 3년 가까이 유니티로 만든 게임의 UI 상당수가 NGUI 였습니다.

## 만든 사람이 저장소에 적어 둔 말

README 가 열 줄이 안 됩니다. 그런데 그 안에 이 글에 필요한 게 다 있습니다.

> "NGUI became extremely popular shortly after its launch, derailing my plan to get started as an independent game developer."

인디 게임을 만들려다 UI 시스템 만드는 사람이 됐다는 말입니다. 그다음 줄이 유명합니다.

> "It also ended up being the starting point for Unity's own UI system."

**유니티 자체 UI 의 출발점이 됐다**고 만든 사람이 직접 적었습니다. uGUI 를 쓰다가 NGUI 를 열어 보면 낯익은 이름이 계속 나오는데, 우연이 아닙니다.

마지막 줄도 봐 둘 만합니다.

> "As of this writing (year 2025), it's still backwards compatible with projects created over a decade ago -- and I am using it in all of my own projects."

10년 넘은 프로젝트가 아직 돌아간다는 것. 이게 NGUI 를 아직 만나게 되는 이유이기도 합니다.

## 2025년 10월에 MIT 로 풀렸습니다

원래는 에셋 스토어에서 파는 유료 에셋이었습니다. README 에 이렇게 적혀 있습니다. "As of October 2025, NGUI is now completely free and open source."

`License.txt` 는 MIT 이고 `Copyright (c) 2011-2025 Tasharen Entertainment Inc.` 입니다. 조건 하나가 본문이 아니라 README 에 붙어 있습니다.

> "if you make your own UI system for some other engine using NGUI's code as the starting point, a thank you would be appreciated"

라이선스 조항이 아니라 부탁입니다. MIT 이니 지켜야 할 의무는 저작권 표시뿐입니다.

바뀐 것이 하나 더 있습니다. **이제는 코드를 읽고 고쳐서 쓸 수 있습니다.** 오래된 프로젝트를 이어받았는데 NGUI 쪽에서 문제가 나면, 예전에는 에셋 스토어 버전을 기다리거나 구매한 소스를 뒤져야 했습니다. 지금은 저장소에서 바로 봅니다.

## 한 상자에 전부 들어 있습니다

저장소의 `Assets/NGUI/Scripts` 를 열어 보면 폴더가 나뉘어 있습니다. 목록을 보면 이 시스템이 무엇을 다 떠안고 있었는지가 한눈에 보입니다.

<figure class="diagram">
<svg viewBox="0 0 680 286" role="img" aria-label="NGUI 는 한 상자에 여덟 가지가 들어 있고 유니티 쪽은 같은 자리가 따로따로 나뉘어 있는 그림">
<text x="24" y="24" font-size="13" fill="var(--text)">한 덩어리로 오는가, 따로 고르는가</text>
<text x="24" y="50" font-size="11.5" fill="var(--accent2)">NGUI 하나를 넣으면</text>
<rect x="24" y="62" width="290" height="190" rx="10" fill="var(--accent2)" fill-opacity="0.08" stroke="var(--accent2)"></rect>
<rect x="38" y="76" width="123" height="34" rx="6" fill="var(--bg-subtle)" stroke="var(--border)"></rect>
<text x="99" y="97" font-size="9.5" fill="var(--text)" font-family="var(--font-mono)" text-anchor="middle">UIPanel</text>
<rect x="171" y="76" width="123" height="34" rx="6" fill="var(--bg-subtle)" stroke="var(--border)"></rect>
<text x="232" y="97" font-size="9.5" fill="var(--text)" font-family="var(--font-mono)" text-anchor="middle">UIWidget</text>
<rect x="38" y="120" width="123" height="34" rx="6" fill="var(--bg-subtle)" stroke="var(--border)"></rect>
<text x="99" y="141" font-size="9.5" fill="var(--text)" font-family="var(--font-mono)" text-anchor="middle">UIRoot</text>
<rect x="171" y="120" width="123" height="34" rx="6" fill="var(--bg-subtle)" stroke="var(--border)"></rect>
<text x="232" y="141" font-size="9.5" fill="var(--text)" font-family="var(--font-mono)" text-anchor="middle">UICamera</text>
<rect x="38" y="164" width="123" height="34" rx="6" fill="var(--bg-subtle)" stroke="var(--border)"></rect>
<text x="99" y="185" font-size="9.5" fill="var(--text)" font-family="var(--font-mono)" text-anchor="middle">UIAtlas</text>
<rect x="171" y="164" width="123" height="34" rx="6" fill="var(--bg-subtle)" stroke="var(--border)"></rect>
<text x="232" y="185" font-size="9.5" fill="var(--text)" font-family="var(--font-mono)" text-anchor="middle">UIFont</text>
<rect x="38" y="208" width="123" height="34" rx="6" fill="var(--bg-subtle)" stroke="var(--border)"></rect>
<text x="99" y="229" font-size="9.5" fill="var(--text)" font-family="var(--font-mono)" text-anchor="middle">Tweening</text>
<rect x="171" y="208" width="123" height="34" rx="6" fill="var(--bg-subtle)" stroke="var(--border)"></rect>
<text x="232" y="229" font-size="9.5" fill="var(--text)" font-family="var(--font-mono)" text-anchor="middle">UIScrollView</text>
<text x="169" y="270" font-size="10.5" fill="var(--text-muted)" text-anchor="middle">고를 게 없고 맞출 것도 없습니다</text>
<text x="366" y="50" font-size="11.5" fill="var(--accent)">유니티 쪽에서 같은 자리</text>
<rect x="366" y="76" width="140" height="34" rx="6" fill="var(--bg-subtle)" stroke="var(--accent)"></rect>
<text x="436" y="97" font-size="9.5" fill="var(--text)" text-anchor="middle">Canvas</text>
<rect x="516" y="76" width="140" height="34" rx="6" fill="var(--bg-subtle)" stroke="var(--accent)"></rect>
<text x="586" y="97" font-size="9.5" fill="var(--text)" text-anchor="middle">Graphic</text>
<rect x="366" y="120" width="140" height="34" rx="6" fill="var(--bg-subtle)" stroke="var(--accent)"></rect>
<text x="436" y="141" font-size="9.5" fill="var(--text)" text-anchor="middle">Canvas Scaler</text>
<rect x="516" y="120" width="140" height="34" rx="6" fill="var(--bg-subtle)" stroke="var(--accent)"></rect>
<text x="586" y="141" font-size="9.5" fill="var(--text)" text-anchor="middle">EventSystem</text>
<rect x="366" y="164" width="140" height="34" rx="6" fill="var(--bg-subtle)" stroke="var(--accent)"></rect>
<text x="436" y="185" font-size="9.5" fill="var(--text)" text-anchor="middle">Sprite Atlas</text>
<rect x="516" y="164" width="140" height="34" rx="6" fill="var(--bg-subtle)" stroke="var(--warn)" stroke-dasharray="4 3"></rect>
<text x="586" y="185" font-size="9.5" fill="var(--text)" text-anchor="middle">TextMeshPro</text>
<rect x="366" y="208" width="140" height="34" rx="6" fill="var(--bg-subtle)" stroke="var(--warn)" stroke-dasharray="4 3"></rect>
<text x="436" y="229" font-size="9.5" fill="var(--text)" text-anchor="middle">외부 트윈 라이브러리</text>
<rect x="516" y="208" width="140" height="34" rx="6" fill="var(--bg-subtle)" stroke="var(--accent)"></rect>
<text x="586" y="229" font-size="9.5" fill="var(--text)" text-anchor="middle">ScrollRect</text>
<text x="511" y="270" font-size="10.5" fill="var(--text-muted)" text-anchor="middle">점선은 기본이 아니라 따로 가져오는 것입니다</text>
</svg>
<figcaption>2011년에는 오른쪽 자리가 전부 비어 있었습니다.</figcaption>
</figure>

| NGUI 에 있는 것 | 하는 일 | 유니티 쪽에서 그 자리 |
| --- | --- | --- |
| `UIPanel` | "collecting, sorting and updating widgets in addition to generating widgets' geometry" | Canvas |
| `UIWidget` | 화면에 그려지는 것들의 밑바탕 | Graphic |
| `UIRoot` | 전체 크기를 화면에 맞춰 잡습니다 | Canvas Scaler |
| `UICamera` | 입력을 받아 알려 줍니다 | EventSystem + Graphic Raycaster |
| `UIAtlas` / `NGUIAtlas` | 작은 그림을 한 장으로 묶습니다 | Sprite Atlas |
| `UIFont` / `NGUIText` | 글자를 그립니다 | TextMeshPro |
| `Tweening/` | 값을 시간에 따라 움직입니다 | (없음. DOTween 같은 것을 따로 씁니다) |
| `Interaction/UIScrollView` `UIGrid` | 스크롤과 줄 세우기 | ScrollRect + Layout Group |

마지막 두 줄이 이 표의 요지입니다. **2011년에는 유니티가 이 중 어느 것도 안 갖고 있었습니다.** 아틀라스도, 비트맵 폰트도, 트윈도 전부 NGUI 가 같이 들고 와야 했습니다. 그래서 통짜 한 덩어리입니다.

유니티는 나중에 이걸 쪼개서 각각 기본 기능으로 넣었습니다. 지금 uGUI 로 UI 를 만들면 아틀라스는 Sprite Atlas, 글자는 TextMeshPro, 트윈은 외부 라이브러리를 각각 고릅니다. 고를 수 있게 된 대신 조합을 직접 맞춰야 합니다. NGUI 는 고를 게 없는 대신 맞출 것도 없었습니다.

## 유니티 UI 와 크게 갈리는 지점이 셋입니다

코드를 열기 전에 이 셋만 알아 두면 하이어라키를 봤을 때 덜 당황합니다.

**첫째, 그리는 순서를 하이어라키로 안 정합니다.** `UIWidget` 에 `depth` 라는 정수가 있고 그 숫자가 순서입니다. [하이어라키 맨 아래가 화면 맨 앞이다](/posts/unity-ui-canvas-draw-order/)에서 본 uGUI 규칙과 정반대입니다. 오브젝트를 위아래로 옮겨도 순서가 안 바뀝니다.

**둘째, 입력이 콜라이더로 갑니다.** `UICamera` 는 카메라에 붙는 컴포넌트이고, 소스 주석이 이렇게 시작합니다. "This script should be attached to each camera that's used to draw the objects with UI components on them." 물리 레이캐스트로 콜라이더를 맞히고, 맞은 오브젝트에 `OnClick()` `OnPress(bool)` `OnDrag(delta)` 같은 이름으로 알려 줍니다. 버튼에 콜라이더가 붙어 있는 게 정상입니다.

**셋째, UI 가 월드에 놓인 진짜 오브젝트입니다.** `UIRoot` 의 주석이 한 줄입니다. "This is a script used to keep the game object scaled to 2/(Screen.height)." 화면 높이에 맞춰 루트를 축소해 두고, 전용 카메라로 그 영역을 비춥니다. uGUI 의 Screen Space Overlay 처럼 화면에 직접 얹는 방식이 아닙니다.

셋 다 **유니티에 UI 전용 경로가 없던 시절에 게임 오브젝트와 물리로 UI 를 만들면 이렇게 된다** 는 결과입니다. 이상해 보이는 선택이 아니라 그때 쓸 수 있던 재료의 결과입니다.

## 왜 아직 만나는가

새로 시작하는 프로젝트에 NGUI 를 고를 이유는 거의 없습니다. 유니티가 기본으로 주는 것이 그때와 비교가 안 되고, 새로 들어오는 사람이 아는 쪽은 uGUI 입니다.

그래도 만나게 됩니다.

- **오래된 프로젝트를 이어받을 때.** 2012년에서 2016년 사이에 시작한 유니티 프로젝트 중에 NGUI 를 쓴 것이 많습니다. 그중 일부가 아직 서비스 중입니다
- **갈아엎을 이유가 없을 때.** 돌아가는 UI 를 통째로 옮기는 것은 화면 수만큼 드는 일입니다. 새 기능만 붙이고 기존 화면은 그대로 두는 판단이 흔합니다
- **10년 넘게 호환이 유지됐기 때문.** 만든 사람이 README 에 적어 둔 그 호환성이, 역설적으로 옮길 이유를 하나 줄여 왔습니다

이어받는 쪽에서 제일 위험한 것은 **uGUI 라고 생각하고 손대는 것** 입니다. 오브젝트를 맨 아래로 내려도 앞으로 안 나오고, 콜라이더를 지우면 버튼이 안 눌리고, 캔버스를 찾으면 없습니다. 체계가 다른 것이지 고장 난 게 아닙니다.

## 정리

- NGUI 는 2011년에 나왔습니다. **유니티에 런타임 UI 가 없던 시절** 에 그 자리를 채웠습니다
- 유니티 자체 UI 는 2014년 4.6 부터입니다. README 표현으로 NGUI 가 "the starting point for Unity's own UI system" 입니다
- 2025년 10월부터 **MIT 오픈소스** 입니다. 이제 코드를 읽고 고쳐 쓸 수 있습니다
- 아틀라스, 비트맵 폰트, 트윈, 스크롤, 줄 세우기까지 **한 상자에 다 들어 있습니다.** 그때는 유니티에 아무것도 없었기 때문입니다
- 크게 갈리는 셋: **순서는 `depth` 숫자**, **입력은 콜라이더와 물리 레이캐스트**, **UI 는 월드에 놓인 오브젝트**
- 새로 고를 이유는 거의 없지만, 이어받은 프로젝트에서 만납니다. uGUI 라고 생각하고 손대는 것이 제일 위험합니다