배열이란 선언·생성 초기화 길이·순회 기본값 자주 나는 오류 2차원 배열 📝 문제풀이
◀ 이전 📋 목차 CH 09 ▶
🗄️ CHAPTER 08 · 중급

값 여러 개를 한 묶음으로 — 배열

변수 하나에 값 하나. 그런데 점수 30개, 이름 100개를 다뤄야 한다면? 변수 100개를 만들 순 없어요. 배열(array)같은 타입의 값 여러 개를 한 이름으로 묶어 관리하는 방법이에요. 인덱스만 익히면 절반은 끝납니다.

🎯 이 장을 끝내면
🗃️
배열이란
왜 배열이 필요할까요?
"변수 여러 개" 대신 "한 묶음". 이 장의 전부가 여기서 시작돼요.

지금까지는 값 하나에 변수 하나였어요. 학생 3명 점수라면 score1, score2, score3처럼요. 그런데 학생이 30명, 100명이라면? 변수 100개를 손으로 만드는 건 현실적이지 않죠.

🧩 변수 여러 개 vs 배열 하나 변수 여러 개 — 이름이 제각각(score1, score2…). 개수가 늘면 반복 처리도 어려워요.
배열 하나 — 이름 하나(scores)에 값 여러 개를 담고, 번호(인덱스)로 골라 써요. 반복문과 찰떡궁합이에요. 💡 한 줄 정의: 배열은 "같은 타입의 값 여러 개를 한 이름으로 묶은, 크기가 고정된 상자들의 줄"이에요.

아래 그림처럼 배열은 칸(요소)이 나란히 줄지어 있고, 각 칸에는 0부터 시작하는 번호(인덱스)가 붙어 있어요. 이 번호로 원하는 칸을 콕 집어 읽고 씁니다.

int[] scores = {90, 85, 100, 70, 60};
[0]
90
[1]
85
[2]
100
[3]
70
[4]
60
🧭
이번 장의 핵심 한 가지. 나머지가 헷갈려도 이것만은 새겨두세요 — 인덱스는 1이 아니라 0부터 시작합니다. 첫 요소는 arr[0]이에요.
array index 0-based length new for-each 2차원 배열 ArrayIndexOutOfBounds
📦
선언·생성
배열 만들기 — new int[5]
"몇 칸짜리인지" 크기를 정해 상자를 만들어요. 크기는 나중에 못 바꿔요.

배열은 두 가지가 필요해요 — 선언(어떤 타입의 배열인지 이름 붙이기)과 생성(실제로 칸을 몇 개 만들지 정하기). 보통 한 줄에 같이 씁니다.

int[] arr = new int[5];   // int를 담는 5칸짜리 배열 생성
// 인덱스는 0부터 4까지:  arr[0], arr[1], arr[2], arr[3], arr[4]

arr[0] = 10;   // 첫 번째 칸에 10 저장
arr[4] = 50;   // 마지막(다섯 번째) 칸에 50 저장
System.out.println(arr[0]);   // 10
System.out.println(arr[4]);   // 50
🔍 int[] arr = new int[5]; 한 조각씩 int[] — "int들을 담는 배열" 타입. 대괄호가 배열임을 뜻해요. (int arr[]처럼 뒤에 붙여도 되지만, int[] arr를 권장해요.)
new int[5] — 실제로 5칸을 메모리에 만들어요. 이 5가 배열의 크기(length)예요.
arr — 만든 배열을 가리키는 이름(변수). ⚠️ 크기는 생성할 때 정해지고, 그 뒤로 바꿀 수 없어요. 5칸으로 만들면 영원히 5칸이에요. (더 필요하면 CH에서 배울 컬렉션을 씁니다.)
🎯
인덱스 범위 = 0 ~ (크기−1). 크기가 5면 유효한 인덱스는 0,1,2,3,4예요. 마지막 인덱스는 4지 5가 아니에요. arr[5]는 존재하지 않아 오류가 나요(뒤에서 설명).
✏️
초기화
값 채우기 — 세 가지 방법
만들면서 한 번에 채우거나, 만든 뒤 하나씩 넣거나.

배열에 값을 넣는 방법은 크게 세 가지예요. 상황에 맞게 골라 쓰면 됩니다.

// ① 중괄호로 한 번에 채우기 (가장 간단, 선언과 동시에만 가능)
int[] a = {10, 20, 30};        // 3칸짜리, 값 10·20·30

// ② new int[]{ ... } — ①과 같지만, 나중에 대입할 때도 쓸 수 있음
int[] b;
b = new int[]{1, 2, 3, 4};     // ①의 { } 만 쓰면 이 자리에선 오류!

