---
title: "스크롤 목록은 창문 뒤에서 긴 종이를 움직이는 것이다"
description: "인벤토리 같은 스크롤 목록을 칸(Grid Layout Group), 종이와 창(Scroll View), 가림막(Mask, RectMask2D) 세 부품으로 나눠, 칸이 꺾이는 규칙과 끝에서 튕기는 동작을 그림으로 봅니다."
author: "유니얼"
pubDate: 2026-09-10
category: "game-dev/unity/ui"
tags: ["Unity", "UI", "uGUI"]
canonical: https://blog.unialgames.com/posts/unity-ui-grid-scroll-mask/
---
인벤토리 화면을 떠올려 봅니다. 아이템 칸이 격자로 놓여 있고, 위아래로 밀면 목록이 움직이고, 창 밖으로 나간 칸은 보이지 않습니다.

Unity 에서 이 화면은 **부품 셋** 으로 나뉩니다.

<figure class="diagram">
<svg viewBox="0 0 680 350" role="img" aria-label="스크롤 목록의 세 부품. 칸은 Grid Layout Group 이 늘어놓은 아이템들, 종이는 칸을 붙인 긴 Content, 창은 Viewport 로 그 뒤에서 종이를 움직이며 창 밖은 마스크가 가린다">
<text x="30" y="30" font-size="14" fill="var(--text)">1. 칸</text>
<text x="30" y="48" font-size="11" fill="var(--text-muted)">Grid Layout Group</text>
<rect x="30" y="70" width="36" height="36" rx="5" fill="var(--accent-soft)" stroke="var(--accent)" stroke-width="1.2" stroke-opacity="1" fill-opacity="1"></rect>
<rect x="74" y="70" width="36" height="36" rx="5" fill="var(--accent-soft)" stroke="var(--accent)" stroke-width="1.2" stroke-opacity="1" fill-opacity="1"></rect>
<rect x="118" y="70" width="36" height="36" rx="5" fill="var(--accent-soft)" stroke="var(--accent)" stroke-width="1.2" stroke-opacity="1" fill-opacity="1"></rect>
<rect x="30" y="114" width="36" height="36" rx="5" fill="var(--accent-soft)" stroke="var(--accent)" stroke-width="1.2" stroke-opacity="1" fill-opacity="1"></rect>
<rect x="74" y="114" width="36" height="36" rx="5" fill="var(--accent-soft)" stroke="var(--accent)" stroke-width="1.2" stroke-opacity="1" fill-opacity="1"></rect>
<rect x="118" y="114" width="36" height="36" rx="5" fill="var(--accent-soft)" stroke="var(--accent)" stroke-width="1.2" stroke-opacity="1" fill-opacity="1"></rect>
<text x="30" y="178" font-size="12" fill="var(--text-muted)">아이템을 격자로</text>
<text x="30" y="196" font-size="12" fill="var(--text-muted)">늘어놓습니다</text>
<line x1="176" y1="112" x2="210" y2="112" stroke="var(--text-muted)" stroke-width="1.5"></line><polygon points="210,107 218,112 210,117" fill="var(--text-muted)"></polygon>
<text x="232" y="30" font-size="14" fill="var(--text)">2. 종이</text>
<text x="232" y="48" font-size="11" fill="var(--text-muted)">Content</text>
<rect x="232" y="62" width="148" height="250" rx="4" fill="var(--bg)" stroke="var(--text-muted)" stroke-dasharray="4 4"></rect>
<rect x="240" y="70" width="36" height="36" rx="5" fill="var(--accent-soft)" stroke="var(--accent)" stroke-width="1.2" stroke-opacity="1" fill-opacity="1"></rect>
<rect x="286" y="70" width="36" height="36" rx="5" fill="var(--accent-soft)" stroke="var(--accent)" stroke-width="1.2" stroke-opacity="1" fill-opacity="1"></rect>
<rect x="332" y="70" width="36" height="36" rx="5" fill="var(--accent-soft)" stroke="var(--accent)" stroke-width="1.2" stroke-opacity="1" fill-opacity="1"></rect>
<rect x="240" y="118" width="36" height="36" rx="5" fill="var(--accent-soft)" stroke="var(--accent)" stroke-width="1.2" stroke-opacity="1" fill-opacity="1"></rect>
<rect x="286" y="118" width="36" height="36" rx="5" fill="var(--accent-soft)" stroke="var(--accent)" stroke-width="1.2" stroke-opacity="1" fill-opacity="1"></rect>
<rect x="332" y="118" width="36" height="36" rx="5" fill="var(--accent-soft)" stroke="var(--accent)" stroke-width="1.2" stroke-opacity="1" fill-opacity="1"></rect>
<rect x="240" y="166" width="36" height="36" rx="5" fill="var(--accent-soft)" stroke="var(--accent)" stroke-width="1.2" stroke-opacity="1" fill-opacity="1"></rect>
<rect x="286" y="166" width="36" height="36" rx="5" fill="var(--accent-soft)" stroke="var(--accent)" stroke-width="1.2" stroke-opacity="1" fill-opacity="1"></rect>
<rect x="332" y="166" width="36" height="36" rx="5" fill="var(--accent-soft)" stroke="var(--accent)" stroke-width="1.2" stroke-opacity="1" fill-opacity="1"></rect>
<rect x="240" y="214" width="36" height="36" rx="5" fill="var(--accent-soft)" stroke="var(--accent)" stroke-width="1.2" stroke-opacity="1" fill-opacity="1"></rect>
<rect x="286" y="214" width="36" height="36" rx="5" fill="var(--accent-soft)" stroke="var(--accent)" stroke-width="1.2" stroke-opacity="1" fill-opacity="1"></rect>
<rect x="332" y="214" width="36" height="36" rx="5" fill="var(--accent-soft)" stroke="var(--accent)" stroke-width="1.2" stroke-opacity="1" fill-opacity="1"></rect>
<rect x="240" y="262" width="36" height="36" rx="5" fill="var(--accent-soft)" stroke="var(--accent)" stroke-width="1.2" stroke-opacity="1" fill-opacity="1"></rect>
<rect x="286" y="262" width="36" height="36" rx="5" fill="var(--accent-soft)" stroke="var(--accent)" stroke-width="1.2" stroke-opacity="1" fill-opacity="1"></rect>
<rect x="332" y="262" width="36" height="36" rx="5" fill="var(--accent-soft)" stroke="var(--accent)" stroke-width="1.2" stroke-opacity="1" fill-opacity="1"></rect>
<line x1="392" y1="112" x2="426" y2="112" stroke="var(--text-muted)" stroke-width="1.5"></line><polygon points="426,107 434,112 426,117" fill="var(--text-muted)"></polygon>
<text x="448" y="30" font-size="14" fill="var(--text)">3. 창</text>
<text x="448" y="48" font-size="11" fill="var(--text-muted)">Viewport + 마스크</text>
<rect x="456" y="70" width="36" height="36" rx="5" fill="var(--accent-soft)" stroke="var(--accent)" stroke-width="1.2" stroke-opacity="0.18" fill-opacity="0.18"></rect>
<rect x="502" y="70" width="36" height="36" rx="5" fill="var(--accent-soft)" stroke="var(--accent)" stroke-width="1.2" stroke-opacity="0.18" fill-opacity="0.18"></rect>
<rect x="548" y="70" width="36" height="36" rx="5" fill="var(--accent-soft)" stroke="var(--accent)" stroke-width="1.2" stroke-opacity="0.18" fill-opacity="0.18"></rect>
<rect x="456" y="118" width="36" height="36" rx="5" fill="var(--accent-soft)" stroke="var(--accent)" stroke-width="1.2" stroke-opacity="0.18" fill-opacity="0.18"></rect>
<rect x="502" y="118" width="36" height="36" rx="5" fill="var(--accent-soft)" stroke="var(--accent)" stroke-width="1.2" stroke-opacity="0.18" fill-opacity="0.18"></rect>
<rect x="548" y="118" width="36" height="36" rx="5" fill="var(--accent-soft)" stroke="var(--accent)" stroke-width="1.2" stroke-opacity="0.18" fill-opacity="0.18"></rect>
<rect x="456" y="166" width="36" height="36" rx="5" fill="var(--accent-soft)" stroke="var(--accent)" stroke-width="1.2" stroke-opacity="1" fill-opacity="1"></rect>
<rect x="502" y="166" width="36" height="36" rx="5" fill="var(--accent-soft)" stroke="var(--accent)" stroke-width="1.2" stroke-opacity="1" fill-opacity="1"></rect>
<rect x="548" y="166" width="36" height="36" rx="5" fill="var(--accent-soft)" stroke="var(--accent)" stroke-width="1.2" stroke-opacity="1" fill-opacity="1"></rect>
<rect x="456" y="214" width="36" height="36" rx="5" fill="var(--accent-soft)" stroke="var(--accent)" stroke-width="1.2" stroke-opacity="1" fill-opacity="1"></rect>
<rect x="502" y="214" width="36" height="36" rx="5" fill="var(--accent-soft)" stroke="var(--accent)" stroke-width="1.2" stroke-opacity="1" fill-opacity="1"></rect>
<rect x="548" y="214" width="36" height="36" rx="5" fill="var(--accent-soft)" stroke="var(--accent)" stroke-width="1.2" stroke-opacity="1" fill-opacity="1"></rect>
<rect x="456" y="262" width="36" height="36" rx="5" fill="var(--accent-soft)" stroke="var(--accent)" stroke-width="1.2" stroke-opacity="0.18" fill-opacity="0.18"></rect>
<rect x="502" y="262" width="36" height="36" rx="5" fill="var(--accent-soft)" stroke="var(--accent)" stroke-width="1.2" stroke-opacity="0.18" fill-opacity="0.18"></rect>
<rect x="548" y="262" width="36" height="36" rx="5" fill="var(--accent-soft)" stroke="var(--accent)" stroke-width="1.2" stroke-opacity="0.18" fill-opacity="0.18"></rect>
<rect x="448" y="62" width="148" height="250" rx="4" fill="none" stroke="var(--text-muted)" stroke-dasharray="4 4" stroke-opacity="0.5"></rect>
<rect x="440" y="114" width="164" height="150" rx="6" fill="none" stroke="var(--text)" stroke-width="2.5"></rect>
<line x1="624" y1="160" x2="624" y2="220" stroke="var(--accent)" stroke-width="2"></line><polygon points="619,160 624,150 629,160" fill="var(--accent)"></polygon><polygon points="619,220 624,230 629,220" fill="var(--accent)"></polygon>
<text x="612" y="252" font-size="11" fill="var(--accent)">끌면</text>
<text x="612" y="268" font-size="11" fill="var(--accent)">종이가</text>
<text x="612" y="284" font-size="11" fill="var(--accent)">움직임</text>
<text x="448" y="342" font-size="12" fill="var(--text-muted)">흐린 칸은 마스크가 가린 부분</text>
</svg>
<figcaption>칸을 긴 종이에 붙이고, 그 종이를 창 뒤에서 움직입니다. 창 밖은 가림막이 가립니다.</figcaption>
</figure>

