오늘 팀원이 계좌관리 시스템 구축 과제를 했는데 내가 한 것과 달라서 궁금하여 이참에 TIL거리로 삼아 공부하기로 했다.
코드를 쓴 걸 보다가 willSet
이라는걸 봤는데 팀원의 블로그 글 중 마지막에 'willSet
을 사용하던 didSet
을 사용하던 출력은 같다' 라고 하여 비교도 해보고 어느 상황에 많이 사용하는지도 알아보고 싶었다.
willSet
은 "곧 바뀔 거야"라고 미리 말해주는 것
willSet
은 값이 바뀌기 전에 실행되고, 예를 들어 친구가 나한테 "이제 곧 사과를 줄 게" 라고 말하는 것과 비슷하다. 값이 바뀌기 전에 그 값이 뭐로 바뀔지 먼저 알려주는 것이다.didSet
은 "바뀌었어!" 라고 알려주는 것
didSet
은 값이 바뀐 후에 실행되고, 예를 들어 친구가 "나 이제 사과를 먹었어!" 라고 말하는 것처럼 이미 바뀐 상태를 알려주는 역할을 하는 것이다.var appleCount: Int = 5 {
willSet {
print("사과가 곧 \(newValue)개로 바뀔 거야!")
}
didSet {
print("사과가 \(oldValue)개에서 \(appleCount)개로 바뀌었어!")
}
}
appleCount = 7
코드 중 oldValue
는 함수가 아니라 프로퍼티 감시자에서 자동으로 제공되는 특별한 변수
이다.
oldValue
는 이전의 값을 가리키는 변수이고, 새로 값이 설정될 때 자동으로 그 이전 값을 저장하게 된다. 그래서 appleCount
가 5
에서 7
로 변경될 때, oldValue
는 자연스럽게 변경 전 값인 5
가 된다.
willSet
은 새로 바뀔 값인 newValue
를 미리 말해준다.didSet
은 바뀌기 전의 값인 oldValue
와 지금 값 appleCount
를 알려준다.willSet
: " 곧 바뀔 거야! " (값이 바뀌기 직전에 실행)
didSet
: " 바뀌었어! " (값이 바뀐 후에 실행)
아래 코드는 클래스에 여러 가지 기능을 추가하고 didSet
을 이용해 여러 상태변경을 바로바로 확인할 수 있도록 해본 것이다.
willSet
과 didSet
을 공부하면서 프로퍼티의 변화 과정을 관리하는 기능이 얼마나 중요한지 조금은 알게 되었다. 처음에는 단순히 값을 변경하고 그에 따라 특정한 코드를 실행하는 것이라고 생각했는데 실제로 다양한 상황에서 유용하게 활용될 수 있다는 점이 꽤 흥미로웠다.
우선, willSet
은 값을 변경하기 직전의 상태를 추적하고 어떤 값으로 바뀔지 미리 알고 대응할 수 있다는 것이 큰 장점인데 특히 값이 바뀌기 전에 특정 조건에 따라 미리 경고를 주거나 준비 작업을 해야 할 때 매우 유용하게 쓸 수 있다는 점에서 기본적인 어플에서 많이 봤던 팝업들이 생각났다.
반면, didSet
은 값이 변경된 후 그 변화를 추적하고 그에 맞는 후속 작업을 처리하는걸 순조롭게 해주는 것 같다. 어떤 값이 변경되었는지 그리고 oldValue
와 현재 상태도 비교해서 그에 따라 추가적인 작업을 수행할 수 있었다. 게임 시스템처럼 특정 목표에 도달했을 때 이걸 바로 반영하여 승리 메시지를 출력하거나 특정 레벨업을 제공하는 것처럼 상태 변화에 따른 직관적인 반응을 구현할 수 있는 점이 매력적이었다.
이 두 가지 기능은 각각 프로퍼티가 변하기 전과 후의 시점에서 다른 역할을 맡고 있기 때문에 사용 목적에 따라 적절히 조합하여 활용할 수 있다는 것도 재미있었다. 물론 둘 다 값의 변화를 관리하는 데 유용하지만 언제 변화를 감지하고 어떤 시점에서 코드를 실행할지를 고민하면서 적절하게 설계해야 한다는 점이 중요하다는 것도 알게 된 것 같다.
그래도 이 두 가지를 잘 이해하고 사용하면 앞으로 더 효율적인 것을 만들 수 있겠다는 자신감도 얻었다. 실제로 활용해보고 적재적소에 사용하는 연습도 해보려한다.
그리고 마음 한켠에 있는 게임을 만들고 싶다는 작은 욕망으로 player를 나 자신으로 설정 해봤는데, 저거 해보겠다고 시간이 꽤 지나버렸다. 다음에는 willSet
도 섞어서 온도 조절 시스템
을 만들어보려고 한다.
TIL 개당 100포인트라고 생각하며 저 코드처럼 꾸준히 레벨업 하는 사람이 되고싶다 !
댓글의 score
와 level
연동을 한번 도전 해봤다.
score
가 변경될 때마다 didSet
이 호출되고, 그 안에서 자동으로 level
이 업데이트된다. 여기서는 점수가 100점 이상일 때마다 레벨이 1씩 올라가도록 설계하였다. 점수 100점당 레벨 1
로 설정했다.
level
도 didSet
을 통해 자동으로 변화를 추적해서 이전 레벨과 새 레벨을 비교해준 뒤 출력한다. 이 방식으로 레벨업을 함수로 따로 처리하지 않고도 점수에 따라 레벨이 자연스럽게 변경될 수 있다.
그리고 Point
메서드를 통해 포인트를 추가할 때 자동으로 score
가 변경되고 그에 따라 level
도 함께 업데이트 되도록 했다. 레벨업이 자동화되어서 점수 변화에 따라 레벨이 자연스럽게 설정 될 수 있도록 !
그래서 levelUp
같은 별도의 수동적인 메서드 없이도 점수에 따라 레벨이 자동으로 계산되니까 코드가 더 간결해지기도 했고, 새로운 규칙이 생기면 score
의 didSet
안에서 간단히 점수와 레벨의 관계도 수정할 수 있다.
levelup을 함수로 따로 빼지 않고 레벨별 점수를 설정해서 score의 didSet에 넣어보는 것도 좋을 거 같아요~