구조체(Struct)와 클래스(Class)는 Swift에서 데이터를 모델링하고 저장하는 데 사용되는 두 가지 기본적인 타입이다. 이 두 타입 간의 주요 차이점 중 하나는 메모리적인 측면에서의 동작이다.
구조체는 값 타입이다. 이는 구조체 인스턴스가 복사될 때, 별도의 메모리 공간이 할당되고 해당 값이 복사된다.
구조체는 스택(Stack) 메모리에 저장된다. 스택은 고정된 크기의 메모리 블록을 사용하며, 빠른 데이터 접근이 가능하다.
구조체 인스턴스가 함수에 전달될 때나 다른 변수에 할당될 때, 해당 인스턴스의 복사본이 생성되어 전달된다.
주로 작은 데이터나 간단한 값 타입을 나타낼 때 사용하며, 간단한 데이터를 처리하는데 유용하다.
구조체의 ARC 예제를 살펴보면 아래와 같다.
struct Point {
var x: Int
var y: Int
}
var point1: Point
var point2: Point
var point3: Point
point1 = Point(x: 1, y: 2)
point2 = point1
point3 = point1
// 구조체는 복사본이 생성되므로 별도의 참조 횟수가 관리되지 않음
print("point1: \(point1)")
print("point2: \(point2)")
print("point3: \(point3)")
구조체는 값 타입이기 때문에 복사할 때마다 새로운 인스턴스가 생성된다. 따라서 별도의 참조 횟수를 관리하지 않는다. 위의 예제에서는 point1, point2, point3 모두 서로 독립적인 복사본을 갖고 있다.
클래스는 참조 타입이다. 이는 클래스 인스턴스가 복사되지 않고, 인스턴스의 참조가 전달된다.
클래스는 힙(Heap) 메모리에 저장된다. 힙은 동적으로 크기가 할당되며, 런타임에 메모리를 할당하고 해제할 수 있다.
클래스 인스턴스가 함수에 전달되거나 다른 변수에 할당될 때, 해당 인스턴스의 참조가 전달된다. 이는 같은 인스턴스를 여러 변수에서 참조할 수 있다는 것을 의미한다.
클래스는 상속을 지원하고, 객체 지향 프로그래밍에서 주요한 역할을 한다.
클래스의 ARC 예제를 살펴보면 아래와 같다.
class Person {
var name: String
init(name: String) {
self.name = name
print("\(name) is initialized")
}
deinit {
print("\(name) is deallocated")
}
}
var person1: Person?
var person2: Person?
var person3: Person?
person1 = Person(name: "Alice")
person2 = person1
person3 = person1
person1 = nil
person2 = nil
person3 = nil
이 예제에서 Person 클래스는 이름을 저장하는 속성을 갖고 있으며, person1, person2, person3은 모두 같은 Person 인스턴스를 참조하고 있다.
만일 인스턴스를 더 이상 참조하지 않게 되면 (nil로 설정하거나 다른 객체를 참조할 때), 해당 객체의 deinit 메서드가 호출되어 객체가 해제(deallocated)됨을 알 수 있다. 클래스의 인스턴스는 참조 횟수(reference count)에 기반하여 메모리에서 해제된다.
메모리 측면에서 보면, 클래스는 참조 카운트에 기반한 메모리 관리를 하지만, 구조체는 값 복사를 통해 메모리를 관리한다. 이러한 차이점은 메모리 관리 측면에서 구조체와 클래스를 선택할 때 고려해야 할 중요한 요소 중 하나이다.