프로그래밍iOS 개발자

스위프트에서 속성 관찰자(property observers)는 어떻게 작동하며 그 필요성은 무엇인가요?

Hintsage AI 어시스턴트로 면접 통과

답변.

스위프트의 속성 관찰자(property observers)는 속성 값의 변경에 반응할 수 있게 해줍니다. 이 개념은 스위프트와 함께 등장하여 데이터 변경에 대한 투명한 제어와 변경 시 자동화된 로직을 강화하기 위해 만들어졌습니다.

질문의 역사:

스위프트 이전에는 이러한 동작이 setter나 특별한 메서드를 통해 수동으로 구현되는 경우가 많았습니다. 스위프트에서는 이러한 관찰자가 언어의 표준 도구로 등장했습니다.

문제:

개발자는 속성이 변경되는 시점을 포착할 수 있어야 하며, 예를 들어 UI를 업데이트하거나 데이터 유효성을 검사하는 작업이 필요합니다. 관찰자가 없으면 코드는 더 복잡하고 읽기 어려워집니다.

해결책:

스위프트에는 두 가지 주요 관찰자가 있습니다:

  • willSet은 값이 변경되기 전에 호출됩니다.
  • didSet은 새 값이 할당된 후에 호출됩니다.

관찰자는 stored property에 추가할 수 있으며, lazy 속성과 computed 속성은 제외됩니다.

코드 예시:

class Temperature { var celsius: Double { willSet { print("곧 새로운 값이 설정됩니다: ", newValue) } didSet { print("이전 값은:", oldValue, ", 새로운 값은:", celsius) } } init(celsius: Double) { self.celsius = celsius } } let temp = Temperature(celsius: 22) temp.celsius = 28 // willSet과 didSet이 호출됩니다.

주요 특징:

  • willSet 관찰자에서는 special variable인 newValue에 접근할 수 있습니다.
  • didSet에서는 oldValue에 접근할 수 있습니다.
  • 속성이 초기화(init)될 때는 관찰자가 호출되지 않습니다.

트릭 질문.

관찰자를 computed 속성에 추가할 수 있나요?

아니요, computed 속성에는 willSet과 didSet을 추가할 수 없습니다. 이미 자체 게터와 세터가 있기 때문입니다. willSet/didSet은 오직 stored 속성에만 해당됩니다.

초기화기에서 속성을 변경할 때 관찰자들이 호출되나요?

아니요, property observers는 초기화(init) 동안 호출되지 않습니다. 초기화가 완료된 후 값이 변경될 때만 작동합니다.

현재 값을 자기 자신에게 할당할 때, 예를 들어 x = x?

관찰자는 값이 변경되지 않았더라도 여전히 호출됩니다! 이는 부작용을 초래할 수 있으니 주의해야 합니다.

var value: Int = 0 { didSet { print("didSet은 항상 호출됩니다!") } } value = value // didSet이 호출됩니다.

일반적인 실수와 안티 패턴

  • 사이드 이펙트에 대한 의존성: 비즈니스 로직을 오직 didSet/willSet에서 구현하면 코드가 불투명해집니다.
  • "빈" 값 변경 시 사이드 이펙트를 잘못 관리함.
  • setter에서의 행동 구현 대신 computed property에 관찰자를 사용하는 것.

실제 사례

부정적 케이스

개발자가 didSet에서 UI 업데이트를 수행했지만, 값의 변경을 확인하지 않았습니다. UI는 "빈" 할당에도 업데이트되어 성능이 저하되었습니다.

장점:

  • 빠른 구현, 코드가 적음

단점:

  • 불필요한 작업이 증가하고 디버깅이 복잡해짐

긍정적 케이스

didSet에서 이전 값과 새로운 값의 동등성을 검사했습니다. 값이 실제로 변경된 경우에만 UI가 업데이트되었습니다.

장점:

  • 사이드 이펙트를 최소화하고 높은 성능을 유지합니다.

단점:

  • 추가적인 if 검사 필요, 코드가 조금 더 많아짐