Swift

@dynamicMemberLookup

Phililip
728x90

안녕하세요.

 

 

TCA(The Composable Architecture)를 공부하다가 처음 보는 @dynamicMemberLookup 이란 설정이 눈에 들어왔습니다.

 

그래서 이번에는 @dynamicMemberLookup 속성에 대해 알아보려고 해요.

 


# @dynamicMemberLookup 

 

Apply this attribute to a class, structure, enumeration, or protocol to enable members to be looked up by name at runtime. The type must implement a subscript(dynamicMember:) subscript.

 

클래스, 구조체, enum, 프로토콜에 적용할 수 있다. 이 설정을 적용하면 멤버를 런타임 때 이름으로 조회할 수 있게 된다. 그리고 subscript(dynamicMember:) subscript를 구현해야 한다.

 

 

말만 살짝 추상적일 뿐 어려운 내용은 아니니 예시를 통해 직접 알아볼게요.

 

 

아래와 같은 구조체를 만들어봤어요.

 

 

 

MyStruct 인스턴스의 data 필드에 접근할 때는 dot(.) operator를 사용합니다.

(이걸 명시적 멤버 표현(explicit member expression)이라고도 합니다.)

 

그리고 data 필드의 "key1" 이란 필드로 접근할 때는 대괄호([])를 사용하죠.

 

 

 

위 예시를 토대로 살펴봤을 때, dot(.) operator를 사용하면 현재 어떤 필드에 접근 가능한지 컴파일 타임 때 알려줍니다.

(Xcode 상에서 dot(.)을 입력하고 esc를 눌러보면 목록들이 쭈루룩 나오죠? 이때가 컴파일 타임이라고 이해하시면 됩니다.)

 

 

 

대괄호([])를 통해 접근하는 필드는 컴파일 타임 때 알 수 없어요. 그래서 아래처럼 dot(.) operator를 사용하고 싶어도 컴파일 타임 때 에러가 발생합니다.

 

 

 

여기서 @dynamicMemberLookup 속성이 등장하는 것이죠ㅎㅎ

 

@dynamicMemberLookup 속성을 사용하면 dot(.) operator를 사용해서 런타임 때 특정 필드로 접근할 수 있게 됩니다.

 

 

위에서 구현한 MyStruct 구조체에 @dynamicMemberLookup 속성을 적용시켜볼게요.

(subscript(dynamicMember:) 함수를 꼭 구현해줘야 합니다.)

 

 

dot(.) operator 뒤에서 esc를 눌러봤을 때 key1 이란 필드가 없죠?

 

 

그럼에도 dot(.) operator를 사용했을 때 컴파일 에러도 발생하지 않았고 subscript를 통해서 data["key1"] 이란 값을 잘 가져온 것을 볼 수 있어요. (즉, 런타임 때 결정된다는 것입니다.)

 

 

 

# subscript(dynamicMember:)

subscript(dynamicMember:)에는 2가지 타입의 인자만 넘길 수 있습니다.

 

String 타입은 ExpressibleByStringLiteral 프로토콜을 준수하고 있기 때문에 subscript 인자로 사용할 수 있습니다.

 

 

KeyPath 타입을 인자로 넘기는 경우 String 타입과는 다른 큰 특징이 하나 있는데요.

 

컴파일 타임 때 dot(.) operator로 어떤 멤버에 접근할지 결정할 수 있다는 것입니다.

 

 

# subscript(dynamicMember:) & KeyPath

바로 예시를 보여드릴게요.

 

 

인자로 KeyPath를 넘겼다는 것 말고는 처음에 보여드린 예시하고 큰 차이는 없죠?

 

하지만, dot(.) operator 뒤에 esc를 눌러보면 x랑 y라는 필드가 컴파일 타임 때 보이게 됩니다.

 

 

👍 👍 👍

 

 

 

# TCA에서 @dynamicMemberLookup?

이제 @dynamicMemberLookup이 뭔지 알게 되었으니 TCA 코드를 좀 더 깊게 이해할 수 있겠군요ㅎㅎ

 

제가 처음에 @dynamicMemberLookup을 본 것은 TCA의 ViewStore였습니다.

 

 

오홓.. 그래서 컴파일 타임 때 viewStore.state.count가 아니라 viewStore.count처럼 State 구조체의 필드로 바로 접근할 수 있었던 거구만..ㅎㅎㅎ

 

덕분에 이해하게 되었습니다ㅎㅎ

 

 

 

# 참고

- https://docs.swift.org/swift-book/documentation/the-swift-programming-language/attributes/#dynamicMemberLookup

- https://github.com/apple/swift-evolution/blob/main/proposals/0195-dynamic-member-lookup.md

 


이번 글은 여기서 마무리.

 

 

 

반응형

'Swift' 카테고리의 다른 글

CasePaths 맛보기  (0) 2023.04.02
Result Builders  (0) 2023.04.02
computed property vs method  (0) 2023.01.13
mutating  (1) 2022.12.18
@autoclosure  (2) 2022.12.15