시안에서는 한 장의 그림이지만, 칸이 몇 줄로 꺾이는지는 1 번이, 끝에서 튕기는지는 3 번이 정합니다. 하나씩 봅니다.

## 칸: Grid Layout Group

앞에서 본 Horizontal Layout Group 은 자식이 알려 준 크기를 썼습니다. **Grid Layout Group 은 그 값을 보지 않습니다.**

<x-tabs>
<figure class="diagram" data-tab="Horizontal Layout Group">
<svg viewBox="0 0 680 160" role="img" aria-label="Horizontal Layout Group: 크기가 다른 아이템 셋을 넣었을 때">
<text x="150" y="20" font-size="12" fill="var(--text)">Horizontal Layout Group</text>
<rect x="150" y="30" width="400" height="90" rx="4" fill="none" stroke="var(--text)"></rect>
<rect x="158" y="38" width="48" height="48" rx="6" fill="var(--accent-soft)" stroke="var(--accent)" stroke-width="1.5"></rect>
<text x="182.0" y="66.0" font-size="12" text-anchor="middle" fill="var(--text)">48</text>
<rect x="214" y="38" width="80" height="80" rx="6" fill="var(--accent-soft)" stroke="var(--accent)" stroke-width="1.5"></rect>
<text x="254.0" y="82.0" font-size="12" text-anchor="middle" fill="var(--text)">80</text>
<rect x="302" y="38" width="56" height="56" rx="6" fill="var(--accent-soft)" stroke="var(--accent)" stroke-width="1.5"></rect>
<text x="330.0" y="70.0" font-size="12" text-anchor="middle" fill="var(--text)">56</text>
<text x="150" y="142" font-size="12" fill="var(--text-muted)">자식이 알려 준 크기대로</text>
</svg>
<figcaption>아이템이 알려 준 크기 48, 80, 56 이 그대로 쓰입니다.</figcaption>
</figure>
<figure class="diagram" data-tab="Grid Layout Group">
<svg viewBox="0 0 680 160" role="img" aria-label="Grid Layout Group: 크기가 다른 아이템 셋을 넣었을 때">
<text x="150" y="20" font-size="12" fill="var(--text)">Grid Layout Group</text>
<rect x="150" y="30" width="400" height="90" rx="4" fill="none" stroke="var(--text)"></rect>
<rect x="158" y="38" width="64" height="64" rx="6" fill="var(--accent-soft)" stroke="var(--accent)" stroke-width="1.5"></rect>
<text x="190.0" y="74.0" font-size="12" text-anchor="middle" fill="var(--text)">48</text>
<rect x="230" y="38" width="64" height="64" rx="6" fill="var(--accent-soft)" stroke="var(--accent)" stroke-width="1.5"></rect>
<text x="262.0" y="74.0" font-size="12" text-anchor="middle" fill="var(--text)">80</text>
<rect x="302" y="38" width="64" height="64" rx="6" fill="var(--accent-soft)" stroke="var(--accent)" stroke-width="1.5"></rect>
<text x="334.0" y="74.0" font-size="12" text-anchor="middle" fill="var(--text)">56</text>
<text x="150" y="142" font-size="12" fill="var(--warn)">자식 크기와 상관없이 전부 Cell Size 64</text>
</svg>
<figcaption>숫자는 아이템이 원래 알려 준 크기인데, 칸은 모두 64 입니다.</figcaption>
</figure>
</x-tabs>

