새벽의 기록

[SOPT] 문법 스터디 #1 콜렉션 타입 본문

SOPT/문법 스터디

[SOPT] 문법 스터디 #1 콜렉션 타입

OneTen 2024. 11. 11. 00:15
콜렉션 타입
	- 배열, 세트, 딕셔너리를 사용할 때 성능 차이를 알아보고, 각 타입의 특징을 정리해봅시다 !
	- Swift playground로 예제 코드를 짜고, 메모리를 찍어봅시다 !
	- 값 타입(예: 배열)과 참조 타입(예: 클래스) 의 차이와 각각의 장단점

 

1. 배열, 세트, 딕셔너리를 사용할 때 성능 차이를 알아보고, 각 타입의 특징을 정리해봅시다 !
(Swift playground로 예제 코드를 짜고, 메모리를 찍어봅시다 !)

 

배열(Array)

 
순서대로 같은 타입의 값을 저장합니다. 같은 값은 배열에 다른 순서로 존재할 수 있습니다.
→ 순서가 있고 중복이 가능함

 
코드

import Foundation

// 프로세스의 시스템 시간(절대 시간)을 구하는 메서드인 CFAbsoluteTimeGetCurrent 사용
// CFAbsoluteTimeGetCurrent

// 데이터 준비
let testData = Array(1...100000)

// 배열 테스트
var array: [Int] = []

// 배열에 데이터 삽입하기 전 현재시간
let arrayStart = CFAbsoluteTimeGetCurrent()

array.append(contentsOf: testData)

// 배열에 데이터를 모두 삽입한 뒤 현재시간
let arrayInsertTime = CFAbsoluteTimeGetCurrent() - arrayStart

let arraySearchStart = CFAbsoluteTimeGetCurrent()
let _ = array.contains(99999)
let arraySearchTime = CFAbsoluteTimeGetCurrent() - arraySearchStart

// 결과 출력
print("Array insertion time: \(arrayInsertTime)")
print("Array search time: \(arraySearchTime)")

 
배열 성능테스트 결과
데이터 삽입에 걸린 시간 : 0.047590017318725586
데이터 조회에 걸린 시간 : 0.007430076599121094
 
 
 

집합(Set)

집합은 반복되지 않은 값에 순서가 없는 콜렉션 타입입니다.
순서와 상관없이 같은 타입의 다른 값을 저장합니다.
아이템의 순서가 중요하지 않거나 아이템이 반복되면 안될 때 사용할 수 있습니다.
집합에 저장하기 위해 타입은 반드시 Hashable 해야 하며, Swift의 모든 기본 타입 (String, Int, Double, Bool)은 기본적으로 Hashable 합니다.
→ 중복이 없으며 순서가 없음
→ 특정 순서로 집합의 값을 사용하려면 별도의 정렬과정을 거쳐야함
 
합집합(union), 차집합(subtracting), 대칭차집합(symmetricDifference), 교집합(intersection)을 생성하는 내장메서드가 있습니다.
 

코드

import Foundation

// 프로세스의 시스템 시간(절대 시간)을 구하는 메서드인 CFAbsoluteTimeGetCurrent 사용
// CFAbsoluteTimeGetCurrent

// 데이터 준비
let testData = Array(1...100000)

// 집합 테스트
var set: Set<Int> = []

// 집합에 데이터 삽입하기 전 현재시간
let setStart = CFAbsoluteTimeGetCurrent()

set.formUnion(testData)

// 집합에 데이터를 모두 삽입한 뒤 현재시간
let setInsertTime = CFAbsoluteTimeGetCurrent() - setStart

let setSearchStart = CFAbsoluteTimeGetCurrent()
let _ = set.contains(99999)
let setSearchTime = CFAbsoluteTimeGetCurrent() - setSearchStart

// 결과 출력
print("Set insertion time: \(setInsertTime)")
print("Set search time: \(setSearchTime)")

 
집합 성능테스트 결과
데이터 삽입에 걸린 시간 : 0.1843109130859375
데이터 조회에 걸린 시간 : 6.079673767089844e-06
→ 지수 표기법에서 e-06은 소수점 이하 6자리까지 내려간다는 뜻
따라서 보기 쉽게 표현하자면 데이터 조회에 걸린 시간 : 약 0.00000608
 
 

딕셔너리(Dictionary)

