🤖 이 글은 Claude Code(AI)가 작성합니다. | 시리즈 목차 | 이전: 2편
실제 프로그램에서 값을 하나씩 따로 다루는 경우는 드뭅니다. 사용자 목록, 설정 항목, 방문한 페이지의 기록처럼 “여러 값을 묶어서” 다뤄야 하는 상황이 훨씬 많습니다. Swift는 이를 위해 세 가지 기본 컬렉션 타입을 제공합니다.
- Array — 순서가 있는 목록
- Dictionary — 키로 값을 찾는 쌍
- Set — 중복 없는 집합
셋 다 Python의 list, dict, set에 대응하지만 동작 방식에 중요한 차이가 있습니다. 하나씩 살펴보겠습니다.
Array — 순서가 있는 목록
가장 자주 쓰는 컬렉션입니다. 값이 삽입된 순서를 유지하고, 인덱스(0부터 시작)로 접근합니다.
var fruits = ["사과", "바나나", "체리"]
print(fruits[0]) // 사과
print(fruits[2]) // 체리
print(fruits.count) // 3
타입을 명시하면 [String] 또는 Array<String>으로 씁니다. 두 표기는 완전히 동일합니다.
var scores: [Int] = [95, 82, 76]
var names: Array<String> = ["Alice", "Bob"] // 같은 의미, [String]이 관례
배열 조작의 기본 메서드입니다.
var items = ["a", "b", "c"]
items.append("d") // 끝에 추가 → ["a", "b", "c", "d"]
items.insert("z", at: 0) // 특정 위치에 삽입 → ["z", "a", "b", "c", "d"]
items.remove(at: 1) // 인덱스로 삭제 → ["z", "b", "c", "d"]
items.removeLast() // 마지막 삭제 → ["z", "b", "c"]
print(items.isEmpty) // false
print(items.contains("b")) // true
print(items.first) // Optional("z") ← 빈 배열일 수 있으므로 옵셔널
print(items.last) // Optional("c")
first와 last가 옵셔널을 반환하는 이유는 배열이 비어 있을 수 있기 때문입니다. Swift는 이런 “실패 가능성”을 타입으로 표현합니다(옵셔널은 7편에서 자세히 다룹니다).
let으로 선언한 배열은 변경이 불가능합니다.
let fixed = [1, 2, 3]
fixed.append(4) // 오류: let으로 선언된 배열은 수정 불가
Dictionary — 키로 값을 찾는 쌍
키(key)와 값(value)을 쌍으로 저장하고, 키를 이용해 값을 빠르게 찾는 컬렉션입니다. Python의 dict와 거의 같습니다.
var capitals = ["한국": "서울", "일본": "도쿄", "프랑스": "파리"]
print(capitals["한국"]) // Optional("서울")
print(capitals["독일"]) // nil
타입 표기는 [Key: Value] 형식입니다.
var scores: [String: Int] = ["Alice": 95, "Bob": 82]
딕셔너리 조회 결과가 항상 옵셔널인 것에 주목합니다. 해당 키가 없으면 nil이 반환되기 때문입니다. Swift는 이 가능성을 타입 수준에서 강제로 인식하게 만듭니다.
// 값이 있을 때만 처리하는 안전한 패턴
if let city = capitals["한국"] {
print("수도는 \(city)입니다") // 수도는 서울입니다
}
값 추가·수정·삭제는 직관적입니다.
var ages = ["Alice": 30, "Bob": 25]
ages["Carol"] = 28 // 새 키 추가
ages["Alice"] = 31 // 기존 값 수정
ages["Bob"] = nil // 키 삭제
print(ages) // ["Alice": 31, "Carol": 28]
딕셔너리는 순서를 보장하지 않습니다. 같은 딕셔너리를 출력해도 순서가 달라질 수 있습니다. 순서가 필요하다면 Array를 쓰거나, 키를 정렬한 뒤 순회해야 합니다.
Set — 중복 없는 집합
같은 값이 두 번 들어갈 수 없고, 순서도 없습니다. 중복을 자동으로 제거하거나, 두 집합 사이의 관계(교집합·합집합 등)를 계산할 때 씁니다.
var tags: Set<String> = ["swift", "ios", "macos", "swift"]
print(tags) // {"swift", "ios", "macos"} — 중복 제거됨
print(tags.count) // 3
Array 리터럴과 문법이 같아서 타입을 명시해야 Set으로 인식됩니다. 타입 어노테이션 없이 쓰면 Swift는 Array로 추론합니다.
let a: Set = [1, 2, 3, 4]
let b: Set = [3, 4, 5, 6]
print(a.union(b)) // {1, 2, 3, 4, 5, 6} 합집합
print(a.intersection(b)) // {3, 4} 교집합
print(a.subtracting(b)) // {1, 2} 차집합
print(a.isDisjoint(with: b)) // false (공통 원소 있음)
Set의 조회는 Array보다 빠릅니다. Array에서 특정 값을 찾으려면 처음부터 끝까지 하나씩 확인해야 하지만(O(n)), Set은 해시 기반이라 거의 즉시(O(1)) 찾습니다. 순서가 필요 없고 “이 값이 들어 있는가?”만 자주 확인한다면 Set이 더 적합합니다.
for-in 으로 순회하기
세 컬렉션 모두 for-in으로 순회할 수 있습니다.
// Array
let fruits = ["사과", "바나나", "체리"]
for fruit in fruits {
print(fruit)
}
// 인덱스가 필요할 때
for (index, fruit) in fruits.enumerated() {
print("\(index): \(fruit)")
}
// 0: 사과
// 1: 바나나
// 2: 체리
// Dictionary
let capitals = ["한국": "서울", "일본": "도쿄"]
for (country, city) in capitals {
print("\(country)의 수도는 \(city)")
}
// Set (순서 불정)
let tags: Set = ["swift", "ios", "macos"]
for tag in tags {
print(tag)
}
고차 함수 맛보기 — map, filter, reduce
컬렉션을 다룰 때 반복문을 직접 쓰는 대신, 의도를 더 명확하게 표현하는 고차 함수(higher-order function)를 자주 씁니다. 지금 단계에서 완벽히 이해하지 않아도 되지만, 어떤 역할을 하는지 눈에 익혀두면 나중에 편합니다.
map — 각 원소를 변환해 새 배열 반환
let numbers = [1, 2, 3, 4, 5]
let doubled = numbers.map { $0 * 2 }
print(doubled) // [2, 4, 6, 8, 10]
let names = ["alice", "bob", "carol"]
let upper = names.map { $0.uppercased() }
print(upper) // ["ALICE", "BOB", "CAROL"]
filter — 조건을 만족하는 원소만 추려 새 배열 반환
let scores = [88, 42, 95, 61, 73]
let passing = scores.filter { $0 >= 70 }
print(passing) // [88, 95, 73]
reduce — 모든 원소를 하나의 값으로 누적
let prices = [1200, 3500, 800]
let total = prices.reduce(0) { $0 + $1 }
print(total) // 5500
$0, $1은 클로저의 첫 번째, 두 번째 인자를 가리키는 축약 표현입니다. 클로저는 6편에서 자세히 다룹니다. 지금은 “각 원소에 적용할 동작을 { } 안에 쓴다”는 패턴만 기억해도 충분합니다.
세 컬렉션 선택 기준
| 상황 | 선택 |
|---|---|
| 순서가 중요하고, 같은 값이 여러 번 나올 수 있다 | Array |
| 이름(키)으로 값을 빠르게 찾아야 한다 | Dictionary |
| 중복 없이 모아야 하거나, 집합 연산이 필요하다 | Set |
다른 언어와 비교
| Python | JavaScript | Swift | |
|---|---|---|---|
| 순서 있는 목록 | list |
Array |
Array / [T] |
| 키-값 쌍 | dict |
Object / Map |
Dictionary / [K: V] |
| 중복 없는 집합 | set |
Set |
Set<T> |
| 딕셔너리 조회 결과 | 없으면 KeyError |
없으면 undefined |
없으면 nil (옵셔널) |
let으로 선언 시 |
(불변 컬렉션 없음) | const도 내용 수정 가능 |
내용 수정 불가 |
Swift에서 let으로 선언한 컬렉션은 원소 추가·삭제 모두 불가합니다. JavaScript의 const는 재할당만 막을 뿐 내용 수정은 허용하는 것과 다릅니다.
핵심 요약
- Array는 순서 있는 목록, Dictionary는 키-값 쌍, Set은 중복 없는 집합이다.
- Dictionary 조회 결과는 항상 옵셔널이다. 해당 키가 없을 수 있기 때문이다.
- Set은 중복을 자동 제거하고, 값 존재 여부 확인이 Array보다 빠르다.
let으로 선언한 컬렉션은 내용을 변경할 수 없다.map,filter,reduce는 반복문 대신 컬렉션 변환 의도를 간결하게 표현하는 고차 함수다.
다음 편은 4편 — 제어 흐름: if, switch, guard, for, while입니다. Swift의 switch가 다른 언어와 얼마나 다른지, guard가 왜 존재하는지를 다룹니다.
🤖 Generated with Claude Code