---
title: "방향 (x, y) 로 각도 구하기: 총구를 마우스로 돌리는 Atan2"
description: "2D 게임에서 총구를 마우스 쪽으로 돌리려면 방향 (x, y) 에서 각도를 구해야 합니다. 세로 ÷ 가로 가 tan 이고, 그 비율에서 각도를 거꾸로 찾는 것이 Atan 입니다. Atan 이 정반대 방향을 가리지 못하는 이유와 Atan2 가 그것을 고치는 과정을 숫자로 따라갑니다."
author: "유니얼"
pubDate: 2026-11-05
category: "game-dev/math"
tags: ["Unity", "기초"]
canonical: https://blog.unialgames.com/posts/math-angle/
---
2D 슈팅 게임에서 총구가 마우스 쪽을 보게 하고 싶습니다.
마우스 쪽 방향 (3, 3) 은 빼기 한 번으로 나오지만, 총을 돌리려면 45° 라는 **각도**가 필요합니다.

세로 ÷ 가로 를 tan 이라 부르고, 그 비율에서 각도를 거꾸로 찾는 함수가 Atan 입니다.
그런데 Atan 은 (1, 1) 과 (−1, −1) 처럼 정반대인 방향에 같은 각도를 줘서, 마우스가 왼쪽 아래에 있으면 총구가 오른쪽 위를 봅니다.
x 와 y 를 따로 받는 **`Mathf.Atan2(y, x)`** 가 네 방향 모두에서 맞는 각도를 줍니다.

> **방향 (x, y) 의 각도는 `Mathf.Atan2(y, x)` 입니다. y 가 먼저입니다.
> 결과는 −180° ~ 180° 를 라디안으로 준 값이라, 도로 쓰려면 `Mathf.Rad2Deg` 를 곱합니다.
> `Atan(y / x)` 는 오른쪽 절반의 각도만 알아서, 왼쪽을 가리키는 방향에서 정반대를 줍니다.**

## 무엇을 알고 무엇을 구하나

**방향**은 "어느 쪽으로 얼마나" 를 가로와 세로 두 숫자로 적은 화살표입니다. 도착 위치에서 출발 위치를 빼면 출발에서 도착으로 가는 화살표가 나옵니다.
총이 (1, 2), 마우스가 (4, 5) 에 있으면 방향은 (4 − 1, 5 − 2) = **(3, 3)** 입니다. 오른쪽으로 3, 위로 3 입니다.

이 화살표 끝에서 바닥으로 수직선을 내리면 직각삼각형(한 각이 90° 인 삼각형)이 생깁니다. 바닥에 누운 변이 **가로 x**, 내린 수직선이 **세로 y** 이고, 우리가 구할 것은 화살표와 바닥(오른쪽, +x) 사이의 각 θ 입니다. θ(세타)는 x 가 "어떤 수" 를 뜻하듯 "어떤 각도" 를 가리키는 글자입니다.

