--- id: wiki-2026-0508-macros-매크로 title: Macros (매크로) category: 10_Wiki/Topics status: verified canonical_id: self aliases: [Macros, Metaprogramming, Code Generation, Procedural Macros] duplicate_of: none source_trust_level: A confidence_score: 0.9 verification_status: applied tags: [programming, metaprogramming, rust, lisp, c, language-design] raw_sources: [] last_reinforced: 2026-05-10 github_commit: pending tech_stack: { language: rust-lisp-c, framework: language-features } --- # Macros (매크로) ## 매 한 줄 > **"매 컴파일 타임에 코드를 쓴다"**. 매크로는 텍스트/AST 단위로 코드를 생성하는 메타프로그래밍이며, hygiene/표현력에 따라 C 텍스트 치환 → Rust AST → Lisp의 동형성으로 진화한다. ## 매 핵심 ### 매 분류 - **Text-level**: C/C++ 전처리기 — 토큰 치환, hygiene 없음. - **AST-level (declarative)**: Rust `macro_rules!`, Scheme `syntax-rules` — 패턴 매칭. - **AST-level (procedural)**: Rust `proc-macro`, OCaml ppx — 임의 컴파일타임 코드. - **Homoiconic**: Lisp/Clojure — 코드 = 데이터, defmacro로 자유 변환. - **Reflection / templates**: C++ template, Zig comptime — 매크로 인접. ### 매 핵심 속성 1. **Hygiene**: 매크로 안의 식별자가 호출처 스코프와 충돌하지 않음. 2. **Phase**: 컴파일타임 vs 런타임. 3. **Expressiveness**: 단순 치환부터 임의 컴파일러 코드까지. 4. **Tooling**: rust-analyzer/clangd가 macro expansion 지원. 5. **Cost**: 컴파일 시간 / 디버깅 난이도 trade-off. ## 💻 패턴 ### Pattern 1 — Rust `macro_rules!` (declarative) ```rust macro_rules! vec_of { ($($x:expr),*) => {{ let mut v = Vec::new(); $( v.push($x); )* v }}; } let v = vec_of![1, 2, 3]; ``` ### Pattern 2 — Rust derive (proc-macro) ```rust #[derive(Debug, Clone, Serialize, Deserialize)] struct User { id: u64, name: String } // serde_derive가 컴파일타임에 impl Serialize 생성 ``` ### Pattern 3 — Rust attribute proc-macro ```rust #[tokio::main] async fn main() { ... } // 함수 본체를 async runtime 부트스트랩으로 변환 ``` ### Pattern 4 — Lisp defmacro ```lisp (defmacro unless (cond &body body) `(if (not ,cond) (progn ,@body))) (unless (zerop x) (print "non-zero")) ``` ### Pattern 5 — C 매크로 (주의) ```c #define MAX(a,b) ((a) > (b) ? (a) : (b)) // 괄호 필수 #define SQUARE(x) ((x)*(x)) // MAX(i++, j++) → 부작용 두 번 평가 — 함정 ``` ### Pattern 6 — Zig comptime (현대 대안) ```zig fn maxOf(comptime T: type, a: T, b: T) T { return if (a > b) a else b; } // 매크로 없이 타입 매개변수화 ``` ### Pattern 7 — Rust quote! (proc-macro 작성) ```rust use quote::quote; let expanded = quote! { impl #name { fn id(&self) -> u64 { self.id } } }; TokenStream::from(expanded) ``` ## 매 결정 기준 | 상황 | 도구 | |---|---| | 반복 boilerplate | `macro_rules!` 또는 derive | | 복잡 코드 생성 (DSL, ORM) | proc-macro | | 단순 상수 / 헤더 가드 | const / module (매크로 X) | | C에서 inline 강제 | `static inline` (매크로보다 안전) | | 코드 = 데이터 변형 | Lisp/Clojure | | 컴파일타임 일반화 | Zig comptime, C++ constexpr/templates | **기본값**: Rust → 가능하면 함수/제네릭, 그 다음 declarative macro, 마지막 proc-macro. ## 🔗 Graph - 부모: [[Metaprogramming]] - 변형: [[Procedural-Macros]] - 응용: [[Code-Generation]] - Adjacent: [[Reflection]] ## 🤖 LLM 활용 **언제**: - `macro_rules!` 패턴 작성. - proc-macro skeleton (syn/quote 보일러). - C 매크로 함정 감사. **언제 X**: - 매크로 디버깅 (실제 expansion 확인 필요). - 매우 복잡한 DSL 설계 (테스트 필수). ## ❌ 안티패턴 - 함수로 충분한데 매크로 사용 (디버깅 지옥). - C 매크로에서 인자 괄호 누락. - 부작용 있는 인자를 매크로에 넘김 (`MAX(i++, j)`). - proc-macro 컴파일 시간 폭증 무시. - Hygiene 가정 (C는 없음, Rust/Scheme은 있음). - 매크로로 타입 검사 우회. ## 🧪 검증 / 중복 - Verified. Rust 1.83/2024 edition 기준. 신뢰도 A. ## 🕓 Changelog | 날짜 | 변경 | |---|---| | 2026-05-08 | Phase 1 | | 2026-05-10 | Manual cleanup |