@dynamicCallable을 사용한 DSL (Domain Specific Language) 구축

작성일 :

@dynamicCallable을 사용한 DSL (Domain Specific Language) 구축

@dynamicCallable의 기본 개념

Swift 5.0에서 도입된 @dynamicCallable 속성은 자연스러운 문법으로 메서드를 호출할 수 있게 해주는 기능입니다. 이 속성 덕분에 객체를 함수처럼 호출할 수 있게 되며, 이를 통해 도메인 특화 언어(DSL)를 구현하는데 매우 유용합니다. DSL은 특정 문제 영역에 맞춰 최적화된 언어로, 코드를 직관적이고 간결하게 작성할 수 있게 해줍니다.

@dynamicCallable을 사용하면 객체가 함수 호출처럼 보이게 만들 수 있으며 이는 문법을 매우 깔끔하게 만듭니다. 이 기능을 사용하려면 먼저 클래스나 구조체에 @dynamicCallable 속성을 추가하고, dynamicallyCall(withArguments:) 또는 dynamicallyCall(withKeywordArguments:) 메서드를 구현해야 합니다.

예를 들어, 다음과 같이 @dynamicCallable을 사용하여 객체를 함수처럼 호출하는 예제를 볼 수 있습니다.

swift
@dynamicCallable
struct FunctionLike {
    func dynamicallyCall(withArguments args: [Int]) -> Int {
        return args.reduce(0, +)
    }
}

let sum = FunctionLike()
let result = sum(1, 2, 3, 4) // 결과는 10

위의 코드에서 sum(1, 2, 3, 4)는 실제로 sum.dynamicallyCall(withArguments: [1, 2, 3, 4])와 동일하게 동작합니다. 이처럼 @dynamicCallable을 사용하면 객체를 더욱 직관적이고 간결하게 사용할 수 있습니다.

DSL (Domain Specific Language) 구축하기

이제 @dynamicCallable을 사용하여 DSL을 구축하는 과정을 단계별로 살펴보겠습니다. 여기에서는 간단한 예제로 JSON 객체를 생성하는 DSL을 만들어보겠습니다.

1. 기본 구조 정의하기

먼저 JSON 객체를 표현할 클래스를 정의합니다. 이 클래스는 @dynamicCallable 속성을 가지고 있으며, 키워드 인자를 사용하여 JSON의 키-값 쌍을 추가는 기능을 제공합니다.

swift
@dynamicCallable
class JSONBuilder {
    var jsonObject: [String: Any] = [:]

    func dynamicallyCall(withKeywordArguments keyValuePairs: KeyValuePairs<String, Any>) {
        for (key, value) in keyValuePairs {
            jsonObject[key] = value
        }
    }

    func build() -> [String: Any] {
        return jsonObject
    }
}

@dynamicCallable 속성을 통해 dynamicallyCall(withKeywordArguments:) 메서드를 구현하여 키워드 인자를 받아들이고, 이를 jsonObject 딕셔너리에 추가합니다.

2. DSL 사용 예제

다음은 JSONBuilder 클래스를 사용하여 JSON 객체를 생성하는 예제입니다.

swift
let jsonBuilder = JSONBuilder()
jsonBuilder(name: "John Doe", age: 29, isActive: true)
let jsonObject = jsonBuilder.build()
print(jsonObject) // [