로딩 화면 미니 게임의 숨겨진 비밀

옛날 격투 게임이나 레이싱 게임을 하다 보면은 로딩 화면에서 미니 게임이 뜨는 경우가 있습니다. 단순하게 이용자의 편의를 위한 서비스처럼 보일 수 있지만 이건 로딩이라는 작업의 구조적인 특성 덕분에 공짜로 가능해지는 것에 가깝습니다. 이번 포스팅에서 해당 구조를 직접 코드로 재현해서 확인해보겠습니다.

1. 로딩은 대체로 기다리는 시간이다

게임이 로딩 화면에서 하는 일들은 대체로 네트워크나 디스크에서 모델, 텍스처, 사운드 파일을 읽어 오는 작업이라고 할 수 있는데요.

이런 작업은 CPU가 계산을 하는 것이 아니라 저장장치가 데이터를 가져올 때까지 그냥 기다리는 입출력 대기 시간이 대부분을 차지합니다. 문제는 이 대기를 게임의 메인 루프(화면을 띄우고 입력을 받는 반복문)가 그대로 떠안으면 그 시간 동안 화면도 그리지 못하고 입력도 받지 못하는 완전히 멈춘 상태가 된다는 것입니다.

2. 비동기 로딩과 동기 로딩의 차이

이 대기를 처리하는 방식은 크게 둘로 나뉘어지는데요. 메인 루프가 로딩 함수를 직접 호출하고 끝날 때까지 그 자리에서 대기하는 동기 로딩과 로딩을 별도의 스레드에 위임하고 메인 루프는 자기 할 일을 계속하는 비동기 로딩입니다.

로딩 화면에서 미니 게임이 가능한 이유는 이 비동기 로딩 방식 덕분이라고 할 수 있는데요. 로딩은 백그라운드에서 알아서 진행되며 메인 루프는 그동안 할 작업이 없어서 노는 것이 아니라 미니 게임의 입력과 화면을 처리하는 데 그 시간을 쓸 수 있는 것입니다.

3. 직접 실험해보았습니다.

말로는 이해가 가도 체감이 잘 되지를 않아서 파이썬을 이용해 2초짜리 가짜 로딩 작업을 만들어 두고 두 방식의 차이를 직접 실험하고 측정해보았는데요.

방법은 다음과 같습니다. 60fps를 목표로 하는 메인 루프를 만들고 동기 방식에서는 로딩 함수를 메인 스레드에서 그대로 호출하였습니다. 비동기 방식에서는 로딩을 별도 스레드에 넘기고 메인 스레드는 2초 동안 원래 목표하던 주기대로 프레임을 계속 세도록 제작했습니다.

결과는 각각 5회씩 반복 측정하였습니다. 동기 방식에서는 2초 내내 메인 루프가 완전히 멈춰서 그 사이에 진행된 프레임이 정확이 0이었습니다. 그러나 비동기 방식에서는 같은 2초 동안 메인 루프가 평균 120프레임(60fps 기준 이론상으로 최댓값과 거의 정확히 일치합니다)을 그대로 처리하였습니다. 로딩 화면에서 미니 게임이 매끄럽게 움직일 수 있는 이유가 숫자로 명확하게 드러난 셈이라고 할 수 있습니다.

비동기 로딩과 동기 로딩 방식에서 2초 동안 처리된 프레임 수를 비교한 실측 막대그래프 데이터

4. 실제 게임 업계에서도 활용한 기법

이 아이디어를 실제로 상품화하고 상용화한 대표적인 사례가 반다이남코입니다. 반다이남코는 1995년경 리지레이서의 로딩 화면에 등장했던 “갤럭시안” 미니게임 방식에 대해서 미국에서 특허를 출원하여 등록 받았고, 이 특허는 2015년에 만료되었다고 합니다.

특허가 유효했던 기간 동안에는 다른 게임사들이 로딩 화면 미니 게임을 자유롭게 넣지 못했다는 이야기가 게임 업계에 잘 알려진 이야기로 남아있을 만큼 이 구조 자체가 상업적 가치를 인정받았던 기법이라는 뜻입니다.

5. 실험의 한계와 주의점

하지만 이번의 실험은 로딩을 디스크 읽기와 같은 입출력 대기로 단순화했다는 한계가 있습니다. 파이썬은 GIL(Global Interpreter Lock)이라는 구조 때문에 CPU 연산이 아주 많은 작업은 스레드를 여러 개 써도 진짜 병렬도 돌지 않습니다.

다행히도 실제 게임의 에셋 로딩도 대부분 입출력 대기가 많기 때문에 이번 포스팅에서 진행한 실험의 결론 자체는 유효합니다. 그러나 만약 로딩 중간에 압축 해제처럼 CPU 연산이 아주 무거운 작업이 섞여 있다면은 이야기가 달라집니다. 실제 게임 엔진들은 이러한 이유로 파이썬의 스레드보다 훨씬 무거운 작업 스케줄러나 별도 프로세스 또는 컴파일 언어의 진짜 병렬 스레드를 활용합니다.

6. 결론

로딩 화면에서 조작 가능한 미니 게임은 그래픽 기술이 아니라 로딩이라는 작업을 어떻게 스레드에 배치하느냐와 연관된 문제였는데요. 로딩을 메인 루프에서 제거하는 순간 그 시간은 더 이상 쓸 데 없는 시간이 아니라 미니 게임을 비롯하여 무엇이든 채워 넣을 수 있는 여유 시간이 된다고 할 수 있습니다.

다음에는 게임 로딩 화면에서 미니 게임을 만나면 그 뒤에는 스레드 하나를 분리하는 결정이 있었다는 것을 떠올리는 것을 추천 드립니다. 작은 인디 게임을 만드는 입장에서도 로딩 스피너 하나만 백그라운드 스레드로 옮겨도 사용자가 느끼는 반응성은 이번 포스팅에서의 실험 만큼이나 극적으로 달라질 수 있습니다.

댓글 남기기