모든 칸이 **Cell Size** 하나로 같아집니다. 인벤토리 칸, 스킬 슬롯, 스테이지 선택 버튼처럼 크기가 같은 것을 늘어놓을 때 씁니다.

<figure class="diagram">
<svg viewBox="0 0 680 312" role="img" aria-label="Grid Layout Group 인스펙터를 옮겨 그린 그림. Padding, Cell Size, Spacing, Start Corner, Start Axis, Child Alignment, Constraint">
<rect x="20" y="14" width="400" height="284" rx="4" stroke="var(--border)" fill="var(--bg)"></rect>
<line x1="20" y1="42" x2="420" y2="42" stroke="var(--border)"></line>
<polygon points="34,24 44,24 39,32" fill="var(--text-muted)"></polygon>
<text x="52" y="33" font-size="13" fill="var(--text)">Grid Layout Group</text>
<text x="36" y="68" font-size="12" fill="var(--text-muted)">Padding</text><rect x="202" y="53" width="204" height="22" rx="3" stroke="var(--border)" fill="var(--bg)"></rect><text x="210" y="68" font-size="12" font-family="var(--font-mono)" fill="var(--text)">8, 8, 8, 8</text>
<text x="36" y="104" font-size="12" fill="var(--text-muted)">Cell Size</text><text x="202" y="104" font-size="11" fill="var(--text-muted)">X</text><rect x="216" y="89" width="76" height="22" rx="3" stroke="var(--border)" fill="var(--bg)"></rect><text x="224" y="104" font-size="12" font-family="var(--font-mono)" fill="var(--text)">64</text><text x="310" y="104" font-size="11" fill="var(--text-muted)">Y</text><rect x="324" y="89" width="82" height="22" rx="3" stroke="var(--border)" fill="var(--bg)"></rect><text x="332" y="104" font-size="12" font-family="var(--font-mono)" fill="var(--text)">64</text>
<text x="36" y="140" font-size="12" fill="var(--text-muted)">Spacing</text><text x="202" y="140" font-size="11" fill="var(--text-muted)">X</text><rect x="216" y="125" width="76" height="22" rx="3" stroke="var(--border)" fill="var(--bg)"></rect><text x="224" y="140" font-size="12" font-family="var(--font-mono)" fill="var(--text)">8</text><text x="310" y="140" font-size="11" fill="var(--text-muted)">Y</text><rect x="324" y="125" width="82" height="22" rx="3" stroke="var(--border)" fill="var(--bg)"></rect><text x="332" y="140" font-size="12" font-family="var(--font-mono)" fill="var(--text)">8</text>
<text x="36" y="176" font-size="12" fill="var(--text-muted)">Start Corner</text><rect x="202" y="161" width="204" height="22" rx="3" stroke="var(--border)" fill="var(--bg)"></rect><text x="210" y="176" font-size="12" font-family="var(--font-mono)" fill="var(--text)">Upper Left</text><polygon points="390,170 398,170 394,175" fill="var(--text-muted)"></polygon>
<text x="36" y="212" font-size="12" fill="var(--text-muted)">Start Axis</text><rect x="202" y="197" width="204" height="22" rx="3" stroke="var(--border)" fill="var(--bg)"></rect><text x="210" y="212" font-size="12" font-family="var(--font-mono)" fill="var(--text)">Horizontal</text><polygon points="390,206 398,206 394,211" fill="var(--text-muted)"></polygon>
<text x="36" y="248" font-size="12" fill="var(--text-muted)">Child Alignment</text><rect x="202" y="233" width="204" height="22" rx="3" stroke="var(--border)" fill="var(--bg)"></rect><text x="210" y="248" font-size="12" font-family="var(--font-mono)" fill="var(--text)">Upper Left</text><polygon points="390,242 398,242 394,247" fill="var(--text-muted)"></polygon>
<text x="36" y="284" font-size="12" fill="var(--text-muted)">Constraint</text><rect x="202" y="269" width="204" height="22" rx="3" stroke="var(--border)" fill="var(--bg)"></rect><text x="210" y="284" font-size="12" font-family="var(--font-mono)" fill="var(--text)">Flexible</text><polygon points="390,278 398,278 394,283" fill="var(--text-muted)"></polygon>
<line x1="410" y1="64" x2="440" y2="64" stroke="var(--border)"></line>
<circle cx="452" cy="64" r="9" stroke="var(--accent)" fill="var(--bg)"></circle>
<text x="452" y="68" font-size="11" text-anchor="middle" fill="var(--accent)">1</text>
<text x="468" y="68" font-size="12" fill="var(--text-muted)">안쪽 여백</text>
<line x1="410" y1="100" x2="440" y2="100" stroke="var(--border)"></line>
<circle cx="452" cy="100" r="9" stroke="var(--accent)" fill="var(--accent)"></circle>
<text x="452" y="104" font-size="11" text-anchor="middle" fill="var(--on-accent)">2</text>
<text x="468" y="104" font-size="12" fill="var(--text)">모든 칸의 크기. 자식 크기는 무시</text>
<line x1="410" y1="136" x2="440" y2="136" stroke="var(--border)"></line>
<circle cx="452" cy="136" r="9" stroke="var(--accent)" fill="var(--bg)"></circle>
<text x="452" y="140" font-size="11" text-anchor="middle" fill="var(--accent)">3</text>
<text x="468" y="140" font-size="12" fill="var(--text-muted)">칸 사이 간격</text>
<line x1="410" y1="172" x2="440" y2="172" stroke="var(--border)"></line>
<circle cx="452" cy="172" r="9" stroke="var(--accent)" fill="var(--bg)"></circle>
<text x="452" y="176" font-size="11" text-anchor="middle" fill="var(--accent)">4</text>
<text x="468" y="176" font-size="12" fill="var(--text-muted)">첫 칸이 놓이는 모서리</text>
<line x1="410" y1="208" x2="440" y2="208" stroke="var(--border)"></line>
<circle cx="452" cy="208" r="9" stroke="var(--accent)" fill="var(--bg)"></circle>
<text x="452" y="212" font-size="11" text-anchor="middle" fill="var(--accent)">5</text>
<text x="468" y="212" font-size="12" fill="var(--text-muted)">가로로 먼저 채울지, 세로로 먼저</text>
<line x1="410" y1="244" x2="440" y2="244" stroke="var(--border)"></line>
<circle cx="452" cy="244" r="9" stroke="var(--accent)" fill="var(--bg)"></circle>
<text x="452" y="248" font-size="11" text-anchor="middle" fill="var(--accent)">6</text>
<text x="468" y="248" font-size="12" fill="var(--text-muted)">칸 묶음 전체의 정렬</text>
<line x1="410" y1="280" x2="440" y2="280" stroke="var(--border)"></line>
<circle cx="452" cy="280" r="9" stroke="var(--accent)" fill="var(--accent)"></circle>
<text x="452" y="284" font-size="11" text-anchor="middle" fill="var(--on-accent)">7</text>
<text x="468" y="284" font-size="12" fill="var(--text)">몇 칸에서 꺾을지</text>
</svg>
<figcaption>Grid Layout Group 인스펙터를 옮겨 그렸습니다. 2 번과 7 번이 Horizontal Layout Group 과 가장 다른 곳입니다.</figcaption>
</figure>

