---
title: "배열은 번호가 붙은 칸 한 줄이다"
description: "값 하나에 변수 하나씩 만들면 백 개를 다룰 수 없습니다. 배열은 이름 하나에 칸을 여러 개 붙여 번호로 꺼냅니다."
author: "유니얼"
pubDate: 2026-09-08
category: "programming/csharp/collections"
tags: ["C#", "자료구조"]
canonical: https://blog.unialgames.com/posts/csharp-array/
---
지금까지 변수 하나에는 값 하나가 들어갔습니다. 학생 세 명의 점수라면 이렇게 됩니다.

```csharp
int score1 = 90;
int score2 = 85;
int score3 = 78;
```

세 명이면 견딥니다. 백 명이면 변수가 백 개입니다.
평균을 구하려면 백 개를 전부 손으로 더해야 하고,
반복문으로 돌리고 싶어도 `score1`, `score2` 는 이름이라 번호로 셀 수가 없습니다.

앞에서 변수 이름은 컴파일이 끝나면 사라진다고 했습니다.
이름은 사람이 읽으려고 붙인 것이라 **실행 중에 이름을 계산해서 만들 수는 없습니다.**

> **이름 하나에 칸을 여러 개 붙이고, 칸은 번호로 꺼내는 것이 배열입니다.**

## 배열은 이렇게 생겼다

<figure class="diagram">
<svg viewBox="0 0 680 190" role="img" aria-label="배열 선언문의 각 부분. 타입, 대괄호, 이름, new, 칸 개수">
<g font-family="var(--font-mono)" font-size="17">
<text x="30" y="40" fill="var(--text)">int</text>
<text x="70" y="40" fill="var(--accent)">[]</text>
<text x="104" y="40" fill="var(--text)">scores</text>
<text x="184" y="40" fill="var(--text-muted)">=</text>
<text x="208" y="40" fill="var(--accent)">new</text>
<text x="252" y="40" fill="var(--text)">int</text>
<text x="292" y="40" fill="var(--accent)">[5]</text>
<text x="330" y="40" fill="var(--text-muted)">;</text>
</g>
<g stroke="var(--border)" stroke-width="1.4" fill="none">
<path d="M46 52 L46 76 L360 76"></path>
<path d="M80 52 L80 100 L360 100"></path>
<path d="M230 52 L230 124 L360 124"></path>
<path d="M302 52 L302 148 L360 148"></path>
</g>
<g font-size="13" fill="var(--text-muted)">
<text x="372" y="80">칸 하나에 들어갈 타입</text>
<text x="372" y="104">한 칸이 아니라 여러 칸이라는 표시</text>
<text x="372" y="128">실제로 자리를 잡는 것은 여기</text>
<text x="372" y="152">칸 개수. 여기서 정해지고 안 바뀐다</text>
</g>
</svg>
<figcaption>타입 뒤의 대괄호가 배열이라는 표시, new 뒤의 숫자가 칸 개수.</figcaption>
</figure>

`int[]` 는 "정수가 여러 개 들어가는 것" 이라는 타입입니다.
`new int[5]` 가 실제로 칸 다섯 개를 만듭니다.

값을 미리 알고 있으면 한 줄로 쓸 수 있습니다.

```csharp
int[] scores = new int[] { 90, 85, 78 };
int[] scores = { 90, 85, 78 };            // 타입이 뻔하면 이렇게도 됩니다
```

칸 개수를 안 적었는데도 됩니다. 적어 준 값이 세 개니 칸도 세 개입니다.

## 칸에는 0부터 번호가 붙는다

앞에서 문자열의 인덱스를 봤습니다. 배열도 똑같습니다.
**인덱스는 순번이 아니라 시작 지점에서 몇 칸 떨어졌는가**입니다.

<x-array>
<script type="application/json">
{
  "label": "몇 번째 칸이 어디에 있나",
  "types": [["byte", 1], ["short", 2], ["int", 4], ["double", 8]],
  "default": 4,
  "count": 5,
  "baseAddr": 4096,
  "note": "칸 하나의 크기는 타입이 정합니다. 그래서 같은 인덱스라도 타입을 바꾸면 주소가 달라집니다."
}
</script>
</x-array>

칸이 빈틈없이 붙어 있으니 몇 번째 칸이든 곱셈과 덧셈 한 번으로 찾아갑니다.
**앞 칸을 하나씩 세지 않습니다.** 첫 칸이든 백 번째 칸이든 걸리는 시간이 같습니다.

이게 배열의 가장 큰 성질입니다.

```csharp
int[] scores = { 90, 85, 78 };

Console.WriteLine(scores[0]);    // 90
Console.WriteLine(scores[2]);    // 78
scores[1] = 100;                 // 쓰기도 됩니다
```

