---
title: "합치는 비용이 그리는 비용보다 클 때"
description: "다이나믹 배칭은 매 프레임 CPU 가 메시를 합칩니다. 그 부등호가 요즘 하드웨어에서 자주 뒤집혀서, URP 에서 우선순위가 내려갔습니다."
author: "유니얼"
pubDate: 2026-09-09
category: "game-dev/unity/rendering"
tags: ["Unity", "최적화", "Batching"]
canonical: https://blog.unialgames.com/posts/unity-dynamic-batching/
---
같은 스프라이트를 쓰는 총알 200발이 화면에 있습니다.
텍스처도 같고 머티리얼도 같습니다. 그런데 GameObject 가 200개라 **메시는 200개** 입니다.
그리라는 명령도 200번 나갑니다.

다이나믹 배칭은 여기에 이렇게 답합니다. **그러면 하나로 합쳐서 한 번에 그리자.**

## 합친다는 것의 의미

<figure class="diagram">
<svg viewBox="0 0 680 250" role="img" aria-label="배칭 전에는 사각형 여덟 개가 각각 그리기 명령을 내고, 배칭 후에는 하나의 병합 메시가 한 번의 그리기 명령을 낸다는 그림">
<text x="20" y="24" font-size="13" fill="var(--text-muted)">배칭 없음</text>
<g stroke="var(--border)" fill="var(--bg)">
<rect x="20" y="40" width="34" height="34"></rect>
<rect x="62" y="40" width="34" height="34"></rect>
<rect x="104" y="40" width="34" height="34"></rect>
<rect x="146" y="40" width="34" height="34"></rect>
<rect x="20" y="82" width="34" height="34"></rect>
<rect x="62" y="82" width="34" height="34"></rect>
<rect x="104" y="82" width="34" height="34"></rect>
<rect x="146" y="82" width="34" height="34"></rect>
</g>
<g stroke="var(--text-muted)" fill="none">
<path d="M190 57 L236 57"></path>
<path d="M190 99 L236 99"></path>
</g>
<text x="200" y="50" font-size="11" fill="var(--text-muted)">x8</text>
<g stroke="var(--warn)" fill="none">
<rect x="240" y="42" width="86" height="70" rx="4"></rect>
</g>
<text x="252" y="72" font-size="13" fill="var(--warn)">Draw x 8</text>
<text x="252" y="94" font-size="12" fill="var(--text-muted)">명령 8회</text>
<text x="20" y="164" font-size="13" fill="var(--text-muted)">다이나믹 배칭</text>
<g stroke="var(--border)" fill="var(--bg)">
<rect x="20" y="180" width="34" height="34"></rect>
<rect x="62" y="180" width="34" height="34"></rect>
<rect x="104" y="180" width="34" height="34"></rect>
<rect x="146" y="180" width="34" height="34"></rect>
</g>
<g stroke="var(--accent)" fill="var(--accent-soft)">
<rect x="240" y="176" width="86" height="42" rx="4"></rect>
</g>
<text x="252" y="202" font-size="13" fill="var(--accent)">Draw x 1</text>
<g stroke="var(--accent)" fill="none">
<path d="M190 197 L236 197"></path>
</g>
<text x="196" y="190" font-size="11" fill="var(--accent)">CPU 가 합침</text>
<text x="360" y="60" font-size="13" fill="var(--text-muted)">배칭은 이 사각형들의 정점을</text>
<text x="360" y="80" font-size="13" fill="var(--text-muted)">월드 공간으로 변환해서</text>
<text x="360" y="100" font-size="13" fill="var(--text-muted)">하나의 버퍼에 이어 붙이는 일입니다</text>
<text x="360" y="140" font-size="13" fill="var(--warn)">그 변환과 병합을</text>
<text x="360" y="160" font-size="13" fill="var(--warn)">매 프레임 CPU 가 합니다</text>
<text x="360" y="196" font-size="12" fill="var(--text-muted)">그리기 명령은 줄었지만</text>
<text x="360" y="214" font-size="12" fill="var(--text-muted)">일이 사라진 것은 아닙니다</text>
</svg>
<figcaption>드로우 콜은 8에서 1로 줄었고, 대신 정점을 옮기는 일이 매 프레임 생겼습니다.</figcaption>
</figure>