**Constraint** 가 몇 칸에서 줄을 꺾을지 정합니다.

- **Flexible:** 부모 너비에 들어가는 만큼 한 줄에 놓고 꺾습니다. 화면이 넓어지면 한 줄의 칸 수가 늘어납니다
- **Fixed Column Count:** 너비와 상관없이 정한 칸 수에서 꺾습니다. 넓으면 옆이 남고, 좁으면 칸이 부모 밖으로 나갑니다
- **Fixed Row Count:** 줄 수를 고정합니다. 옆으로 스크롤되는 목록에 씁니다

부모 너비와 설정을 바꿔 가며 보면, 칸이 어느 순서로 채워지고 어디서 꺾이는지 보입니다.

<x-grid>
<script type="application/json">
{
  "label": "Grid Layout Group 을 직접 바꿔 보기",
  "count": 10,
  "cell": [
    64,
    64
  ],
  "spacing": [
    8,
    8
  ],
  "padding": 8,
  "height": 240,
  "widths": [
    [
      "좁게",
      240
    ],
    [
      "보통",
      400
    ],
    [
      "넓게",
      560
    ]
  ],
  "fixedColumns": 4,
  "fixedRows": 2,
  "default": {
    "width": 1,
    "constraint": 0,
    "corner": 0,
    "axis": 0,
    "align": 0
  },
  "note": "칸 안 숫자가 하이어라키 순서입니다. 부모 높이는 240 으로 고정해 두었습니다. 계산은 uGUI 의 GridLayoutGroup 과 같습니다."
}
</script>
</x-grid>

- **Child Alignment 는 칸 하나가 아니라 칸 묶음 전체** 를 옮깁니다. Flexible 에서 남는 폭이 한쪽에 몰려 보이면 가운데로 두면 됩니다
- **한 줄의 칸 수를 시안과 똑같이 지켜야 하면 Fixed Column Count** 입니다. Flexible 은 기기마다 칸 수가 달라집니다
- **Start Corner 와 Start Axis** 는 채우는 순서를 바꿉니다. 칸 안 숫자가 하이어라키 순서라, 아이템을 정렬해 넣을 때 무엇이 첫 칸에 오는지가 여기서 정해집니다

### 줄이 늘어나면 높이도 늘려야 한다

위에서 좁게를 누르면 넘친 칸이 생깁니다. **Grid 도 부모 크기는 바꾸지 않습니다.**

스크롤 목록의 종이는 아이템 수만큼 길어져야 하니, 그리드에 **Content Size Fitter** 를 붙이고 **Vertical Fit 을 Preferred Size** 로 둡니다. 그리드의 Preferred 높이는 "지금 너비에서 필요한 줄 수" 로 계산됩니다.

**Horizontal Fit 은 Unconstrained** 로 둡니다. Flexible 그리드의 Preferred 너비는 아이템 수의 제곱근만큼의 칸 수라서, 아이템이 10개면 4칸 폭으로 줄어듭니다.

## 종이와 창: Scroll View

GameObject > UI > Scroll View 로 만들면 이런 구조가 생깁니다.