<x-vec>
<script type="application/json">
{
  "label": "총 (1, 2) 에서 마우스 (4, 5) 로",
  "view": [-0.8, -0.8, 5.6, 5.8],
  "steps": [
    { "caption": "총은 (1, 2), 마우스는 (4, 5) 에 있습니다.", "items": [
        {"id": "g", "type": "point", "at": [1, 2], "color": "text", "label": "총 (1, 2)", "labelAt": [1, 1.55]},
        {"id": "m", "type": "point", "at": [4, 5], "color": "accent2", "label": "마우스 (4, 5)", "labelAt": [4, 5.45]}
      ] },
    { "caption": "도착 − 출발 = (4 − 1, 5 − 2) = (3, 3). 오른쪽으로 3, 위로 3 가는 화살표입니다.", "items": [
        {"id": "g", "type": "point", "at": [1, 2], "color": "text", "label": "총 (1, 2)", "labelAt": [1, 1.55]},
        {"id": "m", "type": "point", "at": [4, 5], "color": "accent2", "label": "마우스 (4, 5)", "labelAt": [4, 5.45]},
        {"id": "d", "from": [1, 2], "to": [4, 5], "color": "accent", "label": "방향 (3, 3)", "labelAt": [1.9, 4.0]}
      ] },
    { "caption": "같은 화살표를 원점에서 출발하게 옮겼습니다. 방향은 출발점과 상관없이 (3, 3) 입니다.", "items": [
        {"id": "d", "from": [0, 0], "to": [3, 3], "color": "accent", "label": "방향 (3, 3)", "labelAt": [1.0, 2.2]}
      ] },
    { "caption": "화살표 끝에서 바닥으로 수직선을 내리면 직각삼각형입니다. 가로 3, 세로 3 은 알고, 바닥과 화살표 사이의 각 θ 를 모릅니다.", "items": [
        {"id": "d", "from": [0, 0], "to": [3, 3], "color": "accent", "label": "방향 (3, 3)", "labelAt": [1.0, 2.2]},
        {"id": "h", "type": "line", "from": [0, 0], "to": [3, 0], "color": "muted", "label": "가로 x = 3", "labelAt": [1.5, -0.45]},
        {"id": "v", "type": "line", "from": [3, 0], "to": [3, 3], "color": "muted", "label": "세로 y = 3", "labelAt": [3.95, 1.5]},
        {"id": "t", "type": "text", "at": [0.85, 0.32], "label": "θ = ?", "color": "warn"}
      ] }
  ]
}
</script>
</x-vec>

| 아는 것 | 구할 것 |
| --- | --- |
| 가로 x = 3, 세로 y = 3 | 바닥에서 몇 도 들렸나 (θ) |

각도에서 가로와 세로를 구할 때는 cos 와 sin 을 씁니다. 길이 1 인 화살표를 θ 만큼 들면 끝이 (cos θ, sin θ) 에 있습니다. 30° 면 (0.87, 0.5) 입니다.
여기서는 그 반대입니다. 가로와 세로를 알고 **각도를 모릅니다.** 그래서 가로와 세로 둘만으로 각도를 정해 주는 비율이 필요합니다.

## tan 은 세로 ÷ 가로 다

**tan θ = 세로 ÷ 가로** 입니다. "탄젠트" 라고 읽고, 비탈의 기울기와 같은 말입니다. 옆으로 1 갈 때 위로 얼마 가는가입니다.
cos 와 sin 처럼 이 비율도 삼각형의 크기와 상관없이 각도만으로 정해집니다. (1, 1) 도 (3, 3) 도 세로 ÷ 가로 는 1 입니다.

| 각도 | 길이 1 일 때 (가로, 세로) | tan = 세로 ÷ 가로 |
| --- | --- | --- |
| 0° | (1, 0) | 0 ÷ 1 = 0 |
| 30° | (0.87, 0.5) | 0.5 ÷ 0.87 = 0.58 |
| 45° | (0.71, 0.71) | 1 |
| 60° | (0.5, 0.87) | 0.87 ÷ 0.5 = 1.73 |
| 90° | (0, 1) | 1 ÷ 0. 나눌 수 없음 |

각이 커질수록 비탈이 가팔라져 tan 이 커지고, 90° 에서는 가로가 0 이라 값이 없습니다.

