Swift에서 for-in vs 인덱스 기반 반복(0..<array.count)
Swift에서는 배열이나 컬렉션을 순회할 때 두 가지 주요 방식이 있습니다.
- for-in 반복문
- 인덱스 기반 반복문 (0..<array.count)
Swift 공식 문서와 WWDC 세션, Swift Forums의 논의를 종합하면 다음과 같은 이유로 for-in이 기본 권장 방식입니다.
1. for-in이 권장되는 이유
1.1 언어 차원의 1급 순회 구문
Swift 표준 문서(Sequence)에는 다음과 같이 명시되어 있습니다.
The most common way to iterate over the elements of a sequence is to use a for-in loop.
즉, 시퀀스를 순회하는 가장 일반적이고 권장되는 방법은 for-in입니다.
1.2 안전성과 가독성
- 인덱스 범위 체크(Out of Range) 오류 위험이 없습니다.
- 값만 필요할 때 코드가 명확하고 의도가 바로 드러납니다.
- Swift 컴파일러는 for-in을 내부적으로 최적화하여 IndexingIterator를 효율적으로 사용합니다.
1.3 최적화 수준
Swift Forums의 엔지니어 논의(Performance of array access vs iterator)에 따르면,
배열 순회 시 for element in array가 가장 효율적으로 컴파일됩니다.
컴파일러가 내부적으로 최적의 반복 코드를 생성하기 때문입니다.
for element in array {
print(element)
}
2. 인덱스가 필요한 경우의 올바른 대안
2.1 enumerated() 사용
인덱스와 값을 동시에 사용해야 한다면 enumerated()를 활용합니다.
for (i, value) in array.enumerated() {
print("Index: \(i), Value: \(value)")
}
- 0부터 시작하는 연속 정수 인덱스와 요소 쌍을 반환합니다.
- 공식 문서: Array.enumerated()
2.2 indices 속성 사용
컬렉션 고유 인덱스 타입을 직접 사용해야 한다면 indices를 활용합니다.
for i in array.indices {
let value = array[i]
print("Index \(i): \(value)")
}
- 공식 문서: Collection.indices
- indices는 컬렉션의 실제 인덱스 타입(Array.Index, String.Index 등)을 반환합니다.
- String은 정수 인덱스를 사용하지 않기 때문에 indices 접근이 필수적입니다.
for i in text.indices {
print(text[i])
}
참고: String.indices
3. 인덱스 기반 루프 (0..<array.count)
for i in 0..<array.count {
print(array[i])
}
⚠️ 주의할 점
- Array에서는 동작하지만, 다른 컬렉션(Set, Dictionary, String)에서는 정수 인덱스가 유효하지 않습니다.
- 값만 필요할 때는 불필요하게 인덱스를 다루는 셈이므로 가독성과 안전성이 낮습니다.
- 오프바이원(Off-by-one) 실수가 발생하기 쉽습니다.
→ 따라서 단순 요소 순회에는 for-in을 사용하고, 인덱스가 필요한 경우에만 enumerated() 또는 indices를 선택하는 것이 권장됩니다.
4. 성능 비교
| 방식 | 복잡도 | 컴파일러 최적화 | 안정성 | 권장 여부 |
| for element in array | O(n) | ✅ 최고 수준 | ✅ 안전 | ✅ 권장 |
| for (i, v) in array.enumerated() | O(n) | ✅ 효율적 | ✅ 안전 | ✅ 권장 |
| for i in array.indices | O(n) | ✅ 효율적 | ✅ 안전 | ✅ (특수 케이스) |
| for i in 0..<array.count | O(n) | ⚠️ 동일하지만 범위 객체 생성 | ❌ 위험 | 🚫 비권장 |
5. 성능 분석 (Swift Forums 및 Apple 문서 기반)
- Swift 컴파일러는 for-in 루프를 내부적으로 IndexingIterator 기반으로 변환합니다.
(IteratorProtocol, IndexingIterator) - 이는 직접 인덱스를 다루지 않으므로 안전하면서도 빠릅니다.
- for-in은 ARC 최적화와 함께 인라인 루프가 자동 적용되어 C 수준의 반복 성능을 제공합니다.
참고: “for-in loop over array is the most efficient way to iterate an array” — Swift Forums (2016)
6. 예외적으로 인덱스가 유리한 상황
- 이웃 요소 간 비교가 필요한 경우 (슬라이딩 윈도우)
- 특정 위치의 값만 업데이트해야 할 때
- 로그나 디버깅용으로 인덱스와 값을 함께 출력해야 할 때
이런 경우에도 enumerated() 또는 indices가 선호됩니다.
7. 공식 문서 링크 모음
| 항목 | 문서 링크 |
| Sequence 프로토콜 | https://developer.apple.com/documentation/swift/sequence |
| Array.enumerated() | https://developer.apple.com/documentation/swift/array/enumerated |
| Collection.indices | https://developer.apple.com/documentation/swift/collection/indices |
| String.indices | https://developer.apple.com/documentation/swift/string/indices |
| IndexingIterator | https://developer.apple.com/documentation/swift/indexingiterator |
| IteratorProtocol | https://developer.apple.com/documentation/swift/iteratorprotocol |
| Swift Forums - Iteration 성능 논의 | https://forums.swift.org/t/performance-of-array-access-vs-iterator/6265 |
8. 결론
| 상황 | 권장 방법 | 이유 |
| 단순 순회 | for element in array | 가장 빠르고 안전 |
| 인덱스 + 값 필요 | for (i, v) in array.enumerated() | 가독성, 안정성 |
| 컬렉션 고유 인덱스 필요 | for i in array.indices | 실제 인덱스 접근 |
| 정수 인덱스만 필요 | for i in 0..<array.count | 제한적(배열만 해당) |
➡ 요약:
Swift에서는 가능한 한 for-in을 기본 사용하고, 인덱스가 필요한 경우 enumerated() 또는 indices를 사용하라.
직접 정수 인덱스 반복은 호환성, 안전성, 유지보수성 모두에서 불리하다.
'Dev Study > Swift' 카테고리의 다른 글
| Swift에서 compactMap vs map + filter (0) | 2025.11.11 |
|---|---|
| Swift에서 map vs forEach (0) | 2025.11.11 |
| Swift에서 Lazy 컬렉션 (0) | 2025.11.10 |
| Swift에서 contains(where:) vs filter().count > 0 (0) | 2025.11.10 |
| Swift에서 count > 0 대신 isEmpty를 사용하는 이유 (0) | 2025.11.10 |
| Swift 6.1 기능 정리 (0) | 2025.11.10 |
| Swift 6.0 기능 정리 (0) | 2025.11.10 |
| Swift Throttle vs Debounce 완벽 가이드 (1) | 2025.11.07 |