<figure class="diagram">
<svg viewBox="0 0 680 285" role="img" aria-label="Scroll View 의 하이어라키. Scroll View 에 Scroll Rect, Viewport 에 마스크, Content 에 Grid Layout Group 과 Content Size Fitter 가 붙고 그 아래 아이템들이 있다. Content 는 앵커가 위쪽 가로 stretch, 피벗이 위라 아래로 자란다">
<text x="20" y="40" font-size="13" fill="var(--text)">Scroll View</text>
<text x="20" y="56" font-size="11" fill="var(--text-muted)">Scroll Rect</text>
<text x="42" y="74" font-size="13" fill="var(--text)">Viewport</text>
<text x="42" y="90" font-size="11" fill="var(--text-muted)">RectMask2D 또는 Mask</text>
<text x="64" y="108" font-size="13" fill="var(--accent)">Content</text>
<text x="64" y="124" font-size="11" fill="var(--text-muted)">Grid Layout Group, Content Size Fitter</text>
<text x="86" y="142" font-size="13" fill="var(--text-muted)">아이템 1</text>
<text x="86" y="176" font-size="13" fill="var(--text-muted)">아이템 2</text>
<text x="86" y="210" font-size="13" fill="var(--text-muted)">...</text>
<rect x="390" y="40" width="140" height="210" fill="var(--bg)" stroke="var(--accent)" stroke-dasharray="4 4"></rect>
<rect x="402" y="50" width="116" height="36" rx="5" fill="var(--accent-soft)" stroke="var(--accent)" stroke-opacity="0.3" fill-opacity="0.3"></rect>
<rect x="402" y="96" width="116" height="36" rx="5" fill="var(--accent-soft)" stroke="var(--accent)" stroke-opacity="1" fill-opacity="1"></rect>
<rect x="402" y="142" width="116" height="36" rx="5" fill="var(--accent-soft)" stroke="var(--accent)" stroke-opacity="1" fill-opacity="1"></rect>
<rect x="402" y="188" width="116" height="36" rx="5" fill="var(--accent-soft)" stroke="var(--accent)" stroke-opacity="1" fill-opacity="1"></rect>
<rect x="380" y="70" width="160" height="140" rx="4" fill="none" stroke="var(--text)" stroke-width="2.5"></rect>
<circle cx="390" cy="40" r="4" stroke="var(--warn)" stroke-width="2" fill="var(--bg)"></circle>
<polygon points="460.0,33 467.0,40 460.0,47 453.0,40" fill="var(--accent)"></polygon>
<line x1="460.0" y1="252" x2="460.0" y2="270" stroke="var(--accent)" stroke-width="2"></line>
<text x="550" y="44" font-size="11" fill="var(--text-muted)">피벗 위</text>
<text x="550" y="60" font-size="11" fill="var(--text-muted)">앵커 위 stretch</text>
<text x="550" y="140.0" font-size="11" fill="var(--text)">창</text>
<text x="550" y="240" font-size="11" fill="var(--accent)">아래로 자람</text>
</svg>
<figcaption>Content 가 종이, Viewport 가 창입니다. Content 는 피벗이 위라서 아이템이 늘면 아래로만 자랍니다.</figcaption>
</figure>

- **Scroll View** 에 붙은 **Scroll Rect** 가 끌기와 튕기기를 맡습니다
- **Viewport** 가 창입니다. 이 크기가 곧 보이는 범위이고, 마스크가 붙어 창 밖을 가립니다
- **Content** 가 종이입니다. 앵커는 위쪽 가로 stretch, 피벗은 위입니다. 앞에서 본 대로 크기는 피벗을 중심으로 바뀌니, 아이템이 늘어도 윗부분은 제자리이고 아래로만 길어집니다

처음 만들어진 Content 는 높이가 정해진 값이라, 위 절처럼 Content Size Fitter 로 아이템 수에 맞춰야 합니다.

<figure class="diagram">
<svg viewBox="0 0 680 384" role="img" aria-label="Scroll Rect 인스펙터를 옮겨 그린 그림. Content, Horizontal, Vertical, Movement Type, Elasticity, Inertia, Deceleration Rate, Scroll Sensitivity, Viewport">
<rect x="20" y="14" width="400" height="356" rx="4" stroke="var(--border)" fill="var(--bg)"></rect>
<line x1="20" y1="42" x2="420" y2="42" stroke="var(--border)"></line>
<polygon points="34,24 44,24 39,32" fill="var(--text-muted)"></polygon>
<text x="52" y="33" font-size="13" fill="var(--text)">Scroll Rect</text>
<text x="36" y="68" font-size="12" fill="var(--text-muted)">Content</text><rect x="202" y="53" width="204" height="22" rx="3" stroke="var(--border)" fill="var(--bg)"></rect><text x="210" y="68" font-size="12" font-family="var(--font-mono)" fill="var(--text)">Content (Rect Transform)</text>
<text x="36" y="104" font-size="12" fill="var(--text-muted)">Horizontal</text><rect x="202" y="92" width="16" height="16" rx="3" stroke="var(--text-muted)" fill="var(--accent)"></rect><polyline points="206,100 209,104 214,96" fill="none" stroke="var(--on-accent)" stroke-width="2"></polyline>
<text x="36" y="140" font-size="12" fill="var(--text-muted)">Vertical</text><rect x="202" y="128" width="16" height="16" rx="3" stroke="var(--text-muted)" fill="var(--accent)"></rect><polyline points="206,136 209,140 214,132" fill="none" stroke="var(--on-accent)" stroke-width="2"></polyline>
<text x="36" y="176" font-size="12" fill="var(--text-muted)">Movement Type</text><rect x="202" y="161" width="204" height="22" rx="3" stroke="var(--border)" fill="var(--bg)"></rect><text x="210" y="176" font-size="12" font-family="var(--font-mono)" fill="var(--text)">Elastic</text><polygon points="390,170 398,170 394,175" fill="var(--text-muted)"></polygon>
<text x="36" y="212" font-size="12" fill="var(--text-muted)">Elasticity</text><rect x="202" y="197" width="204" height="22" rx="3" stroke="var(--border)" fill="var(--bg)"></rect><text x="210" y="212" font-size="12" font-family="var(--font-mono)" fill="var(--text)">0.1</text>
<text x="36" y="248" font-size="12" fill="var(--text-muted)">Inertia</text><rect x="202" y="236" width="16" height="16" rx="3" stroke="var(--text-muted)" fill="var(--accent)"></rect><polyline points="206,244 209,248 214,240" fill="none" stroke="var(--on-accent)" stroke-width="2"></polyline>
<text x="36" y="284" font-size="12" fill="var(--text-muted)">Deceleration Rate</text><rect x="202" y="269" width="204" height="22" rx="3" stroke="var(--border)" fill="var(--bg)"></rect><text x="210" y="284" font-size="12" font-family="var(--font-mono)" fill="var(--text)">0.135</text>
<text x="36" y="320" font-size="12" fill="var(--text-muted)">Scroll Sensitivity</text><rect x="202" y="305" width="204" height="22" rx="3" stroke="var(--border)" fill="var(--bg)"></rect><text x="210" y="320" font-size="12" font-family="var(--font-mono)" fill="var(--text)">1</text>
<text x="36" y="356" font-size="12" fill="var(--text-muted)">Viewport</text><rect x="202" y="341" width="204" height="22" rx="3" stroke="var(--border)" fill="var(--bg)"></rect><text x="210" y="356" font-size="12" font-family="var(--font-mono)" fill="var(--text)">Viewport (Rect Transform)</text>
<line x1="410" y1="64" x2="440" y2="64" stroke="var(--border)"></line>
<circle cx="452" cy="64" r="9" stroke="var(--accent)" fill="var(--bg)"></circle>
<text x="452" y="68" font-size="11" text-anchor="middle" fill="var(--accent)">1</text>
<text x="468" y="68" font-size="12" fill="var(--text-muted)">움직일 종이</text>
<line x1="410" y1="100" x2="440" y2="100" stroke="var(--border)"></line>
<circle cx="452" cy="100" r="9" stroke="var(--accent)" fill="var(--accent)"></circle>
<text x="452" y="104" font-size="11" text-anchor="middle" fill="var(--on-accent)">2</text>
<text x="468" y="104" font-size="12" fill="var(--text)">가로로도 움직일지</text>
<line x1="410" y1="136" x2="440" y2="136" stroke="var(--border)"></line>
<circle cx="452" cy="136" r="9" stroke="var(--accent)" fill="var(--bg)"></circle>
<text x="452" y="140" font-size="11" text-anchor="middle" fill="var(--accent)">3</text>
<text x="468" y="140" font-size="12" fill="var(--text-muted)">세로로 움직일지</text>
<line x1="410" y1="172" x2="440" y2="172" stroke="var(--border)"></line>
<circle cx="452" cy="172" r="9" stroke="var(--accent)" fill="var(--accent)"></circle>
<text x="452" y="176" font-size="11" text-anchor="middle" fill="var(--on-accent)">4</text>
<text x="468" y="176" font-size="12" fill="var(--text)">끝에서 어떻게 할지</text>
<line x1="410" y1="208" x2="440" y2="208" stroke="var(--border)"></line>
<circle cx="452" cy="208" r="9" stroke="var(--accent)" fill="var(--bg)"></circle>
<text x="452" y="212" font-size="11" text-anchor="middle" fill="var(--accent)">5</text>
<text x="468" y="212" font-size="12" fill="var(--text-muted)">끝을 넘었다 돌아오는 시간</text>
<line x1="410" y1="244" x2="440" y2="244" stroke="var(--border)"></line>
<circle cx="452" cy="244" r="9" stroke="var(--accent)" fill="var(--accent)"></circle>
<text x="452" y="248" font-size="11" text-anchor="middle" fill="var(--on-accent)">6</text>
<text x="468" y="248" font-size="12" fill="var(--text)">손을 뗀 뒤 미끄러질지</text>
<line x1="410" y1="280" x2="440" y2="280" stroke="var(--border)"></line>
<circle cx="452" cy="280" r="9" stroke="var(--accent)" fill="var(--bg)"></circle>
<text x="452" y="284" font-size="11" text-anchor="middle" fill="var(--accent)">7</text>
<text x="468" y="284" font-size="12" fill="var(--text-muted)">1초 뒤 남는 속도의 비율</text>
<line x1="410" y1="316" x2="440" y2="316" stroke="var(--border)"></line>
<circle cx="452" cy="316" r="9" stroke="var(--accent)" fill="var(--bg)"></circle>
<text x="452" y="320" font-size="11" text-anchor="middle" fill="var(--accent)">8</text>
<text x="468" y="320" font-size="12" fill="var(--text-muted)">마우스 휠, 트랙패드 감도</text>
<line x1="410" y1="352" x2="440" y2="352" stroke="var(--border)"></line>
<circle cx="452" cy="352" r="9" stroke="var(--accent)" fill="var(--bg)"></circle>
<text x="452" y="356" font-size="11" text-anchor="middle" fill="var(--accent)">9</text>
<text x="468" y="356" font-size="12" fill="var(--text-muted)">창. 보이는 범위</text>
</svg>
<figcaption>Scroll Rect 인스펙터를 옮겨 그렸습니다. 2 번, 4 번, 6 번이 목록의 손맛을 정합니다.</figcaption>
</figure>

