Collection Data 스위프트 구조를 소개합니다.좋은 글이라 생각되어 번역합니다. 핵심적인 부분을 제외하고는 번역을 제외하고 의역했습니다. 본문은 여기를 참고해주세요.
Introduction
많은 데이터를 처리하는 어플리케이션을 만들고 있을 때를 생각해보세요. 언제 데이터를 넣고 어떻게 그 많은 데이터를 효율적으로 핸들링을 하실 건가요?
많은 데이터를 처리 할 경우에는 Array
, Dictionary
, Sets
에 대한 근본적인 개념을 알고 있는게 중요합니다. 이 collection data structures
에 명확한 개념을 가질 경우 처리 속도는 어마어마하게 빨라 질 것 입니다.
튜토리얼의 순서는 다음과 같습니다.
- 데이터 구조에 대해 개념을 가지고,
Big-O
표기법에 대해 배워봅니다. - 여러가지 자료 구조들에 대해 숙지합니다.
- 데이터 구조들의 퍼포먼스를 비교해봅니다.
- 추가의 팁으로 다른 구조들을 조금 더 알아봅니다.
What is Big-O Notation?
컴퓨터에서 데이터를 처리할 때 걸리는 시간 또는 차지하는 메모리 공간 은 일반적으로 데이터의 양 에 비례하게 됩니다.
Big-O 표기법은 이 때 필요한 시간, 공간을 점근적으로(asymptotically) 표현하는 방법이며, 이렇게 표현한 것을 시간복잡도(time complexity), 공간복잡도(space complexity)라고 부릅니다.
아래는 자주 만날 수 있는 시간복잡도의 Big-O 표기법과 설명을 빠른 것부터 나열한 것입니다.
O(1)
: 제일 이상적입니다. 처리하는 데이터의 양(n)에 관계 없이 상수 시간만큼 소요되는 경우입니다.O(log n)
: 좋은 퍼포먼스를 보여주는 그래프입니다. 데이터 구조에 있는 아이템이 늘어나도 매우 천천히 연산의 횟수가 늘어나게(=걸리는 시간도) 됩니다.O(n)
: 중간 단계의 퍼포먼스를 보여주는 그래프입니다. 데이터 구조랑 연산횟수가 일차함수(linear)를 그리며 증가합니다.O(n (log n))
: (데이터가 10M~100M 넘어갈 경우) 낮은 단계의 퍼포먼스를 보여주는 그래프입니다. 비교 기반 정렬(comparison based sort)의 시간복잡도 하한(lower bound)이기도 합니다.O(n²)
: 데이터구조에 있는 아이템수의 제곱에 비례하여 늘어납니다. 여기서 부턴 성능이 매우 떨어지고, 추천하지 않습니다.O(2^n)
: 2의 데이터 구조의 갯수 제곱만큼 증가합니다. 매우 나쁜 퍼포먼스를 보여줍니다. 원소 n개 집합의 모든 부분집합을 출력하는 경우의 시간복잡도와 같습니다.O(n!)
: 최악의 케이스입니다. 이렇게 코딩이 될 경우에는 답이 없습니다.
Common iOS Data Structures
Arrays
, Dictionaries
, Sets
가 가장 흔한 데이터 구조입니다. 각각의 구조와 성능에 대해 알아봅니다. 또한 Objective-C
와Swift
에서 각각의 데이터구조를 비교해봅니다.
Arrays
Array
는 순서를 가지고 있는 배열입니다.index
를 통해서 각각의 아이템에 접근 할 수 있습니다. 인덱스를 가지고 아이템을 가져오는 것을subscripting
이라고 합니다.Objective-C
의NSArray
는Swift
에서let
으로 선언된Array
와 같습니다.NSMutableArray
는var
로 선언된Array
와 같습니다.- 최악의 케이스는
O(log n)
이 실행되지만 보통O(1)
이 연산됩니다. - 모르는 오브젝트를 찾을 경우 최악은
O(n (log n))
이 실행되지만 보통O(n)
만큼 연산됩니다. - 데이터를 삭제하거나 넣는 경우 최악은
O(n (log n))
이 걸리지만 보통O(1)
만큼 실행됩니다.
이럴때 쓰면 좋습니다.
item
이 어디있는지 아는 경우 동작은 빠르게 작동 할 것입니다.- 아이템이 어디있는지 모를 경우 처음부터 끝까지 동작해야하기 때문에 검색결과가 느립니다.
- 아이템을 어디에 넣고 삭제해야 하는지 알고 있다면 어렵지 않겠지만, 배열을 앞뒤로 살펴야 한다는 것은 시간 소비가 큽니다.
Swift
는 2015년 12월부터 오픈소스입니다. Swift Code로 들어가셔서 구조가 어떻게 되어있는 지 확인해보시는 것도 좋은 방법입니다.
아래는 Objective-C
와 Swift
의 비교 결과입니다.
- Creating a Swift
Array
and anNSArray
degrade at roughly the same rate betweenO(log n)
andO(n)
.Swift
is faster than Foundation by roughly 30 times. This is a significant improvement over Swift 2.3, where it was roughly the same as Foundation! - Adding items to the beginning of an array is considerably slower in a Swift
Array
than in anNSArray
, which is aroundO(1)
. Adding items to the middle of an array takes half the time in SwiftArray
than in anNSArray
. Adding items to the end of a SwiftArray
, which is less thanO(1)
, is roughly 6 times faster than adding items to the end of anNSArray
, which comes in just overO(1)
. - Removing objects is faster in a Swift
Array
than aNSArray
. From the beginning, middle or end, removing an object degrades betweenO(log n)
andO(n)
. Raw time is better inSwift
when you remove from the beginning of an Array, but the distinction is a matter of milliseconds. - Looking up items in
Swift
is faster for the first time since its inception. Look ups by index grow at very close rates for both SwiftArrays
andNSArray
while lookup by object is roughly 80 times faster in Swift.
상기 글은 스위프트가 얼마나 잘 최적화 되었는지 보여줍니다. Swift
쓰세요. 두번 쓰세요.
Dictionaries
- Dictionary(사전)는 특정 순서와 상관없이
key
값을 통해서 값을 찾을 수 있는 데이터 구조입니다. - Dictionary는
subscripting
을 지원하기 떄문에,dictionary["hello"]
와 같은 방법으로hello
라는key
값을 통해서 값에 접근 할 수 있습니다. NSDictionary
와NSMutableDictionary
의 차이는Array
일 경우와 같습니다.Swift
의 Dictionary는 타입을 지정해줘야 합니다. (NSDictionary
가NSObject
를 갖는 것 처럼)
이럴때 쓰면 좋습니다.
- 순서가 없을 경우 Dictionary를 사용하시면 됩니다.
- 순서가 아닌
key
값으로 접근 할 경우 좋습니다.cats["Ellen"]
이렇게 사용할 경우 Optional이 return되기 때문에if let
이나guard
로 풀어주는 것을 권장합니다.12345if let ellensCat = cats["Ellen"] {print("Ellen's cat is named \(ellensCat).")} else {print("Ellen's cat's name not found!")}
아래는 Objective-C
와 Swift
의 비교 결과입니다.
- In raw time, creating Swift
Dictionaries
is roughly 6 times faster than creatingNSMutableDictionaries
but both degrade at roughly the sameO(n
) rate. - Adding items to Swift
Dictionaries
is roughly 100 times faster than adding them toNSMutableDictionaries
in raw time, and both degrade close to the best-case-scenarioO(1)
rate promised by Apple’s documentation. - Removing items from Swift
Dictionaries
is roughly 8 times faster than removing items fromNSMutableDictionaries
, but the degradation of performance is again close toO(1)
for both types. - Swift is also faster at lookup, with both performing roughly at an
O(1)
rate. This version of Swift is the first where it beats Foundation by a significant amount.
퍼포먼스가 크게 차이가 나지 않는다고 합니다.
Sets
- Set(집합)은 순서가 없고 유일한 값을 저장하는 데이터 구조입니다. 중복으로 데이터를 등록 할 수 없습니다.
Set
에 선언되어있는 값들은 모두 같은type
이어야 합니다.Objective-c
에서는 각각NSSet
과NSMutableSet
이 있습니다.
이럴때 쓰면 좋습니다.
- Set은 유니크한 값을 중복없이 뽑을 경우 좋습니다.
Snippet
을 하나 보겠습니다.123456789101112let names = ["John", "Paul", "George", "Ringo", "Mick", "Keith", "Charlie", "Ronnie"]var stringSet = Set<String>() // 1var loopsCount = 0while stringSet.count < 4 {let randomNumber = arc4random_uniform(UInt32(names.count)) // 2let randomName = names[Int(randomNumber)] // 3print(randomName) // 4stringSet.insert(randomName) // 5loopsCount += 1 // 6}// 7print("Loops: " + loopsCount.description + ", Set contents: " + stringSet.description)
- Set을 초기화 합니다.
- 아이템를 랜덤으로 뽑습니다
- 인덱스에 있는 아이를 가져옵니다
- 로그를 남깁니다
mutable set
에 값을 저장합니다. 만약 값이 저장되어 있는 경우에는 값을 저장하지 않습니다.- 루프 카우트를 늘려서 루프를 다 돌게 합니다
- 루프가 끝나면 값을 로그에 남깁니다
|
|
로그에는 6개의 값이 찍혔지만 결론적으로 Set
에는 4개의 값이 들어가 있습니다.
덜 알려졌지만 있는 데이터 구조들
NSCache
NSCache
를 사용하는 것은NSMutableDictionary
를 사용하는것과 매우 유사합니다.- 다른 점은 메모리가 낮아질 경우
NSCache
데이터는 지워 질 수 있습니다. 그리고 항상 재생성됩니다.캐시는 화면뒤에서 비동기적으로 자동으로 메모리에 상주 할 지, 남을지 결정합니다.
NSCountedSet
NSMutableSet
을 상속받아서 만들어진 데이터 구조로, 얼마나 많은 오브젝트가mutable set
에 더해해졌는지 알 수 있게 해줍니다.- 하단 코드를 참고해주세요
|
|
NSOrderedSet
NSOrderedSet
은 개별적인 오브젝트들의 그룹을 순서대로 저장 할 수있게 해줍니다.ordered set
을Array
의 대안으로 테스팅할 때 사용해보시면 배열보다 더 빠른것을 느낄 수 있습니다.
NSHashTable and NSMapTable
NSHashTable
은NSMutableSet
과 비슷하지만 몇가지 다른점이 있습니다NSHashTable
은 오브젝트 뿐만 아니라non-object
또한 더할 수 있습니다.NSHashTableOptions
로 메모리 또한 관리 할 수 있습니다.NSMapTable
은 dictionary 같은 자료구조이지만,NSHashTable
과 비슷하게 메모리를 관리한다는 측면이 있습니다.