문자열과 다른 점이 여기입니다. 앞에서 문자열은 읽을 수만 있고 쓸 수 없다고 했습니다.
**배열은 칸의 내용을 바꿀 수 있습니다.** 못 바꾸는 것은 칸의 개수입니다.

## 만들면 칸에 기본값이 들어간다

앞에서 지역 변수는 값을 넣기 전에 쓸 수 없다고 했습니다.
배열은 다릅니다.

```csharp
int[] scores = new int[3];

Console.WriteLine(scores[0]);    // 0
```

에러가 아니라 `0` 이 나옵니다. `new` 로 자리를 잡을 때 그 자리를 전부 0으로 채우기 때문입니다.

| 타입 | 기본값 |
| --- | --- |
| 숫자 (`int`, `double` 등) | `0` |
| `bool` | `false` |
| `char` | 번호 0번 문자 |
| `string` 처럼 참조를 담는 것 | `null` (아직 아무것도 안 가리킴) |

전부 **비트가 전부 0인 상태**입니다. 앞에서 본 대로 메모리에는 비트만 있고
그걸 무엇으로 읽을지는 타입이 정합니다. 0으로 채운 비트를 `int` 로 읽으면 0,
`bool` 로 읽으면 `false` 입니다.

## Length 와 반복문

칸이 몇 개인지는 `Length` 로 알 수 있습니다.

```csharp
int[] scores = { 90, 85, 78 };

for (int i = 0; i < scores.Length; i++)
{
    Console.WriteLine(scores[i]);
}
```

앞에서 `for (int i = 0; i < 길이; i++)` 형태가 왜 굳어졌는지 이야기했습니다.
여기가 그 자리입니다. 인덱스가 0부터니 `Length` **미만**까지 돌면 정확히 맞습니다.

`<=` 로 쓰면 마지막 한 바퀴에서 없는 칸을 건드립니다.

```csharp
for (int i = 0; i <= scores.Length; i++)    // i 가 3 일 때 터집니다
```

## 없는 칸을 건드리면 터진다

```csharp
int[] scores = { 90, 85, 78 };

Console.WriteLine(scores[3]);    // IndexOutOfRangeException
```

앞에서 정수가 넘칠 때는 예외도 경고도 없이 조용히 돌아간다고 했습니다.
배열은 반대입니다. **없는 칸을 건드리면 그 자리에서 프로그램이 멈춥니다.**

조용히 넘어가는 것보다 낫습니다. 남의 메모리를 읽거나 덮어쓰면
훨씬 나중에, 전혀 관계없어 보이는 곳에서 이상하게 동작합니다.
그때는 원인을 찾을 수가 없습니다.

## 칸 개수는 나중에 못 바꾼다

배열의 한계가 여기 있습니다.

```csharp
int[] scores = new int[3];

scores[3] = 100;      // 칸이 없습니다. 늘어나지 않습니다
```

`new int[3]` 이 실행되는 순간 메모리에 세 칸 분량의 자리가 잡힙니다.
그 뒤는 다른 것이 쓰고 있을 수 있으니 뒤로 늘릴 수가 없습니다.

늘리려면 **더 큰 배열을 새로 만들고 옮겨 담는 수밖에** 없습니다.

```csharp
int[] bigger = new int[6];

for (int i = 0; i < scores.Length; i++)
{
    bigger[i] = scores[i];
}

scores = bigger;
```

앞에서 본 문자열 `+` 와 똑같은 구조입니다. 고치는 것처럼 보이지만 새로 만들고 옮기는 것입니다.

**그래서 배열은 개수가 정해져 있을 때 씁니다.** 요일 7개, 게임 판 9칸처럼요.
개수가 실행 중에 변하는 것은 배열로 다루기 번거롭습니다.

## 정리

- 배열은 이름 하나에 같은 타입의 칸을 여러 개 붙인 것입니다.
- `int[] a = new int[5];` 에서 대괄호가 배열 표시, `new` 뒤의 숫자가 칸 개수입니다.
- 칸에는 0부터 번호가 붙습니다. 인덱스는 시작 지점에서 몇 칸 떨어졌는가입니다.
- 칸이 붙어 있어서 몇 번째 칸이든 찾는 시간이 같습니다.
- 문자열과 달리 칸의 내용은 바꿀 수 있습니다. 못 바꾸는 것은 개수입니다.
- 만들 때 전부 기본값(비트가 0인 상태)으로 채워집니다.
- 없는 칸을 건드리면 예외가 나면서 멈춥니다.
- 칸 개수는 만든 뒤에 못 늘립니다. 늘리려면 새로 만들어 옮겨야 합니다.