**2 번 Horizontal 은 기본으로 켜져 있습니다.** 세로 목록인데 켜 두면 옆으로도 조금씩 흔들리니 끕니다.

4 번부터 7 번은 말로 설명하기보다 직접 끌어 보는 편이 빠릅니다.

<x-scroll>
<script type="application/json">
{
  "label": "Scroll View 를 끌어 보기",
  "items": 12,
  "rowHeight": 40,
  "spacing": 4,
  "view": [
    240,
    200
  ],
  "default": {
    "movement": 0,
    "inertia": true,
    "mask": true,
    "action": 0
  },
  "note": "종이 위치 0 이 맨 위, 324 가 맨 아래입니다. Elasticity 0.1 과 Deceleration Rate 0.135 는 Unity 기본값입니다. 움직임은 uGUI ScrollRect 의 계산을 따라 했습니다."
}
</script>
</x-scroll>

- **Elastic:** 끝에서 고무줄처럼 버팁니다. 당길수록 무거워져서 손가락만큼 따라오지 않고, 놓으면 돌아옵니다. **Elasticity** 가 작을수록 빨리 돌아옵니다
- **Clamped:** 끝에서 딱 멈춥니다
- **Unrestricted:** 끝이 없습니다. 목록보다는 큰 지도처럼 경계가 없는 화면에 씁니다
- **Inertia** 를 켜면 손을 뗀 뒤에도 미끄러집니다. **Deceleration Rate** 0.135 는 1초 뒤 속도가 13.5 퍼센트 남는다는 뜻입니다. 0 에 가까울수록 금방 멈추고, 1 에 가까울수록 오래 미끄러집니다
- 위에서 **마스크를 끄면** 창 밖의 종이가 그대로 보입니다. 다음 절의 가림막이 하는 일입니다

## 가림막: Mask 와 RectMask2D

창 밖을 가리는 컴포넌트는 둘입니다. 자르는 모양이 다릅니다.

