---
title: "입력창은 컴포넌트 하나가 아니라 오브젝트 묶음이다"
description: "시안의 입력창은 사각형 하나지만 Unity 에서는 배경, 안내 문구, 입력 글자, 커서가 각각 따로입니다. 구조와 인스펙터 값, Content Type, 글자 수 제한, 모바일 키보드까지 그림으로 봅니다."
author: "유니얼"
pubDate: 2026-09-17
category: "game-dev/unity/ui"
tags: ["Unity", "UI", "uGUI"]
canonical: https://blog.unialgames.com/posts/unity-ui-input-field/
---
시안에서 입력창은 둥근 사각형 하나에 안내 문구가 들어간 모양입니다. Unity 에서는 이게 **오브젝트 여러 개가 겹친 묶음** 입니다. 배경, 안내 문구, 입력한 글자, 깜빡이는 커서가 각각 따로 있고 정하는 자리도 다릅니다.

입력창도 두 갈래입니다. 안에서 글자를 그리는 컴포넌트가 무엇이냐에 따라 나뉩니다.

- **Text 기반 InputField**: 인스펙터에 `Input Field` 로 적혀 있고, 안의 글자는 예전부터 있던 `Text` 컴포넌트가 그립니다
- **TMP_InputField**: 인스펙터에 `TMP_Input Field` 로 적혀 있고, 안의 글자는 TextMeshPro 가 그립니다

아래에서 볼 값들은 두 쪽이 거의 같습니다. 다른 자리만 따로 적었습니다.

## 입력창의 구조

