블로그로 돌아가기
C#

C# LINQ 사용법: 실무 웹 개발자를 위한 단계별 가이드

c# linq 사용법을 통해 실무 웹 개발에서 컬렉션 쿼리, 필터링, 그룹화, 성능 최적화까지 바로 적용 가능한 예제와 체크리스트를 제공합니다. 코드 중심으로 설명합니다. 실무 적용 흐름과 자주 하는 실수까지 함께 확인할 수 있습니다.

csharplinqdotnet데이터처리성능최적화
C# LINQ 사용법을 설명하는 기술 블로그용 다이어그램 이미지

c# linq 사용법이 필요한 상황

c# linq 사용법은 컬렉션과 DB 쿼리 작업을 더 직관적이고 선언적으로 처리하고자 할 때 필수입니다. 이 글에서는 LINQ의 핵심 개념부터 실무에서 바로 적용 가능한 예제, 성능·보안·운영 관점의 주의점과 체크리스트까지 제공합니다. 읽으면 어떤 상황에서 LINQ를 쓰고 피해야 하는지, 자주 쓰는 패턴과 주의할 포인트를 바로 적용할 수 있습니다.

c# linq 사용법 핵심 개념

LINQ(Language Integrated Query)는 C# 문법 내에서 컬렉션과 데이터 소스에 대해 쿼리를 작성할 수 있게 합니다. 주요 개념은 다음과 같습니다.

  • 연산 유형: 조회(Select), 필터(Where), 정렬(OrderBy), 그룹화(GroupBy), 집계(Aggregate)
  • 연산자 체이닝: 여러 연산자를 조합해 선언적으로 처리
  • 지연 실행(Deferred Execution) vs 즉시 실행(Immediate Execution)
  • IQueryable vs IEnumerable: 실행 위치(클라이언트 vs 서버)를 결정

IQueryable을 통해 DB 프로바이더가 SQL로 변환하도록 하면 서버 측에서 필터링이 이루어지지만, IEnumerable로 변환하면 메모리로 로드된 후 클라이언트에서 처리됩니다.

c# linq 사용법 실무 예제

아래 예제는 EF Core를 사용하는 웹 API에서 흔히 쓰는 패턴입니다. 필터링, 페이징, 프로젝션을 포함합니다.

// 예: EF Core + ASP.NET Core 컨트롤러 내부 public async Task<IActionResult> GetUsers(string role, int page = 1, int pageSize = 20) { IQueryable<User> query = _dbContext.Users; if (!string.IsNullOrEmpty(role)) query = query.Where(u => u.Role == role); var total = await query.CountAsync(); // 서버에서 count var items = await query .OrderBy(u => u.Id) .Skip((page - 1) * pageSize) .Take(pageSize) .Select(u => new { u.Id, u.Name, u.Email }) .ToListAsync(); return Ok(new { total, items }); }

위 코드에서 CountAsync, ToListAsync 같은 즉시 실행 메서드를 호출하기 전까지는 쿼리가 데이터베이스로 전달되지 않습니다. 따라서 불필요한 ToList() 호출을 피하면 메모리 사용과 성능을 절약할 수 있습니다.

언제 쓰면 좋고 언제 피해야 할까

  • 언제 쓰면 좋은가

    • 데이터 소스(컬렉션 또는 DB)에 대해 필터, 정렬, 그룹화, 집계를 선언적으로 표현할 때
    • 가독성과 유지보수성이 중요할 때
    • EF Core 같은 ORM이 SQL로 변환해 효율적으로 처리할 수 있을 때
  • 언제 피해야 하는가

    • 복잡한 탐색이나 트리 기반 알고리즘 처리가 필요해 반복문이 더 명확할 때
    • 작은 컬렉션에서 LINQ 오버헤드가 문제되는 극한 성능 요구 시
    • DB로부터 이미 많은 데이터를 불러와 클라이언트에서 추가 처리해야 하는 경우(가능하면 서버에서 전처리)

판단 기준표

구분항목1항목2항목3
내용사용 목적데이터 크기권장 여부
내용필터/정렬/집계큰 경우 서버필터링(IQueryable)권장
내용복잡한 알고리즘작은 경우 루프 사용 고려상황에 따라

