프로그래밍언어

[Swift] Mirror 타입

애기공룡훈련병 2025. 2. 16. 06:58
반응형

Swift에서 리플렉션(Reflection)은 코드가 런타임에서 자신의 속성을 검사하고 수정할 수 있도록 해주는 강력한 기능입니다. 이를 위해 Swift는 Mirror 타입을 제공하며, 이를 활용하면 객체의 프로퍼티를 탐색하고, 구조를 동적으로 이해할 수 있습니다.

이 글에서는 Mirror의 개념을 설명하고, 실제 코드 예제와 함께 이를 어떻게 활용할 수 있는지 살펴보겠습니다.

1. Mirror

Mirror는 Swift에서 객체의 메타데이터(프로퍼티, 타입 정보 등)를 추출하는 기능을 제공합니다. 다음과 같은 정보를 제공할 수 있습니다.

  • 객체의 타입
  • 프로퍼티 목록 및 각 프로퍼티의 값
  • 클래스 또는 구조체의 계층 정보

Mirror의 기본 구조

 

2.  Mirror를 이용한 Property 검사

다음은 Mirror를 사용하여 구조체의 프로퍼티를 검사하는 예제입니다.

struct Person {
    let name: String
    let age: Int
}

let person = Person(name: "Minsu", age: 30)
let mirror = Mirror(reflecting: person)

print("Type: \(mirror.subjectType)")
for child in mirror.children {
    print("Property: \(child.label ?? "unknown"), Value: \(child.value)")
}

실행 결과

Type: Person
Property: name, Value: Minsu
Property: age, Value: 30

 

 

3. Mirror를 활용한 객체의 계층 구조 탐색

Mirror는 부모 클래스의 정보를 조회하는 기능도 제공합니다. 다음 예제를 보겠습니다.

class Animal {
    let species = "Unknown"
}

class Dog: Animal {
    let breed = "Labrador"
}

let dog = Dog()
let mirror = Mirror(reflecting: dog)

print("Type: \(mirror.subjectType)")
for child in mirror.children {
    print("Property: \(child.label ?? "unknown"), Value: \(child.value)")
}

if let superclassMirror = mirror.superclassMirror {
    print("Superclass Type: \(superclassMirror.subjectType)")
    for child in superclassMirror.children {
        print("Property: \(child.label ?? "unknown"), Value: \(child.value)")
    }
}

실행 결과

Type: Dog
Property: breed, Value: Labrador
Superclass Type: Animal
Property: species, Value: Unknown

계층 구조 도식화

4. Mirror 활용 예제: JSON 변환기

Mirror를 활용하면 객체를 JSON 형태로 변환하는 기능도 쉽게 구현할 수 있습니다.

func convertToJSON<T>(_ object: T) -> String? {
    let mirror = Mirror(reflecting: object)
    var dict: [String: Any] = [:]
    
    for child in mirror.children {
        if let key = child.label {
            dict[key] = child.value
        }
    }
    
    if let jsonData = try? JSONSerialization.data(withJSONObject: dict, options: .prettyPrinted),
       let jsonString = String(data: jsonData, encoding: .utf8) {
        return jsonString
    }
    return nil
}

struct User {
    let username: String
    let age: Int
}

let user = User(username: "bob123", age: 28)
if let jsonString = convertToJSON(user) {
    print(jsonString)
}

실행 결과 (JSON 변환)

{
  "username" : "bob123",
  "age" : 28
}
 

5. Mirror의 한계

  1. 불변 프로퍼티 접근 문제: let 키워드로 선언된 프로퍼티는 값을 수정할 수 없음
  2. Method 접근 불가: Mirror는 메서드 정보를 제공하지 않음
  3. Enum의 case 정보 부족: Mirrorenum의 현재 case 이름을 알 수 없음
반응형