<x-tabs>
<figure class="diagram" data-tab="Text 기반 InputField">
<svg viewBox="0 0 680 300" role="img" aria-label="Text 기반 InputField의 오브젝트 구조와 화면에서 겹쳐 보이는 모습">
<text x="30" y="26" font-size="12" fill="var(--text-muted)">하이어라키</text>
<rect x="30" y="40" width="250" height="34" rx="4" fill="var(--accent-soft)" stroke="var(--accent)"></rect><text x="42" y="55" font-size="12" fill="var(--text)">InputField</text><text x="42" y="68" font-size="10" font-family="var(--font-mono)" fill="var(--text-muted)">Image + InputField</text>
<line x1="46" y1="74" x2="46" y2="104" stroke="var(--border)"></line>
<rect x="46" y="104" width="234" height="34" rx="4" fill="var(--bg)" stroke="var(--border)"></rect><text x="58" y="119" font-size="12" fill="var(--text)">Placeholder</text><text x="58" y="132" font-size="10" font-family="var(--font-mono)" fill="var(--text-muted)">Text</text>
<line x1="46" y1="138" x2="46" y2="168" stroke="var(--border)"></line>
<rect x="46" y="168" width="234" height="34" rx="4" fill="var(--bg)" stroke="var(--border)"></rect><text x="58" y="183" font-size="12" fill="var(--text)">Text</text><text x="58" y="196" font-size="10" font-family="var(--font-mono)" fill="var(--text-muted)">Text</text>
<rect x="46" y="222" width="234" height="34" rx="4" fill="var(--bg)" stroke="var(--text-muted)" stroke-dasharray="5 4"></rect><text x="58" y="237" font-size="12" fill="var(--text)">… Input Caret</text><text x="58" y="250" font-size="10" font-family="var(--font-mono)" fill="var(--text-muted)">실행 중에 생김</text>
<line x1="330" y1="30" x2="330" y2="280" stroke="var(--border)"></line>
<text x="370" y="26" font-size="12" fill="var(--text-muted)">화면에서는 겹쳐 보입니다</text>
<rect x="370" y="52" width="270" height="56" rx="6" fill="var(--bg-subtle)" stroke="var(--accent)" stroke-width="1.5"></rect>
<rect x="380" y="59" width="250" height="42" fill="none" stroke="var(--accent2)" stroke-dasharray="4 3"></rect>
<text x="392" y="86" font-size="14" fill="var(--text-muted)" font-style="italic">이름을 입력하세요</text>
<text x="370" y="128" font-size="11" fill="var(--accent)">1 배경 (Image)</text>
<text x="370" y="146" font-size="11" fill="var(--accent2)">2 글자가 놓이는 자리 (안쪽 여백은 이 사각형)</text>
<text x="370" y="164" font-size="11" fill="var(--text-muted)">3 안내 문구 (입력이 있으면 사라짐)</text>
<rect x="370" y="186" width="270" height="56" rx="6" fill="var(--bg-subtle)" stroke="var(--accent)" stroke-width="1.5"></rect>
<text x="392" y="220" font-size="14" fill="var(--text)">서병필</text>
<rect x="442" y="202" width="2" height="24" fill="var(--accent)"></rect>
<text x="370" y="262" font-size="11" fill="var(--text)">입력이 들어오면 안내 문구 대신 글자와 커서가 보입니다</text>
<text x="370" y="280" font-size="11" fill="var(--text-muted)">커서는 실행 중에 만들어집니다</text>
</svg>
<figcaption>배경, 안내 문구, 입력 글자가 각각 다른 오브젝트입니다.</figcaption>
</figure>
<figure class="diagram" data-tab="TMP_InputField">
<svg viewBox="0 0 680 300" role="img" aria-label="TMP_InputField의 오브젝트 구조와 화면에서 겹쳐 보이는 모습">
<text x="30" y="26" font-size="12" fill="var(--text-muted)">하이어라키</text>
<rect x="30" y="40" width="250" height="34" rx="4" fill="var(--accent-soft)" stroke="var(--accent)"></rect><text x="42" y="55" font-size="12" fill="var(--text)">InputField (TMP)</text><text x="42" y="68" font-size="10" font-family="var(--font-mono)" fill="var(--text-muted)">Image + TMP_InputField</text>
<line x1="46" y1="74" x2="46" y2="96" stroke="var(--border)"></line>
<rect x="46" y="96" width="234" height="34" rx="4" fill="var(--bg)" stroke="var(--border)"></rect><text x="58" y="111" font-size="12" fill="var(--text)">Text Area</text><text x="58" y="124" font-size="10" font-family="var(--font-mono)" fill="var(--text-muted)">RectMask2D</text>
<line x1="62" y1="130" x2="62" y2="152" stroke="var(--border)"></line>
<rect x="62" y="152" width="218" height="34" rx="4" fill="var(--bg)" stroke="var(--border)"></rect><text x="74" y="167" font-size="12" fill="var(--text)">Placeholder</text><text x="74" y="180" font-size="10" font-family="var(--font-mono)" fill="var(--text-muted)">TextMeshPro - Text (UI)</text>
<line x1="62" y1="186" x2="62" y2="208" stroke="var(--border)"></line>
<rect x="62" y="208" width="218" height="34" rx="4" fill="var(--bg)" stroke="var(--border)"></rect><text x="74" y="223" font-size="12" fill="var(--text)">Text</text><text x="74" y="236" font-size="10" font-family="var(--font-mono)" fill="var(--text-muted)">TextMeshPro - Text (UI)</text>
<rect x="62" y="256" width="218" height="34" rx="4" fill="var(--bg)" stroke="var(--text-muted)" stroke-dasharray="5 4"></rect><text x="74" y="271" font-size="12" fill="var(--text)">… Input Caret</text><text x="74" y="284" font-size="10" font-family="var(--font-mono)" fill="var(--text-muted)">실행 중에 생김</text>
<line x1="330" y1="30" x2="330" y2="280" stroke="var(--border)"></line>
<text x="370" y="26" font-size="12" fill="var(--text-muted)">화면에서는 겹쳐 보입니다</text>
<rect x="370" y="52" width="270" height="56" rx="6" fill="var(--bg-subtle)" stroke="var(--accent)" stroke-width="1.5"></rect>
<rect x="380" y="59" width="250" height="42" fill="none" stroke="var(--accent2)" stroke-dasharray="4 3"></rect>
<text x="392" y="86" font-size="14" fill="var(--text-muted)" font-style="italic">이름을 입력하세요</text>
<text x="370" y="128" font-size="11" fill="var(--accent)">1 배경 (Image)</text>
<text x="370" y="146" font-size="11" fill="var(--accent2)">2 글자가 놓이는 자리 (안쪽 여백은 이 사각형)</text>
<text x="370" y="164" font-size="11" fill="var(--text-muted)">3 안내 문구 (입력이 있으면 사라짐)</text>
<rect x="370" y="186" width="270" height="56" rx="6" fill="var(--bg-subtle)" stroke="var(--accent)" stroke-width="1.5"></rect>
<text x="392" y="220" font-size="14" fill="var(--text)">서병필</text>
<rect x="442" y="202" width="2" height="24" fill="var(--accent)"></rect>
<text x="370" y="262" font-size="11" fill="var(--text)">입력이 들어오면 안내 문구 대신 글자와 커서가 보입니다</text>
<text x="370" y="280" font-size="11" fill="var(--text-muted)">커서는 실행 중에 만들어집니다</text>
</svg>
<figcaption>TMP_InputField 는 Text Area 가 한 겹 더 있고 거기서 글자를 잘라 냅니다.</figcaption>
</figure>
</x-tabs>

