이전 글에서는 유니티의 GameObject와 언리얼 엔진의 Actor가 어떤 차이를 가지는지 정리했습니다.
두 엔진 모두 Component 기반 구조를 적극적으로 사용하지만,
실제로는 객체를 바라보는 방식과 철학이 다르다는 점도 함께 살펴봤습니다.
그런데 최근에는 ECS(Entity Component System), Data Oriented Design, Job System 같은 키워드들이 점점 더 자주 등장하기 시작했습니다.
그리고 처음 이런 구조를 접하면 자연스럽게 이런 생각이 들기도 합니다.
“Component 구조도 꽤 좋아 보이는데, 왜 또 새로운 구조가 등장하는 걸까?”
실제로 ECS는 처음 보면 굉장히 낯설게 느껴질 수 있습니다.
기존 객체 지향 구조와도 느낌이 다르고, GameObject나 Actor 기반 구조와도 차이가 있기 때문입니다.
하지만 ECS가 등장하게 된 흐름을 조금씩 따라가다 보면,
결국 최근 게임 엔진들이 무엇을 중요하게 보기 시작했는지가 보이기 시작합니다.
이번 글에서는 왜 최근 게임 엔진들이 ECS 구조에 관심을 가지기 시작했는지,
그리고 왜 객체보다 데이터를 더 중요하게 보기 시작했는지를 정리해보려고 합니다.
기존 Component 구조도 훌륭하다
새로운 개념을 살펴보기 전에 미리 정리해둘 중요한 부분이 있습니다.
Component 기반 구조가 나쁘다는 것이 절대 아니라는 것입니다.
실제로 다양한 측면에서 Component 기반 구조는 여전히 강력합니다.
- 유지보수
- 기능 분리
- 재사용성
- 조합 구조
예를 들어, 유니티에서는 다양한 컴포넌트를 조합해 게임 오브젝트를 쉽게 구성할 수 있습니다.
- Rigidbody
- Collider
- AudioSource
언리얼 엔진 역시 컴포넌트를 적극적으로 활용합니다.
- SceneComponent
- MeshComponent
- CameraComponent
즉, Component 기반 구조는 상속 구조가 가지던 복잡한 문제들을 많이 해결했습니다.
하지만 프로젝트 규모가 더 커지고, 객체 수가 폭발적으로 증가하기 시작하면 또 다른 문제가 등장하기 시작합니다.
게임은 같은 작업을 굉장히 많이 반복한다
예를 들어, 게임 안에 몬스터가 1000마리 있다고 가정해보겠습니다.
그리고 모든 몬스터는 매 프레임 여러 작업들을 반복적으로 수행합니다.
- 이동
- 충돌 검사
- 애니메이션 업데이트
즉, 게임은 “같은 종류의 데이터 처리”를 굉장히 많이 반복하는 프로그램이라는 것을 알 수 있습니다.
문제는 기존 객체 지향 구조에서는 데이터가 메모리 여기저기에 흩어질 가능성이 높다는 점입니다.
아래와 같은 구조를 생각해 봅시다.
class Monster
{
public:
Transform transform;
Renderer renderer;
Inventory inventory;
AIComponent ai;
AudioComponent audio;
};
Monster의 다양한 기능을 컴포넌트 단위로 분리해 구성했습니다.
자연스럽고, 모듈화되어 있으며, 재활용이 가능한 컴포넌트 기반 구조로 잘 설계되어 있습니다.
그런데 이 때 몬스터의 이동을 처리하는 상황을 생각해보겠습니다.
CPU 입장에서는 Transform 데이터만 필요할 것입니다.
하지만 Monster 객체 안에는 다양한 정보들이 함께 섞여 있습니다.
- 렌더링 데이터
- 오디오 데이터
- 인벤토리 데이터
즉, 필요하지 않은 데이터까지 함께 메모리에서 읽게 될 가능성이 생깁니다.
그리고 미리 말씀을 드리면, CPU는 동일한 성격의 데이터가 연속적으로 메모리에 배치되어 있는 것을 좋아합니다.
최근 CPU는 연산보다 메모리 접근이 더 중요해지기 시작했다
CPU의 단순 연산 자체가 비싼 작업이던 시절도 있었습니다.
하지만 최근 CPU는 굉장히 빠릅니다.
이제 문제는 데이터를 얼마나 빠르게 가져올 수 있는가입니다.
즉, CPU가 계산 자체는 굉장히 빠르게 수행할 수 있는데,
메모리 접근이 느려서 기다리는 상황이 발생하기 시작합니다.
그리고 이 과정에서 Cache Miss, Cache Locality 같은 개념들이 점점 더 중요해지기 시작했습니다.
최근 게임 엔진들이 아래 나열한 구조를 중요하게 보기 시작한 이유도 결국 이런 흐름과 연결됩니다.
- vector
- SoA
- Data Oriented Design
ECS는 데이터를 더 잘 모아둔다
ECS 구조의 핵심 아이디어 중 하나는 “같은 종류의 데이터를 가능한 연속적으로 배치하자”에 가깝습니다.
예를 들어, 기존 구조에서는 객체 단위로 데이터가 섞여 있을 수 있습니다.
지금까지 살펴본 고민의 결과로 “객체 중심”으로 클래스를 설계했기 때문입니다.
Monster
{
Transform
Renderer
Inventory
Audio
}
반면, ECS에서는 Transform 데이터만 따로 모아둡니다.
Transform Components
{
Position[1000];
Rotation[1000];
}
즉, 이동을 처리하는 시스템은 Transform 데이터만 집중적으로 순회할 수 있습니다.
이런 구조는 Cache 효율 측면에서 굉장히 유리해질 수 있습니다.
ECS는 객체보다 데이터를 더 중요하게 본다
여기서 중요한 변화가 등장합니다.
객체 지향 프로그래밍에서는 “객체” 자체가 중심이었습니다.
예를 들어, Player 객체, Monster 객체, NPC 객체 등 객체가 중심입니다.
하지만 ECS에서는 객체보다 데이터를 더 중요하게 보기 시작합니다.
- Position 데이터
- Velocity 데이터
- Health 데이터
즉, “이 객체가 누구인가”보다, “이 데이터들을 어떻게 빠르게 처리할 것인가”가 더 중요해지기 시작합니다.
그리고 이런 흐름은 최근 CPU 구조와도 굉장히 잘 맞습니다.
최근 엔진들이 ECS에 관심을 가지는 이유
그렇다면, 최근의 게임 엔진들이 ECS 개념에 관심을 갖는 이유는 무엇일까요?
그 이유는 최근의 게임 규모가 과거와 비교해 훨씬 더 커졌기 때문입니다.
예를 들면, 최근에 발매된 게임에서는 대량의 객체가 게임 공간에 나타나는 게 자연스럽습니다.
- 수천 개의 NPC
- 대규모 시뮬레이션
- 수많은 파티클
- 대규모 물리 처리
그리고 이런 환경에서는 객체를 얼마나 아름답게 설계했는가보다,
데이터를 얼마나 빠르게 처리할 수 있는가가 더 중요할 수 있습니다.
즉, 최근 엔진 구조는 점점 “객체 중심”보다,
“데이터 처리 중심”방향으로 이동하고 있다고 볼 수 있습니다.
유니티도 ECS를 적극적으로 연구하기 시작했다
실제로 유니티 역시 DOTS(Data Oriented Technology Stack)를 통해 ECS 구조를 적극적으로 연구하기 시작했습니다.
왜냐하면 기존 GameObject 구조만으로는 대규모 데이터 처리에서 한계가 보이기 시작했기 때문입니다.
예를 들어, 수십만 개의 객체를 동시에 처리하는 상황에서는, 기존 객체 지향적인 구조보다 데이터 중심 구조가 훨씬 유리해질 수 있습니다.
즉, ECS는 단순한 유행이 아니라, 최근 하드웨어 구조와 게임 규모 변화에 대응하기 위한 흐름에 가깝습니다.
ECS가 모든 문제를 해결해주는 것은 아니다
물론 ECS가 모든 상황에서 무조건 좋은 것은 아닙니다.
실제로 ECS는 여러 단점들을 가지고 있습니다. 특히 사람이 이해하기에 적합한 구조는 아닙니다.
- 구조가 낯설고
- 디버깅이 어려울 수 있으며
- 객체 개념이 약해질 수 있고
- 코드 가독성이 떨어질 수 있음
특히, 작은 프로젝트에서는 기존 Component 구조가 훨씬 단순하고 편할 수도 있습니다.
즉, 중요한 것은 ECS가 절대적인 정답이라는 것이 아닙니다.
프로젝트 규모, 데이터 처리량, 성능 요구사항에 따라 더 적합한 구조가 달라질 수 있습니다.
따라서 다양한 설계 구조가 있고, 각각의 장단점을 잘 이해한 후에 프로젝트의 상황에 맞게 적절하게 선택할 수 있어야 합니다.
최근 게임 엔진 구조는 점점 CPU와 데이터를 의식하기 시작했다
최근 게임 엔진 구조는 점점 CPU가 동작하는 방식에 잘 맞도록 발전하고 있습니다.
예전에는 객체를 얼마나 잘 추상화할 것인가를 중요했다면,
최근에는 데이터를 어떻게 배치할 것인가, Cache 효율을 어떻게 높일 것인가, 반복 처리를 어떻게 최적화할 것인가와 같은 부분들이 점점 더 중요해지고 있습니다.
즉, 최근 게임 엔진 구조는 점점 “객체 관점” 보다, |
“데이터와 CPU 관점”으로 이동하고 있다고 볼 수 있습니다.
결국 중요한 것은 문제를 바라보는 관점
ECS를 보면 굉장히 낯설고 복잡한 구조처럼 느껴질 수도 있습니다.
하지만 이런 변화의 흐름을 따라가다 보면 결국
최근 게임 엔진들이 어떤 문제를 해결하려고 하는지가 보이기 시작합니다.
대규모 데이터 처리, Cache 효율, 반복 처리 최적화 같은 문제들이 점점 중요해지기 시작했고,
ECS는 이런 문제를 해결하기 위해 등장한 방법 중 하나라고 볼 수 있습니다.
즉, 최근 엔진 구조 변화는 단순한 유행이 아니라, 하드웨어 구조와 게임 규모 변화에 대응하기 위한 대응책입니다.
마무리
최근 게임 엔진 구조를 보다 보면, ECS, Data Oriented Design, Job System 같은 키워드들을 점점 더 자주 접하게 됩니다.
굉장히 낯설게 느껴질 수도 있습니다.
하지만 조금 더 깊게 들여다보면,
최근 게임 엔진들이 데이터를 어떻게 처리할 것인가를 점점 더 중요하게 보기 시작했다는 것을 알게됩니다.
그리고 이런 흐름을 이해하기 시작하면, 왜 최근 엔진 구조가 지금과 같은 방향으로 발전하고 있는지도 조금씩 보이기 시작합니다.