게임을 개발하려면 먼저 수학을 공부해라
“피타고라스의 정리를 설명해 보세요.”
스타트업을 운영하던 시절, 개발자 면접에서 내가 자주 던지던 질문이다. 중학교 수학이니 누구나 3초 만에 답할 줄 알았다. 그런데 실제로는 대학을 졸업한, 심지어 공대를 나온 지원자의 절반 이상이 제대로 답하지 못했다. a² + b²까지는 어렵게 꺼내는데, 그게 무엇을 뜻하는지, 어디에 쓰는지로 넘어가면 거기서 말이 끊겼다.
나는 그런 지원자를 거의 다 떨어뜨렸다. 냉정해 보이지만 이유는 분명했다.
면접에서 피타고라스를 묻는 진짜 이유
공식을 외웠는지 확인하려던 질문이 아니다. 그 질문 하나로 세 가지를 봤다.
- 기본기 — 12년 배운 것 중 가장 자주 쓰는 연장을 기억하고 있는가
- 연결력 — 그 공식이 지금 만드는 게임의 어느 코드와 이어지는지 떠올리는가
- 태도 — “그냥 엔진 함수 쓰면 되잖아요"에서 멈추는 사람인가, 그 안이 궁금한 사람인가
셋 중에서도 세 번째가 결정적이었다. 게임 개발에서 피타고라스 정리는 교양이 아니라 매일 손에 쥐는 연장이다. 캐릭터와 몬스터 사이의 거리를 재는 그 순간, 이미 그 공식을 쓰고 있는 거다.
좌표 (20, 20)에 플레이어가 있고 (100, 80)에 적이 있다고 하자. x 차이 80과 y 차이 60으로 직각삼각형이 만들어지고, 빗변은 100이다. 그리고 이 100이라는 숫자 하나로 “적이 도망칠지, 공격할지"가 갈린다. AI 로직도, 사거리 판정도, 어그로 범위도 전부 여기서 시작한다.
Unity Korea의 수포자를 위한 게임수학 영상에서도 이 예시를 가장 먼저 꺼낸다. 두 캐릭터의 거리 측정이 실시간 렌더링 콘텐츠에서 제일 흔하게 쓰이는 연산이라는 것이다. 내 경험과 정확히 같다.
수학 없이 게임 없다
과장 없이 쓴다. 게임 개발에서 수학은 선택 과목이 아니라 언어다.
그리고 최적화된 게임이란 결국 수학을 잘 이용해서 가장 빠르게 연산하는 로직을 만드는 기술이다. 같은 결과를 내는 코드라도 어떤 수학적 형태로 표현하느냐에 따라 프레임이 갈린다.
가장 알기 쉬운 예가 거리 비교다. 위 영상에서는 매그니튜드(길이) 연산이 비싼 이유를 제곱근 때문이라고 설명한다. 루트 연산이 사이클을 많이 먹으니까, 단순히 “누가 더 가까운가"만 볼 거라면 제곱근을 씌우지 말고 제곱 상태 그대로 비교하라는 것이다. a가 b보다 크면 a²도 b²보다 크니까 대소 관계는 바뀌지 않는다.
| 상황 | 나쁜 선택 | 좋은 선택 |
|---|---|---|
| 사거리 안인지 판정 | 거리를 구한 뒤 반경과 비교 | 거리의 제곱과 반경의 제곱을 비교 |
| 방향만 필요할 때 | 벡터를 그대로 사용 | 정규화(normalize)해서 길이 1로 |
| 각도 회전 | 매 프레임 삼각함수 재계산 | 필요한 시점에만 계산하고 결과 캐싱 |
이 차이를 아는 사람과 모르는 사람이 짠 코드는, 몬스터가 10마리일 때는 똑같아 보인다. 500마리가 되는 순간 갈라진다. 나는 바로 그 지점이 중수와 고수를 나눈다고 생각한다. 보통과 최고를 나누는 자리도 같다.
벡터는 이미 매일 쓰고 있다
면접에서 두 번째로 확인하던 건 벡터였다. 신기하게도 “벡터가 뭔가요"에는 다들 답한다. “크기와 방향을 가진 양"이라고. 교과서 문장 그대로다.
문제는 그다음이다.
“그럼 지금 만들고 계신 게임에서 벡터를 어디에 쓰셨어요?”
여기서 막히면 그건 아는 게 아니다. 영상에서도 짚듯이, 유니티에서 모든 오브젝트가 가진 Transform의 position이 이미 벡터다. 유니티를 켜는 순간 누구나 벡터를 쓰고 있는 거다. 다만 그걸 ‘포지션’이라는 이름으로 부를 뿐이다.
벡터에서 실무자가 몸으로 알아야 할 건 이 정도다.
- 덧셈 — a 벡터 끝에 b 벡터를 이어 붙이는 것. 부모-자식 오브젝트의 상대 위치, 하이어라키 구조를 다룰 때 계속 나온다.
- 뺄셈 — B에서 A로 향하는 벡터를 만드는 것. “적이 나를 향하는 방향"이 여기서 나온다.
- 정규화 — 길이를 1로 만들어 순수한 방향만 남기는 것. 셰이더와 물리 연산이 이걸 전제로 돌아간다.
- 길이 — 내부적으로 피타고라스 정리 그 자체다.
넷 다 유니티가 함수로 제공한다. Vector2.Distance도 뚜껑을 열면 피타고라스다. 그래서 몰라도 쓸 수는 있다. 영상에서도 “알고 쓰는 것과 모르고 쓰는 것은 차이가 있다"고 반복해서 말한다.
나는 여기서 조금 더 나간다. 모르고 쓰면 버그가 났을 때 손을 못 댄다. 캐릭터가 이상한 방향으로 미끄러질 때, 정규화를 빠뜨렸는지 부호를 뒤집었는지 판단하려면 결국 벡터 연산이 머릿속에 그림으로 그려져야 한다. 함수 이름만 아는 사람은 그 순간 검색창을 열고, 그림이 그려지는 사람은 코드를 연다. 이 차이가 하루짜리 버그와 5분짜리 버그를 만든다.
삼각함수는 총알과 캐릭터가 증명한다
삼각함수는 많은 사람에게 첫 번째 좌절 지점이다. 나도 학교에서 “사인은 필기체 s를 이렇게 그으니까"라는 식으로 배웠다. 그건 이해가 아니라 암기법이다.
실제로 게임에서 삼각함수가 뭘 하는지 보면 훨씬 단순하다.
사인과 코사인은 원을 그린다. 반지름이 1인 원 위의 점에서 x가 코사인, y가 사인이다. 빗변이 1이라 나눗셈이 생략됐을 뿐이다.
그래서 방사형 멀티샷을 만들 때 이 둘을 쓴다. 위 영상의 데모가 정확히 이걸 보여준다. 총알 10발을 90도 부채꼴로 뿌린다면 순서는 이렇다.
- 전체 각도를 (총알 수 - 1)로 나눠 간격을 구한다
- 시작 각도를 전체 각도의 절반만큼 음수로 잡는다
- 반복문을 돌며 각도를 누적한다
- 각도를 라디안으로 변환한다
- 방향 벡터의 x에 코사인, y에 사인을 넣는다
탄젠트는 기울기다. 사인을 코사인으로 나눈 값, 즉 x가 늘어날 때 y가 얼마나 변하는지다. 탑다운 게임에서 캐릭터가 이동 방향을 바라보게 만들 때, 속도 벡터를 정규화하고 Atan2(y, x)로 각도를 얻어 회전에 넣는다. 각도를 모르는 상태에서 방향으로부터 각도를 역으로 구하는 것이라 역삼각함수(아크탄젠트)를 쓴다.
이 두 개만 직접 손으로 짜봐도 삼각함수는 더 이상 시험 범위가 아니게 된다. 게임을 만드는 도구가 된다.
도(degree)와 라디안을 헷갈리면 캐릭터가 돈다
실무에서 본 가장 흔한 초보 버그가 각도 단위다.
유니티 인스펙터의 Rotation은 도(60분법)다. 사람이 읽기 편하라고 만든 단위다. 반면 수학 함수는 라디안을 받는다. 반지름이 1일 때 호의 길이가 1인 각도가 1라디안이고, π가 180도에 대응한다.
Mathf.Sin에 45를 그냥 넣으면 45도가 아니라 45라디안이 들어간다. 캐릭터는 당연히 엉뚱한 데를 본다. Mathf.Deg2Rad와 Mathf.Rad2Deg가 존재하는 이유가 이거다.
이걸 “함수 두 개 외우기"로 넘기면 또 틀린다. 왜 두 단위가 따로 있는지, 어느 쪽이 사람용이고 어느 쪽이 수학용인지 한 번만 이해하면 다시는 안 틀린다.
그래서 무엇을 공부해야 하나
나는 개발자에게 수학과 전공 수준의 지식을 요구하지 않는다. 영상의 강연자도 “게임 개발에 딱 필요한 부분만 안다"고 솔직하게 말한다. 나도 같은 입장이다. 필요한 범위는 생각보다 훨씬 좁다.
체크리스트로 정리하면 이 정도다.
- 피타고라스 정리를 두 캐릭터의 거리로 설명할 수 있다
- 제곱근 연산이 비싸다는 걸 알고, 비교만 할 땐 제곱 상태로 비교한다
- 벡터의 덧셈과 뺄셈을 화살표 그림으로 그릴 수 있다
- 정규화가 왜 필요한지 한 문장으로 말할 수 있다
- 사인과 코사인이 원을 그린다는 걸 안다
- 탄젠트가 기울기라는 걸 알고, Atan2를 회전에 써봤다
- 도와 라디안을 변환할 줄 안다
전부 중학교와 고등학교 초반 범위다. 다만 학교에서 배운 방식으로는 부족하다. 공식을 외운 상태와, 그 공식이 코드 한 줄로 변환되는 경로를 아는 상태는 완전히 다른 상태다.
공부 방법은 단순하다. 개념 하나를 읽으면 반드시 그걸로 뭔가를 하나 만들어봐라. 벡터 뺄셈을 읽었으면 적이 플레이어를 추적하는 코드를 짜고, 사인을 읽었으면 부채꼴 탄막을 쏴보는 거다. 만들어본 수학만 남는다.
용어는 영어로 보는 게 빠르다
하나 덧붙이고 싶은 게 있다. 위 영상에서 인상 깊었던 지적인데, 우리가 쓰는 수학 용어 상당수가 일본식 한자를 거쳐 들어오면서 실생활과 멀어졌다는 이야기다.
‘빗변’이 대표적이다. 영어로는 hypotenuse인데, hypo(아래)와 teinein 계열 어원이 붙은 말이라 “아래로 당겨진 변"이라는 감각이 단어에 살아 있다. ‘제곱’과 ‘정사각형’도 영어에서는 둘 다 square다. 제곱이 곧 정사각형의 넓이라는 게 단어 하나로 드러난다.
이 지적에는 나도 동의한다. 실제로 셰이더나 엔진 문서를 읽다 보면 한국어 번역서보다 원문이 훨씬 빨리 이해되는 경우가 많다. normalize, magnitude, opposite, adjacent 같은 단어를 영어 그대로 익혀두면 문서와 코드와 머릿속 개념이 하나로 붙는다.
마치며
- 개발자 면접에서 피타고라스 정리를 물으면 절반 이상이 답을 못 했고, 나는 그들을 뽑지 않았다.
- 게임 개발에서 수학은 교양이 아니라 매일 쓰는 연장이다. 거리 판정 한 줄에 이미 들어 있다.
- 최적화란 결국 수학으로 가장 빠른 연산 로직을 만드는 기술이고, 여기서 중수와 고수가 갈린다.
- 벡터와 삼각함수는 개념을 아는 데서 끝나면 안 된다. 코드로 만들어본 만큼만 실력이 된다.
- 필요한 범위는 좁다. 다만 외운 상태가 아니라 그림으로 그려지는 상태여야 한다.
자주 묻는 질문
Q. 게임 개발자가 되려면 수학을 어느 정도까지 알아야 하나?
전공 수준은 필요 없다. 피타고라스 정리, 벡터 연산(덧셈·뺄셈·정규화·길이), 삼각함수(사인·코사인·탄젠트), 라디안 개념 정도가 출발선이다. 이후 셰이더나 3D 회전을 다루게 되면 내적·외적과 행렬, 쿼터니언으로 넘어간다.
Q. 엔진이 함수를 다 제공하는데 원리를 알아야 하나?
써먹는 데는 몰라도 된다. 하지만 버그가 났을 때, 그리고 성능을 짜내야 할 때 차이가 난다. 방향이 이상하게 나오거나 프레임이 떨어질 때 원인을 짚으려면 함수 안쪽이 그림으로 그려져야 한다.
Q. 수학을 완전히 놓았는데 지금 시작해도 되나?
된다. 필요한 범위가 좁은 데다 게임이라는 눈에 보이는 결과가 있어서 학교 수학보다 훨씬 잘 붙는다. 개념 하나를 읽을 때마다 그걸로 작은 기능을 하나씩 만들어보는 방식을 권한다.
Q. 왜 거리 비교에 제곱근을 쓰지 말라고 하나?
제곱근 연산이 CPU 사이클을 많이 먹기 때문이다. 크기 비교만 할 때는 양쪽 모두 제곱 상태로 둬도 대소 관계가 바뀌지 않는다. 그래서 엔진들도 제곱된 길이를 반환하는 별도 함수를 제공한다.
Q. 벡터 정규화(normalize)는 언제 쓰나?
방향만 필요하고 크기는 필요 없을 때 쓴다. 이동 방향, 조명 계산, 셰이더의 법선 벡터 같은 것들이 대표적이다. 길이를 1로 맞춰두면 이후 연산이 크게 단순해진다.
