---
title: "연산자는 값을 만든다"
description: "+, %, ==, && 같은 기호들이 각각 무엇을 하고 어떤 값을 만드는지 한 번에 봅니다. = 와 == 의 차이부터 ++ 의 전위와 후위까지."
author: "유니얼"
pubDate: 2026-09-08
category: "programming/csharp/basics"
tags: ["C#", "기초"]
canonical: https://blog.unialgames.com/posts/csharp-operators/
---
지금까지 쓴 기호는 `=` 와 `+` 정도였습니다.
앞으로 나올 코드에는 `%`, `!=`, `&&`, `+=` 같은 게 섞여 나옵니다.

기호마다 하는 일은 다르지만 공통점이 하나 있습니다.

> **연산자는 값을 받아서 값을 만듭니다.**

`7 + 3` 은 `10` 이라는 값을 만들고, `5 > 3` 은 `true` 라는 값을 만듭니다.
**계산을 하는 게 아니라 값을 만든다**고 보는 게 정확합니다.

## 계산하는 기호 (산술 연산자)

| 기호 | 하는 일 | 예시 | 결과 |
| --- | --- | --- | --- |
| `+` | 더하기 | `7 + 3` | `10` |
| `-` | 빼기 | `7 - 3` | `4` |
| `*` | 곱하기 | `7 * 3` | `21` |
| `/` | 나누기 | `7 / 3` | `2` |
| `%` | 나눈 **나머지** | `7 % 3` | `1` |

`7 / 3` 이 `2` 인 게 이상하면 앞 글을 보세요.
정수끼리 나누면 몫만 남고 나머지는 그 자리에서 버려집니다.

`-` 는 빼기 말고 **부호를 뒤집는 데도** 씁니다.

```csharp
int a = 5;
int b = -a;    // -5
```

### `%` 는 나머지를 줍니다

처음 보는 기호일 겁니다. `7 ÷ 3` 은 몫이 2에 나머지가 1이니
`7 / 3` 은 `2` 고 `7 % 3` 은 `1` 입니다.

**나눗셈보다 오히려 자주 씁니다.**

```csharp
if (n % 2 == 0)                       // 2로 나눈 나머지가 0이면 짝수
{
    Console.WriteLine("짝수");
}

index = (index + 1) % items.Count;    // 끝에 가면 0으로 돌아옵니다
```

두 번째 것은 앞에서 본 정수의 원과 같은 이야기입니다.
`%` 는 **값을 정해진 범위 안에서 돌게 만드는 도구**입니다.

## 값을 쓰는 기호 (대입 연산자)

| 기호 | 하는 일 | 줄이기 전 |
| --- | --- | --- |
| `=` | 오른쪽 값을 왼쪽 자리에 쓴다 | |
| `+=` | 더해서 다시 쓴다 | `a = a + 5` |
| `-=` | 빼서 다시 쓴다 | `a = a - 5` |
| `*=` | 곱해서 다시 쓴다 | `a = a * 5` |
| `/=` | 나눠서 다시 쓴다 | `a = a / 5` |
| `%=` | 나머지를 구해 다시 쓴다 | `a = a % 5` |

```csharp
int a = 10;
a += 5;    // 15
a *= 2;    // 30
a -= 5;    // 25
```

### `=` 는 "같다"가 아니다

수학에서 `=` 는 양쪽이 같다는 뜻입니다. 프로그래밍에서는 아닙니다.

> **`=` 는 "오른쪽을 계산해서 왼쪽 자리에 써라" 는 명령입니다.**

그래서 `a = a + 10` 이 말이 됩니다. 수학이었다면 성립할 수 없는 문장입니다.
앞에서 본 대로 **왼쪽은 자리고 오른쪽은 값**입니다.

`a += 10` 은 그걸 줄여 쓴 것뿐이고, 실제로는 세 가지 일이 일어납니다.

<x-steps>
<script type="application/json">
{
  "label": "a += 10 이 하는 일",
  "steps": [
    { "tag": "STEP 1", "title": "읽는다", "text": "a 의 자리에서 지금 값을 가져옵니다. 20이었다고 합시다." },
    { "tag": "STEP 2", "title": "계산한다", "text": "가져온 20에 10을 더해 30을 만듭니다. 이 시점에 메모리는 아직 20입니다." },
    { "tag": "STEP 3", "title": "다시 쓴다", "text": "만든 30을 a 의 자리에 씁니다. 이제 메모리가 30입니다." }
  ]
}
</script>
</x-steps>

읽고, 계산하고, 다시 씁니다. 이 분해가 다음 기호를 설명합니다.

## 1씩 올리고 내리는 기호 (증감 연산자)

| 기호 | 하는 일 | 줄이기 전 |
| --- | --- | --- |
| `++` | 1 더한다 | `a = a + 1` |
| `--` | 1 뺀다 | `a = a - 1` |

반복문에서 가장 많이 봅니다. 그런데 **붙이는 위치가 앞이냐 뒤냐**로 나뉩니다.

### `++` 의 차이는 식이 건네는 값이다

전위와 후위를 헷갈리는 이유는 **"어느 쪽이 먼저 증가하나"** 로 외우기 때문입니다.
그렇게 보면 안 됩니다.

