Swift에는 특정 타입에 대해서 런타임에서 조사할 수 있도록 하는 기능이 있습니다.
이를 Reflection이라고 합니다.
Reflection은 특정 타입에 대해 해당 타입이 무엇이고 그 타입이 가지는 프로퍼티들을 알려주기 때문에 디버깅에서 주로 쓰입니다.
공식 문서에서도 디버깅과 리플렉션이 같이 수록되어 있습니다.
Debugging and Reflection
Fortify your code with runtime checks, and examine your values' runtime representation
그럼 Reflection이 뭔지에 대해 더 알아보도록 하겠습니다.
Reflection을 썼을 때의 차이점
먼저 reflection을 사용했을 때 어떤 장점이 있는지 간단하게 살펴보도록 하겠습니다.
class Point {
let x: Double
let y: Double
}
다음과 같이 좌표정보를 가지고 있는 Point라는 타입이 있습니다.
콘솔을 통해 해당 타입을 디버깅한다고 할 때 Reflection을 활용할 때와 아닐 때의 차이는 분명합니다.
let p = Point(x: 1.0, y: 2.0)
// 일반적인 콘솔 print
print(p)
// Output:
// Point
// Reflection을 사용한 콘솔 print
dump(p)
// Output:
// Point
// - x: 1.0
// - y: 2.0
여기서 dump는 Reflection을 사용해서 출력을 해주는 함수인데
print로 p를 찍었을 때는 Point라는 타입 정보만 나왔지만 dump로 p를 찍었을 때는 프로퍼티와 그 값까지 알려주는 것을 알 수 있습니다.
이렇듯 reflection을 사용하는 dump 함수를 사용하면 우리가 디버깅을 할 때 더 자세한 정보를 얻을 수 있습니다.
Mirror
그럼 dump 함수가 reflection의 전부일까요? 아닙니다.
dump 함수의 설명을 보시면 주어진 객체의 mirror를 사용해서 객체의 내용을 가져온다는 내용이 있습니다.
이 Mirror가 reflection의 핵심입니다.
Mirror는 dump의 결과처럼 객체의 내용을 담고 있으며 객체마다 기본적으로 Mirror가 있습니다.
Mirror에는 단순히 프로퍼티 정보뿐만 아니라 객체가 어떤 타입인지,
해당 객체가 class, struct, enum, collection 등 중에서 어떤 기반인지,
해당 객체의 프로퍼티의 이름과 값에 대한 정보들을 알 수 있습니다.
let mirror = Mirror(reflecting: p)
print(mirror.displayStyle) // Optional(Swift.Mirror.DisplayStyle.class)
print(mirror.subjectType) // Point
print(mirror.children) // AnyCollection<(label: Optional<String>, value: Any)>(_box: Swift._RandomAccessCollectionBox<Swift.LazyMapSequence<Swift.Range<Swift.Int>, (label: Swift.Optional<Swift.String>, value: Any)>>)
print(mirror.children.first) // Optional((label: Optional("x"), value: 1.0))
CustomReflectable
Mirror는 알아서 객체에 맞게 생성되지만 이것이 마음에 들지 않을 경우 따로 커스텀할 수 있습니다.
커스텀할 객체에서 CustomReflectable 프로토콜을 상속해 주는 것이 그 방법입니다.
extension Point: CustomReflectable {
var customMirror: Mirror { ... }
}
단순히 dump에 찍히는 문구를 더 보기 좋게 하던지, 이 객체의 children으로 특정 값을 추가해 주거나 제거해 준다던지와 같은 커스텀이 가능합니다.
정리
Swift의 강력한 기능인 Reflection에 대해 알아보았습니다.
잘 사용하면 여러 방면에서 활용할 수 있는 기능이기 때문에 알아두고 써먹을 기회가 있을 때 이 기능을 잘 떠올려서 써먹을 수 있으면 좋겠습니다.
끝으로 이 Reflection을 활용하고 발전시킨 PointFree의 라이브러리 소개하면서 마치겠습니다.
https://github.com/pointfreeco/swift-custom-dump
GitHub - pointfreeco/swift-custom-dump: A collection of tools for debugging, diffing, and testing your application's data struct
A collection of tools for debugging, diffing, and testing your application's data structures. - GitHub - pointfreeco/swift-custom-dump: A collection of tools for debugging, diffing, and testing...
github.com
'Tech' 카테고리의 다른 글
Decorator Pattern(데코레이터 패턴) (0) | 2023.11.05 |
---|---|
Swift Macro 정리 (0) | 2023.10.29 |
iOS 개발자가 코틀린 코드를 볼 때 필요한 몇 가지 문법 (0) | 2023.09.19 |
Swift Dependencies (0) | 2023.08.26 |
StoreKit 기초 (0) | 2023.08.26 |