- **배경** 은 루트 오브젝트의 Image 입니다. 크기가 변하는 입력창이면 늘어나도 모서리가 지켜지도록 아홉 조각으로 나눠 뽑아 주세요
- **안내 문구(Placeholder)** 와 **입력 글자(Text)** 는 서로 다른 오브젝트입니다. 폰트, 크기, 색을 따로 정합니다
- **안쪽 여백** 은 배경에 있는 값이 아니라, 글자 오브젝트가 배경 안에서 얼마나 들어와 있는지로 만듭니다. 기본값은 좌우 10, 위 7, 아래 6 입니다. 시안의 패딩 값을 여기에 넣습니다
- **커서는 실행 중에 만들어집니다.** 하이어라키에 미리 보이지 않고 시안으로 잡을 수도 없습니다. 색과 두께와 깜빡임은 인스펙터 값으로만 정합니다

## 안내 문구는 따로 있는 글자입니다

기본으로 만들면 안내 문구는 **기울임에 투명도 절반** 으로 들어갑니다. 시안에서 안내 문구를 본문과 같은 굵기의 회색으로 그렸다면 그것도 적어 주셔야 합니다. 자동으로 따라가지 않습니다.

- 안내 문구는 **입력이 한 글자라도 들어오면 사라집니다.** 입력 중에도 남는 라벨이 필요하면 그건 입력창 밖에 따로 두는 글자입니다
- 안내 문구 자리는 글자가 아니어도 됩니다. 아이콘 이미지를 넣을 수도 있습니다
- 안내 문구와 입력 글자의 **크기가 다르면 글자가 앉는 높이도 달라집니다.** 둘을 같은 크기로 맞추는 편이 안전합니다

## 인스펙터에서 정해지는 것들