// ③ 빈 배열을 만든 뒤, 인덱스로 하나씩 대입
int[] c = new int[3];          // {0, 0, 0} 상태 (기본값)
c[0] = 100;
c[1] = 200;
c[2] = 300;                    // 이제 {100, 200, 300}
📝 { } 초기화의 함정 int[] a = {10, 20, 30}; 처럼 선언과 동시일 때만 중괄호만으로 됩니다.
아래처럼 선언과 대입을 나누면 중괄호만으로는 안 되고 new int[]{ }를 써야 해요. 🚫 int[] a; a = {10, 20, 30};컴파일 오류.   ✅ a = new int[]{10, 20, 30};
💡
대입은 arr[인덱스] = 값; 형태예요. 등호(=) 왼쪽에 칸을 두면 쓰기, 오른쪽에 두면 읽기예요. arr[0] = arr[1];은 "1번 칸 값을 읽어 0번 칸에 쓴다"는 뜻이죠.
🔁
길이 · 순회
arr.length 와 배열 훑기
배열은 반복문과 만날 때 진짜 힘을 발휘해요.

배열의 칸 개수(크기)는 arr.length로 알 수 있어요. 아주 자주 헷갈리는 포인트 — 괄호가 없습니다. 메서드가 아니라 필드(속성)라서 arr.length()가 아니라 arr.length예요. (참고: 문자열 String은 반대로 str.length()로 괄호가 있어요.)

🔤
용어 — 순회(traverse). 배열의 요소를 처음부터 끝까지 하나씩 차례로 훑는 것을 "순회한다"고 해요. 아래처럼 반복문으로 배열을 순회하는 게 이 장에서 가장 많이 쓰는 활용이에요.
int[] arr = {10, 20, 30, 40, 50};
System.out.println(arr.length);   // 5  ← 괄호 없음!

// ① 일반 for — 인덱스가 필요할 때 (0부터 length-1까지)
for (int i = 0; i < arr.length; i++) {
    System.out.println(i + "번째: " + arr[i]);
}

// ② 향상된 for (for-each) — 값만 순서대로 필요할 때 더 간결
for (int v : arr) {
    System.out.println(v);        // 10, 20, 30, 40, 50
}
⚖️ 일반 for vs 향상된 for 일반 fori < arr.length로 도는 표준형. 인덱스 i를 쓸 수 있어 "몇 번째"를 알거나 값을 수정할 때 좋아요.
향상된 forfor (int v : arr). 인덱스 없이 값만 처음부터 끝까지 훑어요. 짧고 실수(범위 초과)가 없어요. 👉 값을 읽기만 하면 향상된 for가 편하고, 인덱스가 필요하거나 값을 바꿔야 하면 일반 for를 씁니다.
⚠️
일반 for의 조건은 i < arr.length여야 해요. 실수로 i <= arr.length로 쓰면 마지막에 arr[length]를 건드려 범위 초과 오류가 납니다.
0️⃣
기본값
비어 보이지만 사실 채워져 있어요
new로 만든 배열은 저절로 "기본값"으로 초기화돼요.

new int[5]처럼 값을 안 넣고 만들어도, 각 칸은 쓰레기값이 아니라 타입별 기본값으로 자동 초기화돼요. 그래서 int 배열은 만들자마자 전부 0이에요.

타입 분류예시배열 생성 시 기본값
정수형int, long, short, byte0 (long은 0L)
실수형double, float0.0
문자형char'\u0000' (코드값 0, 널 문자)
논리형booleanfalse
참조형String, 객체 배열null
🔤
참조형(reference type) — int·double처럼 값을 직접 담는 기본형과 달리, String이나 배열·객체는 값 자체가 아니라 "그 값이 어디에 있는지(위치)"를 담는 타입이에요. 그래서 배열도 참조형이고, 아직 위치를 정하지 않은 칸의 기본값은 null(가리키는 곳 없음)이 돼요. 참고로 arr2 = arr1;처럼 배열을 통째로 대입하면 값이 복제되는 게 아니라 둘이 같은 배열 하나를 가리키게 돼요(이걸 얕은 복사라고 해요). 값까지 따로 복사하려면 요소를 하나씩 옮겨 담아야 합니다.
int[] nums   = new int[3];        // {0, 0, 0}
double[] rate = new double[2];    // {0.0, 0.0}
boolean[] on = new boolean[2];    // {false, false}
String[] names = new String[2];   // {null, null}

System.out.println(nums[0]);      // 0
System.out.println(on[0]);        // false
System.out.println(names[0]);     // null
🧠
참조형 배열은 주의. String[] names = new String[2];는 칸이 전부 null이에요. 값을 넣기 전에 names[0].length()처럼 쓰면 NullPointerException이 나요. 먼저 names[0] = "홍길동";으로 채운 뒤 써야 해요.
🚨
자주 나는 오류
배열 초보가 꼭 만나는 두 벽
이름이 길어서 무섭지만, 원리는 아주 단순해요.

