게임 프로그래밍을 하려면 수학부터 공부해라 (2탄)
게임 프로그래머가 되려는 후배들에게 나는 여전히 수학 공부의 중요성을 강조한다. 모든 수학이라기보다는, 게임에서 유독 자주 쓰이는 수학이 따로 있다. 벡터, 삼각함수, 행렬.
두 직선이 이루는 각도를 구해야 하는 상황이 오면 나는 생각하기 전에 손이 먼저 움직인다. 코사인 법칙이나 벡터의 내적, 둘 중 하나다. 부드럽게 움직이는 무언가를 만들어야 하면 삼각함수를 꺼낸다. 고민의 단계가 없다.
이건 내가 똑똑해서가 아니다. 하도 많이 써서 그렇다. 게임을 만들다 보면 같은 문제가 형태만 바꿔서 계속 돌아오고, 그때마다 같은 도구를 집어 들게 된다. 그러다 어느 순간부터 벡터와 삼각함수가 공식처럼 손에 붙는다.
총알이 비행기를 따라가지 않는 순간
가장 알기 쉬운 예가 슈팅 게임의 총알이다.
Unity Korea의 수포자를 위한 게임수학 2부 영상도 정확히 이 장면으로 시작한다. 멀티샷을 사인과 코사인으로 각도를 나눠 쏘는 데까지는 잘 된다. 그런데 비행기가 회전하면 총알은 여전히 오른쪽으로만 날아간다. 영상에서는 이걸 “어색하잖아요"라고 표현한다.
이 어색함의 정체가 수학 문제다.
- 총알 자체의 발사각: 알파
- 비행기가 회전한 각: 베타
- 최종적으로 필요한 각: 알파 + 베타
여기서 초보자가 가장 먼저 시도하는 게 cos(α) + cos(β)다. 그리고 틀린다. 각도는 더할 수 있어도, 각도의 코사인끼리는 더할 수 없다. 영상에서도 이 지점을 짚으며 삼각함수 덧셈 정리를 꺼낸다.
학교에서 외운 ‘싸코플코싸’가 여기서 나온다
sin(α+β) = sinα·cosβ + cosα·sinβ.
학교에서 리듬으로 외웠던 그 공식이다. 나도 시험 끝나고 바로 버렸다. 영상 진행자도 똑같이 말한다. 학교에서는 이게 어디에 쓰이는지 안 알려주고 외우라고만 했다고.
그런데 게임을 만들면 이게 회전의 공식이라는 걸 알게 된다. 총알이 회전하고, 오브젝트가 회전하고, 카메라가 회전한다. 회전이 없는 게임은 없다.
내가 이 공식을 다시 좋아하게 된 지점이 여기다. 공식이 아니라 문제를 먼저 만났기 때문이다. “비행기가 돌면 총알도 돌아야 한다"는 문제를 손에 쥐고 나서 공식을 보면, 그건 외울 대상이 아니라 답이다.
엔진이 대신 해주는 것과 내가 알아야 하는 것
“유니티가 다 해주는데 굳이?“라는 반문이 나올 만하다.
실제로 해보면 그렇게 간단하지 않다. 영상에서는 비행기의 Z 회전값을 얻으려면 Transform → rotation(쿼터니언) → 오일러 각 변환 → 라디안 변환 순서를 밟아야 한다고 설명한다. 아니면 플레이어 클래스에 회전값을 계속 저장해두고 총알에서 참조하는 방식이 있는데, 이건 코드가 지저분해진다.
반면 삼각함수 덧셈 정리를 알면 총구 방향 벡터와 총알의 원래 각도만으로 곧장 계산된다.
| 접근 | 필요한 단계 | 결과 |
|---|---|---|
| 쿼터니언 경유 | rotation → eulerAngles → Deg2Rad → 재계산 | 동작하지만 우회가 길다 |
| 회전값 캐싱 | 플레이어 클래스에 상태 저장 → 총알에서 참조 | 클래스 간 결합도 상승 |
| 덧셈 정리 적용 | 총구 방향 벡터 + 원래 각도 | 식 한 줄, 의존성 없음 |
내 경험으로는, 엔진 API로 우회한 코드는 나중에 반드시 발목을 잡는다. 다른 오브젝트에 재사용하려 할 때, 최적화가 필요할 때, 셰이더로 옮겨야 할 때. 수식으로 쓴 코드는 그대로 옮겨진다.
내적은 낯선 개념이 아니다
벡터의 내적도 마찬가지다. 나는 이걸 셰이더에서도 쓰고 게임 코어 로직에서도 쓴다. 쓰는 빈도로 따지면 게임 수학에서 상위권이다.
내적의 두 얼굴은 이렇다.
A·B = |A||B|cosθ— 두 벡터가 이루는 각도를 알려준다.A·B = ax·bx + ay·by + az·bz— 성분끼리 곱해서 더한다.
같은 값이다. 표현만 다르다. 영상에서는 이 두 식이 결국 피타고라스 정리와 제2 코사인 법칙에서 유도된다는 걸 보여준다. 즉 내적은 새로운 개념이 아니라 이미 아는 것을 다르게 쓴 것이다.

