deltaTime 완벽 이해 | 왜 프레임마다 시간이 다를까?

//
//

🚀 들어가며

deltaTime은 게임 개발에서 반드시 이해해야 하는 핵심 개념입니다.

게임을 만들다가 이런 경험을 해보셨을 겁니다.

컴퓨터가 빠르면 게임이 빨라지고
컴퓨터가 느리면 게임이 느려진다

같은 코드인데 실행 환경에 따라 게임 속도가 달라집니다.

이 문제를 해결하는 핵심 개념이 바로 deltaTime입니다.


🎯 문제 상황

C++ deltaTime 개념 설명 이미지, 프레임 속도에 따른 이동 차이와 일정한 속도 유지 구조
프레임마다 시간이 달라도 deltaTime을 사용하면 일정한 속도를 유지할 수 있습니다.
position += speed;

이 코드는 매 프레임마다 위치를 증가시킵니다.

문제는 프레임 수입니다.

60 FPS → 1초에 60번 실행
120 FPS → 1초에 120번 실행

즉, 프레임이 많을수록 더 많이 이동합니다.

60 FPS → 60번 이동
120 FPS → 120번 이동

👉 결과: 컴퓨터 성능에 따라 게임 속도가 달라짐


//

🎯 deltaTime이란 무엇인가?

이 문제에 대한 해결 방법은 deltaTime을 적용하는 것입니다.

그렇다면, deltaTime이란 무엇일까요?

deltaTime은 바로 이전 프레임과 현재 프레임 사이의 시간입니다.

deltaTime = 현재 시간 - 이전 시간

이 값을 이용하면 “프레임 기준”이 아니라 “시간 기준”으로 계산할 수 있습니다.

position += speed * deltaTime;

🧠 직관적으로 이해하기

deltaTime은 “속도” 개념으로 이해하면 쉽습니다.

이동 거리 = 속도 × 시간

게임에서도 동일합니다.

👉 speed는 “1초 동안 이동하는 거리”
👉 deltaTime은 “이번 프레임에서 흐른 시간”


🔢 실제 숫자로 이해하기

speed = 10 (1초에 10 이동)

60 FPS:

deltaTime ≈ 0.016
10 * 0.016 = 0.16

120 FPS:

deltaTime ≈ 0.008
10 * 0.008 = 0.08

👉 프레임마다 이동량은 다르지만
👉 1초 기준 이동량은 동일합니다


🎮 deltaTime 계산하기

아래 코드는 Windows에서 제공하는 고해상도 타이머인 QueryPerformanceCounter를 활용해 deltaTime을 계산한 코드입니다.

#include <Windows.h>

LARGE_INTEGER frequency;
QueryPerformanceFrequency(&frequency);

LARGE_INTEGER prevTime;
QueryPerformanceCounter(&prevTime);

while (true)
{
    LARGE_INTEGER currentTime;
    QueryPerformanceCounter(&currentTime);

    float deltaTime =
        static_cast(currentTime.QuadPart - prevTime.QuadPart)
        / static_cast(frequency.QuadPart);

    prevTime = currentTime;
}

🔍 코드 설명

먼저 QueryPerformanceFrequency는 고해상도 타이머가 1초에 몇 번 카운트되는지 알려줍니다.

LARGE_INTEGER frequency;
QueryPerformanceFrequency(&frequency);

예를 들어 frequency.QuadPart 값이 10,000,000이라면,
타이머가 1초에 10,000,000번 증가한다는 의미입니다.

그 다음 QueryPerformanceCounter를 이용해 현재 카운터 값을 가져옵니다.

LARGE_INTEGER prevTime;
QueryPerformanceCounter(&prevTime);

이 값은 이전 프레임 시간을 저장하기 위한 기준값입니다.

루프 안에서는 매 프레임 다시 현재 시간을 가져옵니다.

LARGE_INTEGER currentTime;
QueryPerformanceCounter(&currentTime);

이제 현재 시간과 이전 시간의 차이를 계산합니다.

currentTime.QuadPart - prevTime.QuadPart

하지만 이 값은 아직 “초” 단위가 아닙니다.
고해상도 타이머의 카운터 차이일 뿐입니다.

그래서 이 값을 frequency.QuadPart로 나누어 초 단위 시간으로 변환합니다.

float deltaTime =
    static_cast<float>(currentTime.QuadPart - prevTime.QuadPart)
    / static_cast<float>(frequency.QuadPart);

즉, 이 계산식의 의미는 다음과 같습니다.

deltaTime = (현재 카운터 값 - 이전 카운터 값) / 1초당 카운터 증가량

마지막으로 현재 시간을 이전 시간으로 저장합니다.

prevTime = currentTime;

이 코드가 있어야 다음 프레임에서 새로운 시간 차이를 계산할 수 있습니다.

정리하면 이 코드는 매 프레임마다 다음 흐름을 반복합니다.

현재 시간 측정
↓
이전 시간과 차이 계산
↓
초 단위 deltaTime으로 변환
↓
현재 시간을 다음 프레임의 이전 시간으로 저장

⚠️ 실무에서 중요한 문제

deltaTime이 너무 클 때

deltaTime = 0.5
position += speed * 0.5;

👉 캐릭터가 순간이동처럼 움직일 수 있습니다

그래서 보통 제한을 둡니다.

deltaTime = std::min(deltaTime, 0.033f);

🎯 고정 프레임 vs 가변 프레임

가변 프레임

매 프레임 deltaTime이 다름

고정 프레임

항상 일정한 값 사용

게임 엔진은 상황에 따라 두 방식을 조합합니다.


🧠 게임 루프와의 관계

게임 루프
↓
deltaTime 계산
↓
Tick (Update)
↓
Render

deltaTime은 게임 루프의 핵심입니다.


🧠 deltaTime을 꼭 써야 하는 이유

deltaTime을 사용하지 않으면 게임은 “프레임에 의존적인 구조”가 됩니다.

빠른 컴퓨터 → 게임 빨라짐
느린 컴퓨터 → 게임 느려짐

이 상태에서는 게임 플레이 경험이 사용자 환경에 따라 완전히 달라집니다.

반대로 deltaTime을 적용하면,

모든 환경에서 동일한 속도 유지

가 가능해집니다.

그래서 deltaTime은 단순한 보정 값이 아니라,
게임의 일관성을 보장하는 핵심 요소라고 볼 수 있습니다.


🎯 핵심 정리

  • deltaTime은 프레임 간 시간 차이이다
  • 프레임이 아닌 시간 기준으로 계산해야 한다
  • position += speed * deltaTime 형태로 사용한다
  • 게임 속도를 일정하게 유지하는 핵심 요소이다

이 구조를 이해하면
게임 엔진의 시간 처리 방식이 어떻게 동작하는지 보이기 시작합니다.


🎮 마무리

deltaTime은 단순한 변수 하나처럼 보이지만,

👉 게임 전체 속도를 결정하는 핵심 요소입니다.


🚀 한 단계 더 나아가고 싶다면

deltaTime은 게임 루프, 입력 시스템, 물리 처리와 모두 연결됩니다.

이러한 구조는 단순한 문법 수준이 아니라,
게임 엔진 내부에서 객체를 어떻게 다루는지와 깊이 연결됩니다.

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

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

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

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

단순히 사용하는 것을 넘어서,
엔진이 어떻게 동작하는지 이해하는 데 초점을 맞춘 내용입니다.

//
   

댓글 남기기

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