<figure class="diagram">
<svg viewBox="0 0 680 330" role="img" aria-label="입력창 인스펙터. 글자 수 제한, Content Type, Line Type, 커서 깜빡임과 두께, 선택 색이 여기서 정해진다">
<rect x="20" y="20" width="330" height="292" rx="4" fill="var(--bg)" stroke="var(--border)"></rect>
<polygon points="34,30 44,30 39,38" fill="var(--text-muted)"></polygon>
<text x="52" y="39" font-size="13" fill="var(--text)">Input Field</text>
<line x1="20" y1="48" x2="350" y2="48" stroke="var(--border)"></line>
<text x="36" y="76" font-size="12" fill="var(--text-muted)">Text Component</text><rect x="186" y="62" width="150" height="20" rx="3" fill="var(--bg)" stroke="var(--border)"></rect><text x="194" y="76" font-size="11" font-family="var(--font-mono)" fill="var(--text)">Text</text><polygon points="320,70 330,70 325,76" fill="var(--text-muted)"></polygon>
<text x="36" y="100" font-size="12" fill="var(--text-muted)">Placeholder</text><rect x="186" y="86" width="150" height="20" rx="3" fill="var(--bg)" stroke="var(--border)"></rect><text x="194" y="100" font-size="11" font-family="var(--font-mono)" fill="var(--text)">Placeholder</text><polygon points="320,94 330,94 325,100" fill="var(--text-muted)"></polygon>
<text x="36" y="124" font-size="12" fill="var(--text)">Character Limit</text><rect x="186" y="110" width="150" height="20" rx="3" fill="var(--bg)" stroke="var(--accent)"></rect><text x="194" y="124" font-size="11" font-family="var(--font-mono)" fill="var(--text)">0</text>
<text x="36" y="148" font-size="12" fill="var(--text)">Content Type</text><rect x="186" y="134" width="150" height="20" rx="3" fill="var(--bg)" stroke="var(--accent)"></rect><text x="194" y="148" font-size="11" font-family="var(--font-mono)" fill="var(--text)">Standard</text><polygon points="320,142 330,142 325,148" fill="var(--text-muted)"></polygon>
<text x="36" y="172" font-size="12" fill="var(--text)">Line Type</text><rect x="186" y="158" width="150" height="20" rx="3" fill="var(--bg)" stroke="var(--accent)"></rect><text x="194" y="172" font-size="11" font-family="var(--font-mono)" fill="var(--text)">Single Line</text><polygon points="320,166 330,166 325,172" fill="var(--text-muted)"></polygon>
<text x="36" y="196" font-size="12" fill="var(--text)">Caret Blink Rate</text><rect x="186" y="182" width="150" height="20" rx="3" fill="var(--bg)" stroke="var(--accent)"></rect><text x="194" y="196" font-size="11" font-family="var(--font-mono)" fill="var(--text)">0.85</text>
<text x="36" y="220" font-size="12" fill="var(--text)">Caret Width</text><rect x="186" y="206" width="150" height="20" rx="3" fill="var(--bg)" stroke="var(--accent)"></rect><text x="194" y="220" font-size="11" font-family="var(--font-mono)" fill="var(--text)">1</text>
<text x="36" y="244" font-size="12" fill="var(--text)">Custom Caret Color</text><rect x="186" y="231" width="16" height="16" rx="3" fill="var(--bg)" stroke="var(--accent)"></rect>
<text x="36" y="268" font-size="12" fill="var(--text)">Selection Color</text><rect x="186" y="254" width="150" height="20" rx="3" fill="var(--bg)" stroke="var(--accent)"></rect><text x="194" y="268" font-size="11" font-family="var(--font-mono)" fill="var(--text)">연한 파랑</text>
<text x="36" y="292" font-size="12" fill="var(--text-muted)">Read Only</text><rect x="186" y="279" width="16" height="16" rx="3" fill="var(--bg)" stroke="var(--border)"></rect>
<circle cx="372" cy="124" r="9" fill="var(--accent)"></circle><text x="372" y="128" font-size="11" text-anchor="middle" fill="var(--on-accent)">1</text><text x="388" y="128" font-size="12" fill="var(--text)">0 이면 글자 수 제한이 없습니다</text><text x="388" y="145" font-size="12" fill="var(--text-muted)">넘으면 조용히 안 써집니다</text>
<circle cx="372" cy="176" r="9" fill="var(--accent)"></circle><text x="372" y="180" font-size="11" text-anchor="middle" fill="var(--on-accent)">2</text><text x="388" y="180" font-size="12" fill="var(--text)">입력 종류입니다</text><text x="388" y="197" font-size="12" fill="var(--text-muted)">키보드와 검증이 같이 바뀝니다</text>
<circle cx="372" cy="228" r="9" fill="var(--accent)"></circle><text x="372" y="232" font-size="11" text-anchor="middle" fill="var(--on-accent)">3</text><text x="388" y="232" font-size="12" fill="var(--text)">한 줄인지 여러 줄인지</text>
<circle cx="372" cy="268" r="9" fill="var(--accent)"></circle><text x="372" y="272" font-size="11" text-anchor="middle" fill="var(--on-accent)">4</text><text x="388" y="272" font-size="12" fill="var(--text)">커서 깜빡임과 두께, 색</text><text x="388" y="289" font-size="12" fill="var(--text-muted)">선택했을 때의 색</text>
<text x="372" y="60" font-size="12" fill="var(--text-muted)">시안에서 정해 주면 좋은 값들</text>
<text x="372" y="316" font-size="11" fill="var(--text-muted)">커서는 오브젝트가 아니라 이 값들로만 조절합니다</text>
</svg>
<figcaption>입력창 인스펙터. 커서와 선택 색은 오브젝트가 아니라 이 값으로 정합니다.</figcaption>
</figure>

- **Character Limit** 은 0 이 제한 없음입니다. 제한을 넘긴 글자는 **아무 표시 없이 그냥 안 들어갑니다.** 한도에 닿았을 때 무엇을 보여 줄지는 시안에서 정해야 합니다
- **Content Type** 은 입력 종류입니다. 아래에서 따로 봅니다
- **Line Type** 은 한 줄인지 여러 줄인지입니다. 한 줄은 줄바꿈이 없고 엔터가 확정입니다
- **커서와 선택 색** 은 여기서 정합니다. 커서 깜빡임 기본값은 0.85, 두께는 1 픽셀입니다. 두께를 2 이상으로 올리면 굵은 커서가 됩니다

## Content Type 하나가 여러 가지를 같이 바꿉니다

