데이터 지향 설계: 게임 프로그래밍의 새 흐름
프레임이 흔들리는 순간, 플레이어는 코드 구조를 보지 못하지만 결과는 바로 느낍니다. 몬스터가 많아질수록 AI가 늦어지고, 이펙트가 겹칠수록 입력 반응이 무거워지며, 디버그할 때마다 객체 참조가 얽혀 있다면 이제 관심사는 단순한 최적화가 아니라 게임 프로그래밍 아키텍처입니다.
최근 게임 개발 흐름에서 데이터 지향 설계가 다시 강하게 언급되는 이유도 여기에 있습니다. 더 빠른 CPU, 더 큰 메모리만 믿는 방식으로는 모바일, 콘솔, PC, 핸드헬드, 클라우드 스트리밍까지 동시에 대응하기 어렵습니다. Will Perone 같은 개발자 포트폴리오 사이트에서 다루기 좋은 주제이기도 합니다. 수학 라이브러리, 엔진 코드, 게임플레이 시스템이 모두 결국 데이터를 어떻게 배치하고 계산하느냐로 이어지기 때문입니다.
객체보다 데이터 흐름을 먼저 보는 이유
트렌드는 코드 스타일보다 하드웨어 현실에서 시작됩니다
객체 지향 설계가 사라진다는 뜻은 아닙니다. 다만 실시간 게임에서는 캐릭터, 총알, 파티클, UI 애니메이션, 물리 상태처럼 매 프레임 갱신되는 대상이 많고, 이때 CPU 캐시와 메모리 접근 패턴이 성능을 크게 좌우합니다. 데이터 지향 설계는 개별 객체의 멋진 계층 구조보다 같은 연산을 받는 데이터를 한곳에 모아 빠르게 순회하는 방식에 집중합니다.
예를 들어 1만 개의 투사체가 각각 position, velocity, lifetime을 가진 객체라면 읽어야 할 메모리 위치가 흩어지기 쉽습니다. 반대로 위치 배열, 속도 배열, 수명 배열을 분리해 순회하면 CPU가 다음 데이터를 예측하기 쉬워집니다. 이 차이는 작은 샘플에서는 잘 보이지 않지만, 실제 게임 장면처럼 수천 개 단위의 엔티티가 움직일 때 분명해집니다.
GDC처럼 업계 개발자들이 기술 변화를 공유하는 자리에서도 성능, 제작비, 툴 파이프라인은 꾸준히 연결된 화두입니다. 용어 자체가 낯설다면 GDC의 기본 정의를 먼저 확인해도 좋습니다. 행사의 이름보다 중요한 것은, 실무자들이 왜 프레임 안정성과 제작 효율을 같은 테이블에 올려놓는가입니다.
- 캐시 친화성: 연속된 데이터를 읽게 만들어 메모리 대기 시간을 줄입니다.
- 배치 처리: 같은 로직을 여러 대상에 한 번에 적용해 분기와 호출 비용을 낮춥니다.
- 병렬화 준비: 작업 단위를 데이터 묶음으로 나누면 잡 시스템이나 워커 스레드로 넘기기 쉽습니다.
- 예측 가능한 비용: 프레임마다 어떤 데이터가 얼마나 처리되는지 계산하기 쉬워집니다.
성능 튜닝은 느린 함수를 찾아내는 일이기도 하지만, 더 깊게 들어가면 느려질 수밖에 없는 데이터 배치를 바꾸는 일입니다.
ECS는 유행어가 아니라 증상에 대한 처방입니다
ECS, 즉 Entity Component System은 데이터 지향 설계가 게임 코드에 적용된 대표적인 형태입니다. 엔티티는 식별자에 가깝고, 컴포넌트는 순수 데이터이며, 시스템은 그 데이터를 처리하는 로직입니다. 이 구조는 캐릭터 클래스를 점점 두껍게 만드는 대신 움직임, 체력, 입력, 렌더링 상태를 분리해서 각 시스템이 필요한 데이터만 보게 합니다.
중요한 점은 ECS를 도입한다고 자동으로 빨라지는 것이 아니라는 사실입니다. 기존 객체 구조를 이름만 컴포넌트로 바꾸면 오히려 복잡도가 늘어납니다. 데이터 지향 설계의 핵심은 프레임에서 실제로 반복되는 계산을 찾아내고, 그 계산이 읽고 쓰는 데이터를 최소한의 형태로 재배치하는 것입니다.
엔진과 툴체인이 밀어주는 방향
Unity, Unreal, 자체 엔진 모두 같은 질문을 던집니다
2026년 기준으로 상용 엔진과 자체 엔진의 방향은 조금씩 다르지만 질문은 비슷합니다. 더 많은 오브젝트를 어떻게 안정적으로 갱신할 것인가, 디자이너가 만든 콘텐츠를 어떻게 런타임 친화적인 데이터로 변환할 것인가, 멀티코어 환경을 어떻게 자연스럽게 활용할 것인가입니다. Unity의 DOTS와 ECS, Unreal의 Mass Entity 같은 흐름은 이 질문에 대한 대표적인 엔진 차원의 답변입니다.
특히 오픈월드, 시뮬레이션, 대규모 NPC, 탄막, 전략 게임, 도시 건설 게임처럼 많은 개체가 동시에 상태를 바꾸는 장르에서는 데이터 지향 접근이 점점 기본 소양에 가까워지고 있습니다. 단순히 빠른 언어를 고르는 문제를 넘어, 게임 데이터를 어떤 단위로 저장하고 어떤 순서로 변환할지가 엔진 설계의 중심으로 이동하고 있습니다.
이 변화는 기획과도 연결됩니다. 수천 개 유닛이 움직이는 게임을 만들고 싶다면 기획 단계에서부터 한 프레임에 처리될 상태 수, 시뮬레이션 빈도, 화면 밖 개체 처리 방식이 논의되어야 합니다. 게임 개발에서 기획자의 역할을 더 넓게 보고 싶다면 기획자라는 직무 설명도 참고할 만합니다. 기술 선택은 개발자만의 결정처럼 보이지만, 실제로는 게임 규칙과 콘텐츠 밀도의 선택이기도 합니다.
- 에디터 데이터는 사람이 이해하기 쉬운 형태로 유지합니다. 프리팹, 블루프린트, 씬 오브젝트는 제작자에게 친절해야 합니다.
- 런타임 데이터는 기계가 빠르게 처리하기 쉬운 형태로 변환합니다. 불필요한 문자열, 깊은 참조, 빈번한 동적 할당을 줄입니다.
- 빌드 파이프라인에서 변환과 검증을 자동화합니다. 잘못된 데이터가 런타임까지 들어오지 않게 막는 것이 중요합니다.
- 디버깅 뷰를 별도로 준비합니다. 데이터 지향 구조는 눈으로 따라가기 어려울 수 있어 툴 지원이 필수입니다.
AI 코드 보조 시대에도 구조 감각은 더 중요해집니다
최근 개발자는 코드 보조 도구로 반복 코드를 빠르게 만들 수 있습니다. 하지만 AI가 생성한 코드는 대체로 요구사항을 만족하는 형태에 집중하며, 게임 런타임의 데이터 배치나 프레임 예산까지 자동으로 보장하지는 않습니다. 그래서 데이터 지향 설계는 AI 시대에 덜 중요한 기술이 아니라, 오히려 생성된 코드를 검토하는 기준이 됩니다.
예를 들어 AI가 적 캐릭터 200종의 상태 클래스를 각각 만들어준다면 당장은 편할 수 있습니다. 하지만 공통 갱신 루프, 상태 전이 테이블, 압축 가능한 데이터 필드를 분리하지 않으면 나중에 밸런스 패치와 성능 최적화가 동시에 어려워집니다. 빠르게 생성한 코드를 오래 운영 가능한 구조로 바꾸는 감각이 개발자의 경쟁력이 됩니다.
- 생성된 코드의 반복 패턴을 찾고 시스템 단위로 합칠 수 있는지 봅니다.
- 런타임 할당이 매 프레임 발생하는지 확인합니다.
- 데이터 소유권이 명확한지 검토합니다. 누가 읽고 누가 쓰는지가 불분명하면 병렬화가 막힙니다.
- 테스트 가능한 수학 함수와 엔진 의존 로직을 분리합니다. 이 지점에서 math 라이브러리 설계가 힘을 발휘합니다.
수학 라이브러리가 데이터 지향 설계의 중심에 서는 순간
벡터와 행렬은 자료구조 선택의 문제이기도 합니다
게임 프로그래밍에서 math는 단순한 보조 도구가 아닙니다. 위치, 회전, 스케일, 속도, 가속도, 충돌 경계, 카메라 행렬, 스켈레톤 포즈까지 거의 모든 런타임 상태가 수학 자료형을 거칩니다. 그래서 데이터 지향 설계를 진지하게 적용하려면 Vec3, Quaternion, Matrix 같은 기본 타입이 어떤 메모리 레이아웃을 가지는지부터 봐야 합니다.
예를 들어 구조체 배열 방식은 사용하기 쉽지만, 특정 연산에서 x값만 대량으로 읽어야 한다면 배열 구조체보다 구조체의 배열이 유리할 수 있습니다. 물론 모든 코드를 SoA로 바꾸면 API가 거칠어지고 개발 속도가 떨어질 수 있습니다. 중요한 것은 읽기 쉬운 인터페이스와 빠른 내부 표현을 분리하는 설계입니다.
Will Perone의 사이트 키워드에 math와 game programming이 함께 있는 이유도 이 지점에서 설득력이 생깁니다. 수학 라이브러리는 엔진 아래쪽에 조용히 놓여 있지만, 데이터 지향 설계에서는 프레임 전체의 데이터 이동량을 좌우하는 기반이 됩니다. 작은 타입 하나의 정렬, 패딩, 복사 비용이 누적되면 게임플레이 시스템 전체에 영향을 줍니다.
- AoS: 객체마다 x, y, z를 함께 두는 방식입니다. 코드가 자연스럽고 디버깅이 쉽지만 대량 SIMD 처리에는 불리할 수 있습니다.
- SoA: x 배열, y 배열, z 배열을 나누는 방식입니다. 같은 축을 한 번에 처리하기 좋지만 API가 낯설어질 수 있습니다.
- Hybrid: 외부 API는 Vec3처럼 제공하고 내부 핫패스만 SoA로 변환합니다. 작은 팀에서 현실적인 절충안이 됩니다.
- Alignment: SIMD나 플랫폼별 최적화를 고려할 때 정렬 조건을 무시하면 기대한 성능이 나오지 않습니다.
수학 라이브러리는 예쁜 연산자 오버로딩보다, 어느 플랫폼에서 어떤 데이터가 얼마나 자주 복사되는지를 설명할 수 있어야 합니다.
핫패스와 콜드패스를 나누면 리팩터링 범위가 보입니다
모든 코드를 데이터 지향으로 바꾸려는 시도는 비용이 큽니다. 메뉴 UI, 저장 파일 관리, 업적 시스템, 간단한 퀘스트 트리처럼 성능 민감도가 낮은 영역은 읽기 쉬운 객체 모델이 더 낫습니다. 반면 이동, 조준, 충돌 후보 생성, 애니메이션 샘플링, 가시성 판단처럼 매 프레임 대량 처리되는 곳은 핫패스로 보고 별도 설계를 검토할 만합니다.
실무에서는 먼저 프레임 타임을 측정한 뒤, 같은 데이터가 반복적으로 순회되는 루프를 찾는 방식이 좋습니다. 이미 빠른 코드를 더 빠르게 만드는 데 시간을 쓰기보다, 데이터가 흩어져 있어서 캐시 미스가 잦고 병렬화가 어려운 루프를 고르는 편이 효과적입니다. 이때 성능 숫자만 보지 말고 코드 변경으로 툴, 디버깅, 콘텐츠 제작 흐름이 얼마나 흔들리는지도 함께 봐야 합니다.
- 측정: 프레임에서 반복 시간이 큰 시스템을 찾습니다.
- 분류: 계산 데이터, 표시 데이터, 디버그 데이터를 나눕니다.
- 재배치: 가장 자주 읽는 필드부터 연속 메모리로 모읍니다.
- 검증: 성능뿐 아니라 결과 결정성, 저장 호환성, 툴 표시가 유지되는지 확인합니다.
작은 팀이 따라가기 전에 확인할 경계선
유행을 도입하는 비용도 예산입니다
데이터 지향 설계는 매력적이지만 모든 프로젝트의 정답은 아닙니다. 2D 퍼즐 게임, 짧은 내러티브 게임, UI 중심 앱형 게임처럼 화면에 등장하는 동적 개체가 적고 병목이 렌더링이나 네트워크에 있는 경우라면 ECS 전환이 오히려 개발 속도를 떨어뜨릴 수 있습니다. 최신 기술을 쓰는 것보다 프로젝트의 실제 위험을 줄이는 선택이 더 중요합니다.
특히 인디 개발에서는 학습 비용이 곧 제작 비용입니다. 개발자가 한 명뿐인데 툴링, 디버거, 에디터 변환기, 직렬화 규칙까지 모두 직접 만들어야 한다면 본편 콘텐츠가 늦어질 수 있습니다. 예산을 제도적으로 관리한다는 관점이 궁금하다면 계획예산 제도 설명처럼 자원을 목표에 맞게 배분하는 개념을 빌려 생각해볼 수 있습니다. 게임 기술 선택도 결국 제한된 시간과 인력을 어디에 쓸지 정하는 문제입니다.
따라서 작은 팀이라면 전체 엔진을 갈아엎기보다 핫패스 한두 곳에 제한적으로 적용하는 편이 현실적입니다. 예를 들어 파티클 업데이트, 적 감지 후보, 탄환 이동, 간단한 군중 이동처럼 입력과 출력이 명확한 시스템부터 시작하면 실패해도 되돌리기 쉽습니다. 반대로 세이브 데이터, 에디터 워크플로, 네트워크 직렬화와 깊게 얽힌 핵심 구조부터 바꾸면 리스크가 급격히 커집니다.
- 도입해볼 만한 경우: 수천 개 이상의 반복 개체, 명확한 프레임 병목, 안정적인 데이터 스키마가 있을 때입니다.
- 조심해야 할 경우: 게임 규칙이 자주 바뀌고, 디자이너 툴이 아직 없고, 디버깅 시간이 부족할 때입니다.
- 피해야 할 경우: 성능 문제가 확인되지 않았는데 기술 유행 때문에 구조를 바꾸려는 상황입니다.
- 현실적인 출발점: 기존 객체 모델은 유지하되 런타임 계산용 캐시 배열을 별도로 만드는 방식입니다.
이 글이 일부러 다루지 않은 예외들
데이터 지향 설계만으로 게임 성능 문제가 모두 해결되지는 않습니다. GPU 병목이 큰 장면, 서버 권위형 멀티플레이, 스트리밍 월드의 I/O 문제, 애니메이션 리타게팅 비용, 플랫폼별 메모리 제한은 별도의 분석이 필요합니다. 또한 C++, C#, Rust, Zig처럼 언어가 달라지면 같은 설계라도 구현 난이도와 도구 지원이 달라집니다.
또 하나의 예외는 팀 문화입니다. 데이터 지향 코드는 잘 설계되면 강력하지만, 팀원이 구조를 이해하지 못하면 수정 장벽이 높아집니다. 그래서 문서, 샘플, 디버그 뷰, 성능 테스트가 함께 있어야 합니다. 개인 포트폴리오나 기술 블로그에서는 완성된 엔진 전체보다 작은 샘플을 통해 의도를 보여주는 편이 더 설득력 있습니다. 예컨대 5만 개 점 이동 시뮬레이션, SoA와 AoS 벤치마크, SIMD 적용 전후 그래프처럼 독자가 직접 차이를 상상할 수 있는 프로젝트가 좋습니다.
- 벤치마크 숫자는 테스트 환경과 데이터 크기를 함께 공개합니다.
- 코드 예제는 최적화 전 구조와 최적화 후 구조를 나란히 보여줍니다.
- 예외 조건은 숨기지 않습니다. 작은 데이터에서는 차이가 없거나 오히려 복잡해질 수 있음을 밝혀야 신뢰가 생깁니다.
- 다음 실험은 렌더링, 물리, AI 중 하나로 범위를 좁힙니다. 한 번에 모든 시스템을 바꾸는 실험은 원인을 흐립니다.

- 다음글게임 AI 경로찾기는 NavMesh부터 고르는 게 맞다 26.09.16
등록된 댓글이 없습니다.