순서와 상관없이 같은 타입의 키(key)와 같은 타입의 값(value)를 저장합니다.
각 Value는 값에 대한 식별자로 동작하는 유니크한 Key 와 조합됩니다.
특정 단어를 찾기위해 사전을 찾는 방법과 같이 Key를 기준으로 Value값을 찾을 때 딕셔너리를 사용합니다.
→ 순서가 없으며 Key-Value쌍의 저장형태
→ 각 Key값은 중복되지 않고, Key값을 기준으로 Value값을 검색
→ Value 자체에는 순서가 없지만 Key에는 있어서 for문을 통해 순회 가능

코드

import Foundation

// 프로세스의 시스템 시간(절대 시간)을 구하는 메서드인 CFAbsoluteTimeGetCurrent 사용
// CFAbsoluteTimeGetCurrent

// 데이터 준비
let testData = Array(1...100000)

// 딕셔너리 테스트
var dictionary: [Int: Bool] = [:]

// 딕셔너리에 데이터 삽입하기 전 현재시간
let dictionaryStart = CFAbsoluteTimeGetCurrent()

for number in testData {
    dictionary[number] = true
}

// 딕셔너리에 데이터를 모두 삽입한 뒤 현재시간
let dictionaryInsertTime = CFAbsoluteTimeGetCurrent() - dictionaryStart

let dictionarySearchStart = CFAbsoluteTimeGetCurrent()
let _ = dictionary[99999]
let dictionarySearchTime = CFAbsoluteTimeGetCurrent() - dictionarySearchStart

// 결과 출력
print("Dictionary insertion time: \(dictionaryInsertTime)")
print("Dictionary search time: \(dictionarySearchTime)")

 
딕셔너리 성능테스트 결과
데이터 삽입에 걸린 시간 : 0.5630179643630981
데이터 조회에 걸린 시간 : 5.0067901611328125e-06
→ 지수 표기법에서 e-06은 소수점 이하 6자리까지 내려간다는 뜻
따라서 보기 쉽게 표현하자면 데이터 조회에 걸린 시간 : 약 0.000005006

 

정리

 배열집합딕셔너리
데이터 삽입0.04750.18430.5630
데이터 조회0.0074약 0.0000060.000005

 
데이터 삽입 : 배열 > 집합 > 딕셔너리 순으로 빠름
데이터 조회 : 딕셔너리 > 집합 > 배열 순으로 빠름
 
 
메모리 비교

  1. 배열은 순서와 중복 허용 때문에 메모리 사용량이 많을 수 있다.
  2. 집합은 중복을 허용하지 않기에 고유성 유지에 추가 메모리를 사용한다.
  3. 딕셔너리는 키와 값 쌍을 저장하기 때문에 메모리 사용량이 가장 높을 수 있다.

일반적인 성능 요약
• Array는 작은 데이터셋이나 정렬된 데이터를 다룰 때 효율적입니다.
• Set은 고유한 요소를 빠르게 삽입 및 검색해야 할 때 성능이 뛰어납니다.
• Dictionary는 키-값 관계를 기반으로 빠르게 값을 조회하거나 업데이트할 때 효율적입니다.
 
 

2. 값 타입(예: 배열)과 참조 타입(예: 클래스) 의 차이와 각각의 장단점

 
값 타입 (Value Type) 
- 특징: 데이터 복사, 독립적 인스턴스 생성
- 예시: struct, enum, 배열 등 기본 자료형
- 장점: 안정성, 예측 가능성, 스레드 안전성
- 단점: 큰 데이터의 복사 비용, 추가 메모리 사용
→ 값 자체를 복사하므로 다른 곳에서 원본이 변경되는 걱정을 할 필요가 없으나,
복사할 때마다 메모리를 추가로 사용하므로 비용이 큰 편
 
 
 
참조 타입 (Reference Type) 
- 특징: 데이터 전달, 인스턴스 공유
- 예시: class, closure
- 장점: 성능 최적화, 데이터 공유 용이
- 단점: 예측 불가성, 스레드 안전성 문제, 메모리 누수 가능성
→ 동일한 인스턴스를 여러 곳에서 참조할 수 있어 데이터 공유가 쉽고 참조를 전달하기 때문에 복사 비용이 들지 않는다.
→ 여러 곳에서 같은 인스턴스를 참조할 수 있어 데이터의 변경이 예측하기 어려울 수 있고, 강한 순환 참조(strong reference cycle) 등으로 인해 메모리 누수가 발생할 수 있다.

Comments