① 범위를 벗어난 인덱스 — ArrayIndexOutOfBoundsException
크기 5짜리 배열의 유효 인덱스는 0~4예요. arr[5]arr[-1]처럼 범위 밖을 건드리면 실행 중에 이 예외가 터져요. (컴파일은 통과, 실행 때 발생!)

🔤
예외(Exception) — 프로그램이 실행되다가 "이건 잘못됐어!" 하고 멈추게 만드는 오류를 말해요. 배열 범위를 벗어나거나, 0으로 나누거나, null인 값을 건드릴 때 자바가 예외를 던져(throw) 프로그램을 중단시켜요. 이름이 길고 무섭게 생겼지만, 사실은 "여기서 뭐가 잘못됐다"고 알려주는 신호랍니다.
int[] arr = new int[5];   // 인덱스 0,1,2,3,4 만 유효
System.out.println(arr[5]);   // 💥 ArrayIndexOutOfBoundsException: Index 5 out of bounds for length 5

② 크기가 고정 — 칸을 더 추가할 수 없음
배열은 만들 때 정한 크기에서 늘리거나 줄일 수 없어요. 3칸 배열에 4번째 값을 "추가"하는 문법은 없습니다. 개수가 자주 바뀌는 데이터라면, 뒤 챕터에서 배울 컬렉션(예: ArrayList)이 더 알맞아요.

🔤
컬렉션(Collection) — 배열처럼 여러 값을 담는 자바의 도구 모음인데, 배열과 달리 크기가 자동으로 늘었다 줄었다 해요. 대표 주자가 ArrayList로, .add()로 값을 계속 추가하고 .remove()로 뺄 수 있어요. "개수가 정해져 있으면 배열, 자주 바뀌면 컬렉션"이라고 기억하면 편해요. (자세한 건 뒤 챕터에서 다뤄요.)
🛡️ 범위 초과를 피하는 습관 1. 반복은 항상 i < arr.length 조건으로 돌기 (<= 금지).
2. 인덱스를 직접 계산했다면 0 <= idx && idx < arr.length인지 확인.
3. "마지막 요소"는 arr[arr.length - 1]로 접근 (숫자를 손으로 쓰지 말기). 이 셋만 지켜도 ArrayIndexOutOfBoundsException은 거의 안 만나요.
🔲
2차원 배열
표(행·열)를 담는 배열
"배열의 배열". 좌표·행렬·격자 데이터를 다룰 때 써요.

지금까지는 한 줄로 늘어선 1차원 배열이었어요. 2차원 배열행(row)과 열(column)이 있는 표라고 생각하면 됩니다. 좌석표, 지도, 시간표 같은 걸 담기 좋아요.

int[][] m = new int[2][3];   // 2행 3열 (총 6칸), 전부 0으로 초기화

m[0][0] = 1;  m[0][1] = 2;  m[0][2] = 3;   // 0번 행
m[1][0] = 4;  m[1][1] = 5;  m[1][2] = 6;   // 1번 행

System.out.println(m[1][2]);   // 6  ← 1번 행, 2번 열
System.out.println(m.length);      // 2  ← 행의 개수
System.out.println(m[0].length);   // 3  ← 0번 행의 열 개수
int[][] m = { {1,2,3}, {4,5,6} };  — m[행][열]
[0][0]
1
[0][1]
2
[0][2]
3
[1][0]
4
[1][1]
5
[1][2]
6

2차원 배열을 전부 훑을 땐 for를 두 번 겹쳐(이중 for) 써요. 바깥 for는 행, 안쪽 for는 열을 돌아요.

int[][] m = { {1, 2, 3}, {4, 5, 6} };

for (int i = 0; i < m.length; i++) {          // 행: 0, 1
    for (int j = 0; j < m[i].length; j++) {   // 열: 0, 1, 2
        System.out.print(m[i][j] + " ");
    }
    System.out.println();   // 한 행 끝나면 줄바꿈
}
// 출력:
// 1 2 3
// 4 5 6
💡
m.length는 행 개수, m[i].length는 그 행의 열 개수예요. 이중 for에서 안쪽 조건을 m[i].length로 쓰면, 행마다 열 개수가 달라도(가변 배열) 안전하게 돌 수 있어요.
🧠 이 장 핵심 요약
📝
문제풀이 · 점검
배운 걸 가볍게 점검해봐요
시험이 아니라 "내가 이해했나" 확인용이에요. 틀려도 바로 해설이 나와요.
🧪
문제를 풀면 즉시 정답과 해설이 나오고, 위쪽 바에 점수가 쌓여요. 네 가지 유형(객관식 · O/X · 빈칸 · 코드결과)을 섞어 두었어요. 편하게 눌러보세요.
CH 09 🧩 메서드 — 코드를 이름 붙은 블록으로 묶어 재사용하기(매개변수·반환값)