각 오브젝트의 메시는 자기 로컬 좌표계에 있습니다. 한 버퍼에 이어 붙이려면
전부 같은 좌표계로 옮겨야 합니다. 그래서 배칭은 **정점을 월드 공간으로 변환하는 일** 입니다.

정점이 몇 개 안 되면 이건 싼 작업입니다. 스프라이트 하나는 사각형이라 정점 4개뿐입니다.
총알 200발이면 800개 정점을 옮기고 그리기 명령 199번을 아낍니다. 남는 장사입니다.

## 부등호

그래서 이 조건이 전부입니다.

> **합치는 비용 < 그리기 명령 비용** 일 때만 이득입니다.

왼쪽은 정점 수에 비례해서 커지고, 오른쪽은 하드웨어와 그래픽스 API 가 정합니다.
그리고 **오른쪽이 계속 싸지고 있습니다.** 요즘 API 는 드로우 콜 하나를 넘기는 비용이
예전보다 훨씬 낮습니다. 부등호가 뒤집히기 좋은 조건입니다.

<x-calc>
<script type="application/json">
{
  "label": "부등호가 어디서 뒤집히는지 보기",
  "inputs": [
    { "id": "n", "label": "오브젝트 수", "options": [10, 50, 200, 800], "default": 200, "suffix": "개" },
    { "id": "v", "label": "하나당 정점 수", "options": [4, 40, 200], "default": 4, "suffix": "개" },
    { "id": "d", "label": "그리기 명령 하나 비용", "options": [["요즘 하드웨어", 1], ["예전 하드웨어", 6]], "default": 1 }
  ],
  "bars": [
    { "label": "그냥 그리기", "expr": "n * d", "unit": "단위" },
    { "label": "합쳐서 그리기", "expr": "n * v * 0.05 + d", "unit": "단위", "accent": true }
  ],
  "verdict": { "expr": "bars[1] < bars[0]", "yes": "합치는 쪽이 이득", "no": "합치는 쪽이 손해" },
  "note": "실제 밀리초가 아니라 부등호가 어느 쪽으로 기우는지만 보는 그림입니다. 정점이 많아질수록, 그리기 명령이 쌀수록 합치기가 불리해집니다."
}
</script>
</x-calc>

정점 4개짜리 스프라이트는 몇 개를 놓든 합치는 쪽이 이깁니다.
정점 40개만 돼도 요즘 하드웨어에서는 뒤집힙니다.
그리고 예전 하드웨어로 바꾸면 다시 합치는 쪽이 이깁니다.
**"다이나믹 배칭은 좋다" 는 문장에 유통기한이 있었다는 뜻입니다.**

## 조건

이득이든 손해든, 애초에 배칭이 걸리려면 조건을 만족해야 합니다.

- **같은 머티리얼** 이어야 합니다. 텍스처가 다르면 다른 머티리얼입니다
- **정점 수 제한** 이 있습니다. 정점 특성 개수에 따라 상한이 정해집니다.
  스프라이트는 여유롭게 통과하지만 조금만 복잡한 메시면 걸립니다
- 스케일이 음수로 뒤집힌 오브젝트, 라이트맵이 다른 오브젝트 등은 빠집니다

조건을 못 맞춘 오브젝트는 조용히 빠져서 개별로 그려집니다.
에러가 안 나기 때문에, 배칭이 걸린다고 믿고 있는데 실제로는 안 걸린 상태가 흔합니다.
Frame Debugger 를 열어서 확인하는 게 유일한 방법입니다.

## Unity 6 에서의 위치

URP 에서 다이나믹 배칭은 **우선순위가 내려갔습니다.** 기본 주력이 아닙니다.
위의 부등호가 자주 뒤집히기 때문입니다.

다만 **꺼진 것은 아닙니다.** 주력 방식이 처리하지 못하는 오브젝트에 대해
폴백으로 계속 돕니다. 그러니 "다이나믹 배칭은 이제 안 쓴다" 도 정확한 말이 아닙니다.
프로젝트 설정에서 끄고 켤 수 있고, 2D 처럼 정점이 적은 콘텐츠에서는
켜 두는 쪽이 이득인 경우가 남아 있습니다.