게임 플레이 UI 최적화: 입력 지연부터 드로우콜까지

게임 플레이 인터페이스를 빠르고 읽기 쉽게 유지하기 위한 측정 방법, 구조 설계, 엔진별 구현 힌트를 정리합니다. HUD·인벤토리·월드 공간 UI에서 자주 발생하는 병목과 대응 사례를 다룹니다.

✓ 복사 완료!
챕터GPU & 드로우콜/배칭 최적화
난이도중급
상태● 검토 완료
대상 엔진
UnityUnreal Engine
최종 업데이트
게임 플레이 UI 최적화: 입력 지연부터 드로우콜까지

UI 최적화는 ‘보이는 것’과 ‘그리는 것’을 함께 다룬다

게임 플레이 UI는 체력바, 조준점, 퀘스트 추적, 피해 수치처럼 화면에 오래 남아 있고 자주 갱신된다. 따라서 UI 최적화는 단순히 프레임을 올리는 작업이 아니다. 필요한 정보를 적절한 순간에 읽히게 하고 입력 반응과 렌더링 비용을 예측 가능하게 만드는 일이다.

특히 저사양 기기나 스위치 같은 제한된 하드웨어에서는 UI가 작은 비용처럼 보여도 누적되기 쉽다. 투명 패널의 중첩, 전체 레이아웃 재계산, 빈번한 텍스트 변경, 월드 공간 체력바의 과도한 생성이 대표적인 원인이다.

전투 중 체력바와 탄약 표시, 퀘스트 추적 UI가 배치된 게임 화면 예시

먼저 프레임이 아니라 프레임 타임을 측정한다

평균 FPS만 보면 짧은 끊김을 놓치기 쉽다. UI를 열거나 알림이 쌓이는 순간에 CPU와 GPU 시간이 튀는지 확인해야 한다. 프로파일링할 때는 다음 장면을 따로 재현하는 편이 좋다.

  • HUD만 표시한 전투 장면
  • 인벤토리를 열고 빠르게 스크롤하는 장면
  • 다수 적의 체력바와 피해 숫자가 동시에 나타나는 장면
  • 해상도와 UI 스케일을 바꾼 장면

측정 순서는 단순하다. 증상을 재현하고 CPU·GPU·메모리 중 어느 쪽이 병목인지 확인한 뒤 가장 큰 비용 하나를 줄이고 다시 측정한다. 여러 항목을 한 번에 고치면 효과의 원인을 알기 어렵다.

flowchart TD
    A[문제가 보이는 플레이 장면 재현] --> B[프레임 타임과 프로파일러 기록]
    B --> C{주 병목은?}
    C -->|CPU| D[레이아웃·스크립트·텍스트 갱신 점검]
    C -->|GPU| E[오버드로우·마스크·머티리얼 점검]
    C -->|메모리| F[생성·파괴와 문자열 할당 점검]
    D --> G[한 가지 변경 후 재측정]
    E --> G
    F --> G

사례 1: HUD 전체를 매 프레임 갱신하지 않는다

체력, 탄약, 쿨다운은 매 프레임 값을 대입하기보다 값이 실제로 바뀔 때만 갱신한다. 게이지가 부드럽게 움직여야 한다면 표시용 보간은 매 프레임 수행하되 텍스트·아이콘·레이아웃까지 함께 다시 만들지 않도록 분리한다.

다음은 Unity C#에서 체력 텍스트를 변경된 경우에만 갱신하는 간단한 예다.

using TMPro;
using UnityEngine;

public class HealthHud : MonoBehaviour
{
    [SerializeField] private TMP_Text healthText;
    private int shownHealth = int.MinValue;

    public void SetHealth(int currentHealth)
    {
        if (shownHealth == currentHealth)
            return;

        shownHealth = currentHealth;
        healthText.SetText("{0}", currentHealth);
    }
}

SetText처럼 서식 값을 직접 받는 API는 상황에 따라 문자열 조합에서 생길 수 있는 임시 할당을 줄이는 데 도움이 된다. 다만 실제 효과는 사용하는 텍스트 컴포넌트와 호출 방식에 따라 달라지므로 메모리 프로파일러로 확인해야 한다.

사례 2: 인벤토리는 ‘모든 칸’을 만들 필요가 없다

수백 개 아이템을 가진 인벤토리에서 모든 셀을 한꺼번에 생성하면 레이아웃 계산과 스크롤 비용이 커진다. 화면에 보이는 범위와 약간의 여유분만 UI 셀로 유지하고 스크롤 위치에 맞춰 데이터만 교체하는 가상화가 효과적이다.

가상화 구현에서 중요한 점은 셀 객체를 재사용할 때 이전 상태를 완전히 초기화하는 것이다. 선택 테두리, 희귀도 색상, 비동기 아이콘 요청, 버튼 이벤트가 남아 있으면 잘못된 아이템이 표시될 수 있다.

스크롤 위치에 따라 재사용되는 인벤토리 아이템 셀 구조 예시

