유니티 그래픽스 렌더링 최적화하기 2 – 렌더링 문제의 유형

 

//
//

🚀 들어가며

이전글 – 렌더링 개요

이번 글에서는 렌더링 성능 문제의 기본 개념을 정리해보겠습니다.

  • 렌더링 병목(Rendering Bottleneck)
  • CPU Bound
  • GPU Bound
  • Profiler
  • Frame Debugger

렌더링 최적화에서 가장 중요한 것은 “무엇이 병목인지 정확히 파악하는 것”입니다.

문제를 제대로 이해하지 못한 상태에서 최적화를 진행하면 오히려 성능이 더 나빠질 수도 있습니다.


🧠 렌더링에서 가장 중요한 개념

렌더링에서 가장 중요한 개념 중 하나는 다음입니다.

CPU와 GPU는 모두, 프레임을 렌더링하기 위한 자신의 작업을 완료해야 합니다.

즉, CPU 또는 GPU 중 하나라도 작업 처리에 너무 오래 걸리면, 프레임 렌더링이 지연될 수 있습니다.

그리고 이 지연이 계속 발생하면 FPS 저하가 발생합니다.


//

🎯 렌더링 문제의 2가지 원인

렌더링 문제는 크게 2가지 유형으로 나눌 수 있습니다.

  • 비효율적인 파이프라인
  • 처리 가능한 양보다 많은 데이터

🔥 1. 비효율적인 파이프라인

렌더링 파이프라인 내부의 특정 단계가 너무 오래 걸리는 경우입니다.

즉,

한 단계가 느려짐

전체 흐름이 막힘

프레임 지연 발생

이런 현상을 병목(Bottleneck)이라고 부릅니다.

예를 들어

  • Draw Call 처리
  • SetPass Call
  • 쉐이더 처리

등이 병목이 될 수 있습니다.


🔥 2. 데이터 양이 너무 많은 경우

아무리 효율적인 렌더링 파이프라인이라도 처리 가능한 데이터 양에는 한계가 있습니다.

예를 들어 아래와 같은 상황이 원인이 될 수 있습니다.

  • 너무 많은 오브젝트
  • 너무 높은 해상도
  • 과도한 파티클
  • 복잡한 쉐이더

즉, 시스템이 감당 가능한 양보다 더 많은 작업을 시키는 상황입니다.


🧠 CPU Bound와 GPU Bound

지금까지 설명한 렌더링 병목 구조를 그림으로 정리해보면 다음과 같습니다.

핵심은 렌더링 최적화는 단순히 성능을 높이는 작업이 아니라, 현재 어떤 부분이 병목인지 정확히 파악하는 과정이라는 점입니다.

Unity 렌더링 최적화에서 CPU Bound와 GPU Bound 병목 구조를 설명하는 인포그래픽
Unity 렌더링 최적화에서 CPU Bound와 GPU Bound 병목 원인, Profiler, Frame Debugger, 멀티쓰레드 렌더링 구조를 정리한 이미지입니다.

위 구조처럼 렌더링 병목은

  • CPU가 느린 경우(CPU Bound)
  • GPU가 느린 경우(GPU Bound)

로 크게 나눌 수 있습니다.

그리고 병목 위치에 따라 최적화 방법 역시 완전히 달라집니다.

즉, Profiler와 Frame Debugger를 이용해 현재 어떤 작업이 가장 오래 걸리는지 먼저 파악하는 것이 렌더링 최적화의 핵심이라고 볼 수 있습니다.


🎯 CPU Bound

CPU가 렌더링 작업 처리에 너무 오래 걸리는 상태입니다.

즉,
CPU 작업 처리 지연

GPU가 기다림

프레임 속도 저하

대표 원인

  • 너무 많은 Draw Call
  • SetPass Call
  • Culling 비용
  • 스크립트 처리

🎯 GPU Bound

GPU가 렌더링 작업 처리에 너무 오래 걸리는 상태입니다.

즉,

GPU 처리 지연

프레임 생성 느려짐

FPS 감소

대표 원인

  • 오버드로우
  • 복잡한 쉐이더
  • 과도한 포스트 프로세싱
  • 고해상도 렌더링

🎮 가장 중요한 것은 프로파일링

최적화를 진행하기 전에 반드시 먼저 해야 하는 작업이 있습니다.

바로 프로파일링(Profiling)입니다.

왜냐하면 문제 원인에 따라 해결 방법이 완전히 달라지기 때문입니다.

예를 들어 CPU Bound 문제와 GPU Bound 문제는 서로 해결 방법이 다릅니다.

즉, 원인을 모른 채 최적화를 시작하면 의미 없는 작업이 될 수 있습니다.


🧠 최적화는 균형 잡기다

렌더링 최적화는 단순히 한 부분만 빠르게 만드는 작업이 아닙니다.

오히려 균형(balance)을 맞추는 작업에 가깝습니다.

예를 들어, CPU 부담 감소 / GPU 부담 증가 같은 상황도 발생할 수 있습니다.

따라서 변경 사항 적용 후에는 반드시 다시 프로파일링해야 합니다.


🎯 Unity Profiler

Unity Profiler는 게임의 성능 상태를 실시간으로 확인할 수 있는 도구입니다.
성능 병목 원인을 파악하는 핵심 도구입니다.

확인 가능한 항목

  • CPU 사용량
  • GPU 사용량
  • 메모리 사용량
  • 렌더링 비용
  • 스크립트 비용

🔥 Profiler로 확인할 수 있는 것

예를 들어

  • 어떤 함수가 오래 걸리는지
  • Draw Call이 많은지
  • GC가 발생하는지
  • 메모리 사용량이 높은지

같은 정보를 확인할 수 있습니다.

