--- id: wiki-2026-0508-aspect-oriented-programming-aop title: Aspect Oriented Programming (AOP) category: 10_Wiki/Topics status: verified canonical_id: self aliases: [AOP, Aspect Programming, Cross-cutting Concerns] duplicate_of: none source_trust_level: A confidence_score: 0.9 verification_status: applied tags: [architecture, paradigm, spring, decorator] raw_sources: [] last_reinforced: 2026-05-10 github_commit: pending tech_stack: language: Java / TypeScript / Python framework: Spring AOP / AspectJ / NestJS --- # Aspect-Oriented Programming (AOP) ## 매 한 줄 > **"매 cross-cutting concern을 separate aspect로 modularize."**. 1997년 Gregor Kiczales (Xerox PARC) 의 AspectJ 가 시초. 2026 현재 Spring AOP 6.x, NestJS interceptor, Python decorator 가 주류 — logging/transaction/security 같이 매 객체 가로지르는 logic을 매 한 곳에 모음. ## 매 핵심 ### 매 용어 - **Aspect**: 매 cross-cutting concern 의 modular 단위 (e.g. `LoggingAspect`). - **Join Point**: 매 program execution 의 한 지점 (method call, field access). - **Pointcut**: 매 join point 의 selection expression. - **Advice**: 매 pointcut 매칭 시 실행할 code (`@Before`, `@After`, `@Around`). - **Weaving**: 매 aspect 와 base code 결합 — compile-time / load-time / runtime. ### 매 cross-cutting concerns - Logging / tracing - Transaction management - Security / authorization - Caching - Performance monitoring - Error handling / retry - Audit trail ### 매 응용 1. Spring `@Transactional` — DB transaction 자동 commit/rollback. 2. NestJS `@UseInterceptors` — request/response transform. 3. Python `@functools.lru_cache` — pure caching aspect. 4. OpenTelemetry auto-instrumentation — runtime byte-code weaving. ## 💻 패턴 ### Spring AOP — @Around aspect ```java @Aspect @Component public class LoggingAspect { @Around("execution(* com.example.service.*.*(..))") public Object logExecutionTime(ProceedingJoinPoint pjp) throws Throwable { long start = System.currentTimeMillis(); try { Object result = pjp.proceed(); long elapsed = System.currentTimeMillis() - start; log.info("{} took {} ms", pjp.getSignature(), elapsed); return result; } catch (Throwable t) { log.error("{} threw {}", pjp.getSignature(), t.getMessage()); throw t; } } } ``` ### Spring — @Transactional declarative TX ```java @Service public class OrderService { @Transactional(rollbackFor = Exception.class, isolation = Isolation.READ_COMMITTED) public Order placeOrder(OrderRequest req) { Order order = orderRepo.save(new Order(req)); inventoryRepo.decrement(req.getItems()); // Any RuntimeException → automatic rollback via AOP proxy return order; } } ``` ### NestJS — Interceptor (AOP-style) ```typescript import { CallHandler, ExecutionContext, Injectable, NestInterceptor } from '@nestjs/common'; import { Observable, tap } from 'rxjs'; @Injectable() export class TimingInterceptor implements NestInterceptor { intercept(ctx: ExecutionContext, next: CallHandler): Observable { const start = Date.now(); return next.handle().pipe( tap(() => console.log(`${ctx.getHandler().name} took ${Date.now() - start}ms`)), ); } } @Controller('orders') @UseInterceptors(TimingInterceptor) export class OrdersController { /* ... */ } ``` ### Python — Decorator as aspect ```python import functools, time, logging def timed(func): @functools.wraps(func) def wrapper(*args, **kwargs): start = time.perf_counter() try: return func(*args, **kwargs) finally: elapsed = time.perf_counter() - start logging.info(f"{func.__name__} took {elapsed*1000:.1f}ms") return wrapper @timed def expensive_calc(n: int) -> int: return sum(i * i for i in range(n)) ``` ### Python — Class-based retry aspect ```python def retry(times: int = 3, on: tuple = (Exception,)): def decorator(func): @functools.wraps(func) def wrapper(*args, **kwargs): last = None for attempt in range(times): try: return func(*args, **kwargs) except on as e: last = e time.sleep(2 ** attempt) raise last return wrapper return decorator @retry(times=5, on=(httpx.HTTPError,)) def fetch_remote(url: str) -> dict: return httpx.get(url).json() ``` ### AspectJ pointcut DSL ```java @Pointcut("execution(public * com.example.repo.*.find*(..))") public void anyFinder() {} @Pointcut("@annotation(com.example.Audited)") public void auditedMethod() {} @Before("anyFinder() && auditedMethod()") public void audit(JoinPoint jp) { auditService.log(jp.getSignature().toShortString(), Instant.now()); } ``` ### TypeScript — method decorator ```typescript function Cached(ttlMs: number): MethodDecorator { const cache = new Map(); return (_t, _k, desc: PropertyDescriptor) => { const original = desc.value; desc.value = function (...args: unknown[]) { const key = JSON.stringify(args); const entry = cache.get(key); if (entry && entry.exp > Date.now()) return entry.value; const value = original.apply(this, args); cache.set(key, { value, exp: Date.now() + ttlMs }); return value; }; }; } class Pricing { @Cached(60_000) fetchRate(currency: string) { /* ... */ } } ``` ## 매 결정 기준 | 상황 | Approach | |---|---| | Java enterprise, declarative TX | Spring AOP (proxy-based) | | 매 method 매칭 + field access weaving | AspectJ (compile/load-time) | | Node.js HTTP layer | NestJS Interceptor / Guard | | Python script / function-level | Decorator | | Cross-language tracing | OpenTelemetry auto-instrumentation | **기본값**: framework-native (Spring AOP / NestJS interceptor / decorator). 매 raw AspectJ 는 매 매우 specific 한 경우만. ## 🔗 Graph - 부모: [[Object-Oriented-Programming]] · [[Software-Architecture]] - 변형: [[Middleware]] - 응용: [[Spring-Framework]] · [[NestJS]] · [[OpenTelemetry]] - Adjacent: [[Dependency_Injection_(DI)|Dependency-Injection]] · [[Cross-Cutting-Concerns]] ## 🤖 LLM 활용 **언제**: cross-cutting concern (logging/TX/security/caching) 이 매 여러 service 에 반복, declarative style 선호, framework 가 AOP 지원. **언제 X**: 매 한두 곳만 쓰는 logic (직접 호출이 명확), 매 magic 회피 culture, 매 debug 어려움 감수 못할 때. ## ❌ 안티패턴 - **Aspect 안 business logic**: 매 aspect 는 매 cross-cutting 만 — 매 domain rule 넣지 X. - **너무 broad pointcut**: `execution(* *.*(..))` — 매 unintended weaving. - **Self-invocation 의 proxy bypass**: 매 같은 class 안 method call 은 매 proxy 통과 안 함 (Spring). - **Order 의존**: 매 multiple aspect 매 ordering 명시 X 면 매 비결정적. - **Aspect explosion**: 매 100+ aspect → 매 control flow 추적 불가. ## 🧪 검증 / 중복 - Verified (Spring Framework 6.x docs, AspectJ programming guide, NestJS docs). - 신뢰도 A. ## 🕓 Changelog | 날짜 | 변경 | |---|---| | 2026-05-08 | Phase 1 | | 2026-05-10 | Manual cleanup — AOP full content with Spring/NestJS/Python patterns |