[swift] 리소스 관리

Swift 언어는 효율적이고 안정적인 리소스 관리를 지원하기 위해 여러 가지 기능을 제공합니다. 이 포스트에서는 메모리 관리와 파일 시스템 리소스 관리에 초점을 맞추어 설명하겠습니다.

1. 메모리 관리

1.1. ARC (자동 참조 계수)

Swift는 Automatic Reference Counting (ARC)을 사용하여 메모리를 자동으로 관리합니다. ARC는 객체가 참조되는 동안 메모리에 대한 참조 계수를 추적하는 데 사용됩니다. 객체의 참조 계수가 0이 되면 해당 객체는 자동으로 메모리에서 해제됩니다.

class Person {
    let name: String
    init(name: String) {
        self.name = name
    }
    deinit {
        print("\(name) 객체가 메모리에서 해제되었습니다.")
    }
}

var person1: Person? = Person(name: "John")
var person2: Person? = person1

person1 = nil
person2 = nil

위의 예제에서 person1person2Person 클래스의 인스턴스를 참조하고 있습니다. person1nil로 설정하면 해당 인스턴스의 참조 계수가 0이 되므로 Person 클래스의 deinit 메서드가 호출되어 메모리에서 자동으로 해제됩니다.

1.2. 강한 참조와 약한 참조

강한 참조는 기본적으로 Swift의 참조입니다. 하지만 종종 강한 참조로 인해 순환 참조가 발생하는 경우가 있습니다. 이러한 문제를 해결하기 위해 약한 참조(Weak Reference)와 비소유 참조(Unowned Reference)를 사용할 수 있습니다.

class Person {
    let name: String
    var car: Car?
    init(name: String) {
        self.name = name
    }
    deinit {
        print("\(name) 객체가 메모리에서 해제되었습니다.")
    }
}

class Car {
    let model: String
    weak var owner: Person?
    init(model: String) {
        self.model = model
    }
    deinit {
        print("Car 객체가 메모리에서 해제되었습니다.")
    }
}

var person: Person? = Person(name: "John")
var car: Car? = Car(model: "BMW")

person?.car = car
car?.owner = person

person = nil
car = nil

위의 예제에서 personcar의 관계가 상호참조되었습니다. 하지만 personnil로 설정할 때, car 객체의 주인(owner)은 약한 참조로 설정되어 있으므로 메모리에서 자동으로 해제됩니다.

2. 파일 시스템 리소스 관리

2.1. 번들 리소스

Swift에서 번들 리소스에 접근하려면 Bundle 클래스를 사용합니다. 번들은 앱과 함께 번들에 포함되어 있는 파일 및 리소스의 컨테이너입니다.

if let path = Bundle.main.path(forResource: "data", ofType: "txt") {
    if let contents = try? String(contentsOfFile: path) {
        print(contents)
    }
}

위의 예제에서는 data.txt 파일을 번들 리소스에서 찾아 그 내용을 읽어옵니다. Bundle.main.path(forResource:ofType:) 메서드를 사용하여 파일 경로를 가져온 뒤, String(contentsOfFile:) 메서드를 사용하여 해당 파일의 내용을 읽을 수 있습니다.

2.2. 파일 핸들링

파일 핸들링은 파일을 읽고 쓰는 등의 작업을 수행하는 기능을 말합니다. Swift에서는 FileManager 클래스를 사용하여 파일을 생성, 복사, 이동, 삭제 등의 작업을 수행할 수 있습니다.

let fileManager = FileManager.default
let documentsDirectory = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first

let filePath = documentsDirectory?.appendingPathComponent("file.txt")
let contents = "Hello, World!"

// 파일 쓰기
try? contents.write(to: filePath!, atomically: true, encoding: .utf8)

// 파일 읽기
if let fileContents = try? String(contentsOf: filePath!, encoding: .utf8) {
    print(fileContents)
}

위의 예제에서는 문서 디렉토리에 file.txt 파일을 생성하고, 해당 파일에 내용을 씁니다. 그 후, String(contentsOf:) 메서드를 사용하여 파일의 내용을 읽어옵니다.

참고 자료