https://www.youtube.com/watch?v=2OCPdw2KTic
위 KWDC23 영상을 보고 정리한 글임니다. 자세한 내용은 위 링크를 봐주세 5
특정 입력이 들어왔을 때 특정 출력으로 매핑 되어야 하는지를 정의하는 규칙이나 패턴
하지만 Swift의 매크로는 좀 다름니다.
구조체에서 생성자를 자동으로 제공해주는 멤버별 이니셜라이저를 예로 설명해주심. 작성하지 않아도 컴파일러 단에서 자동으로 생성해주는 코드이다~
Macro는 컴파일러를 수정하지 않고 Swift 패키지에 배포할 수 있는 방식입니다.
@BestSodeul
struct Person {
let name: String
let height: CGFloat
// let isSodeulBest: Bool = true, 얘는 Macro가 생성해줌
}
1 + 1을 넣으면 (1 + 1, "1 + 1")을 만들어주는 매크로를 만드려고 함
let calculations = [
#stringify(1 + 1),
#stringify(2 - 3),
#stringify(3 * 5)
]
먼저 컴파일러가 #, @ 기호를 보고 매크로를 판단합니다. 그리고 해당 구현이 포함된 컴파일러 플러그인에 코드를 전송합니다. 그리고 확장이라는 매크로에 의해 생성된 코드조각을 컴파일러가 반환받습니다.
@freestanging(expression) -> 값을 반환하는 코드 조각 생성
@freestanging(declaration) -> 하나 이상의 선언을 생성
@attached(peer) -> 적용된 선언과 함께 새로운 선언을 추가
@attached(accdessor) -> 프로퍼티에 접근자(accessor)를 추가
@attached(memberAttribute) -> 적용된 타입 또는 익스텐션의 선언에 attribute를 추가
@attached(member) -> 적용된 타입 또는 익스텐션 내부에 새로운 선언을 추가
@attached(conformance) -> 타입 또는 익스텐션에 프로토콜 conformance를 추가
매크로는 라이브러리와 비슷하게 패키지 형태로 배포가 됩니다.
위에서 살펴본 #stringify
의 코드로 살펴보겠습니다.
@freestanding(expression)
public macro stringify<T>(_ value: T) -> (T, String)
= #eternalMacro(module: "KWDCMacros", type: "StringifyMacro")
이 처럼 별도의 플러그인에서 매크로를 확장하도록 관계를 정의해야 합니다. (KWDCMacros 모듈의 StringifyMacro 타입을 살펴봐라 라는 뜻)
KWDCMacros에서 이제 매크로의 실제 구현을 담당합니다.
다음 KWDCClient 에서는 매크로의 동작을 테스트할 수 있습니다. import KWDC를 하고 Client 프로그램에서 사용될 매크로를 API 형태로 노출합니다.
위에 살펴본 부분에서 member role에 관해서 설명해주셨슴
위 매크로를 enum에 적용했을 때 구조체에만 사용해주세요 라는 메시지를 띄우면 더 가독성이 좋아지니까 추가하러 가보겠슴다
위 사진에 구현 부에 아래의 코드를 추가해주면 댐니다
guard declaration.is(StructDeclSyntax.self) else {
throw MyError.notAStruct
}
더 자세하게 오류를 띄우려면, import SwiftDiagnostics
를 추가하여 아래와 같이 해주시믄 됩니다.
여기서 node란, 개발자가 사용한 매크로가 넘어옵니다.
외부 정보를 사용하면 x
매크로는 컴파일러가 제공하는 정보만을 사용해야 합니다. 컴파일러는 매크로 구현이 순수함수라고 가정합니다. 즉, 제공된 데이터가 변경되지 않았따면 확장도 변경되지 않을 것이라고 가정합니다. 이를 우회하면 일관성 없는 동작이 발생할 수 있습니다.
매크로 시스템은 이러한 규칙을 위반할 수 있는 일부 동작을 방지하기 위해 설계되었슴니다. 플러그인은 안전한 샌드박스 내에서 별도의 프로세스로 실행됨니다. 하지만 샌드박스가 모든 동작을 차단하지는 않슴니다~
일반적으로 다른 API들과 같이 라이브러리에 선언되고, 실제 구현은 별도의 플러그인에 되어 있고 이는 안전한 샌드박스에서 실행됩니다.