[G1-Sync] Manual knowledge update

This commit is contained in:
Antigravity Agent
2026-05-10 22:08:15 +09:00
parent 21ac3ed255
commit 504fd5fb42
3011 changed files with 380280 additions and 206977 deletions
@@ -0,0 +1,362 @@
---
id: ios-swift-macros-deep
title: Swift Macros — compile-time codegen
category: Coding
status: draft
source_trust_level: B
verification_status: conceptual
created_at: 2026-05-09
updated_at: 2026-05-09
tags: [ios, swift, vibe-coding]
tech_stack: { language: "Swift", applicable_to: ["iOS"] }
applied_in: []
aliases: [Swift Macros, freestanding macro, attached macro, SwiftSyntax, codegen]
---
# Swift Macros
> Swift 5.9+ 의 hygenic codegen. **Freestanding (`#stringify(x)`) + attached (`@Observable`)**. Boilerplate ↓.
## 📖 핵심 개념
- Compile-time expansion (no runtime).
- Hygenic (scope 격리).
- SwiftSyntax 가 backbone.
- Type-safe.
## 💻 코드 패턴
### Freestanding macro
```swift
let (result, source) = #stringify(2 + 3)
print(result) // 5
print(source) // "(2 + 3)"
```
`#stringify` 가 expression + source string.
### @Observable (Apple)
```swift
import Observation
@Observable
class UserModel {
var name: String = ""
var age: Int = 0
}
// Auto-generates:
// - Tracking infrastructure
// - withMutation calls
// - Observer registration
```
→ SwiftUI 가 자동 observe.
### @Model (SwiftData)
```swift
import SwiftData
@Model
class Item {
var name: String
var quantity: Int
init(name: String, quantity: Int) {
self.name = name
self.quantity = quantity
}
}
// Auto-generates:
// - Persistence
// - Relationships
// - Identity
```
### Custom macro 작성
```swift
// Package.swift
import CompilerPluginSupport
import PackageDescription
let package = Package(
name: "MyMacros",
platforms: [.macOS(.v13)],
products: [
.library(name: "MyMacros", targets: ["MyMacros"]),
],
dependencies: [
.package(url: "https://github.com/apple/swift-syntax.git", from: "509.0.0"),
],
targets: [
.macro(
name: "MyMacroPlugin",
dependencies: [
.product(name: "SwiftSyntaxMacros", package: "swift-syntax"),
.product(name: "SwiftCompilerPlugin", package: "swift-syntax"),
]
),
.target(name: "MyMacros", dependencies: ["MyMacroPlugin"]),
]
)
```
### Stringify implementation
```swift
import SwiftSyntax
import SwiftSyntaxMacros
public struct StringifyMacro: ExpressionMacro {
public static func expansion(
of node: some FreestandingMacroExpansionSyntax,
in context: some MacroExpansionContext
) -> ExprSyntax {
guard let arg = node.arguments.first?.expression else {
return ""
}
return "(\(arg), \(literal: arg.description))"
}
}
```
```swift
// MyMacros
@freestanding(expression)
public macro stringify<T>(_ value: T) -> (T, String) = #externalMacro(module: "MyMacroPlugin", type: "StringifyMacro")
```
### Attached macro
```swift
@AddInit
struct User {
let name: String
let age: Int
}
// Auto-generates:
// init(name: String, age: Int) {
// self.name = name
// self.age = age
// }
```
```swift
public struct AddInitMacro: MemberMacro {
public static func expansion(...) throws -> [DeclSyntax] {
// Generate init from struct properties.
}
}
```
### @Test (Swift Testing)
```swift
import Testing
@Test
func addTwoNumbers() {
#expect(1 + 1 == 2)
}
@Test(arguments: [(1, 2, 3), (5, 5, 10)])
func add(_ a: Int, _ b: Int, _ expected: Int) {
#expect(a + b == expected)
}
```
→ XCTest 의 modern.
### Use case
```
- @Observable: SwiftUI state.
- @Model: SwiftData persistence.
- @Test: testing.
- Custom: builder, Codable boilerplate, lens.
→ Boilerplate 가 큰 → macro 의 답.
```
### Power 와 cost
```
+ Boilerplate 줄임.
+ Type-safe.
+ Compile-time error.
- Compile time ↑.
- Debug 어려움 (expanded code).
- Learning curve.
→ Library author 가 자주 작성.
App dev 가 사용 만 흔함.
```
### Diagnostics
```swift
public static func expansion(...) throws -> [DeclSyntax] {
guard let structDecl = declaration.as(StructDeclSyntax.self) else {
throw MacroError.notStruct
}
if structDecl.members.isEmpty {
context.diagnose(Diagnostic(
node: declaration,
message: SimpleDiagnosticMessage(
message: "Struct has no members",
diagnosticID: .init(domain: "MyMacros", id: "empty"),
severity: .error
)
))
}
// ...
}
```
→ Compile error in Xcode.
### Expanded code 보기
```
Xcode Editor → Right-click → Expand Macro.
또는:
swift -dump-ast file.swift
```
→ Generated code 검토.
### Conformance macro
```swift
@AddCodable
struct User {
let name: String
}
// Generates: Codable conformance.
```
→ Boilerplate ↓ (Swift 가 자동 Codable 도 OK 가, custom logic 필요 시 macro).
### Macro vs property wrapper
```
Property wrapper:
- Runtime.
- 작은 logic.
- 매 access 가 cost.
Macro:
- Compile-time.
- 큰 codegen.
- 0 runtime cost.
→ @Published (옛 Combine) → @Observable (modern macro).
```
### Macro vs protocol extension
```
Protocol extension:
- 다이나믹 dispatch.
- 매 type 가 자체.
Macro:
- 정적 codegen.
- 정밀 control.
→ 매 use case 가 다름.
```
### 함정
```
- Compile time 폭발 (큰 macro).
- Diagnostics 가 confusing.
- Macro 의 변경 = 모든 user recompile.
- Test 가 어려움 (compile-time).
- IDE auto-complete 가 약함.
```
### Production examples
```
- @Observable (Apple, Swift Observation framework).
- @Model (SwiftData).
- @Test (Swift Testing).
- @AsyncFailable (실험).
- TCA (The Composable Architecture)의 @Reducer.
```
### Library author 의 use case
```
- Codable 보다 정밀 JSON.
- Protocol witness table.
- Dependency injection.
- DSL builder.
- Lens / optic.
```
### Compile time
```
큰 macro = 큰 expansion = 큰 compile.
- 10 macro × 1000 line = 10000 line generated.
- Incremental compile 가 partial.
```
→ Profile + optimize.
### Macro testing
```swift
import SwiftSyntaxMacrosTestSupport
func testStringify() {
assertMacroExpansion(
'''
#stringify(1 + 2)
''',
expandedSource: '''
(1 + 2, "1 + 2")
''',
macros: ['stringify': StringifyMacro.self]
)
}
```
→ Snapshot test.
### vs Sourcery / GYB (옛)
```
Sourcery: 외부 tool, code generation.
GYB: Apple internal.
Swift Macros: native, type-safe.
→ Macro 가 modern.
```
### Future
```
2026: Macros 가 mainstream.
- 더 많은 framework 가 macro.
- TCA / Vapor 가 macro 채택.
- Codegen ecosystem 발달.
```
## 🤔 의사결정 기준
| 작업 | 추천 |
|---|---|
| State management | @Observable |
| Persistence | @Model (SwiftData) |
| Testing | @Test |
| Boilerplate (init, codable) | Custom macro |
| 작은 codegen | Property wrapper |
| 외부 tool | Sourcery (legacy) |
## ❌ 안티패턴
- **모든 거 macro**: compile time.
- **Diagnostics 없음**: bad UX.
- **Test 없음**: silent break.
- **Macro 의 macro**: complexity.
- **Big logic in macro**: compile slow.
## 🤖 LLM 활용 힌트
- Swift 5.9+ macro.
- Apple 의 @Observable / @Model / @Test.
- Library author 의 답.
- SwiftSyntax + SwiftCompilerPlugin.
## 🔗 관련 문서
- [[iOS_Swift_Macros]]
- [[iOS_SwiftData_Patterns]]
- [[iOS_Swift_Concurrency_async_await]]