<x-compare>
<script type="application/json">
{
  "label": "전위와 후위",
  "tabs": [
    { "label": "전위 ++n", "code": "int n = 5;\nint x = ++n;\n\n// n = 6\n// x = 6", "stats": [["메모리의 n", "6"], ["식이 건넨 값", "6 (올린 뒤의 값)"]], "tone": "good" },
    { "label": "후위 n++", "code": "int n = 5;\nint x = n++;\n\n// n = 6\n// x = 5", "stats": [["메모리의 n", "6"], ["식이 건넨 값", "5 (올리기 전의 값)"]], "tone": "good" }
  ]
}
</script>
</x-compare>

**두 경우 모두 메모리의 `n` 은 6이 됩니다.** 거기에는 차이가 없습니다.
다른 것은 **그 식이 주변에 건네주는 값**입니다.

- `++n` 은 올린 다음 그 값을 건넵니다
- `n++` 은 올리기 전 값을 건네고 나서 올립니다

번호표를 뽑는 것과 같습니다. 번호를 올린 뒤에 뽑느냐, 뽑고 나서 올리느냐입니다.
어느 쪽이든 다음 사람이 받을 번호는 같습니다.

그래서 **식의 값을 아무도 안 쓰는 자리에서는 차이가 없습니다.**

```csharp
for (int i = 0; i < 10; i++)   // i++ 든 ++i 든 똑같습니다
```

`for` 문의 세 번째 칸은 값을 건네받는 사람이 없습니다.
성능 차이도 없습니다. 그냥 습관대로 쓰면 됩니다.

## 견주는 기호 (비교 연산자)

| 기호 | 뜻 | 예시 | 결과 |
| --- | --- | --- | --- |
| `==` | 같다 | `5 == 5` | `true` |
| `!=` | 다르다 | `5 != 3` | `true` |
| `>` | 크다 | `5 > 3` | `true` |
| `<` | 작다 | `5 < 3` | `false` |
| `>=` | 크거나 같다 | `5 >= 5` | `true` |
| `<=` | 작거나 같다 | `3 <= 5` | `true` |

**`=` 와 `==` 는 완전히 다릅니다.** 등호 하나는 "써라" 는 명령이고,
등호 두 개가 "같으냐" 는 질문입니다. 처음에 제일 많이 틀리는 자리입니다.

### 비교의 결과는 언제나 `bool`

`10 > 5` 는 숫자를 만들지 않습니다. **참이나 거짓 하나를 만듭니다.**

```csharp
bool result = 10 > 5;      // true
Console.WriteLine(10 > 5); // True
```

양팔 저울과 같습니다. 무게가 얼마인지는 안 알려주고
**어느 쪽이 무거운지만** 알려줍니다.

그래서 `if` 안에 들어갈 수 있는 것은 `bool` 뿐입니다.
C 나 C++ 에서는 0이 아니면 참으로 쳤지만 C# 은 아닙니다.

```csharp
int a = 5;
if (a) { }        // 컴파일 에러: int 를 bool 로 변환할 수 없습니다
if (a != 0) { }   // 이렇게 써야 합니다
```

이 규칙이 유명한 실수 하나를 막아줍니다.

```csharp
if (a = 5) { }    // 컴파일 에러
```

`=` 는 대입이라 이 식이 만드는 값은 `5`(int)입니다. `bool` 이 아니니 컴파일이 안 됩니다.
C 에서는 이게 그냥 돌아가서 잡기 어려운 버그가 됐습니다.
**C# 에서는 오타가 빌드 단계에서 걸립니다.**

## 조건을 엮는 기호 (논리 연산자)

조건 하나로 모자랄 때 씁니다. **받는 것도 `bool` 이고 만드는 것도 `bool`** 입니다.

| 기호 | 뜻 | 예시 | 결과 |
| --- | --- | --- | --- |
| `&&` | 그리고 (둘 다 참이어야) | `true && false` | `false` |
| `\|\|` | 또는 (하나만 참이면) | `true \|\| false` | `true` |
| `!` | 아니다 (뒤집는다) | `!true` | `false` |

```csharp
if (hp > 0 && !isStunned)        // 체력이 있고, 기절 상태가 아니면
if (isVip || totalSpent > 100)   // VIP 이거나, 많이 썼으면
```

`!` 는 뒤집기만 합니다. `!isStunned` 는 "기절이 아니면" 이라고 읽습니다.
`bool` 변수 이름을 `is...` · `has...` 로 지으면 이 줄이 문장처럼 읽힙니다.

## 정리

- 연산자는 값을 받아서 값을 만든다.
- `%` 는 나눈 나머지다. 짝수 판별이나 순환 인덱스에 쓴다.
- `=` 는 "같다" 가 아니라 "오른쪽을 계산해 왼쪽 자리에 써라" 는 명령이다.
- `a += 10` 은 읽고 · 계산하고 · 다시 쓰는 세 가지 일이다.
- `++` 의 전위와 후위는 메모리 결과가 같다. 다른 건 식이 건네는 값이다.
- 비교의 결과는 언제나 `bool` 이다. 그래서 `if (a = 5)` 가 컴파일 에러로 걸린다.
- 논리 연산자는 `bool` 을 받아 `bool` 을 만든다.