<x-vec>
<script type="application/json">
{
  "label": "tan = 세로 ÷ 가로",
  "view": [-0.6, -0.7, 4.2, 4.2],
  "cases": [
    { "name": "각도를 바꾸면", "steps": [
      { "caption": "0°. 비탈이 없어 위로 0. tan 0° = 0.", "items": [
          {"id": "a", "from": [0, 0], "to": [1, 0.0], "color": "accent"},
          {"id": "h", "type": "line", "from": [0, 0], "to": [1, 0], "color": "muted", "label": "가로 1", "labelAt": [0.5, -0.4]},
          {"id": "v", "type": "line", "from": [1, 0], "to": [1, 0.0], "color": "accent2", "label": "세로 0", "labelAt": [1.65, 0.25]},
          {"id": "t", "type": "text", "at": [0.42, 0.14], "label": "0°", "color": "warn"}
        ] },
      { "caption": "30°. 옆으로 1 갈 때 위로 0.58. tan 30° = 0.58.", "items": [
          {"id": "a", "from": [0, 0], "to": [1, 0.58], "color": "accent"},
          {"id": "h", "type": "line", "from": [0, 0], "to": [1, 0], "color": "muted", "label": "가로 1", "labelAt": [0.5, -0.4]},
          {"id": "v", "type": "line", "from": [1, 0], "to": [1, 0.58], "color": "accent2", "label": "세로 0.58", "labelAt": [1.65, 0.29]},
          {"id": "t", "type": "text", "at": [0.42, 0.14], "label": "30°", "color": "warn"}
        ] },
      { "caption": "45°. 옆으로 1, 위로 1. tan 45° = 1.", "items": [
          {"id": "a", "from": [0, 0], "to": [1, 1.0], "color": "accent"},
          {"id": "h", "type": "line", "from": [0, 0], "to": [1, 0], "color": "muted", "label": "가로 1", "labelAt": [0.5, -0.4]},
          {"id": "v", "type": "line", "from": [1, 0], "to": [1, 1.0], "color": "accent2", "label": "세로 1", "labelAt": [1.65, 0.5]},
          {"id": "t", "type": "text", "at": [0.42, 0.14], "label": "45°", "color": "warn"}
        ] },
      { "caption": "60°. 옆으로 1 갈 때 위로 1.73. tan 60° = 1.73.", "items": [
          {"id": "a", "from": [0, 0], "to": [1, 1.73], "color": "accent"},
          {"id": "h", "type": "line", "from": [0, 0], "to": [1, 0], "color": "muted", "label": "가로 1", "labelAt": [0.5, -0.4]},
          {"id": "v", "type": "line", "from": [1, 0], "to": [1, 1.73], "color": "accent2", "label": "세로 1.73", "labelAt": [1.65, 0.865]},
          {"id": "t", "type": "text", "at": [0.42, 0.14], "label": "60°", "color": "warn"}
        ] },
      { "caption": "75°. 위로 3.73. 90° 에 가까울수록 세로가 끝없이 커지고, 90° 에서는 가로가 0 이라 나눌 수 없습니다.", "items": [
          {"id": "a", "from": [0, 0], "to": [1, 3.73], "color": "accent"},
          {"id": "h", "type": "line", "from": [0, 0], "to": [1, 0], "color": "muted", "label": "가로 1", "labelAt": [0.5, -0.4]},
          {"id": "v", "type": "line", "from": [1, 0], "to": [1, 3.73], "color": "accent2", "label": "세로 3.73", "labelAt": [1.65, 1.865]},
          {"id": "t", "type": "text", "at": [0.42, 0.14], "label": "75°", "color": "warn"}
        ] }
    ] },
    { "name": "크기만 바꾸면", "steps": [
      { "caption": "(1, 1). 세로 ÷ 가로 = 1 ÷ 1 = 1. 크기가 달라도 각도가 45° 로 같으면 비율도 1 입니다.", "items": [
          {"id": "a", "from": [0, 0], "to": [1, 1], "color": "accent", "label": "(1, 1)", "labelAt": [0.55, 1.3]},
          {"id": "h", "type": "line", "from": [0, 0], "to": [1, 0], "color": "muted", "label": "가로 1", "labelAt": [0.5, -0.4]},
          {"id": "v", "type": "line", "from": [1, 0], "to": [1, 1], "color": "accent2", "label": "세로 1", "labelAt": [1.6, 0.5]},
          {"id": "t", "type": "text", "at": [0.42, 0.14], "label": "45°", "color": "warn"}
        ] },
      { "caption": "(2, 2). 세로 ÷ 가로 = 2 ÷ 2 = 1. 크기가 달라도 각도가 45° 로 같으면 비율도 1 입니다.", "items": [
          {"id": "a", "from": [0, 0], "to": [2, 2], "color": "accent", "label": "(2, 2)", "labelAt": [1.55, 2.3]},
          {"id": "h", "type": "line", "from": [0, 0], "to": [2, 0], "color": "muted", "label": "가로 2", "labelAt": [1.0, -0.4]},
          {"id": "v", "type": "line", "from": [2, 0], "to": [2, 2], "color": "accent2", "label": "세로 2", "labelAt": [2.6, 1.0]},
          {"id": "t", "type": "text", "at": [0.42, 0.14], "label": "45°", "color": "warn"}
        ] },
      { "caption": "(3, 3). 세로 ÷ 가로 = 3 ÷ 3 = 1. 크기가 달라도 각도가 45° 로 같으면 비율도 1 입니다.", "items": [
          {"id": "a", "from": [0, 0], "to": [3, 3], "color": "accent", "label": "(3, 3)", "labelAt": [2.55, 3.3]},
          {"id": "h", "type": "line", "from": [0, 0], "to": [3, 0], "color": "muted", "label": "가로 3", "labelAt": [1.5, -0.4]},
          {"id": "v", "type": "line", "from": [3, 0], "to": [3, 3], "color": "accent2", "label": "세로 3", "labelAt": [3.6, 1.5]},
          {"id": "t", "type": "text", "at": [0.42, 0.14], "label": "45°", "color": "warn"}
        ] }
    ] }
  ]
}
</script>
</x-vec>