<x-tabs>
<figure class="diagram" data-tab="Mask">
<svg viewBox="0 0 680 250" role="img" aria-label="Mask: 동그란 틀 이미지에 Mask 를 붙이면 자식인 사각형 초상화가 틀 모양대로 동그랗게 잘린다. Show Mask Graphic 을 끄면 틀 자체는 안 보이고 모양만 쓰인다">
<defs><clipPath id="m5-circle"><circle cx="520" cy="120" r="70"></circle></clipPath></defs>
<text x="30" y="30" font-size="13" fill="var(--text)">틀 (Image + Mask)</text>
<circle cx="100" cy="120" r="70" fill="var(--bg)" stroke="var(--text)" stroke-width="2"></circle>
<text x="100" y="212" font-size="11" text-anchor="middle" fill="var(--text-muted)">동그란 이미지</text>
<text x="220" y="124" font-size="20" text-anchor="middle" fill="var(--text-muted)">+</text>
<text x="250" y="30" font-size="13" fill="var(--text)">자식 (사각 초상화)</text>
<g opacity="1"><rect x="260" y="50" width="140" height="140" fill="var(--accent-soft)" stroke="var(--accent)"></rect><circle cx="330.0" cy="108.8" r="25.2" fill="var(--accent)" fill-opacity="0.6"></circle><rect x="290.8" y="142.4" width="78.4" height="47.6" rx="28.0" fill="var(--accent)" fill-opacity="0.6"></rect></g>
<line x1="416" y1="120" x2="436" y2="120" stroke="var(--text-muted)" stroke-width="1.5"></line><polygon points="436,115 444,120 436,125" fill="var(--text-muted)"></polygon>
<text x="460" y="30" font-size="13" fill="var(--text)">결과</text>
<g opacity="0.15"><rect x="450" y="50" width="140" height="140" fill="var(--accent-soft)" stroke="var(--accent)"></rect><circle cx="520.0" cy="108.8" r="25.2" fill="var(--accent)" fill-opacity="0.6"></circle><rect x="480.8" y="142.4" width="78.4" height="47.6" rx="28.0" fill="var(--accent)" fill-opacity="0.6"></rect></g>
<g clip-path="url(#m5-circle)"><g opacity="1"><rect x="450" y="50" width="140" height="140" fill="var(--accent-soft)" stroke="var(--accent)"></rect><circle cx="520.0" cy="108.8" r="25.2" fill="var(--accent)" fill-opacity="0.6"></circle><rect x="480.8" y="142.4" width="78.4" height="47.6" rx="28.0" fill="var(--accent)" fill-opacity="0.6"></rect></g></g>
<circle cx="520" cy="120" r="70" fill="none" stroke="var(--text)" stroke-width="2"></circle>
<text x="520" y="212" font-size="11" text-anchor="middle" fill="var(--text-muted)">흐린 부분은 잘려서 안 보임</text>
<text x="30" y="240" font-size="12" fill="var(--text-muted)">틀 이미지의 모양대로 자릅니다. Show Mask Graphic 을 끄면 틀은 안 그리고 모양만 씁니다.</text>
</svg>
<figcaption>동그라미, 둥근 모서리처럼 사각형이 아닌 모양으로 자를 때 씁니다.</figcaption>
</figure>
<figure class="diagram" data-tab="RectMask2D">
<svg viewBox="0 0 680 270" role="img" aria-label="RectMask2D: 사각형 창 밖으로 나간 목록 줄은 잘리고, Softness 를 주면 창 위아래 가장자리가 흐리게 사라진다">
<defs><linearGradient id="r5-fade" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stop-color="#fff" stop-opacity="0"></stop><stop offset="0.16" stop-color="#fff" stop-opacity="1"></stop><stop offset="0.84" stop-color="#fff" stop-opacity="1"></stop><stop offset="1" stop-color="#fff" stop-opacity="0"></stop></linearGradient><mask id="r5-soft" maskUnits="userSpaceOnUse" x="420" y="60" width="200" height="150"><rect x="420" y="60" width="200" height="150" fill="url(#r5-fade)"></rect></mask><clipPath id="r5-hard"><rect x="120" y="60" width="200" height="150"></rect></clipPath></defs>
<text x="120" y="20" font-size="13" fill="var(--text)">Softness 0</text>
<rect x="132" y="30" width="176" height="32" rx="5" fill="var(--accent-soft)" stroke="var(--accent)" opacity="0.12"></rect><text x="148" y="51" font-size="12" fill="var(--text)" opacity="0.12">아이템 1</text><rect x="132" y="70" width="176" height="32" rx="5" fill="var(--accent-soft)" stroke="var(--accent)" opacity="0.12"></rect><text x="148" y="91" font-size="12" fill="var(--text)" opacity="0.12">아이템 2</text><rect x="132" y="110" width="176" height="32" rx="5" fill="var(--accent-soft)" stroke="var(--accent)" opacity="0.12"></rect><text x="148" y="131" font-size="12" fill="var(--text)" opacity="0.12">아이템 3</text><rect x="132" y="150" width="176" height="32" rx="5" fill="var(--accent-soft)" stroke="var(--accent)" opacity="0.12"></rect><text x="148" y="171" font-size="12" fill="var(--text)" opacity="0.12">아이템 4</text><rect x="132" y="190" width="176" height="32" rx="5" fill="var(--accent-soft)" stroke="var(--accent)" opacity="0.12"></rect><text x="148" y="211" font-size="12" fill="var(--text)" opacity="0.12">아이템 5</text><rect x="132" y="230" width="176" height="32" rx="5" fill="var(--accent-soft)" stroke="var(--accent)" opacity="0.12"></rect><text x="148" y="251" font-size="12" fill="var(--text)" opacity="0.12">아이템 6</text>
<g clip-path="url(#r5-hard)"><rect x="132" y="30" width="176" height="32" rx="5" fill="var(--accent-soft)" stroke="var(--accent)" opacity="1"></rect><text x="148" y="51" font-size="12" fill="var(--text)" opacity="1">아이템 1</text><rect x="132" y="70" width="176" height="32" rx="5" fill="var(--accent-soft)" stroke="var(--accent)" opacity="1"></rect><text x="148" y="91" font-size="12" fill="var(--text)" opacity="1">아이템 2</text><rect x="132" y="110" width="176" height="32" rx="5" fill="var(--accent-soft)" stroke="var(--accent)" opacity="1"></rect><text x="148" y="131" font-size="12" fill="var(--text)" opacity="1">아이템 3</text><rect x="132" y="150" width="176" height="32" rx="5" fill="var(--accent-soft)" stroke="var(--accent)" opacity="1"></rect><text x="148" y="171" font-size="12" fill="var(--text)" opacity="1">아이템 4</text><rect x="132" y="190" width="176" height="32" rx="5" fill="var(--accent-soft)" stroke="var(--accent)" opacity="1"></rect><text x="148" y="211" font-size="12" fill="var(--text)" opacity="1">아이템 5</text><rect x="132" y="230" width="176" height="32" rx="5" fill="var(--accent-soft)" stroke="var(--accent)" opacity="1"></rect><text x="148" y="251" font-size="12" fill="var(--text)" opacity="1">아이템 6</text></g>
<rect x="120" y="60" width="200" height="150" fill="none" stroke="var(--text)" stroke-width="2"></rect>
<text x="420" y="20" font-size="13" fill="var(--text)">Softness Y 24</text>
<rect x="432" y="30" width="176" height="32" rx="5" fill="var(--accent-soft)" stroke="var(--accent)" opacity="0.12"></rect><text x="448" y="51" font-size="12" fill="var(--text)" opacity="0.12">아이템 1</text><rect x="432" y="70" width="176" height="32" rx="5" fill="var(--accent-soft)" stroke="var(--accent)" opacity="0.12"></rect><text x="448" y="91" font-size="12" fill="var(--text)" opacity="0.12">아이템 2</text><rect x="432" y="110" width="176" height="32" rx="5" fill="var(--accent-soft)" stroke="var(--accent)" opacity="0.12"></rect><text x="448" y="131" font-size="12" fill="var(--text)" opacity="0.12">아이템 3</text><rect x="432" y="150" width="176" height="32" rx="5" fill="var(--accent-soft)" stroke="var(--accent)" opacity="0.12"></rect><text x="448" y="171" font-size="12" fill="var(--text)" opacity="0.12">아이템 4</text><rect x="432" y="190" width="176" height="32" rx="5" fill="var(--accent-soft)" stroke="var(--accent)" opacity="0.12"></rect><text x="448" y="211" font-size="12" fill="var(--text)" opacity="0.12">아이템 5</text><rect x="432" y="230" width="176" height="32" rx="5" fill="var(--accent-soft)" stroke="var(--accent)" opacity="0.12"></rect><text x="448" y="251" font-size="12" fill="var(--text)" opacity="0.12">아이템 6</text>
<g mask="url(#r5-soft)"><rect x="432" y="30" width="176" height="32" rx="5" fill="var(--accent-soft)" stroke="var(--accent)" opacity="1"></rect><text x="448" y="51" font-size="12" fill="var(--text)" opacity="1">아이템 1</text><rect x="432" y="70" width="176" height="32" rx="5" fill="var(--accent-soft)" stroke="var(--accent)" opacity="1"></rect><text x="448" y="91" font-size="12" fill="var(--text)" opacity="1">아이템 2</text><rect x="432" y="110" width="176" height="32" rx="5" fill="var(--accent-soft)" stroke="var(--accent)" opacity="1"></rect><text x="448" y="131" font-size="12" fill="var(--text)" opacity="1">아이템 3</text><rect x="432" y="150" width="176" height="32" rx="5" fill="var(--accent-soft)" stroke="var(--accent)" opacity="1"></rect><text x="448" y="171" font-size="12" fill="var(--text)" opacity="1">아이템 4</text><rect x="432" y="190" width="176" height="32" rx="5" fill="var(--accent-soft)" stroke="var(--accent)" opacity="1"></rect><text x="448" y="211" font-size="12" fill="var(--text)" opacity="1">아이템 5</text><rect x="432" y="230" width="176" height="32" rx="5" fill="var(--accent-soft)" stroke="var(--accent)" opacity="1"></rect><text x="448" y="251" font-size="12" fill="var(--text)" opacity="1">아이템 6</text></g>
<rect x="420" y="60" width="200" height="150" fill="none" stroke="var(--text)" stroke-width="2"></rect>
<text x="20" y="140" font-size="12" fill="var(--text-muted)">창 (Viewport)</text>
<text x="120" y="258" font-size="12" fill="var(--text-muted)">가장자리가 칼로 자른 듯</text>
<text x="420" y="258" font-size="12" fill="var(--text-muted)">위아래가 흐리게 사라진다</text>
</svg>
<figcaption>사각형으로만 자릅니다. 대신 가장자리를 흐리게 할 수 있고 더 가볍습니다.</figcaption>
</figure>
</x-tabs>

