Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
Tags
- Observable
- combine
- ribs
- ios
- RxCocoa
- UICollectionView
- HIG
- Clean Code
- 클린 코드
- swift documentation
- clean architecture
- MVVM
- 리펙토링
- tableView
- 리팩토링
- Human interface guide
- rxswift
- 리펙터링
- Refactoring
- 애니메이션
- Xcode
- Protocol
- swiftUI
- uiscrollview
- uitableview
- UITextView
- collectionview
- map
- SWIFT
- 스위프트
Archives
- Today
- Total
김종권의 iOS 앱 개발 알아가기
[iOS - swift] 11. WWDC2023 정리 - (3) Swift Macro의 expansion (Syntax를 이용하여 매크로 구현방법, literal interpolation, TokenSyntax, ExprSyntax, MacroExpansionContext, 이름 충돌) 본문
WWDC 정리/WWDC 2023 정리
[iOS - swift] 11. WWDC2023 정리 - (3) Swift Macro의 expansion (Syntax를 이용하여 매크로 구현방법, literal interpolation, TokenSyntax, ExprSyntax, MacroExpansionContext, 이름 충돌)
jake-kim 2023. 6. 17. 01:30(1). Swift Macro의 expansion (Macro의 목적, Macro 모델, Macro Role 이해하기, @freestanding, @attached)
(2). Swift Macro의 expansion (Macro 구현 방법, 올바른 Macro 작성 방법)
(3). Swift Macro의 expansion (Syntax를 이용하여 매크로 구현방법, literal interpolation, TokenSyntax, ExprSyntax, MacroExpansionContext, 이름 충돌)
Syntax를 이용하여 매크로 구현하기
- 매크로가 올바르게 적용되었는지 확인한 후에도 실제로 확장을 만들어야함
- SwiftSyntax는 이를 위한 다양한 도구를 제공
- Syntax node는 immutable하지만 새로운 노드를 만들거나 기존 노드의 수정된 버전을 반환하는 API가 존재
- SwiftSyntaxBuilder는 하위 노드 중 일부가 trailing closure로 지정되는 SwiftUI 스타일 구문 빌더를 추가
Syntax로 만들기
- #unwrap에 대한 매크로 구현 방법
ex) 최종 결과물
- guard 부분을 makeGuardStmt() helper 메소드로 따로 분리하고 문자열로 만들기
- 매개변수로 받는 message를 추가 ("was already checked" 부분)
- message는 임의의 표현식이므로 ExprSyntax 노드 타입으로 변경
- guard let 조건은 변수 이름일 뿐이므로 표현식이 아니라 "토큰"이라는 점을 제외하면 이와 유사하며 TokenSyntax 노드 타입인 wrapped 매개변수로 변경
- unwrap에 실패할 때 "Unexpectedly ..." 코드를 출력하는데, Syntax 노드의 문자열화된 구문을 출력하도록 수정이 필요
- \(literal:)과 같이 문자열을 이 안에 넣는 special interpolation 방법을 사용
- 이렇게 사용하면 SwiftSyntax가 문자열의 내용을 문자열 리터럴로 추가
- original expression에 대한 내용을 가지고 있는 ExprSyntax 파라미터를 추가하여 messagePrefix에 적용
- ExprSyntax는 description 프로퍼티를 가지고 있기에 이 값을 messagePrefix 변수에 사용
- "literal:" interpolation을 사용하면 좋은 이유?
- 문자열에 특수 문자가 포함되어 있는지 자동으로 감지하고 escape를 추가하거나 raw literal로 변환하여 코드가 유효한지 확인
- 자동으로 유효한지 확인해주기 때문에 올바른 작업을 유도하기가 쉬움
context를 사용하여 파일 이름과 line number 정보 추가하기
- preconditionFailure에도 file과 line이 있는데 여기에도 Syntax를 이용하여 처리가 가능
- MacroExpansionContext를 사용하면 소스코드의 file, line 정보를 알 수 있으므로 이것을 사용
- context.location(of:)를 사용하면 모든 노드의 위치에 대한 노드 생성이 가능
- 아래 코드에서 force-unwrap을 사용하는 이유는, originalWrapped는 사용자가 작성한 인수 중 하나이므로 해당 위치는 절대 nil이 아님
- 이 객체가 가지고 있는 프로퍼티인 file, line을 사용
매크로의 Name Collision
- 매크로를 사용할 때 외부에 wrappedValue를 선언하고 내부에서도 wrappedValue를 사용할 때 wrappedValue는 더 가까운 값을 찾게 됨
- 개발자가 이런 실수를 안하는게 좋지만, 이러한 같은 이름을 사용하지 못하게 매크로 구현 방법이 존재
- 목적) 매크로 내부의 이름은 외부의 이름과 구별되므로 서로 충돌될 수 없게 만들기
- Macro Expansion Context를 사용하여 "makeUniqueName"기능을 사용
- 이 기능을 사용하면 unique이름을 얻을 수 있고 개발자가 실수로 참조하지 않게끔 가능
- Swift는 왜 매크로 내부의 이름은 외부의 이름과 구별되므로 서로 충돌될 수 없게 만들기 일들을 자동으로 해주지 않는 이유는?
- 많은 매크로가 외부에서 이름을 사용해야 한다는 것을 알았기 때문에 Swift에서 일부러 자동으로 막지 않은것
ex) DictionaryStorage 매크로 - 매크로 내부의 Dictionary와 외부의 Dictionary가 있을때, 자주사용하는 문자열인데 매크로 안에 있으니까 이 단어를 일일이 다 막으면 사용하는 쪽에서는 매크로 내부를 계속 살펴봐야 하는 번거로움이 있기 때문
name specifiers
- 매크로 이름을 선언할 때 named와 prefix가 있는데 매크로의 이름을 선언할 때 사용할 수 있는 기능이 별도로 존쟈재
- 5가지 name specifiers
올바른 매크로 사용법
- Macro는 컴파일러가 제공하는 정보만 사용해야함
- Macro 구현은 순수 함수이며 제공된 데이터가 변경되지 않은 경우 expansion도 변경할 수 없다고 가정
- 이를 어기게 되면 일관되지 않은 동작이 발생할 수 있음
- Compiler plugin은 매크로 구현이 디스크의 파일을 읽거나 네트워크에 액세스하지 못하도록 하는 sandbox에서 실행됨
매크로 잘못된 사용 1)
- #comilationDate와 같은 매크로를 작성하면 안됨
매크로 잘못된 사용 2)
- API를 사용하여 날짜나 난수를 얻거나, expansion의 정보를 전역 변수에 저장하고 다른 expansion에서 사용하는 행위
- 이러한 코드를 개발자가 작성하면 동작은 하지만, 이렇게되면 macro가 오작동할 수 있음으므로 하지 말것
매크로 테스트
- macro plugin은 일반적인 Swift 모듈일 뿐이며, 이 의미는 일반적인 unit test를 작성할 수 있다는 의미
- 테스트 기반 개발은 Swift macro 개발에 매우 효과적인 접근 방식
- SwiftSyntaxMacrosTestSupport의 assertMacroExpansion은 매크로가 올바른 expansion을 생성하는지 확인이 가능
- 아래처럼 assertMacroExpansion에 매크로를 작성하면 안에서 사용한 매크로가 올바른 expansion을 생성, 정확하게 입력했는지 확인이 가능
* 참고
'WWDC 정리 > WWDC 2023 정리' 카테고리의 다른 글
Comments