## arctan 은 tan 을 거꾸로 돌린다

tan 은 **각도를 넣으면 비율**을 줍니다. 우리는 비율을 알고 각도를 알고 싶으니 거꾸로 가는 함수가 필요합니다.
그것이 **arctan**(아크탄젠트)이고, 코드에서는 줄여서 **Atan** 이라고 씁니다. tan⁻¹ 라고도 적습니다.

| tan 의 방향 | arctan 의 방향 |
| --- | --- |
| tan 45° = 1 | Atan(1) = 45° |
| tan 30° = 0.58 | Atan(0.58) = 30° |
| tan 60° = 1.73 | Atan(1.73) = 60° |

방향 (4, 3) 이면 세로 ÷ 가로 = 3 ÷ 4 = 0.75 이고, Atan(0.75) ≈ 36.9° 입니다. (3, 3) 은 3 ÷ 3 = 1 이라 45° 입니다.

이것으로 문제가 풀린 것 같지만, 마우스가 총의 왼쪽으로 가면 틀립니다.

## Atan 은 정반대 방향을 가리지 못한다

(1, 1) 은 오른쪽 위, (−1, −1) 은 왼쪽 아래로 정반대입니다. 그런데 세로 ÷ 가로 를 구하면

| 방향 | 가리키는 곳 | 세로 ÷ 가로 | Atan |
| --- | --- | --- | --- |
| (1, 1) | 오른쪽 위 | 1 ÷ 1 = 1 | 45° |
| (−1, −1) | 왼쪽 아래 | (−1) ÷ (−1) = 1 | 45° (틀림) |
| (1, −1) | 오른쪽 아래 | (−1) ÷ 1 = −1 | −45° |
| (−1, 1) | 왼쪽 위 | 1 ÷ (−1) = −1 | −45° (틀림) |