그림 하나로 보면 감이 더 빨리 온다. 초록 벡터 b에서 파란 벡터 a로 수직선을 내리면 주황색 화살표가 남는다. 이게 정사영, 그러니까 “b가 a 방향으로 얼마나 기여하는가"다. 45도에 길이가 3이니 정사영은 약 2.12, 여기에 a의 길이 4를 곱하면 8.49가 나온다. 내적이라는 게 결국 한 벡터를 다른 벡터 방향으로 눌러 붙인 다음 길이를 곱한 값이라는 얘기다.
그래서 부호가 곧바로 의미가 된다. 그림처럼 두 벡터가 예각이면 정사영이 앞쪽으로 남아 양수, 90도를 넘어가면 정사영이 반대편으로 넘어가서 음수. 각도를 실제로 구하지 않아도 부호만 보면 “앞이냐 뒤냐"가 끝난다.
실무에서는 두 번째 식을 쓴다. 코사인 연산은 컴퓨터 입장에서 비싼 연산이기 때문이다. 영상에서도 같은 이유로 코드에서는 성분 곱셈 형태를 쓴다고 설명한다.
정규화하면 계산이 무너져 내린다
두 벡터의 길이를 1로 맞춰두면 |A||B|가 사라지고 cosθ만 남는다. 위 그림에서 4와 3이라는 길이가 통째로 지워지고 cos 45°만 남는 셈이다. 그러면 결과값이 이렇게 정리된다.
- 같은 방향 → 1
- 직각 → 0
- 반대 방향 → -1
이 세 줄이 게임 로직의 절반을 처리한다. 적이 내 뒤에 있는지, 시야각 안에 들어왔는지, 빛이 면을 정면으로 때리는지. 셰이더의 기본 조명 처리도 이 원리다. 빛의 방향과 면의 법선 방향을 내적해서 밝기를 정한다.
그래서 수학부터 공부하라는 거다
여기까지 오면 내 결론이 왜 그런지 보일 거다.
게임 개발자가 되려면 수학부터 공부해야 한다. 문법이나 엔진 사용법보다 먼저다. 이유는 세 가지다.
첫째, 단순한 움직임이 자연스러워진다. 사인 값에 시간을 곱해 넣으면 물결, 바람, 호흡, 흔들림이 나온다. 이걸 조건문과 상수로 흉내 내려면 코드는 몇 배로 늘어나고 결과는 어색하다.
둘째, 무거운 계산이 가벼워진다. 각도를 구하려고 아크코사인을 부르는 대신 내적 결과의 부호만 보면 되는 경우가 많다. 수식을 아는 것과 모르는 것의 차이가 프레임으로 나타난다.
셋째, AI에게 끌려다니지 않는다. 영상에서도 이 얘기가 나온다. 자료를 만들면서 AI에게 공식 그림을 요청했더니 이상한 걸 주는 경우가 많았다고. 알고 있어야 틀린 걸 걸러낸다. 의존과 보조의 차이가 여기서 갈린다.
수포자였어도 늦지 않다
한 가지는 솔직하게 말해두겠다. 게임에서 쓰는 수학은 순수 수학의 전 범위가 아니다.
영상에서도 이 점을 짚는다. 그래픽스에서 다루는 행렬은 4×4, 3×3 같은 정방행렬뿐이고, 좌표계도 유클리드 좌표계다. 양자역학 쪽 수학과 비교하면 다루는 영역이 훨씬 제한적이다.
즉 필요한 건 넓이가 아니라 순서다.
순서대로 밟으면 되는 체크리스트
- 피타고라스 정리 — 모든 것의 출발점
- 삼각비와 단위원 — x는 cos, y는 sin
- 벡터 덧셈·뺄셈 — 위치와 방향의 차이
- 벡터 내적 — 각도, 유사도, 조명
- 삼각함수 덧셈 정리 — 회전
- 행렬 — 회전·이동·스케일의 통합
수학은 스텝이 끊기면 그다음이 막힌다. 중간에 하나를 놓치면 뒤가 통째로 어려워 보인다. 어렵게 느껴진다면 재능 문제가 아니라 순서 문제일 가능성이 크다.
공부하는 법에 대한 내 방식
나는 공식을 먼저 외우는 방식을 권하지 않는다.
만들고 싶은 걸 먼저 정한다. 총알을 부채꼴로 뿌리고 싶다, 적이 내 뒤에 있는지 알고 싶다, 물체를 둥실 떠 있게 하고 싶다. 그다음 그 문제를 푸는 데 필요한 수학만 파고든다. 그렇게 몇 번 반복하면 도구가 손에 남는다.
지금 당장 해볼 수 있는 세 가지를 적어둔다.
- 부채꼴 발사 — for문으로 각도를 나누고 cos, sin으로 방향 벡터를 만든다. 개수와 간격만 바꿔가며 패턴을 만들어보면 된다.
- 뒤통수 판정 — 내 정면 벡터와 (적 위치 - 내 위치) 벡터를 정규화해서 내적한다. 값이 음수면 뒤다.
- 둥실거리는 오브젝트 — y 위치에
sin(시간 × 속도) × 진폭을 더한다. 진폭과 속도만 조절해도 느낌이 크게 달라진다.
세 개 다 30분 안에 된다. 그리고 이 셋을 만들어본 사람과 아닌 사람은, 반년 뒤 코드가 완전히 달라져 있다.
마치며
- 게임 수학은 별도의 학문이 아니라 피타고라스 정리에서 뻗어나온 한 줄기다. 내적도, 덧셈 정리도 결국 같은 뿌리다.
- 엔진이 대신 해주는 부분은 있지만, 원리를 모르면 우회 경로만 길어지고 코드가 지저분해진다.
- 내적은 한 벡터를 다른 벡터 방향으로 눌러 붙인 값이다. 정규화하면 1, 0, -1로 정리되고, 이 세 값이 방향 판정과 조명 처리의 기본이 된다.
- 공식부터 외우지 말고 만들고 싶은 것부터 정한 뒤 필요한 수학을 파는 순서가 훨씬 빠르다.
- 어렵게 느껴진다면 재능이 아니라 순서의 문제다. 피타고라스 → 삼각비 → 벡터 → 내적 → 덧셈 정리 → 행렬 순으로 밟으면 된다.
자주 묻는 질문
Q. 게임 개발에 수학이 정말 필수인가?
캐주얼한 2D 게임이라면 엔진 기능만으로도 어느 정도는 만들 수 있다. 다만 회전, 조명, 물리, 셰이더 중 하나라도 건드리는 순간 벡터와 삼각함수는 피할 수 없다. 나는 늦게 배울수록 코드가 지저분해진다고 본다.
Q. 수포자인데 어디부터 시작해야 하나?
피타고라스 정리와 단위원부터다. 단위원에서 x는 코사인, y는 사인이라는 사실 하나만 확실히 잡아도 벡터와 내적으로 넘어가는 길이 열린다. 순서를 건너뛰면 뒤가 통째로 어려워 보인다.
Q. 벡터의 내적은 실제로 어디에 쓰나?
두 벡터가 이루는 각도를 구할 때, 적이 시야각 안에 있는지 판정할 때, 셰이더에서 빛의 방향과 면의 방향을 비교해 밝기를 정할 때 쓴다. 벡터를 정규화해두면 결과가 -1에서 1 사이로 나와 바로 쓸 수 있다.
Q. 삼각함수 덧셈 정리는 게임에서 뭘 할 때 쓰나?
회전이다. 이미 각도를 가진 오브젝트에 추가 회전을 더할 때, 각도끼리 그냥 더한 뒤 다시 사인·코사인을 계산하는 대신 덧셈 정리로 곧장 방향 벡터를 구할 수 있다. 회전 행렬도 같은 원리에서 나온다.
Q. AI에게 물어보면 되지 않나?
보조로는 훌륭하다. 다만 참고한 영상에서도 AI가 수식 그림을 잘못 만들어준 사례를 언급한다. 내가 알고 있어야 틀린 답을 걸러낼 수 있다. 의존이냐 보조냐는 결국 내 이해도에 달려 있다.
