정적 배열
배열(array)은 같은 타입의 값을 여러 개 순서대로 모아 담는 자료구조입니다. 변수 하나에는 값 하나만 담을 수 있지만, 배열을 쓰면 점수 목록·주소 목록처럼 여러 데이터를 하나의 이름으로 묶어 다룰 수 있습니다. Solidity의 배열은 크게 두 종류로 나뉘며, 이번 강의에서는 그중 정적 배열(fixed-size array)을 배웁니다.
크기가 고정된 배열
정적 배열은 선언할 때 크기를 정해 두고, 그 크기가 이후 절대 바뀌지 않는 배열입니다. 선언 형식은 타입[크기] 입니다. 예를 들어 uint256[3]은 정수 3개, bool[5]는 불리언 5개를 담습니다.
배열의 각 칸은 인덱스(index)로 구분하며, 인덱스는 항상 0부터 시작합니다. 따라서 uint256[3] 배열의 유효한 인덱스는 0, 1, 2 세 개입니다.
정적 배열의 모든 요소는 선언과 동시에 해당 타입의 기본값으로 채워집니다. uint은 0, bool은 false, address는 address(0) 으로 초기화됩니다.
선언과 사용 예시
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
contract FixedArray {
// 길이가 3으로 고정된 정적 배열
uint256[3] public numbers = [10, 20, 30];
// 인덱스는 0부터 시작합니다.
function first() public view returns (uint256) {
return numbers[0]; // 10
}
// 특정 인덱스 값은 수정할 수 있습니다(크기는 못 바꿈).
function setSecond(uint256 value) public {
numbers[1] = value;
}
}위 예시에서 numbers[1] = value 처럼 칸 안의 값은 자유롭게 바꿀 수 있습니다. 하지만 칸의 개수(길이) 자체는 3으로 영원히 고정됩니다.
정적 배열의 한계
길이가 항상 같으므로 정적 배열에는 push, pop 같은 크기 변경 함수를 쓸 수 없습니다. 또한 유효 범위를 벗어난 인덱스에 접근하면 오류가 발생하는데, 인덱스를 어떻게 적었는지에 따라 오류가 나는 시점이 달라집니다.
- 인덱스가 상수(리터럴)일 때:
uint256[3]배열에numbers[3]처럼 쓰면 컴파일러가 범위를 미리 계산할 수 있으므로 컴파일 오류(Out of bounds array access)로 막힙니다. 배포조차 되지 않습니다. - 인덱스가 변수일 때:
numbers[i]처럼 값이 실행 시점에 정해지면 컴파일러가 미리 알 수 없으므로 컴파일은 통과합니다. 대신 실행 중 범위를 벗어나면 런타임 revert(Panic 오류0x32)가 발생합니다.
변수 인덱스로 배열에 접근할 때는 그 값이 길이 범위 안에 있는지 항상 확인하세요. 상수 인덱스와 달리 컴파일러가 대신 잡아 주지 않습니다.
정적 배열은 개수가 정해진 데이터(예: 주사위 면, 요일 7개)에 잘 맞습니다. 크기를 자유롭게 늘리고 줄여야 한다면 동적 배열을 사용합니다.