C#에서 컬렉션을 다루다 보면 IEnumerable과 IQueryable 중 어떤 인터페이스를 선택해야 할지 고민하게 됩니다. 두 인터페이스는 이름이 비슷하지만, 동작 방식과 성능 면에서 중요한 차이가 있습니다. 이 글에서는 두 인터페이스의 핵심 차이점을 정리하고, 실제 코드 예제와 함께 살펴보겠습니다.
IEnumerable과 IQueryable의 주요 차이점
- 네임스페이스: IEnumerable은 System.Collections 네임스페이스에, IQueryable은 System.Linq 네임스페이스에 정의되어 있습니다.
- 탐색 방향: 두 인터페이스 모두 순방향(forward-only) 컬렉션입니다.
- 지연 로딩(Lazy Loading): IEnumerable은 지연 로딩을 지원하지 않지만, IQueryable은 지연 로딩을 지원합니다.
- 데이터베이스 조회 방식: IEnumerable은 서버에서 SELECT 쿼리를 실행한 뒤 전체 데이터를 클라이언트 메모리로 가져오고, 그 후에 필터링을 수행합니다. 반면 IQueryable은 필터 조건이 모두 포함된 쿼리를 서버 측에서 직접 실행합니다.
- 확장 메서드: IEnumerable의 확장 메서드는 함수 객체(델리게이트)를 매개변수로 받고, IQueryable의 확장 메서드는 식 트리(Expression Tree) 형태의 식 객체를 받습니다.
예제 코드로 확인하는 차이
IEnumerable 사용 예제
dbContext dc = new dbContext();
IEnumerable<SocialMedia> list = dc.SocialMedias.Where(p => p.Name.StartsWith("T"));
list = list.Take<SocialMedia>(1);
IEnumerable 실행 시 생성되는 SQL 문
SELECT [t0].[ID], [t0].[Name] FROM [SocialMedia] AS [t0] WHERE [t0].[Name] LIKE @p0
IEnumerable을 사용하면 WHERE 조건만 데이터베이스에서 처리되고, Take(1)은 클라이언트 메모리에서 실행됩니다. 즉, 조건에 맞는 모든 데이터를 먼저 메모리로 불러온 뒤 상위 1개만 잘라내기 때문에 데이터 양이 많을 경우 성능 저하가 발생할 수 있습니다.
IQueryable 사용 예제
dbContext dc = new dbContext();
IQueryable<SocialMedia> list = dc.SocialMedias.Where(p => p.Name.StartsWith("T"));
list = list.Take<SocialMedia>(1);
IQueryable 실행 시 생성되는 SQL 문
SELECT top 1 [t0].[ID], [t0].[Name] FROM [SocialMedia] AS [t0] WHERE [t0].[Name] LIKE @p0
IQueryable을 사용하면 Take(1) 조건까지 쿼리에 포함되어 SQL 문에 TOP 1이 추가됩니다. 결과적으로 필요한 최소한의 데이터만 데이터베이스에서 가져오므로 훨씬 효율적입니다.
정리: 어떤 것을 사용해야 할까?
이미 메모리에 있는 컬렉션(List, Array 등)을 단순히 순회하는 경우에는 IEnumerable이 적합합니다. 하지만 LINQ to SQL, Entity Framework처럼 데이터베이스와 같은 원격 데이터 소스를 조회할 때는 IQueryable을 사용하는 것이 좋습니다. 필터와 정렬, 페이징 조건이 모두 서버에서 처리되어 불필요한 데이터 전송을 줄이고 애플리케이션 성능을 크게 향상시킬 수 있기 때문입니다.