실무 체크리스트

  • IQueryable과 IEnumerable의 차이를 명확히 이해했는가?
  • 데이터베이스로 처리할 수 있는 연산은 서버에서 수행하도록 쿼리를 구성했는가?
  • 불필요한 ToList()/AsEnumerable() 호출로 인해 조기 실행이 발생하지 않는가?
  • 페이징, 정렬, 필터 순서를 적절히 적용했는가?
  • Select로 필요한 컬럼만 프로젝션하여 전송 데이터 크기를 최소화했는가?
  • N+1 문제를 방지하기 위해 필요한 경우 Include 또는 별도 쿼리로 해결했는가?

성능·보안·운영 주의점

  • 성능
    • ToList(), Count() 등의 즉시 실행 메서드 사용 시점 주의
    • Select로 필요한 필드만 선택해 네트워크 전송 비용 절감
    • 복잡한 쿼리는 DB의 실행 계획을 확인하고 인덱스 설계 고려
  • 보안
    • 사용자 입력을 통해 동적으로 쿼리 표현식(Expression)을 생성할 때 SQL 주입 취약성은 ORM이 대부분 처리하지만, Raw SQL 사용 시 파라미터 바인딩을 반드시 사용
  • 운영
    • 대용량 데이터에서 LINQ 쿼리의 실행 시간 모니터링(예: Application Insights)
    • 쿼리 캐싱과 결과 페이징으로 트래픽 절감

실무 예제: 그룹화와 집계

아래는 주문 데이터를 날짜별로 그룹화해 합계를 계산하는 예제입니다.

var monthly = await _dbContext.Orders .Where(o => o.CreatedAt >= start && o.CreatedAt < end) .GroupBy(o => new { o.CreatedAt.Year, o.CreatedAt.Month }) .Select(g => new { Year = g.Key.Year, Month = g.Key.Month, Total = g.Sum(x => x.Amount), Count = g.Count() }) .OrderBy(x => x.Year).ThenBy(x => x.Month) .ToListAsync();

이 패턴은 서버에서 집계를 수행하므로 메모리 사용을 줄이고 네트워크 전송을 최소화합니다.

c# linq 사용법 관련 비교: IQueryable vs IEnumerable

구분항목1항목2항목3
내용IQueryableIEnumerable실행 위치
내용표현식 트리 변환 가능, SQL로 변환메모리 컬렉션 처리서버(DB) vs 클라이언트(메모리)

선택 기준: DB에서 필터/정렬/집계를 수행해야 하면 IQueryable을 유지하고, 메모리 컬렉션 조작이 필요하면 IEnumerable로 전환합니다.

자주 묻는 질문

Q1: LINQ가 항상 느린가요?

A1: 아니요. 잘 구성된 LINQ(IQueryable 사용, 필요한 컬럼만 선택)는 DB에서 효율적으로 처리되며 빠릅니다. 성능 문제는 주로 불필요한 조기 실행이나 클라이언트 전송으로 인해 발생합니다.

Q2: LINQ에서 N+1 문제는 어떻게 해결하나요?

A2: EF Core의 경우 Include로 관련 엔티티를 미리 로드하거나, 필요한 데이터를 한 번의 조인 쿼리로 가져오는 방식으로 해결합니다. 상황에 따라 별도 DTO 쿼리를 사용하는 것이 좋습니다.

Q3: 복잡한 동적 쿼리는 어떻게 작성하나요?

A3: Expression 빌더(예: PredicateBuilder)나 System.Linq.Expressions를 이용해 안전하게 동적 쿼리식을 생성하고, 가능한 한 IQueryable을 유지해 서버에서 처리되도록 합니다.

Q4: LINQ와 SQL 성능 차이는 어떻게 확인하나요?

A4: 실제 실행되는 SQL을 로깅(예: EF Core의 로그 또는 프로파일러)해서 확인하고, 실행 계획을 분석해 인덱스나 쿼리 구조를 개선합니다.

정리

  • c# linq 사용법은 선언적 쿼리로 가독성과 유지보수성 향상
  • IQueryable과 IEnumerable의 차이를 이해하고 실행 위치를 제어할 것
  • Select로 필요한 컬럼만 가져와 네트워크·메모리 비용을 줄일 것
  • 즉시 실행 메서드 호출 시점을 주의해 불필요한 데이터 로드를 피할 것
  • 실무 체크리스트를 통해 N+1, 페이징, 인덱스 문제를 점검할 것
c# linq 사용법: 실무 예제와 주의점 안내 | RYUSLOG DEV