게임 프로그래머의 진짜 목표는 기능 추가가 아니라 병목과 변경 비용을 줄이는 일이다

게임 프로그래머가 흔히 빠지는 함정이 하나 있다. “무엇을 더 만들어야 하는가?”라는 질문을 너무 빨리 “무엇을 더 정교하게 설계해야 하는가?”로 바꿔 버리는 것이다. 그러다 보면 아직 병목도 확인하지 않았는데 아키텍처를 복잡하게 만들고, 아직 반복 작업도 파악하지 않았는데 툴부터 크게 짓고, 아직 플레이 감각도 검증하지 않았는데 최적화부터 시작하게 된다.
실무에서 프로그래머의 역할은 기능을 많이 추가하는 사람이 되는 데 있지 않다. 더 중요한 일은 어디서 프로젝트가 느려지는지, 그리고 어디서 앞으로의 수정이 비싸질지를 빨리 찾아내는 데 있다. 이 관점이 없으면 성능 최적화도, 클린 코드도, 툴 개발도 모두 목적을 잃는다.
Unity와 Unreal의 공식 문서가 공통적으로 강조하는 것도 결국 측정과 맥락이다. 프레임 시간, 메모리, 스레드 활동, 네트워크, 로딩 구간은 체감 문제로 이어지기 때문에 계측해야 하고, 계측은 에디터 안의 감이 아니라 실제 타깃 환경에 가까운 빌드에서 확인해야 한다. 즉, 게임 프로그래머의 진짜 목표는 “좋아 보이는 코드” 그 자체가 아니라 플레이어 경험과 팀의 변경 속도를 지키는 것에 가깝다.
첫 번째 목표: 플레이어가 체감하는 병목을 계측하고 줄이는 것
성능 이야기를 하면 많은 팀이 곧바로 FPS 숫자만 떠올린다. 하지만 플레이어가 체감하는 병목은 더 넓다.
- 프레임 드랍
- 긴 로딩 시간
- 메모리 급증과 크래시
- 입력 지연
- 네트워크 스파이크
- 배터리 소모와 발열
Unreal의 성능 소개 문서도 프레임 시간과 타깃 하드웨어 예산을 기준으로 보라고 설명하고, Unreal Insights를 스레드, 메모리, 네트워크 분석을 위한 핵심 도구로 제시한다. Unity 역시 Profiler 문서에서 실제 애플리케이션을 프로파일링할 때 플랫폼별 특성과 연결 방식, 그리고 에디터가 데이터에 영향을 줄 수 있다는 점을 별도로 안내한다.
이 말은 곧 이런 뜻이다. 성능 문제는 추측으로 다루면 안 된다.
- “느릴 것 같은 코드”가 아니라 실제로 시간을 많이 쓰는 구간을 봐야 한다
- 에디터에서만 느린 것인지, 빌드에서도 느린 것인지 구분해야 한다
- CPU 병목인지 GPU 병목인지, 메모리인지 I/O인지 분리해서 봐야 한다
- 수정을 했으면 다시 측정해서 이전보다 나아졌는지 확인해야 한다
특히 Unity 문서는 Deep Profiling 자체가 큰 오버헤드를 만들 수 있다고 설명한다. Unreal 문서도 프로파일러를 붙인 상태에서는 성능이 약간 더 나빠질 수 있다고 안내한다. 계측 도구가 필요하지만, 계측 상황 자체가 결과를 왜곡할 수도 있다는 뜻이다. 그래서 프로파일링은 숫자를 보는 일인 동시에 숫자가 어떤 조건에서 나온 것인지를 해석하는 일이다.
결국 플레이어 경험을 지키는 성능 최적화란 이런 순서에 가깝다.
- 타깃 기기와 빌드에서 병목을 찾는다.
- 병목이 CPU, GPU, 메모리, 로딩, 네트워크 중 어디인지 분리한다.
- 플레이어 체감에 큰 순서대로 고친다.
- 다시 측정해서 효과를 확인한다.
이 과정을 건너뛰고 “일단 더 빠를 것 같은 구조”를 만드는 것은 최적화라기보다 추측에 가깝다.
두 번째 목표: 팀의 반복 노동을 줄이는 것
게임 개발에서 생산성을 가장 크게 깎는 것은 종종 런타임 성능이 아니라 반복 노동이다. 데이터를 손으로 옮겨 적어야 하고, 밸런스 값을 바꿀 때마다 빌드를 오래 기다려야 하고, 같은 설정을 여러 씬에서 반복해야 하고, QA가 발견한 이슈를 재현하는 절차가 매번 달라지면 팀은 급격히 느려진다.
이때 툴은 분명 중요하다. 하지만 툴의 목표를 자주 착각한다. 툴은 기능이 많을수록 좋은 것이 아니라 팀이 자주 반복하는 비용을 줄일수록 좋은 것이다.
예를 들어 이런 문제는 툴이나 파이프라인 개선의 가치가 높다.
- 디자이너가 값을 바꿀 때마다 프로그래머가 빌드를 다시 해줘야 하는 구조
- 같은 데이터가 엑셀, 에디터, 서버 설정에 중복 입력되는 구조
- 아티스트가 에셋을 넣을 때 규칙이 제각각이라 검수가 반복되는 구조
- QA가 버그를 보고해도 로그, 버전, 재현 맥락이 빠져 다시 물어봐야 하는 구조
반대로 아직 팀이 자주 쓰지도 않는 기능을 위해 거대한 에디터를 만드는 일은 위험하다. YAGNI는 “You Aren’t Gonna Need It”, 즉 필요가 확인되기 전까지는 미리 일반화하지 말자는 원칙인데, Martin Fowler의 정리도 여기서 여전히 유효하다. 필요가 입증되기 전의 일반화와 추상화는 미래 대비처럼 보이지만, 실제로는 현재의 변경 비용을 높이는 경우가 많다.
툴 프로그래머의 기준은 단순해야 한다.
- 이 툴이 누군가의 반복 작업 시간을 실제로 줄이는가
- 줄이는 시간이 유지보수 비용보다 큰가
- 팀이 매주 쓰는 문제를 해결하는가
이 세 가지에 답하지 못하면, 그 툴은 기술적으로 멋질 수는 있어도 프로젝트를 빠르게 만들지는 못할 가능성이 크다.
세 번째 목표: 앞으로 바뀔 부분의 비용을 낮추는 것
좋은 구조의 핵심은 “한 번에 완벽하다”가 아니라 “나중에 덜 아프다”에 있다. 게임 개발에서는 특히 기획과 콘텐츠가 계속 변하기 때문에, 무엇이 바뀔 가능성이 높은지 읽고 거기에 맞춰 결합도를 낮추는 능력이 중요하다.
예를 들어 이런 질문이 실무적으로 중요하다.
- 스킬 수치가 자주 바뀌는가, 아니면 규칙 자체가 자주 바뀌는가
- 아이템이 늘어나는가, 아니면 아이템 분류 체계가 자주 바뀌는가
- 전투 루프는 고정이고 콘텐츠만 늘어나는가, 아니면 핵심 루프 자체가 아직 흔들리는가
- 라이브 운영 중 서버 검증 규칙이 자주 개편될 가능성이 있는가
이 질문에 대한 답이 있어야 데이터화, 추상화, 툴화의 우선순위를 잡을 수 있다. 자주 변하는 것을 코드 깊숙이 박아 두면 이후 수정이 비싸지고, 반대로 거의 변하지 않는 부분까지 지나치게 일반화하면 읽기와 디버깅이 어려워진다.
Fowler가 기술 부채를 이야기할 때도 중요한 기준은 부채의 존재 여부 자체보다 신중한 선택이었는가, 무모한 선택이었는가에 있다. 짧은 일정 때문에 임시 구현을 택할 수는 있다. 다만 그것이 임시라는 사실을 알고, 어디서 다시 정리할지 계획이 있어야 한다. 가장 위험한 것은 임시 구현을 영구 구조처럼 다루는 경우다.
즉, 메인 프로그래머의 일은 모든 요구를 즉시 일반화하는 것이 아니라, 어떤 변경을 싸게 만들고 어떤 변경은 의도적으로 비싸게 둘지를 결정하는 일에 가깝다.
단계마다 최적화 우선순위는 달라진다
게임 프로그래머의 목표를 한 문장으로 고정하면 자주 실패한다. 프로젝트 단계마다 병목이 달라지기 때문이다.
프로토타입 단계
가장 중요한 것은 학습 속도다.
- 핵심 조작과 루프를 빨리 검증할 수 있는가
- 버리기 쉬운 구조인가
- 질문 하나를 답하는 데 며칠이 걸리지 않는가
이 단계에서는 지나친 일반화보다 빠른 실험이 중요하다.
프로덕션 초중반
가장 중요한 것은 콘텐츠 생산 속도와 결합 안정성이다.
- 디자이너와 아티스트가 병목 없이 데이터를 넣을 수 있는가
- 시스템 간 의존성이 지나치게 꼬이지 않았는가
- 빌드와 테스트가 팀 속도를 심각하게 늦추지 않는가
이 단계에서는 툴, 데이터 구조, 자동화의 가치가 커진다.
출시 전후
가장 중요한 것은 실제 유저 환경의 체감 안정성이다.
- 타깃 기기에서 프레임 시간 예산을 지키는가
- 메모리와 로딩이 허용 범위 안에 있는가
- 크래시, 패킷 지연, 특정 맵 스파이크 같은 치명적 이슈를 추적할 수 있는가
이 단계에서는 계측과 회귀 방지가 핵심이다.
라이브 서비스 단계
가장 중요한 것은 안전한 변경이다.
- 핫픽스가 다른 시스템을 깨지 않는가
- 운영 로그와 모니터링으로 문제를 빨리 찾을 수 있는가
- 콘텐츠 추가가 코드 수정 폭발로 이어지지 않는가
이 단계에서는 “빠르게 고치는 능력”이 새로운 기능 하나를 더 넣는 능력보다 중요해진다.
실무에서 더 유용한 질문
게임 프로그래머라면 “이 구조가 우아한가?”보다 먼저 이런 질문을 던지는 편이 좋다.
- 지금 플레이어가 실제로 겪는 가장 큰 병목은 무엇인가
- 이 병목은 계측 가능한가
- 이 기능은 반복 작업을 줄이는가, 아니면 새 유지보수 지점을 만드는가
- 앞으로 가장 자주 바뀔 부분은 어디인가
- 지금 지는 기술 부채는 신중한 선택인가, 아니면 그냥 미뤄 둔 문제인가
이 질문들에 답하면서 우선순위를 잡는 사람이 결국 팀을 빠르게 만든다.
핵심 정리
게임 프로그래머의 진짜 목표는 기능을 많이 추가하는 데 있지 않다. 더 중요한 일은 플레이어가 체감하는 병목을 계측하고 줄이는 것, 팀의 반복 노동을 줄이는 것, 그리고 앞으로 자주 바뀔 부분의 변경 비용을 낮추는 것이다.
성능 최적화는 추측이 아니라 계측에서 시작해야 하고, 툴 개발은 기능 수보다 실제 반복 비용 절감으로 평가해야 하며, 구조 설계는 완벽함보다 변경 가능성에 맞춰야 한다. 프로젝트 단계마다 무엇이 병목인지 달라지기 때문에, 같은 “좋은 코드”라도 언제는 과하고 언제는 부족할 수 있다.
결국 좋은 게임 프로그래머는 모든 문제를 같은 방식으로 푸는 사람이 아니라, 지금 프로젝트에서 가장 비싼 문제를 먼저 알아보는 사람에 가깝다.
마치며
게임 개발에서는 성능, 효율성, 창의성이 서로 경쟁하는 것처럼 보일 때가 많다. 하지만 실제로는 셋 다 같은 질문으로 수렴한다. “지금 이 프로젝트를 가장 느리게 만드는 것은 무엇인가?”
그 답이 프레임 시간이면 프로파일러를 열어야 하고, 반복 노동이면 툴을 만들어야 하고, 잦은 기획 변경이면 구조를 다시 나눠야 한다. 프로그래머의 본질은 모든 것을 한꺼번에 완벽하게 만드는 데 있지 않다. 지금 가장 비싼 병목을 찾아서, 다음 변경이 덜 무섭게 만드는 데 있다.
참고 자료
- Unity Manual, Profiling your application: https://docs.unity3d.com/2022.2/Documentation/Manual/profiler-profiling-applications.html
- Unity Manual, The Profiler window: https://docs.unity3d.com/es/2021.1/Manual/ProfilerWindow.html
- Epic Games, Introduction to Performance Profiling and Configuration in Unreal Engine: https://dev.epicgames.com/documentation/en-us/unreal-engine/introduction-to-performance-profiling-and-configuration-in-unreal-engine
- Epic Games, Memory Insights in Unreal Engine: https://dev.epicgames.com/documentation/unreal-engine/memory-insights-in-unreal-engine
- Martin Fowler, YAGNI: https://martinfowler.com/bliki/Yagni.html
- Martin Fowler, Technical Debt Quadrant: https://martinfowler.com/bliki/TechnicalDebtQuadrant.html