<figure class="diagram">
<svg viewBox="0 0 680 280" role="img" aria-label="Content Type 에 따라 화면에 보이는 글자와 모바일 키보드가 같이 바뀐다">
<text x="30" y="26" font-size="13" fill="var(--text)">Standard</text>
<rect x="30" y="40" width="180" height="46" rx="6" fill="var(--bg-subtle)" stroke="var(--accent)" stroke-width="1.5"></rect>
<text x="44" y="70" font-size="15" fill="var(--text)">안녕하세요</text>
<rect x="30" y="106" width="180" height="96" rx="6" fill="var(--bg)" stroke="var(--border)"></rect>
<rect x="40" y="118" width="28" height="22" rx="3" fill="var(--bg-subtle)" stroke="var(--border)"></rect>
<text x="54" y="133" font-size="10" text-anchor="middle" fill="var(--text-muted)">ㅂ</text>
<rect x="73" y="118" width="28" height="22" rx="3" fill="var(--bg-subtle)" stroke="var(--border)"></rect>
<text x="87" y="133" font-size="10" text-anchor="middle" fill="var(--text-muted)">ㅈ</text>
<rect x="106" y="118" width="28" height="22" rx="3" fill="var(--bg-subtle)" stroke="var(--border)"></rect>
<text x="120" y="133" font-size="10" text-anchor="middle" fill="var(--text-muted)">ㄷ</text>
<rect x="139" y="118" width="28" height="22" rx="3" fill="var(--bg-subtle)" stroke="var(--border)"></rect>
<text x="153" y="133" font-size="10" text-anchor="middle" fill="var(--text-muted)">ㄱ</text>
<rect x="172" y="118" width="28" height="22" rx="3" fill="var(--bg-subtle)" stroke="var(--border)"></rect>
<text x="186" y="133" font-size="10" text-anchor="middle" fill="var(--text-muted)">ㅅ</text>
<rect x="40" y="146" width="28" height="22" rx="3" fill="var(--bg-subtle)" stroke="var(--border)"></rect>
<rect x="73" y="146" width="28" height="22" rx="3" fill="var(--bg-subtle)" stroke="var(--border)"></rect>
<rect x="106" y="146" width="28" height="22" rx="3" fill="var(--bg-subtle)" stroke="var(--border)"></rect>
<rect x="139" y="146" width="28" height="22" rx="3" fill="var(--bg-subtle)" stroke="var(--border)"></rect>
<rect x="172" y="146" width="28" height="22" rx="3" fill="var(--bg-subtle)" stroke="var(--border)"></rect>
<rect x="40" y="174" width="28" height="22" rx="3" fill="var(--bg-subtle)" stroke="var(--border)"></rect>
<rect x="73" y="174" width="28" height="22" rx="3" fill="var(--bg-subtle)" stroke="var(--border)"></rect>
<rect x="106" y="174" width="28" height="22" rx="3" fill="var(--bg-subtle)" stroke="var(--border)"></rect>
<rect x="139" y="174" width="28" height="22" rx="3" fill="var(--bg-subtle)" stroke="var(--border)"></rect>
<rect x="172" y="174" width="28" height="22" rx="3" fill="var(--bg-subtle)" stroke="var(--border)"></rect>
<text x="30" y="222" font-size="12" fill="var(--text-muted)">한글 자판이 올라옵니다</text>
<text x="250" y="26" font-size="13" fill="var(--text)">Password</text>
<rect x="250" y="40" width="180" height="46" rx="6" fill="var(--bg-subtle)" stroke="var(--accent)" stroke-width="1.5"></rect>
<text x="264" y="70" font-size="15" fill="var(--text)">* * * * *</text>
<rect x="250" y="106" width="180" height="96" rx="6" fill="var(--bg)" stroke="var(--border)"></rect>
<rect x="260" y="118" width="28" height="22" rx="3" fill="var(--bg-subtle)" stroke="var(--border)"></rect>
<text x="274" y="133" font-size="10" text-anchor="middle" fill="var(--text-muted)">ㅂ</text>
<rect x="293" y="118" width="28" height="22" rx="3" fill="var(--bg-subtle)" stroke="var(--border)"></rect>
<text x="307" y="133" font-size="10" text-anchor="middle" fill="var(--text-muted)">ㅈ</text>
<rect x="326" y="118" width="28" height="22" rx="3" fill="var(--bg-subtle)" stroke="var(--border)"></rect>
<text x="340" y="133" font-size="10" text-anchor="middle" fill="var(--text-muted)">ㄷ</text>
<rect x="359" y="118" width="28" height="22" rx="3" fill="var(--bg-subtle)" stroke="var(--border)"></rect>
<text x="373" y="133" font-size="10" text-anchor="middle" fill="var(--text-muted)">ㄱ</text>
<rect x="392" y="118" width="28" height="22" rx="3" fill="var(--bg-subtle)" stroke="var(--border)"></rect>
<text x="406" y="133" font-size="10" text-anchor="middle" fill="var(--text-muted)">ㅅ</text>
<rect x="260" y="146" width="28" height="22" rx="3" fill="var(--bg-subtle)" stroke="var(--border)"></rect>
<rect x="293" y="146" width="28" height="22" rx="3" fill="var(--bg-subtle)" stroke="var(--border)"></rect>
<rect x="326" y="146" width="28" height="22" rx="3" fill="var(--bg-subtle)" stroke="var(--border)"></rect>
<rect x="359" y="146" width="28" height="22" rx="3" fill="var(--bg-subtle)" stroke="var(--border)"></rect>
<rect x="392" y="146" width="28" height="22" rx="3" fill="var(--bg-subtle)" stroke="var(--border)"></rect>
<rect x="260" y="174" width="28" height="22" rx="3" fill="var(--bg-subtle)" stroke="var(--border)"></rect>
<rect x="293" y="174" width="28" height="22" rx="3" fill="var(--bg-subtle)" stroke="var(--border)"></rect>
<rect x="326" y="174" width="28" height="22" rx="3" fill="var(--bg-subtle)" stroke="var(--border)"></rect>
<rect x="359" y="174" width="28" height="22" rx="3" fill="var(--bg-subtle)" stroke="var(--border)"></rect>
<rect x="392" y="174" width="28" height="22" rx="3" fill="var(--bg-subtle)" stroke="var(--border)"></rect>
<text x="250" y="222" font-size="12" fill="var(--text-muted)">글자가 가려져 보입니다</text>
<text x="470" y="26" font-size="13" fill="var(--text)">Integer Number</text>
<rect x="470" y="40" width="180" height="46" rx="6" fill="var(--bg-subtle)" stroke="var(--accent)" stroke-width="1.5"></rect>
<text x="484" y="70" font-size="15" fill="var(--text)">1250</text>
<rect x="470" y="106" width="180" height="96" rx="6" fill="var(--bg)" stroke="var(--border)"></rect>
<rect x="480" y="118" width="28" height="22" rx="3" fill="var(--bg-subtle)" stroke="var(--border)"></rect>
<text x="494" y="133" font-size="10" text-anchor="middle" fill="var(--text-muted)">1</text>
<rect x="513" y="118" width="28" height="22" rx="3" fill="var(--bg-subtle)" stroke="var(--border)"></rect>
<text x="527" y="133" font-size="10" text-anchor="middle" fill="var(--text-muted)">2</text>
<rect x="546" y="118" width="28" height="22" rx="3" fill="var(--bg-subtle)" stroke="var(--border)"></rect>
<text x="560" y="133" font-size="10" text-anchor="middle" fill="var(--text-muted)">3</text>
<rect x="579" y="118" width="28" height="22" rx="3" fill="var(--bg-subtle)" stroke="var(--border)"></rect>
<text x="593" y="133" font-size="10" text-anchor="middle" fill="var(--text-muted)">4</text>
<rect x="612" y="118" width="28" height="22" rx="3" fill="var(--bg-subtle)" stroke="var(--border)"></rect>
<text x="626" y="133" font-size="10" text-anchor="middle" fill="var(--text-muted)">5</text>
<rect x="480" y="146" width="28" height="22" rx="3" fill="var(--bg-subtle)" stroke="var(--border)"></rect>
<rect x="513" y="146" width="28" height="22" rx="3" fill="var(--bg-subtle)" stroke="var(--border)"></rect>
<rect x="546" y="146" width="28" height="22" rx="3" fill="var(--bg-subtle)" stroke="var(--border)"></rect>
<rect x="579" y="146" width="28" height="22" rx="3" fill="var(--bg-subtle)" stroke="var(--border)"></rect>
<rect x="612" y="146" width="28" height="22" rx="3" fill="var(--bg-subtle)" stroke="var(--border)"></rect>
<rect x="480" y="174" width="28" height="22" rx="3" fill="var(--bg-subtle)" stroke="var(--border)"></rect>
<rect x="513" y="174" width="28" height="22" rx="3" fill="var(--bg-subtle)" stroke="var(--border)"></rect>
<rect x="546" y="174" width="28" height="22" rx="3" fill="var(--bg-subtle)" stroke="var(--border)"></rect>
<rect x="579" y="174" width="28" height="22" rx="3" fill="var(--bg-subtle)" stroke="var(--border)"></rect>
<rect x="612" y="174" width="28" height="22" rx="3" fill="var(--bg-subtle)" stroke="var(--border)"></rect>
<text x="470" y="222" font-size="12" fill="var(--text-muted)">숫자판만 올라옵니다</text>
<text x="30" y="256" font-size="12" fill="var(--text)">Content Type 하나를 바꾸면 화면에 보이는 모습과 모바일 키보드가 같이 바뀝니다.</text>
<text x="30" y="274" font-size="12" fill="var(--text-muted)">숫자만 받는 칸에 한글 자판이 올라오면 그 칸의 Content Type 이 안 맞은 것입니다.</text>
</svg>
<figcaption>Content Type 을 바꾸면 보이는 모습과 모바일 키보드가 같이 바뀝니다.</figcaption>
</figure>