음수끼리 나누면 양수가 되고, 한쪽만 음수면 결과가 음수일 뿐 **어느 쪽이 음수였는지는 사라집니다.** 비율 1 하나만 받은 Atan 은 그것이 (1, 1) 에서 왔는지 (−1, −1) 에서 왔는지 알 방법이 없습니다.
그래서 Atan 은 늘 **−90° ~ 90°**, 곧 원의 오른쪽 절반(x 가 양수인 쪽) 각도만 돌려줍니다. 왼쪽 절반을 가리키는 방향은 정반대로 뒤집혀 나옵니다.
x 가 0 인 바로 위 (0, 1) 은 1 ÷ 0 이라 나누는 것부터 할 수 없습니다.

<x-vec>
<script type="application/json">
{
  "label": "네 방향에서 Atan(y / x)",
  "view": [-1.8, -1.8, 1.8, 1.8],
  "steps": [
    { "caption": "(1, 1). 1 ÷ 1 = 1, Atan(1) = 45°. 총구가 마우스 쪽을 봅니다.", "items": [
        {"id": "c", "type": "circle", "at": [0, 0], "r": 1, "color": "muted"},
        {"id": "m", "type": "point", "at": [1, 1], "color": "accent2", "label": "마우스 (1, 1)", "labelAt": [1.15, 1.35]},
        {"id": "g", "from": [0, 0], "to": [0.71, 0.71], "color": "accent", "label": "Atan: 45°", "labelAt": [1.1, 0.35]}
      ] },
    { "caption": "(−1, −1). (−1) ÷ (−1) = 1 이라 답이 또 45°. 총구는 마우스의 정반대를 봅니다.", "items": [
        {"id": "c", "type": "circle", "at": [0, 0], "r": 1, "color": "muted"},
        {"id": "m", "type": "point", "at": [-1, -1], "color": "accent2", "label": "마우스 (−1, −1)", "labelAt": [-1.05, -1.4]},
        {"id": "g", "from": [0, 0], "to": [0.71, 0.71], "color": "warn", "label": "Atan: 45° (틀림)", "labelAt": [1.15, 0.35]}
      ] },
    { "caption": "(1, −1). (−1) ÷ 1 = −1, Atan(−1) = −45°. 맞습니다.", "items": [
        {"id": "c", "type": "circle", "at": [0, 0], "r": 1, "color": "muted"},
        {"id": "m", "type": "point", "at": [1, -1], "color": "accent2", "label": "마우스 (1, −1)", "labelAt": [1.1, -1.4]},
        {"id": "g", "from": [0, 0], "to": [0.71, -0.71], "color": "accent", "label": "Atan: −45°", "labelAt": [1.1, -0.35]}
      ] },
    { "caption": "(−1, 1). 1 ÷ (−1) = −1 이라 답이 −45°. 또 정반대입니다.", "items": [
        {"id": "c", "type": "circle", "at": [0, 0], "r": 1, "color": "muted"},
        {"id": "m", "type": "point", "at": [-1, 1], "color": "accent2", "label": "마우스 (−1, 1)", "labelAt": [-1.05, 1.4]},
        {"id": "g", "from": [0, 0], "to": [0.71, -0.71], "color": "warn", "label": "Atan: −45° (틀림)", "labelAt": [1.15, -0.35]}
      ] },
    { "caption": "Atan 은 나눗셈 결과 하나만 받아서, 답이 늘 오른쪽 절반(−90° ~ 90°)에 떨어집니다. 마우스가 왼쪽 절반에 있으면 정반대가 나옵니다.", "items": [
        {"id": "c", "type": "circle", "at": [0, 0], "r": 1, "color": "muted"},
        {"id": "b", "type": "line", "from": [0, -1.6], "to": [0, 1.6], "color": "muted"},
        {"id": "r", "type": "text", "at": [0.95, 1.5], "label": "Atan 의 답이 나오는 쪽", "color": "accent"},
        {"id": "l", "type": "text", "at": [-0.95, 1.5], "label": "답이 안 나오는 쪽", "color": "warn"}
      ] }
  ]
}
</script>
</x-vec>

## Atan2 는 x 와 y 를 따로 받아 고친다

