버깅 스트레스 끝! PropertyWrapper로 Swift 코드 오류 추적
버깅 스트레스 끝! PropertyWrapper로 Swift 코드 오류 추적
Swift에서 프로그래머들은 종종 코드 오류를 추적할 때 큰 어려움을 겪습니다. 이러한 문제를 해결하기 위해 'PropertyWrapper'라는 기능이 도입되었습니다. PropertyWrapper를 통해 어떻게 코드 오류를 효과적으로 추적하고 디버깅할 수 있는지에 대해 자세히 알아보겠습니다.
PropertyWrapper란?
PropertyWrapper는 Swift 5.1에 도입된 기능으로, 프로퍼티의 접근자 메서드를 감싸는 래퍼를 생성할 수 있습니다. 이를 통해 코드의 중복을 줄이고, 특정 프로퍼티에 대한 추가 기능을 손쉽게 제공할 수 있습니다. 예를 들어, 값을 저장하기 전에 유효성 검사를 하거나, 변화를 감지해 로그를 기록하는 등의 작업이 가능합니다.
PropertyWrapper 사용법
PropertyWrapper를 사용하기 위해서는 @propertyWrapper
키워드를 사용해 래퍼 타입을 정의해야 합니다. 예를 들어, 값의 유효성을 검사하는 단순한 래퍼를 만들어 보겠습니다.
swift@propertyWrapper struct Validated<Value> { private var value: Value? private let validation: (Value) -> Bool init(wrappedValue initialValue: Value?, _ validation: @escaping (Value) -> Bool) { self.validation = validation if let initialValue = initialValue, validation(initialValue) { self.value = initialValue } else { self.value = nil } } var wrappedValue: Value? { get { return value } set { if let newValue = newValue, validation(newValue) { value = newValue } else { print("값이 유효하지 않습니다.") value = nil } } } }
위 예시에서 Validated
래퍼는 값이 유효한지 검사하고, 유효하지 않은 경우 경고 메시지를 출력합니다. 이를 통해 값을 설정할 때 자동으로 유효성 검사가 이루어지도록 할 수 있습니다.
예제: 유효성 검사 래퍼 적용
위에서 만든 Validated
래퍼를 실제 코드에 적용해보겠습니다. 간단한 사용자 정보를 다루는 구조체에 적용해 보겠습니다.
swiftstruct User { @Validated({ $0.count >= 5 }) var username: String? @Validated({ $0 > 0 && $0 <= 100 }) var age: Int? }
이제 User
구조체의 username
과 age
프로퍼티에 유효성 검사를 자동으로 적용할 수 있게 되었습니다. 예를 들면, 사용자가 너무 짧은 이름을 입력하거나, 나이를 음수로 입력하는 실수를 방지할 수 있습니다.
swiftvar user = User() user.username = "abc" // 출력: 값이 유효하지 않습니다. user.username = "swift_user" // 정상적으로 설정됨 user.age = -1 // 출력: 값이 유효하지 않습니다. user.age = 25 // 정상적으로 설정됨
이처럼 PropertyWrapper를 이용하면 특정 프로퍼티에 일관된 검사를 적용하고, 오류를 추적하기가 쉬워집니다.
디버깅을 위한 PropertyWrapper
디버깅을 더 용이하게 하기 위해 Custom Logging PropertyWrapper를 만들어 보겠습니다. 이 래퍼는 값이 변경될 때마다 로그를 기록하여 나중에 디버깅할 때 유용하게 사용할 수 있습니다.
Custom Logging PropertyWrapper 구현
swift@propertyWrapper struct Logged<Value> { private var value: Value private let name: String init(wrappedValue initialValue: Value, name: String) { self.value = initialValue self.name = name print(" print(" (\(self.name) - 초기값 설정: \(self.value))") } var wrappedValue: Value { get { return value } set { print(" print(" (\(self.name) - 값 변경: \(value) -> \(newValue))") value = newValue } } }
위 Logged
래퍼는 초기값 설정 및 값 변경 시마다 로그를 출력합니다. 이를 활용하면 어떤 값이 언제 변경되었는지 추적할 수 있어 디버깅에 큰 도움이 됩니다.
예제: 디버깅을 위한 래퍼 적용
다음은 사용자 정보 구조체에 Logged
래퍼를 적용한 예입니다.
swiftstruct UserWithLogging { @Logged(name: "Username") var username: String @Logged(name: "Age") var age: Int } var user = UserWithLogging(username: "initial_user", age: 20) user.username = "new_user" // 출력: (Username - 값 변경: initial_user -> new_user) user.age = 25 // 출력: (Age - 값 변경: 20 -> 25)
이처럼 Logged
래퍼를 사용하면 프로퍼티 값 변경 시마다 자동으로 로그를 기록하고, 이를 통해 오류를 빠르게 추적할 수 있습니다.
결론
Swift의 PropertyWrapper는 코드 오류를 추적하고 디버깅하기 위한 강력한 도구입니다. 이를 활용하면 프로퍼티의 유효성 검사, 값 변경 로그 기록 등 다양한 기능을 손쉽게 구현할 수 있습니다. 위에서 설명한 방법을 통해 더 효율적이고 유지보수하기 쉬운 코드를 작성할 수 있기를 바랍니다.