고를 수 있는 것은 표준, 자동 교정, 정수, 소수, 영문과 숫자, 이름, 이메일 주소, 비밀번호, 핀 번호, 직접 설정입니다. 하나를 고르면 **입력 검증과 모바일 키보드 종류가 함께** 정해집니다.

- **비밀번호** 는 입력한 글자를 `*` 로 바꿔서 보여 줍니다. 값이 바뀌는 것이 아니라 보이는 것만 가려집니다
- **핀 번호** 는 숫자만 받으면서 가려 줍니다
- **이름** 은 단어의 첫 글자를 대문자로 만듭니다. 한글에는 티가 안 나지만 영문 이름 칸에서는 동작합니다
- 숫자만 받아야 하는 칸에 한글 자판이 올라온다면 그 칸의 Content Type 이 표준으로 남아 있는 것입니다

## 내용과 설정에 따라 보이는 모습

<x-input>
<script type="application/json">
{
  "label": "입력창이 어떻게 보이는가",
  "placeholder": "이름을 입력하세요",
  "note": "커서 깜빡임은 Unity 기본값인 0.85 를 그대로 씁니다."
}
</script>
</x-input>

시안에서 입력창은 보통 **비어 있는 상태 하나** 로 그려집니다. 실제로는 최소한 이 상태들이 있습니다.