`Atan2(y, x)` 는 나누기 전의 x 와 y 를 따로 받습니다. 그래서 Atan 이 잃어버린 부호를 보고 반쪽을 고칠 수 있습니다. 하는 일은 이렇습니다.

| 경우 | Atan2 가 하는 일 | 예 |
| --- | --- | --- |
| x 가 양수 (오른쪽 절반) | Atan(y ÷ x) 를 그대로 | (1, 1) → 45° |
| x 가 음수, y 가 0 이상 (왼쪽 위) | Atan(y ÷ x) 에 180° 를 더함 | (−1, 1) → −45° + 180° = 135° |
| x 가 음수, y 가 음수 (왼쪽 아래) | Atan(y ÷ x) 에서 180° 를 뺌 | (−1, −1) → 45° − 180° = −135° |
| x 가 0 | 나누지 않고 y 의 부호만 봄 | (0, 1) → 90°, (0, −1) → −90° |

180° 를 옮기는 것은 화살표를 원점에 대고 **정반대로 뒤집는 일**입니다. Atan 이 뒤집어서 준 답을 다시 뒤집어 원래 쪽으로 돌려놓는 것입니다.
결과는 −180° ~ 180° 안에 둡니다. 오른쪽 0° 를 가운데 두고 위쪽은 +, 아래쪽은 − 로 대칭이 되게 한 것이고, 그래서 아래쪽(y 가 음수)에서는 180° 를 빼서 음수로 맞춥니다. 왼쪽 아래가 225° 가 아니라 −135° 로 나오는 이유입니다. 225° 와 −135° 는 같은 방향입니다(225 − 360 = −135).

<x-vec>
<script type="application/json">
{
  "label": "Atan2 가 주는 각도 (−180° ~ 180°)",
  "view": [-1.8, -1.5, 1.8, 1.5],
  "steps": [
    { "caption": "오른쪽이 0°. 위로 돌면 +, 아래로 돌면 − 입니다.", "items": [
        {"id": "c", "type": "circle", "at": [0, 0], "r": 1, "color": "muted"},
        {"id": "a0", "from": [0, 0], "to": [1, 0], "color": "accent", "label": "0°", "labelAt": [1.2, 0.15]},
        {"id": "a90", "from": [0, 0], "to": [0, 1], "color": "accent", "label": "90°", "labelAt": [0.25, 1.15]},
        {"id": "am90", "from": [0, 0], "to": [0, -1], "color": "accent", "label": "−90°", "labelAt": [0.3, -1.15]}
      ] },
    { "caption": "왼쪽 위는 위로 돌아 135°, 왼쪽 아래는 아래로 돌아 −135° 입니다.", "items": [
        {"id": "c", "type": "circle", "at": [0, 0], "r": 1, "color": "muted"},
        {"id": "a0", "from": [0, 0], "to": [1, 0], "color": "accent", "label": "0°", "labelAt": [1.2, 0.15]},
        {"id": "a90", "from": [0, 0], "to": [0, 1], "color": "accent", "label": "90°", "labelAt": [0.25, 1.15]},
        {"id": "am90", "from": [0, 0], "to": [0, -1], "color": "accent", "label": "−90°", "labelAt": [0.3, -1.15]},
        {"id": "a135", "from": [0, 0], "to": [-0.71, 0.71], "color": "accent2", "label": "135°", "labelAt": [-0.95, 0.9]},
        {"id": "am135", "from": [0, 0], "to": [-0.71, -0.71], "color": "accent2", "label": "−135°", "labelAt": [-0.95, -0.9]}
      ] },
    { "caption": "바로 왼쪽은 위로 돌아도 아래로 돌아도 닿습니다. 180° 와 −180° 는 같은 방향입니다.", "items": [
        {"id": "c", "type": "circle", "at": [0, 0], "r": 1, "color": "muted"},
        {"id": "a0", "from": [0, 0], "to": [1, 0], "color": "accent", "label": "0°", "labelAt": [1.2, 0.15]},
        {"id": "a90", "from": [0, 0], "to": [0, 1], "color": "accent", "label": "90°", "labelAt": [0.25, 1.15]},
        {"id": "am90", "from": [0, 0], "to": [0, -1], "color": "accent", "label": "−90°", "labelAt": [0.3, -1.15]},
        {"id": "a135", "from": [0, 0], "to": [-0.71, 0.71], "color": "accent2", "label": "135°", "labelAt": [-0.95, 0.9]},
        {"id": "am135", "from": [0, 0], "to": [-0.71, -0.71], "color": "accent2", "label": "−135°", "labelAt": [-0.95, -0.9]},
        {"id": "a180", "from": [0, 0], "to": [-1, 0], "color": "warn", "label": "180° = −180°", "labelAt": [-1.05, 0.18]}
      ] },
    { "caption": "반시계로 225° 돈 자리와 시계로 135° 돈 자리는 같습니다. Atan2 는 −135° 로 줍니다.", "items": [
        {"id": "c", "type": "circle", "at": [0, 0], "r": 1, "color": "muted"},
        {"id": "a0", "from": [0, 0], "to": [1, 0], "color": "accent", "label": "0°", "labelAt": [1.2, 0.15]},
        {"id": "a90", "from": [0, 0], "to": [0, 1], "color": "accent", "label": "90°", "labelAt": [0.25, 1.15]},
        {"id": "am90", "from": [0, 0], "to": [0, -1], "color": "accent", "label": "−90°", "labelAt": [0.3, -1.15]},
        {"id": "a135", "from": [0, 0], "to": [-0.71, 0.71], "color": "accent2", "label": "135°", "labelAt": [-0.95, 0.9]},
        {"id": "am135", "from": [0, 0], "to": [-0.71, -0.71], "color": "accent2", "label": "−135° (= 225°)", "labelAt": [-1.1, -1.1]},
        {"id": "a180", "from": [0, 0], "to": [-1, 0], "color": "warn", "label": "180° = −180°", "labelAt": [-1.05, 0.18]}
      ] }
  ]
}
</script>
</x-vec>

