
기본 개념과 동작 방식 #
- Expression Tree는 코드의 구조를 객체 트리로 표현한 자료구조입니다.
- 트리 각각의 노드는 연산(Operation), 값, 변수, 함수 호출 등 프로그램의 일부를 뜻합니다.
- 한 번 트리를 만든 뒤,
.Compile()메서드를 사용하면 그 구조가 실제 실행 코드(델리게이트)로 변환됩니다. - 컴파일된 결과는 일반 델리게이트처럼 바로 실행할 수 있습니다.
예시 코드 #
using System.Linq.Expressions;
ParameterExpression param = Expression.Parameter(typeof(int), "x");
ConstantExpression constant = Expression.Constant(5);
BinaryExpression body = Expression.Add(param, constant);
Expression<Func<int, int>> lambda = Expression.Lambda<Func<int, int>>(body, param);
var compiledLambda = lambda.Compile();
int result = compiledLambda(10); // result = 15- 위 코드의 트리는 “입력값 x에 5를 더한다"라는 계산을 나타내며, 런타임에 실제 코드로 변환됩니다.
활용 사례 #
- 동적 코드 실행: 프로그램 실행 중 사용자 입력이나 외부 조건에 따라 코드를 동적으로 만들어 실행할 수 있습니다.
- LINQ Provider: Entity Framework나 LINQ to SQL에서 C# 코드를 SQL로 번역할 때 식 트리를 분석하여 변환합니다.
- 메타 프로그래밍: 코드의 구조를 런타임에 분석하고, 동적으로 코드 생성 또는 변환이 필요한 복잡한 로직 구현에 사용됩니다.
- 커스텀 쿼리 빌더: 사용자 조건에 따라 동적으로 WHERE절, 필터링 조건 등을 생성할 때 많이 활용합니다.
성능과 유의사항 #
- 초기 컴파일 비용: 트리 구성과 컴파일에는 오버헤드가 있지만, 컴파일 후 델리게이트는 거의 일반 코드 수준으로 빠르게 동작합니다.
- 정적 코드 대비 한계: 반복적 컴파일 또는 지나치게 복잡한 트리는 성능 저하·메모리 누수 위험이 있으니 재사용하는 방식이 권장됩니다.
- 지원 불가 구문: 전통적인 C# 코드의 모든 제어문(반복문, 예외처리 등)이 식 트리로는 표현이 어렵거나 불가능할 수 있습니다.
- 표준 라이브러리:
System.Linq.Expressions네임스페이스에서 지원되고, 다양한 Factory 메서드와 트리 노드 클래스를 제공합니다.
정리 #
Expression Tree Compilation은 동적 코드 생성, 분석, 최적화, LINQ 기반 데이터 접근 등에서 필수적인 도구이며, 주로 실행 시점에 로직을 유연하게 만들고자 할 때 큰 가치를 발휘합니다.
Executing Expression Trees - C#
Learn about executing expression trees by converting them into executable Intermediate Language (IL) instructions.
Expression<TDelegate>.Compile 메서드 (System.Linq.Expressions)
식 트리로 기술된 람다 식을 실행 코드로 컴파일하고 람다 식을 나타내는 대리자를 생성합니다.