🔥 첨부형 매크로
Swift에서 매크로(Macro)는 선언에 코드를 추가하는 강력한 기능을 제공합니다. 첨부형 매크로(Attached Macro)라고 불리는 이 매크로는 선언 앞에 @
기호와 함께 매크로 이름을 작성하고, 필요한 경우 괄호 안에 인자를 넣어 호출할 수 있어요.
첨부형 매크로는 자신이 붙어있는 선언을 수정하는데, 이는 새로운 메서드를 정의하거나 프로토콜 준수를 추가하는 등의 작업을 통해 이루어집니다.
예를 들어, 다음은 매크로를 사용하지 않은 코드입니다:
struct SundaeToppings: OptionSet { let rawValue: Int static let nuts = SundaeToppings(rawValue: 1 << 0) static let cherry = SundaeToppings(rawValue: 1 << 1) static let fudge = SundaeToppings(rawValue: 1 << 2) }
swift
이 코드에서 SundaeToppings
옵션 셋의 각 옵션은 이니셜라이저를 호출하는데, 이는 반복적이고 수동적이에요. 새로운 옵션을 추가할 때 실수를 하기 쉽겠죠. 예를 들어 줄 끝에 잘못된 숫자를 입력할 수 있습니다.
이제 매크로를 사용한 버전을 살펴봅시다:
@OptionSet<Int> struct SundaeToppings { private enum Options: Int { case nuts case cherry case fudge } }
swift
이 버전의 SundaeToppings
는 @OptionSet
매크로를 호출합니다. 매크로는 private 열거형의 case 목록을 읽고, 각 옵션에 대한 상수 목록을 생성하며, OptionSet
프로토콜에 대한 준수를 추가해요.
비교를 위해 @OptionSet
매크로를 펼친 버전을 살펴보겠습니다. 이 코드는 직접 작성하지 않으며, Swift에게 매크로의 확장을 명시적으로 요청했을 때만 볼 수 있어요.
struct SundaeToppings { private enum Options: Int { case nuts case cherry case fudge } // rawValue 타입 별칭 선언 typealias RawValue = Int // rawValue 속성 선언 var rawValue: RawValue // 기본 이니셜라이저. rawValue를 0으로 초기화 init() { self.rawValue = 0 } // rawValue를 인자로 받는 이니셜라이저 init(rawValue: RawValue) { self.rawValue = rawValue } // nuts 정적 속성. Options.nuts.rawValue를 shift 연산한 값으로 인스턴스 생성 static let nuts: Self = Self(rawValue: 1 << Options.nuts.rawValue) // cherry 정적 속성. Options.cherry.rawValue를 shift 연산한 값으로 인스턴스 생성 static let cherry: Self = Self(rawValue: 1 << Options.cherry.rawValue) // fudge 정적 속성. Options.fudge.rawValue를 shift 연산한 값으로 인스턴스 생성 static let fudge: Self = Self(rawValue: 1 << Options.fudge.rawValue) } // SundaeToppings를 OptionSet 프로토콜 준수하도록 확장 extension SundaeToppings: OptionSet { }
swift
private 열거형 이후의 모든 코드는 @OptionSet
매크로에서 비롯됩니다. 매크로를 사용하여 모든 정적 변수를 생성하는 버전의 SundaeToppings
는 이전의 수동으로 코딩된 버전보다 읽기 쉽고 유지 관리하기 쉽습니다.
이처럼 첨부형 매크로는 선언에 코드를 자동으로 생성하여 추가함으로써 코드를 간결하고 표현력 있게 작성할 수 있도록 도와줍니다. 개발자는 반복적이고 실수하기 쉬운 작업을 매크로에 맡기고, 좀 더 높은 수준의 추상화에 집중할 수 있게 되는 거죠.