Swift의 Copy-on-Write(COW) 동작 방식

sonny·2025년 2월 11일
0

TIL

목록 보기
124/133

1. Copy-on-Write란?

Copy-on-Write(COW)는 값 타입(Value Type)의 복사가 불필요한 경우 실제 데이터를 공유하다가, 변경이 발생할 때 새로운 메모리를 할당하여 복사하는 최적화 기법이다. Swift는 Array, Dictionary, Set 등의 컬렉션 타입에서 COW를 활용하여 성능을 개선한다.

2. COW의 동작 방식

Swift에서 값 타입(예: Array)을 변수에 할당하면 일반적으로 새로운 복사가 일어나지만, 실제로 내부적으로는 동일한 메모리를 참조한다. 이후 값이 변경되는 순간 새로운 메모리를 할당하여 복사를 수행한다.

var array1 = [1, 2, 3]  // 새로운 배열 생성
var array2 = array1     // 동일한 메모리 참조

print(array1 === array2) // true (동일한 메모리 참조)

array2.append(4)         // 변경이 발생하면 새로운 메모리 할당

print(array1)  // [1, 2, 3]
print(array2)  // [1, 2, 3, 4]

array1array2는 초기에는 동일한 메모리를 참조하지만, array2가 변경되는 순간 새로운 메모리를 할당받아 독립적으로 동작하게 된다.

3. COW의 내부 구현

Swift의 표준 라이브러리는 isKnownUniquelyReferenced(_:) 함수를 사용하여 참조가 유일한지 확인한다. 내부적으로 Array, Dictionary 등은 클래스 기반의 스토리지(Storage)를 가지고 있으며, 참조 카운트를 확인하여 복사 여부를 결정한다.

import Foundation

class Storage {
    var values: [Int]
    init(values: [Int]) {
        self.values = values
    }
}

struct COWArray {
    private var storage: Storage
    
    init(values: [Int]) {
        self.storage = Storage(values: values)
    }
    
    mutating func modifyFirstElement(newValue: Int) {
        if !isKnownUniquelyReferenced(&storage) {
            print("Copying storage...")
            storage = Storage(values: storage.values) // 복사 발생
        }
        storage.values[0] = newValue
    }
    
    func printValues() {
        print(storage.values)
    }
}

var cowArray1 = COWArray(values: [1, 2, 3])
var cowArray2 = cowArray1 // 동일한 storage 공유
cowArray2.modifyFirstElement(newValue: 100) // 변경 시 복사 발생

cowArray1.printValues() // [1, 2, 3]
cowArray2.printValues() // [100, 2, 3]

이처럼 isKnownUniquelyReferenced(_:)를 활용하여, 참조가 하나일 경우에만 변경하고 그렇지 않으면 새로운 메모리를 할당하여 복사하는 방식이 COW의 핵심이다.

4. COW가 적용되는 컬렉션 타입

Swift의 표준 라이브러리에서 COW가 적용되는 대표적인 값 타입은 다음과 같다.

  • Array
  • Dictionary
  • Set
  • String

이들은 내부적으로 클래스 기반의 저장소를 사용하여 COW를 구현하고 있다.

5. COW 최적화 활용 방법

  • 불필요한 복사 방지: 값 타입을 다룰 때 변경이 없다면 복사가 발생하지 않도록 주의한다.
  • inout 매개변수 사용: 함수에서 값을 수정해야 한다면 inout을 사용하여 불필요한 복사를 방지할 수 있다.
  • isKnownUniquelyReferenced 활용: 값 타입 내부에서 참조 카운트를 확인하여 복사 여부를 결정할 수 있다.

6. 결론

Copy-on-Write는 Swift에서 값 타입의 성능을 최적화하기 위한 중요한 기법이다. Swift의 기본 컬렉션 타입들은 COW를 통해 불필요한 메모리 복사를 방지하며, 참조가 변경될 때만 복사가 발생하도록 설계되어 있다. 이를 활용하여 불필요한 복사를 최소화하고 성능을 최적화할 수 있다.

profile
iOS 좋아. swift 좋아.

0개의 댓글

관련 채용 정보