이번에 SwiftUI , TCA를 활용하면서 개인 프로젝트를 진행 중인데 이 과정에서 왜 사용하고 있었는지 의문이었던 부분을 기록으로 남겨두려고 한다.
Equatable
먼저 Swift에서 Equatable 프로토콜을 사용하는 이유는 두 객체를 비교해서 동일한지 여부를 판단할 수 있게 해주기 때문에 Equatable 채택해 == 연산자를 구현하는 방식으로 두 객체를 비교하게 된다.
Swift 컴파일러는 struct나 enum이 Equatable을 채택할 때 모든 저장 프로퍼티가 Equatable를 준수하면 자동으로 == 연산자를 구현해주기 떄문에 직접 구현하지 않아도 돼서 매우 편리한 방법이다.
import ComposableArchitecture
import MapKit
struct RunningState: Equatable {
var record: RunningRecord?
var isRunning: Bool = false
var currentLocation: CLLocationCoordinate2D?
var mapRegion: MKCoordinateRegion?
var authorizationStatus: CLAuthorizationStatus = .notDetermined
var heartRate: Int = 0
var cadence: Int = 0
}
예를 들어 이렇게 프로퍼티의 상태에 관련 내용을 모아두게 됐을 때 이런식으로 사용하게 되는데 이 중에서 하나라도 Equatable을 준수하지 않으면 자동 합성이 불가하고 컴파일 에러가 발생하게 된다.
이러한 상황에서 에러가 발생하지 않기 위해 Equatable를 준수하지 않는 타입을 별도로 extenㄴion으로 지정해주면서 에러가 발생하지 않고 사용할 수 있게 한다는 점이 잘 이해가 가지 않았다 ㅎㅎ
위에 있는 프로퍼티들 중 CLLocationCoordinate2D, MKCoordinateRegion 과 같은 타입이 해당 되었는데 이를 해결하기 위해 extension으로 해당 값을 설정해 주었다.
extension CLLocationCoordinate2D: Equatable {
public static func == (lhs: CLLocationCoordinate2D, rhs: CLLocationCoordinate2D) -> Bool {
lhs.latitude == rhs.latitude && lhs.longitude == rhs.longitude
}
}
여기서 latitude , longitude은 Double 타입이고 이 타입은 Equatable를 준수하기 때문에 각각의 값을 비교해 동일한지 여부를 판단하는 로직을 추가해주면 Equatable를 지원하지 않아도 사용할 수 있게 된다.
extension MKCoordinateRegion: Equatable {
public static func == (lhs: MKCoordinateRegion, rhs: MKCoordinateRegion) -> Bool {
lhs.center == rhs.center && lhs.span == rhs.span
}
}
여기서는 center, span을 Equatable로 확장해 그 둘을 각각 비교할 수 있게 만들어주면서 Equatable를 사용할 수 있는 방향으로 구현하였다.
Equatable를 왜 써야할까
그렇다면 왜 이런방식으로 구현해야하는 걸까 그건 상태 관리 및 비교의 필요성이라고 생각한다. 앱 개발 시 State를 관리하고 변경되었는지 여부를 판단해야하는 경우가 많다.
예를 들어 TCA 에서는 상태 변화에 따라 뷰를 업데이트하거나 로직을 처리하는 경우가 많은데 이때 상태를 비교하기 위해서는 Equatable를 준수하도록 구현하여 값이 다른지 같은지를 판단하는게 중요하기 때문이다.
항상 왜 이렇게 사용해야하는지에 대해서 생각하고 그 이유를 머리속에 잘 이해하고 사용하는 습관이 중요한 것 같다 ㅎㅎ
중요하건 중요하지 않건 사용하면서 왜 이렇게 해야하지? 라는 의문이 든다면 그 이유를 한번 찾아보고 기록해나가는 습관을 더욱 키워보자!! (TCA 왜 이렇게 어렵쥐..)
오늘은 여기까지.!!
'◽️ Programming > T I L' 카테고리의 다른 글
Device 잠금 상태 추적해 백그라운드 데이터 업로드 하기 (0) | 2024.11.07 |
---|---|
Firebase RealtimeDatabase 내 데이터 저장하기 (0) | 2024.10.25 |
[Project 일지] Running App (1) (0) | 2024.08.30 |
Swift의 async/await에 대해서 알아보자 (0) | 2024.08.19 |
CropBox를 활용해 이미지 자르기 (0) | 2024.08.16 |