- 비어 있을 때 (안내 문구가 보임)
- 입력 중일 때 (커서가 깜빡임)
- 글자가 상자보다 길 때
- 글자 수 제한에 닿았을 때
- 값이 잘못됐을 때 (에러 문구 자리와 색)
- 못 고치게 잠갔을 때 (Read Only)

여섯 개를 다 그려 달라는 말은 아닙니다. **어떻게 보일지만 한 줄씩 적어 주면** 그대로 만들 수 있습니다.

## 모바일에서는 키보드가 화면을 덮습니다

<figure class="diagram">
<svg viewBox="0 0 680 320" role="img" aria-label="모바일에서 키보드가 올라오면 화면 아래쪽 입력창이 가려진다. 입력창을 위로 올리거나 화면을 밀어 올려야 한다">
<text x="30" y="26" font-size="13" fill="var(--text)">키보드가 없을 때</text>
<rect x="30" y="40" width="150" height="250" rx="16" fill="var(--bg)" stroke="var(--border)" stroke-width="1.5"></rect>
<rect x="46" y="70" width="118" height="26" rx="4" fill="var(--bg-subtle)" stroke="var(--border)"></rect>
<text x="54" y="88" font-size="10" fill="var(--text-muted)">위쪽 내용</text>
<rect x="46" y="230" width="118" height="30" rx="4" fill="var(--bg-subtle)" stroke="var(--accent)" stroke-width="1.5"></rect>
<text x="56" y="250" font-size="11" fill="var(--text-muted)">입력창</text>
<text x="30" y="308" font-size="11" fill="var(--text-muted)">시안에서 보던 자리</text>
<text x="230" y="26" font-size="13" fill="var(--text)">키보드가 올라오면</text>
<rect x="230" y="40" width="150" height="250" rx="16" fill="var(--bg)" stroke="var(--border)" stroke-width="1.5"></rect>
<rect x="246" y="70" width="118" height="26" rx="4" fill="var(--bg-subtle)" stroke="var(--border)"></rect>
<text x="254" y="88" font-size="10" fill="var(--text-muted)">위쪽 내용</text>
<rect x="246" y="214" width="118" height="30" rx="4" fill="var(--bg-subtle)" stroke="var(--warn)" stroke-width="1.5"></rect>
<text x="256" y="233" font-size="11" fill="var(--text-muted)">입력창</text>
<rect x="232" y="236" width="146" height="52" rx="8" fill="var(--bg)" fill-opacity="0.96" stroke="var(--warn)"></rect>
<rect x="232" y="236" width="146" height="52" rx="8" fill="var(--warn)" fill-opacity="0.18"></rect>
<text x="305" y="266" font-size="12" text-anchor="middle" fill="var(--warn)">키보드</text>
<text x="230" y="308" font-size="11" fill="var(--warn)">입력창이 키보드 밑에 깔립니다</text>
<text x="430" y="26" font-size="13" fill="var(--text)">화면을 밀어 올리면</text>
<rect x="430" y="40" width="150" height="250" rx="16" fill="var(--bg)" stroke="var(--border)" stroke-width="1.5"></rect>
<rect x="446" y="70" width="118" height="26" rx="4" fill="var(--bg-subtle)" stroke="var(--border)"></rect>
<text x="454" y="88" font-size="10" fill="var(--text-muted)">위쪽 내용</text>
<rect x="446" y="146" width="118" height="30" rx="4" fill="var(--bg-subtle)" stroke="var(--accent2)" stroke-width="1.5"></rect>
<text x="456" y="166" font-size="11" fill="var(--text-muted)">입력창</text>
<rect x="432" y="190" width="146" height="98" rx="8" fill="var(--text-muted)" fill-opacity="0.18" stroke="var(--text-muted)"></rect>
<text x="505" y="244" font-size="12" text-anchor="middle" fill="var(--text-muted)">키보드</text>
<text x="430" y="308" font-size="11" fill="var(--accent2)">입력창과 확인 버튼이 다 보입니다</text>
<text x="596" y="120" font-size="12" fill="var(--text)">시안에</text>
<text x="596" y="138" font-size="12" fill="var(--text)">키보드가</text>
<text x="596" y="156" font-size="12" fill="var(--text)">올라온 화면도</text>
<text x="596" y="174" font-size="12" fill="var(--text)">같이 주세요</text>
</svg>
<figcaption>키보드가 올라오면 화면 아래쪽 입력창이 가려집니다.</figcaption>
</figure>

