배열과 ArrayList: 순서가 있는 게임 기록 관리
03강. 배열과 ArrayList: 순서가 있는 게임 기록 관리
1. 이번 강의에서 해결할 문제
스테이지 수처럼 크기가 고정된 값과 플레이할 때마다 늘어나는 기록을 같은 구조에 넣으면 불필요한 복사나 빈 공간이 생깁니다.
2. 학습 목표
3. 핵심 개념
배열은 생성할 때 길이가 고정되고 원시 타입도 직접 저장합니다. ArrayList는 내부적으로 크기 조절 가능한 배열을 사용하지만, 용량 증가 방식은 API 계약과 구분해야 합니다. 둘 다 인덱스 접근은 O(1)입니다. 끝 추가는 ArrayList에서 평균적으로 amortized O(1)이지만 용량 확장 순간에는 복사가 필요합니다. 중간 삽입·삭제는 뒤 원소를 이동해 O(n)입니다.
먼저 알아야 할 용어
| 용어 | 뜻 | 주의할 점 |
|---|---|---|
| 원소 | 배열이나 목록에 들어 있는 값 하나 | 이 예제에서는 목표 점수 또는 GameRecord 한 개입니다. |
| 인덱스 | 원소의 순서를 나타내는 0부터 시작하는 번호 | 원소가 3개면 유효 인덱스는 0, 1, 2입니다. |
| 길이·크기 | 현재 사용할 수 있는 원소 수 | 배열은 length, List는 size()로 확인합니다. |
| 용량 | ArrayList 내부 배열이 재할당 없이 담을 수 있는 칸 수 | 공개 API의 size()와 같은 뜻이 아닙니다. |
| amortized O(1) | 가끔 발생하는 큰 복사 비용을 여러 번의 끝 추가에 나누어 본 평균 비용 | 매번 정확히 O(1)이라는 뜻은 아닙니다. |
배열은 스테이지가 정확히 3개처럼 개수가 설계상 고정된 데이터에 알맞습니다. ArrayList는 플레이가 끝날 때마다 기록이 늘어나는 것처럼 실행 중 개수가 변하는 데이터에 알맞습니다. 어느 쪽이 더 최신 자료구조라서 고르는 것이 아니라, 크기 변경 요구에 따라 고릅니다.
4. 단계별 실습
1. 예제 파일 작성
실행 환경: 코드 편집기
실행 위치: C:\dev\game-ranking-algorithms
실행 전 확인: 같은 이름의 파일이 있다면 덮어쓰기 전에 Git diff로 변경 범위를 확인합니다. 선택한 LTS JDK의 java -version과 javac -version이 모두 실행되어야 합니다.
대상 파일: src/OrderedRecords.java
import java.util.ArrayList;
import java.util.List;
public class OrderedRecords {
record GameRecord(String playerId, int score) {}
public static void main(String[] args) {
int[] stageTargets = {500, 800, 1200};
List<GameRecord> records = new ArrayList<>();
records.add(new GameRecord("P1", 700));
records.add(new GameRecord("P2", 950));
records.add(1, new GameRecord("P3", 820));
System.out.println("2스테이지 목표: " + stageTargets[1]);
System.out.println("기록 순서: " + records);
}
}
코드 한 줄씩 이해하기
int[] stageTargets = {500, 800, 1200}은 길이 3인 정수 배열을 만듭니다. 두 번째 값의 인덱스는 1입니다.List<GameRecord> records는 코드를 구체 구현이 아닌 List 계약에 의존하게 합니다.- 실제 객체는
new ArrayList<>()로 만들어 실행 중 기록을 추가할 수 있습니다. - 두 번의
add(value)는 목록 끝에 P1과 P2를 넣습니다. add(1, P3)은 인덱스 1 자리를 비우려고 기존 P2를 뒤로 옮긴 뒤 P3를 넣습니다.- 따라서 최종 순서는 P1, P3, P2이고, 원래 P2가 삭제된 것은 아닙니다.
| 실행 직후 | 목록 상태 |
|---|---|
| 빈 ArrayList 생성 | [] |
| P1 추가 | [P1] |
| P2 추가 | [P1, P2] |
| 인덱스 1에 P3 삽입 | [P1, P3, P2] |
2. PowerShell에서 컴파일·실행
실행 환경: Windows PowerShell
실행 위치: C:\dev\game-ranking-algorithms
실행 전 확인: src/OrderedRecords.java가 저장되었고 out 폴더에는 삭제해도 되는 컴파일 결과만 있는지 확인합니다.
대상: src/OrderedRecords.java와 out 아래 생성되는 class 파일
Set-Location C:\dev\game-ranking-algorithms
New-Item -ItemType Directory -Force .\out | Out-Null
javac -Xlint:all -d .\out .\src\OrderedRecords.java
java -cp .\out OrderedRecords
예상 결과: record의 기본 문자열 표현에는 필드 이름도 포함됩니다. 핵심은 800과 P1 → P3 → P2 순서입니다.
2스테이지 목표: 800
기록 순서: [GameRecord[playerId=P1, score=700], GameRecord[playerId=P3, score=820], GameRecord[playerId=P2, score=950]]
실행 시간은 PC의 CPU·메모리, JDK 버전, JVM 워밍업, 백그라운드 작업과 입력 분포에 따라 달라질 수 있습니다. 측정값은 같은 조건에서 여러 번 비교하고 Big-O 분석과 함께 해석합니다.
5. 코드와 알고리즘이 동작하는 이유
스테이지 목표는 개수가 고정되어 배열이 자연스럽습니다. 기록은 실행 중 늘어나므로 ArrayList가 크기 관리 책임을 맡습니다. add(1, value)는 인덱스 1 이후 원소를 한 칸씩 이동하기 때문에 O(n)이고, get(1)은 기준 주소에서 위치를 계산하므로 O(1)입니다.
6. 자주 하는 실수와 해결법
7. 직접 실습
실습 목표
배열과 ArrayList에서 인덱스로 값을 읽고, 끝 추가와 중간 삽입의 결과 차이를 직접 확인합니다.
시작 전 상태
OrderedRecords.java가 위 코드와 같고 P1, P3, P2 순서가 출력되어야 합니다. 각 변경 전에 예상 목록을 종이에 먼저 적습니다.
1단계: 가장 작은 변경 — 안전한 첫 값과 마지막 값
records.get(0)으로 첫 기록을, records.get(records.size() - 1)로 마지막 기록을 출력합니다. 마지막 인덱스가 size() 자체가 아닌 size() - 1인 이유는 인덱스가 0부터 시작하기 때문입니다.
2단계: 값을 바꾸고 결과 비교
records.add(new GameRecord("P4", 1100))로 끝에 추가한 결과와 records.add(1, ...)로 중간에 삽입한 결과를 비교합니다. 어느 기존 원소가 이동하는지 화살표로 그려 보세요.
3단계: 직접 적용 — 빈 목록도 안전한 출력
새로운 빈 ArrayList<GameRecord>를 만들고, 비어 있으면 "기록 없음", 값이 있으면 첫 기록을 출력하는 조건을 작성합니다. 먼저 isEmpty()를 사용할 위치를 생각한 뒤 구현합니다.
4단계: 스스로 확인
스테이지 목표 배열의 첫 값을 550으로 바꾸고 출력 변화를 확인합니다. 그다음 존재하지 않는 stageTargets[3]을 읽으면 왜 실패하는지, 유효 범위를 0 <= index < length로 설명합니다.
막혔을 때
| 오류 또는 증상 | 원인 | 해결 |
|---|---|---|
ArrayIndexOutOfBoundsException | 배열의 인덱스가 0~length - 1 밖임 | 접근 전 배열 길이와 인덱스를 출력합니다. |
IndexOutOfBoundsException | 빈 List 또는 size() 위치를 읽음 | isEmpty()를 먼저 확인하고 마지막은 size() - 1로 계산합니다. |
| P2가 사라졌다고 생각함 | 중간 삽입 뒤 출력 순서를 놓침 | 삽입 전후 목록을 각각 출력해 P2가 뒤로 이동했는지 확인합니다. |
실습 기록에는 입력 크기, 예상 결과, 실제 결과, 시간·공간 복잡도와 사용한 JDK 버전을 함께 남깁니다.
8. 이해 점검 질문 3개
9. 핵심 요약
다음 강의 연결
다음 강의에서는 문자도 순서가 있는 자료라는 점을 이용해 문자열과 문자 배열의 순회·비교 흐름을 다룹니다.
배열과 ArrayList: 순서가 있는 게임 기록 관리 미니 퀴즈
선택 즉시 정답과 해설을 확인할 수 있습니다. 결과는 이 브라우저에만 저장됩니다.
학습을 마쳤나요?
직접 실습과 점검 질문까지 확인한 뒤 완료로 표시하세요.