[회고] 신입 iOS 개발자가 되기까지 feat. 카카오 자세히보기

🍎 Apple/Swift

[Swift] Copy on write

inu 2022. 1. 26. 20:49
반응형

Copy on write (COW)

이름 그대로 Write가 발생했을 때 Copy를 수행하는 기능입니다. (cf.이는 원래 운영체제에서 프로세스에게 프레임을 할당할 때 메모리 공간 낭비를 막기위해 사용되던 기능인데, Swift에도 비슷한 목적으로 적용되었습니다.)

 

값타입의 데이터는 값을 참조하지 않고 복사합니다. 하지만 이렇게 매번 복사를 할 경우 값이 변경될 필요가 없음에도 매번 새로운 메모리 공간을 할당하여 복사를 수행하게 됩니다. 따라서 메모리가 낭비되고, 오버헤드까지 발생합니다. 그래서 사용되는 것이 Copy on write입니다. Copy on write는 데이터 복사 시에 실제로 값을 복사하지 않고 동일한 값을 참조하도록 합니다. 그리고 값이 변경(Write)될 때 값을 복사해 변경을 적용합니다.

 

이렇게되면 기존의 메모리 낭비 및 오버헤드의 문제점이 해결됩니다. 하지만 기존의 값 유형은 단일 소유만을 고려해 참조횟수를 계산할 필요가 없었던 것에 비해, 생성되는 사본 수를 확인하기 위해 참조횟수를 계산해야 한다는 단점도 존재합니다.



Swift의 원시 타입과 Collection들(Int, Double, String, Array, Set, Dictionary)에는 이러한 Copy on write가 이미 구현되어 있습니다. 사용자 구조체의 경우 구현되어 있지 않기 때문에 직접 구현해줘야 합니다. 참조타입인 Class를 이용해 값타입을 wrapping하는 방식으로 Copy on write를 구현합니다. 아래는 구현의 예시입니다.

struct MediaItem {
    fileprivate class MediaData {
        var name:String
        var format:[String:String]

        init(name:String, format:[String:String]) {
            self.name = name
            self.format = format
        }
    }

    private var data:MediaData

    init(name:String, format:[String:String]) {
        data = MediaData.init(name: name, format: format)
    }
}

extension MediaItem {
    public var name:String {
        get { return data.name }
        set {
        // 이미 copy가 되었는지 아닌지 확인
            if !isKnownUniquelyReferenced(&data){
                self.data = self.data.copy()
            }
            self.data.name = newValue
        }
    }
}

extension MediaItem.MediaData {
    func copy() -> MediaItem.MediaData {
        return MediaItem.MediaData.init(name: name, format: format)
    }
}

// 출처 : https://ichi.pro/ko/swift-copy-on-write-choejeoghwa-77728322183901
반응형

'🍎 Apple > Swift' 카테고리의 다른 글

[Swift] Monad  (0) 2022.03.01
[Swift] Property Wrapper  (0) 2022.02.24
[Swift] 문자열 처리  (0) 2022.01.22
[Swift] NSCache와 NSDictionary의 차이점  (0) 2022.01.22
[Swift] UserDefaults와 Codable, NSCoding  (2) 2022.01.01