입력창이 화면 아래쪽에 있으면 키보드가 올라올 때 그대로 가려집니다. 확인 버튼도 같이 가려집니다. 그래서 입력이 있는 화면은 **키보드가 올라온 상태의 시안** 이 따로 필요합니다. 입력창을 위로 올릴지, 화면 전체를 밀어 올릴지, 스크롤로 만들지가 거기서 정해집니다.

키보드 말고도 모바일에서 달라지는 것이 있습니다.

- **입력창을 누르면 기존 글자가 전부 선택됩니다.** 그 상태에서 한 글자를 치면 전부 지워지고 새로 시작합니다. 이름을 고치러 들어온 사람이 당황하는 지점이라, 그대로 둘지 커서만 놓을지 정해 두면 좋습니다
- 기기 자판 대신 게임 안에서 만든 자판을 쓸 거라면 **기기 자판을 안 띄우는 설정** 을 따로 켭니다

## 시안을 넘길 때 적어 주면 좋은 것

| 항목 | 적어 줄 것 |
| --- | --- |
| 안내 문구 | 문구, 색, 굵기, 기울임 여부. 입력 글자와 크기가 같은지 |
| 안쪽 여백 | 배경에서 글자가 얼마나 들어와 있는지 (좌우와 위아래) |
| 입력 종류 | 숫자만, 이메일, 비밀번호 같은 종류. 모바일 키보드도 같이 바뀝니다 |
| 글자 수 제한 | 최대 글자 수와, 한도에 닿았을 때 보여 줄 것 |
| 줄 | 한 줄인지 여러 줄인지. 여러 줄이면 최대 높이 |
| 커서와 선택 | 커서 색과 두께, 글자를 선택했을 때의 색 |
| 상태 | 비어 있을 때, 입력 중, 에러, 잠김 상태의 모습 |
| 모바일 | 키보드가 올라온 화면에서 입력창과 버튼이 어디에 있는지 |

## 정리

- 입력창은 배경, 안내 문구, 입력 글자, 커서가 각각 다른 오브젝트로 겹쳐 있는 묶음입니다
- 안쪽 여백은 배경이 아니라 글자 오브젝트가 들어와 있는 정도로 만듭니다
- 안내 문구는 따로 있는 글자라 폰트와 색을 따로 정하고, 입력이 들어오면 사라집니다
- 커서는 실행 중에 생겨서 시안으로 못 잡습니다. 색과 두께와 깜빡임은 인스펙터 값으로 정합니다
- Content Type 하나가 입력 검증과 모바일 키보드를 같이 바꿉니다. 비밀번호는 보이는 글자만 가려집니다
- 글자 수 제한을 넘은 글자는 조용히 안 들어갑니다. 한도에 닿았을 때 보여 줄 것을 정해 두세요
- 모바일에서는 키보드가 화면을 덮습니다. 키보드가 올라온 상태의 시안이 따로 필요합니다