재사용 셀의 안전한 갱신 순서

  1. 이전 아이템에 연결된 시각 상태와 이벤트를 초기화한다.
  2. 새 데이터의 식별자를 셀에 기록한다.
  3. 이름, 수량, 희귀도, 잠금 상태를 설정한다.
  4. 아이콘을 비동기로 불러온다면 완료 시점에 식별자가 아직 같은지 확인한다.
public void Bind(ItemData item)
{
    boundItemId = item.Id;
    titleText.SetText(item.Name);
    countText.SetText("{0}", item.Count);
    iconImage.sprite = placeholderSprite;
    LoadIcon(item.IconKey, item.Id);
}

private async void LoadIcon(string iconKey, string expectedItemId)
{
    var sprite = await iconProvider.Load(iconKey);
    if (boundItemId == expectedItemId)
        iconImage.sprite = sprite;
}

렌더링 비용: 투명한 겹침과 마스크를 의심한다

UI는 반투명 이미지가 겹칠수록 같은 화면 영역을 여러 번 그릴 수 있다. 배경 블러, 그림자, 그라데이션, 둥근 모서리 마스크를 한 패널에 중첩하면 모바일 GPU에서 비용이 눈에 띄게 커질 수 있다.

다음 기준으로 정리하면 효과를 보기 좋다.

  • 완전히 가려진 장식 이미지는 제거하거나 합친다.
  • 넓은 반투명 패널 위에 또 다른 반투명 패널을 겹치지 않는다.
  • 스크롤 영역의 마스크는 꼭 필요한 범위에만 사용한다.
  • 동일한 아틀라스와 머티리얼을 사용해 배치가 끊어지지 않게 한다.
  • HUD와 자주 열고 닫는 메뉴를 분리해 불필요한 재빌드를 줄인다.

Unity에서는 Canvas 분할이 유용할 수 있다. 자주 바뀌는 체력·탄약 영역과 거의 변하지 않는 프레임 장식을 같은 Canvas에 두면 작은 변경도 넓은 범위의 재빌드로 이어질 수 있다. 반대로 Canvas를 지나치게 잘게 나누면 관리와 드로우콜이 복잡해질 수 있으므로 갱신 빈도와 화면 범위를 기준으로 나눈다.

Unreal Engine의 UMG에서도 같은 원칙이 적용된다. 매 프레임 바인딩으로 값을 계산하기보다 이벤트 기반 갱신을 우선하고 자주 갱신되지 않는 복잡한 위젯은 Invalidation Box나 Retainer Box의 적용 전후를 프로파일링해 비교한다. 캐싱은 만능이 아니므로 애니메이션과 빈번한 상태 변경이 있는 위젯에 무조건 적용하면 기대한 효과가 나지 않을 수 있다.

월드 공간 UI는 거리와 우선순위로 제한한다

적 머리 위 체력바나 이름표는 전투 정보를 잘 전달하지만 동시에 수십 개가 활성화되면 UI 객체 수와 투명 렌더링 비용이 함께 늘어난다. 다음 규칙을 조합해 표시량을 제한할 수 있다.

  • 카메라 밖 객체는 갱신하지 않는다.
  • 일정 거리 밖에서는 이름표를 숨기거나 단순 아이콘으로 바꾼다.
  • 최근 피해를 입었거나 조준 중인 대상만 상세 체력바를 표시한다.
  • 멀리 있는 군중은 개별 체력바 대신 집단 상태로 요약한다.
  • 반복 생성 대신 풀링으로 체력바 객체를 재사용한다.

이 방식은 성능뿐 아니라 화면의 정보 밀도도 낮춘다. 플레이어가 지금 대응해야 할 대상에 시선이 모이기 때문에 전투 가독성에도 도움이 된다.

출시 전 점검 목록

성능

  • UI 열기, 닫기, 스크롤, 다수 알림 상황을 기기별로 기록했는가?
  • 값이 바뀌지 않았는데 텍스트나 레이아웃을 반복 갱신하지 않는가?
  • 자주 생성·파괴되는 팝업과 피해 숫자에 풀링을 적용했는가?
  • 큰 투명 패널, 블러, 마스크의 중첩을 확인했는가?

플레이 경험

  • 전투 중 중요한 정보가 배경과 이펙트에 묻히지 않는가?
  • 입력 직후 버튼 상태나 선택 피드백이 충분히 빠르게 보이는가?
  • 작은 화면, 큰 글자 설정, 색각 이상 접근성 옵션에서도 핵심 정보가 유지되는가?

UI 최적화의 목표는 가장 복잡한 화면을 만드는 데 있지 않다. 플레이어가 필요한 정보를 지체 없이 이해하고 게임이 안정적인 프레임 타임을 유지하도록 만드는 데 있다. 측정 가능한 장면을 정하고 갱신·레이아웃·렌더링을 나누어 살피면 체감 품질을 해치지 않으면서 비용을 줄일 수 있다.