| 방향 | 세로 ÷ 가로 | `Atan` | `Atan2(y, x)` |
| --- | --- | --- | --- |
| (1, 1) | 1 | 45° | 45° |
| (−1, −1) | 1 | 45° (틀림) | −135° |
| (−1, 1) | −1 | −45° (틀림) | 135° |
| (0, 1) | 0 으로 나눔 | 계산 불가 | 90° |

인자 순서가 `(y, x)` 인 것은 tan 이 **세로 ÷ 가로** 라서입니다. 나눗셈의 위(y)를 먼저, 아래(x)를 나중에 적습니다.

## 코드: 총구를 마우스 쪽으로

유니티의 `Mathf.Atan2` 는 각도를 도가 아니라 **라디안**으로 줍니다. 라디안은 반지름 1 인 원에서 그 각만큼 돈 호의 길이로 각을 재는 단위이고, 180° 가 π(약 3.14) 입니다.

라디안으로 재면 반지름 1 인 원에서 1 라디안 돌 때 원 위를 정확히 1 만큼 갑니다. 반지름이 r 이면 간 거리는 r × 각 입니다. 도로 재면 이런 식마다 × π ÷ 180 이 붙습니다. sin · cos · atan 공식도 이 변환이 없는 라디안으로 만들어져 있어서, C# 의 `System.Math` 와 유니티의 `Mathf` 도 라디안을 받고 돌려줍니다.

`Mathf.Rad2Deg`(180 ÷ π ≈ 57.3)를 곱하면 도가 됩니다. (−1, −1) 이면 `Atan2` 가 −2.36 을 주고, −2.36 × 57.3 ≈ −135° 입니다.

