🚀 들어가며
이번 글에서는 C++ 게임 루프의 기본 구조와 게임이 어떻게 계속 실행되는지를 설명합니다.
게임을 실행하면 캐릭터가 움직이고, 화면이 계속 갱신됩니다.
그렇다면 이런 질문이 자연스럽게 떠오릅니다.
❓ 게임은 어떻게 “계속” 실행되는 걸까?
이 질문에 대한 답이 바로
👉 게임 루프(Game Loop)에 있습니다.
🎯 게임 루프란 무엇인가?
게임 루프는 간단하게 말하면:
게임을 계속 실행시키는 반복 구조
가장 단순한 형태는 다음과 같습니다.
while (running)
{
Tick();
Draw();
}
🔍 이 코드가 하는 일
✔ Tick
- 게임 상태 업데이트
- 캐릭터 이동
- 충돌 처리
- 입력 반영
✔ Draw
- 화면 출력
- 그래픽 업데이트
👉 즉:
게임 루프는 게임의 “심장” 역할을 합니다
⚠️ 하지만 이 구조에는 문제가 있습니다
이 코드 그대로 실행하면:
- CPU를 100% 사용
- 프레임 속도 제어 불가능
- 실행 속도 불안정
🎯 문제의 핵심
👉 컴퓨터는 너무 빠르게 루프를 돌립니다
결과:
- 어떤 PC에서는 너무 빠름
- 어떤 PC에서는 느림
👉 게임이 일정하게 동작하지 않음
🔥 해결 방법: 시간 개념 도입
여기서 등장하는 개념이:
👉 deltaTime
🧠 deltaTime이란?
이전 프레임과 현재 프레임 사이의 시간
예:
position += speed * deltaTime;
👉 이렇게 하면:
- FPS가 달라도
- 움직임이 일정해짐
🧭 deltaTime 계산 흐름
deltaTime은 복잡한 개념이 아닙니다.
핵심은 다음과 같습니다.
이전 프레임 시간 ───── 현재 프레임 시간
│ │
└──── 시간 차이 ─────┘
deltaTime = 현재 프레임 시간 - 이전 프레임 시간
예를 들어보겠습니다.
1프레임 시작 시간: 0.000초
2프레임 시작 시간: 0.016초
deltaTime = 0.016 - 0.000
= 0.016초
0.016초는 약 16ms입니다.
이는 1초에 약 60번 화면이 갱신되는 속도, 즉 60FPS에 가까운 값입니다.
🎮 deltaTime을 왜 곱할까?
캐릭터가 초당 100만큼 이동한다고 가정해보겠습니다.
float speed = 100.0f; position += speed * deltaTime;
만약 deltaTime이 0.016666초라면:
이동 거리 = 100 * 0.016666
= 1.6666
즉, 한 프레임 동안 캐릭터는 1.6666만큼 이동합니다.
🧩 프레임별로 보면 이렇게 됩니다
시간 흐름 0.000초 ── 0.016초 ── 0.032초 ── 0.048초 │ │ │ │ 1프레임 2프레임 3프레임 4프레임 각 프레임 deltaTime ≒ 약 0.016666초
이 경우 매 프레임 이동량은 다음과 같습니다.
1프레임 이동량 = 100 * 0.016666 ≒ 1.6666 2프레임 이동량 = 100 * 0.016666 ≒ 1.6666 3프레임 이동량 = 100 * 0.016666 ≒ 1.6666
그래서 1초 동안 누적하면:
1.6666 * 60프레임 ≒ 100
오차를 제외하면 초당 대략 100만큼 이동하게 됩니다.
⚠️ deltaTime을 사용하지 않으면?
만약 이렇게 작성하면 어떻게 될까요?
position += speed;
이 코드는 프레임마다 100씩 이동합니다.
30FPS 환경 → 1초에 30번 이동 → 100 * 30 = 3000 60FPS 환경 → 1초에 60번 이동 → 100 * 60 = 6000 144FPS 환경 → 1초에 144번 이동 → 100 * 144 = 14400
즉, 게임이 실행되는 환경에 따라 같은 시간(1초)이 경과했을 때의 결과가 달라지고,
FPS가 높은 컴퓨터일수록 캐릭터가 더 빠르게 움직입니다.
실행되는 컴퓨터(하드웨어)의 환경이 달라지더라도 동일한 시간이 흘렀을 때 동일한 결과를 출력해야 합니다.
✅ deltaTime을 사용하면?
position += speed * deltaTime;
이렇게 작성하면 FPS가 달라도 이동 속도가 비슷하게 유지됩니다.
30FPS → deltaTime 약 0.033초 → 100 * 0.033 * 30 ≒ 100 60FPS → deltaTime 약 0.016초 → 100 * 0.016 * 60 ≒ 100 144FPS → deltaTime 약 0.0069초 → 100 * 0.0069 * 144 ≒ 100
🎯 왜 중요한가
게임 루프에서 deltaTime을 사용하면:
- 프레임 독립성 확보
- 다양한 환경에서 동일한 동작
결국 핵심은 이것입니다.
프레임마다 움직이는 양을 정하는 것이 아니라,
실제로 흐른 시간만큼 움직이게 만드는 것
C++ 게임 루프에서 deltaTime은
프레임 독립성을 유지하기 위한 핵심 요소입니다.
이러한 구조는 단순한 예제가 아니라,
실제 게임 엔진 내부에서 그대로 사용되는 방식입니다.
🎮 실제 엔진에서는 어떻게 동작할까?
Unity나 Unreal 같은 엔진에서도
👉 동일한 구조가 존재합니다.
예를 들어 Unity:
- Update()
- FixedUpdate()
Unreal:
- Tick()
👉 내부적으로는 모두 게임 루프 기반입니다.
🧩 조금 더 발전된 구조
하지만 단순한 루프는 부족합니다.
실제 엔진에서는:
- 입력 처리
- 물리 처리
- 렌더링
- 시간 관리
- 등등
👉 여러 단계로 나누어 프레임 처리를 실행합니다.
🔥 핵심 정리
- 게임 루프는 게임에서 프레임을 처리하기 위한 반복 구조
- Tick / Draw 등으로 구성된다
- 프레임 시간(deltaTime)이 반드시 필요하다
🎮 마무리
게임 루프는 단순한 while문이 아니라
👉 게임 엔진 구조의 핵심 개념입니다.
🧠 한 단계 더 생각해보기
여기서 중요한 질문이 하나 더 있습니다.
❓ 프레임을 “고정”해야 할까?
❓ 아니면 “가변”으로 둬야 할까?
👉 이 부분은 게임 루프에서 매우 중요한 주제입니다.
참고로 게임 루프에 대한 더 깊은 이론적 배경은
Robert Nystrom의 『Game Programming Patterns』 중 Game Loop 장을 참고해보셔도 좋습니다.
🎯 다음 글 예고
다음 글에서는 단순한 개념이 아니라
C++로 실제 고정 프레임 게임 루프를 구현하면서
FPS 제어와 busy wait 방식까지 함께 살펴보겠습니다.
👉 C++ 게임 루프 구현 (고정 프레임 방식)
- Fixed timestep
- FPS 제어
- Busy wait 방식
🚀 한 단계 더 나아가고 싶다면
아래 강의도 참고해보셔도 좋습니다.