**Mask** 는 붙은 오브젝트의 **이미지 모양대로** 자식을 자릅니다.

- 동그란 초상화, 둥근 모서리 카드처럼 **사각형이 아닌 모양** 을 만들 수 있습니다
- GPU 의 스텐실이라는 방식을 써서 **가장자리가 딱딱합니다.** 흐리게 할 수 없습니다
- 마스크를 그리고 되돌리는 그리기가 추가되고, 마스크 안의 요소는 밖의 요소와 배칭이 갈립니다

**RectMask2D** 는 RectTransform **사각형으로만** 자릅니다.

- 이미지가 필요 없습니다
- **Softness** 로 가장자리를 흐리게, **Padding** 으로 자르는 사각형을 안쪽으로 줄일 수 있습니다
- 추가 그리기가 없고, **창 밖으로 완전히 나간 요소는 아예 그리지 않습니다.** 아이템이 많은 긴 목록에 유리합니다
- 같은 평면에 있는 2D 요소만 제대로 자릅니다. 3D 로 기울인 요소에는 맞지 않습니다

고르는 법은 간단합니다. **스크롤 창처럼 사각형이면 RectMask2D, 사각형이 아닌 모양이면 Mask** 입니다.
Mask 로 자르면서 가장자리까지 흐리게 하고 싶다면 기본 컴포넌트로는 안 되고, 부드러운 마스크를 만들어 주는 플러그인이 필요합니다.

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

| 적어 줄 것 | 무엇이 정해지나 |
| --- | --- |
| **한 줄에 몇 칸인지**, 화면이 넓어지면 칸 수가 늘어나는지 | Constraint (Flexible 또는 Fixed Column Count) |
| **칸 크기와 간격**, 칸 묶음이 어느 쪽에 붙는지 | Cell Size, Spacing, Child Alignment |
| 아이템이 **어느 모서리부터 어떤 순서로** 채워지는지 | Start Corner, Start Axis |
| **어느 방향으로** 스크롤되는지 | Scroll Rect 의 Horizontal, Vertical |
| 끝에서 **튕기는지 멈추는지**, 손을 떼면 **얼마나 미끄러지는지** | Movement Type, Elasticity, Inertia, Deceleration Rate |
| **창의 모양** 과 가장자리를 흐리게 할지 | RectMask2D 의 Softness, 또는 Mask |

미끄러지는 느낌은 글로 전하기 어렵습니다. 비슷한 느낌의 게임이나 앱을 예로 들어 주면 맞추기 쉽습니다.

## 정리

- 스크롤 목록은 **칸(Grid Layout Group), 종이(Content), 창(Viewport)** 에 **가림막(마스크)** 을 더한 것입니다
- Grid Layout Group 은 **자식 크기를 무시하고 모두 Cell Size** 로 만듭니다. **Constraint** 가 몇 칸에서 꺾을지 정합니다
- 그리드도 부모 크기는 안 바꿉니다. 종이 높이는 **Content Size Fitter 의 Vertical Fit Preferred Size** 로 늘립니다
- Content 는 **피벗이 위** 라서 아래로 자랍니다. 세로 목록이면 Scroll Rect 의 Horizontal 을 끕니다
- 끝에서의 동작은 **Movement Type**, 손을 뗀 뒤의 미끄러짐은 **Inertia 와 Deceleration Rate** 가 정합니다
- **사각형 창은 RectMask2D, 다른 모양은 Mask** 입니다. RectMask2D 는 가볍고 가장자리를 흐리게 할 수 있습니다