🔥 속성 옵저버
속성 옵저버(Property Observers)는 속성 값의 변화를 관찰하고 대응하는 기능을 제공해요. 속성의 값이 설정될 때마다 호출되는데, 새로 설정된 값이 현재 값과 같더라도 호출된답니다.
속성 옵저버는 다음과 같은 곳에 추가할 수 있어요:
- 직접 정의한 저장 속성
- 상속받은 저장 속성
- 상속받은 계산 속성
상속받은 속성의 경우, 서브클래스에서 해당 속성을 재정의(overriding)하여 속성 옵저버를 추가할 수 있습니다. 하지만 직접 정의한 계산 속성의 경우에는 옵저버(Observer)를 만들기보다는 속성의 setter를 사용하여 값의 변화를 관찰하고 대응하는 것이 좋습니다. 속성 재정의에 대한 자세한 내용은 Overriding 부분을 참고해 주세요.
속성에는 다음 두 가지 옵저버를 정의할 수 있답니다:
willSet
: 값이 저장되기 직전에 호출됩니다.didSet
: 새로운 값이 저장된 직후에 호출됩니다.
willSet
옵저버를 구현하면, 새로운 속성 값이 상수 매개변수로 전달됩니다. willSet
구현부에서 이 매개변수의 이름을 지정할 수도 있어요. 만약 매개변수 이름과 괄호를 작성하지 않으면, 기본 매개변수 이름인 newValue
로 사용할 수 있습니다.
마찬가지로, didSet
옵저버를 구현하면, 이전 속성 값을 담고 있는 상수 매개변수가 전달됩니다. 매개변수에 이름을 지정하거나 기본 매개변수 이름인 oldValue
를 사용할 수 있죠. 만약 didSet
옵저버 내부에서 속성에 값을 할당하면, 방금 설정된 값을 새로 할당한 값으로 대체합니다.
그럼 willSet
과 didSet
이 실제로 어떻게 동작하는지 예제를 통해 살펴볼까요? 아래 예제는 StepCounter
라는 새로운 클래스를 정의하고 있어요. 이 클래스는 사람이 걸음을 걸을 때 총 걸음 수를 추적합니다. 이 클래스는 만보계나 다른 걸음 수 측정기의 입력 데이터와 함께 사용되어 사람의 일상 속 운동량을 기록할 수 있겠죠.
class StepCounter { var totalSteps: Int = 0 { willSet(newTotalSteps) { print("About to set totalSteps to \(newTotalSteps)") } didSet { if totalSteps > oldValue { print("Added \(totalSteps - oldValue) steps") } } } } let stepCounter = StepCounter() stepCounter.totalSteps = 200 // About to set totalSteps to 200 // Added 200 steps stepCounter.totalSteps = 360 // About to set totalSteps to 360 // Added 160 steps stepCounter.totalSteps = 896 // About to set totalSteps to 896 // Added 536 steps
swift
위 예제에서 StepCounter
클래스는 Int
타입의 totalSteps
속성을 선언하고 있습니다. 이 속성은 willSet
과 didSet
옵저버를 가진 저장 속성이에요.
totalSteps
에 새로운 값이 할당될 때마다 willSet
과 didSet
옵저버가 호출됩니다. 이는 새로운 값이 현재 값과 같은 경우에도 마찬가지랍니다.
이 예제의 willSet
옵저버는 newTotalSteps
라는 사용자 정의 매개변수 이름을 사용하여 설정될 새로운 값을 전달받아요. 여기서는 단순히 설정될 값을 출력하고 있습니다.
didSet
옵저버는 totalSteps
의 값이 업데이트된 후에 호출됩니다. 새로운 totalSteps
값과 이전 값을 비교하여, 총 걸음 수가 증가했다면 새로 추가된 걸음 수를 나타내는 메시지를 출력해요. didSet
옵저버는 이전 값에 대한 사용자 정의 매개변수 이름을 제공하지 않고, 대신 기본 이름인 oldValue
를 사용하고 있습니다.
속성 옵저버를 사용하면 속성 값의 변화에 따른 추가 작업을 수행할 수 있어 매우 유용합니다. 값의 변화를 추적하고, 필요한 로직을 수행하거나, 다른 객체에 알림을 보내는 등 다양한 용도로 활용할 수 있겠죠?
위 다이어그램은 속성 옵저버의 동작 순서를 나타내고 있어요. 속성 값이 변경되면 먼저 willSet
옵저버가 호출되고, 그 후에 속성에 새로운 값이 실제로 설정됩니다. 마지막으로 didSet
옵저버가 호출되는 거죠.