렌더링 최적화는 Profiler 없이 진행하기 어렵다고 봐도 됩니다.


🎮 Frame Debugger

Frame Debugger는 프레임이 실제로 어떻게 렌더링되는지 단계별로 보여주는 도구입니다.

즉, 이번 프레임에서 무슨 Draw Call이 발생했는가?를 확인할 수 있습니다.


🧠 Frame Debugger로 확인 가능한 것

예를 들어

  • Draw Call 순서
  • 렌더링된 오브젝트
  • 쉐이더 패스
  • GPU 이벤트

같은 정보를 확인할 수 있습니다.

특히, 배칭(Batching)이 왜 깨졌는지 확인할 때 매우 유용합니다.


🎯 먼저 렌더링 문제가 맞는지 확인하자

게임이 느리다고 해서 항상 렌더링 문제가 원인인 것은 아닙니다.

예를 들어

  • 무거운 사용자 스크립트
  • 과도한 물리 연산
  • AI 처리

가 원인일 수도 있습니다.

즉, 렌더링 문제가 맞는지 먼저 확인해야 합니다.

렌더링 문제가 아닌데 렌더링 최적화를 진행하면 큰 의미가 없습니다.


🧠 CPU Bound인지 GPU Bound인지 확인하기

렌더링 문제라는 것이 확인되었다면,
다음 단계는 CPU Bound인지 GPU Bound인지 파악하는 것입니다.

왜냐하면 두 문제는 해결 방법이 완전히 다르기 때문입니다.

  • CPU Bound → Draw Call / Batching 최적화
  • GPU Bound → 쉐이더 / 오버드로우 최적화

처럼 접근 방식이 달라집니다.


🎮 게임이 CPU Bound인 경우

CPU는 렌더링 과정에서 크게 3가지 작업을 수행합니다.

  • 무엇을 그릴지 결정
  • GPU 명령 준비
  • GPU에 명령 전달

이 과정에는 여러 개의 개별 작업이 포함됩니다.


🧠 멀티쓰레드 렌더링

Unity는 여러 쓰레드를 사용해 렌더링 작업을 분산 처리합니다.

예를 들어

  • Main Thread
  • Render Thread
  • Worker Thread

같은 구조를 사용합니다.

즉, 여러 작업을 동시에 처리할 수 있습니다.


🔥 Main Thread

메인 쓰레드는 게임 로직 대부분이 처리되는 곳입니다.

  • 스크립트
  • 렌더링 준비
  • 게임 로직

🔥 Render Thread

렌더 쓰레드는 GPU에 명령을 전달하는 역할을 담당합니다.

즉, Draw Call 전달과 관련된 작업이 처리됩니다.


🔥 Worker Thread

작업 쓰레드는 특정 작업만 처리하는 보조 쓰레드입니다.

  • Culling
  • Mesh Skinning

같은 작업이 Worker Thread에서 처리될 수 있습니다.


🎯 하드웨어에 따라 다르게 동작한다

렌더링 구조는 하드웨어에 따라 달라질 수 있습니다.

예를 들어, CPU 코어 수가 많다면, 더 많은 Worker Thread가 생성될 수도 있습니다.

즉, 동일한 게임이라도 장치에 따라 성능 특성이 달라질 수 있습니다.

그래서 타겟 하드웨어에서 직접 프로파일링하는 것이 매우 중요합니다.


🧠 무조건 최적화하면 안 되는 이유

멀티쓰레드 렌더링은 매우 복잡한 구조입니다.

예를 들어, Culling이 병목인데, GPU 명령 전달 최적화만 진행하면 의미가 없습니다.

즉, 먼저 어떤 작업이 병목인지 파악해야 합니다.


🎯 플랫폼에 따라 제한도 존재한다

모든 플랫폼이 멀티쓰레드 렌더링을 지원하는 것은 아닙니다.

예를 들어, WebGL은 멀티쓰레드 렌더링 지원이 제한적입니다.

이 경우, 모든 CPU 작업이 하나의 쓰레드에서 처리될 수도 있습니다.

즉, 플랫폼에 따라 최적화 전략이 달라질 수 있습니다.


🎯 핵심 정리

  • 렌더링 병목은 CPU Bound와 GPU Bound로 나뉩니다.
  • 최적화 전에 반드시 프로파일링이 필요합니다.
  • Unity Profiler와 Frame Debugger는 핵심 분석 도구입니다.
  • CPU와 GPU 병목은 해결 방법이 다릅니다.
  • 멀티쓰레드 렌더링은 하드웨어에 따라 동작 방식이 달라질 수 있습니다.
  • 무조건 최적화하는 것이 아니라, 병목 원인을 먼저 파악해야 합니다.

🧩 마무리

렌더링 최적화를 공부하다 보면 처음에는 Draw Call이나 쉐이더 같은 부분만 보게 되는 경우가 많습니다.

하지만 실제로는 “무엇이 병목인가?”를 먼저 파악하는 것이 가장 중요합니다.

즉,

  • CPU Bound인지
  • GPU Bound인지
  • 어떤 쓰레드가 오래 걸리는지
  • 어떤 작업이 병목인지

를 이해해야 의미 있는 최적화를 진행할 수 있습니다.

다음 글에서는,
CPU Bound 상황에서 실제로 어떤 렌더링 작업들이 비용을 발생시키는지,
그리고 Batching과 SetPass Call이 왜 중요한지를 조금 더 자세히 살펴보겠습니다.

👉 게임 엔진 구조를 더 깊이 이해하고 싶다면

아래 강의를 통해 직접 구현해보는 것을 추천드립니다.

C++로 만드는 게임 엔진 프레임워크 강의

👉 C++로 만드는 게임 엔진 프레임워크 강의 바로가기

//
   

댓글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다