```csharp
// 마우스의 화면 픽셀 좌표를 월드 좌표로 바꾼다
// 2D 기본 카메라(Orthographic, 멀어도 작아지지 않게 찍는 방식) 기준이다
Vector2 mouseWorldPosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);

// 총에서 마우스로 가는 방향 (도착 − 출발)
Vector2 toMouse = mouseWorldPosition - (Vector2)transform.position;

// y 가 먼저, x 가 나중. 결과는 라디안이다
float radians = Mathf.Atan2(toMouse.y, toMouse.x);

// 라디안에 Rad2Deg(약 57.3)를 곱해 도로 바꾼다
float angle = radians * Mathf.Rad2Deg;

// Quaternion 은 유니티가 회전을 담는 자료형이다
// Quaternion.Euler 는 도 단위 각도로 회전값을 만든다. 2D 는 z 축으로 돈다
transform.rotation = Quaternion.Euler(0f, 0f, angle);
```

`Atan2` 의 0° 는 오른쪽(+x)이고, 각이 커지면 반시계 방향으로 돕니다. 유니티 2D 에서 z 회전이 커질 때 도는 방향도 반시계라서 그대로 넣으면 맞습니다.

다만 총 스프라이트가 **오른쪽을 보도록** 그려져 있어야 합니다. 위(+y)를 보도록 그려져 있으면 회전 0° 에서 이미 90° 쪽을 보고 있으므로, `angle - 90f` 를 넣어야 마우스를 봅니다.

| 스프라이트가 그려진 방향 | 넣을 각도 |
| --- | --- |
| 오른쪽 (+x) | `angle` |
| 위 (+y) | `angle - 90f` |

## 조심할 것

- **`Atan2` 의 인자는 y 가 먼저**입니다. 오른쪽 (1, 0) 은 `Atan2(0, 1)` = 0° 인데, 순서를 바꿔 `Atan2(1, 0)` 으로 쓰면 90° 가 나와 총구가 위를 봅니다
- **`Atan2` 는 라디안**을 줍니다. `Rad2Deg` 를 빼먹으면 −135° 대신 −2.36° 만큼만 돌아 거의 오른쪽을 봅니다. 반대로 `Quaternion.Euler`, `transform.eulerAngles`, 에디터의 Rotation 은 도를 씁니다
- **방향이 (0, 0) 이면 각도가 없습니다.** `Atan2(0, 0)` 은 0 을 돌려주니, 마우스가 총과 정확히 겹치면 총구가 갑자기 오른쪽을 봅니다. 방향의 길이가 아주 작을 때는 회전을 건너뜁니다
- **−180° 와 180° 는 같은 방향인데 숫자는 360 차이**입니다. 바로 왼쪽 근처에서 마우스가 위아래로 살짝만 움직여도 각도가 179° 에서 −179° 로 튑니다. 두 각도의 차이를 그냥 빼면 358° 가 나오니, 차이는 `Mathf.DeltaAngle(a, b)` 로 구합니다. `Mathf.DeltaAngle(179f, -179f)` 는 2 입니다

## 정리

- 방향 (x, y) 에서 각도를 구하는 문제입니다. 화살표 끝에서 수직선을 내리면 가로 x, 세로 y 인 직각삼각형이 됩니다
- tan θ = 세로 ÷ 가로 이고, 비율에서 각도를 거꾸로 찾는 것이 arctan(Atan) 입니다. Atan(1) = 45° 입니다
- Atan 은 나눗셈 결과 하나만 받아 부호를 잃습니다. (1, 1) 과 (−1, −1) 에 같은 45° 를 주고, −90° ~ 90° 만 돌려줍니다
- `Atan2(y, x)` 는 x 가 음수면 180° 를 옮겨 왼쪽 절반을 고치고, x 가 0 이어도 답을 줍니다. 결과는 −180° ~ 180° 입니다
- 결과는 라디안이니 `Mathf.Rad2Deg` 를 곱하고, 스프라이트가 위를 보게 그려졌으면 90° 를 뺍니다