CodeGym /행동 /C# SELF /LINQ 문법: Method Syntax vs Query Syntax

LINQ 문법: Method Syntax vs Query Syntax

C# SELF
레벨 31 , 레슨 1
사용 가능

1. 소개

LINQ 세계에는 쿼리를 작성하는 두 가지 "학파", 두 가지 스타일이 있어. 처음 보면 완전 다르게 느껴질 수도 있는데, 그게 바로 Query Syntax(쿼리 문법)랑 Method Syntax(메서드 문법)이야. 만약 너가 프로그래밍이 무조건 논리적이라고 생각했다면, 오늘은 거기에 예술을 좀 더할 거야. 왜냐면 문법 선택은 붓이랑 연필 중에 뭘 쓸지 고르는 거랑 비슷하거든. 둘 다 그림을 그릴 수 있지만, 하나는 색을 표현하기 좋고, 다른 하나는 윤곽을 그리기 좋아.

왜 두 가지 문법이 필요할까? 좋은 질문이지! 커피 주문한다고 생각해봐. 이렇게 말할 수 있지: "에스프레소에 우유랑 설탕 한 스푼 넣어주세요?". 아니면 쪽지에 "에스프레소. 우유. 설탕 1" 이렇게 쓸 수도 있어. 둘 다 통하지만, 하나는 말투가 더 자연스럽고, 다른 하나는 더 간단하지.

LINQ도 똑같아. 한 문법은 데이터베이스 언어인 SQL이랑 최대한 비슷하게 만들었고, 다른 하나는 더 "C#스럽고" 유연하게 만들었어. 결국 C# 컴파일러는 둘 다 똑같이 메서드 호출로 바꿔버려. 그래서 선택은 거의 읽기 편한지, 네 취향에 달렸지.

둘 다 한번 보자!

2. Method Syntax

이건 LINQ 확장 메서드를 점(.)으로 이어서 계속 호출하는 방식이야. .NET 개발자들 사이에서 특히 인기 많아. 왜냐면 새로운 연산을 쉽게 추가할 수 있고, 결과가 항상 IEnumerable<T>라서 코드 안에서 바로 쓰기 편하거든.

예시: 상품 필터링하고 정렬하기


var filteredProducts = products
    .Where(p => p.Price < 1000)          // 가격으로 필터링
    .OrderBy(p => p.Name)                // 이름으로 정렬
    .ToList();                           // List<Product>로 변환

Where, OrderBy, ToList는 LINQ 확장 메서드들이고, 각각 새로운 데이터셋을 반환해서 계속 이어서 쓸 수 있어.

도식


graph LR
A[products] --> B[Where]
B --> C[OrderBy]
C --> D[ToList]
Method Syntax에서 호출 순서

Method Syntax의 장점

  • 엄청 유연함: 여러 연산을 쉽게 체인으로 만들 수 있어.
  • 모든 게 C# 메서드라서 IDE에서 자동완성도 잘 돼.
  • LINQ에서 할 수 있는 거의 모든 걸 할 수 있음(그 이상도 가능).

또 다른 예시: 18살 이상 유저 이름만 뽑기

예를 들어 User 클래스가 있다고 해보자:


public class User
{
    public string Name { get; set; }
    public int Age { get; set; }
}

이제 성인 유저 이름만 뽑아보자:


List<User> users = ... // 어딘가에 선언됨

var adultNames = users
    .Where(u => u.Age >= 18)
    .Select(u => u.Name)
    .ToList();

3. Query Syntax (SQL 스타일 문법)

이 문법은 C# 개발자들이 SQL을 써본 적 있다면 더 익숙하게 느끼라고 만든 거야. 데이터베이스 쿼리처럼 생겼고, from 키워드로 시작해.

예시: 똑같이 필터링하고 정렬하기


var filteredProducts = 
    from p in products
    where p.Price < 1000
    orderby p.Name
    select p;

이건 그냥 고전적인 쿼리처럼 읽혀: "products 컬렉션에서 p를 뽑고, p.Price < 1000인 것만, p.Name으로 정렬해서, p를 선택".

도식


flowchart TD
    A[products] -->|from p in products| B[where p.Price < 1000]
    B --> C[orderby p.Name]
    C --> D[select p]
Query Syntax에서 쿼리 단계

Query Syntax의 장점

  • SQL이랑 비슷해서 데이터베이스 경험 있으면 이해하기 쉬움.
  • 조건, 그룹화, 조인(join)이 여러 개 들어가는 긴 쿼리에서 더 읽기 편함.

또 다른 예시: 성인 유저 이름만 뽑기


var adultNames = 
    from u in users
    where u.Age >= 18
    select u.Name;

참고: 여기서는 select 뒤에 전체 객체 말고 특정 필드(예: 이름)만 바로 뽑을 수 있어.

4. 비교: Method Syntax vs Query Syntax

Method Syntax Query Syntax
문법
users.Where(...).Select(...)
from u in users where ... select ...
느낌 일반 메서드/체인 SQL
어디서 쓰나 항상, 모든 연산에 모든 연산이 되는 건 아님(예:
Sum
,
Count
는 Method Syntax에서만 가능)
가독성 체인에 좋음 그룹화, 조인에 더 편함
반환값 보통
IEnumerable<T>
보통
IEnumerable<T>
지만, 리스트가 필요하면
.ToList()
추가해야 함

실생활 꿀팁

Microsoft 공식 LINQ 문서 예제는 거의 항상 두 가지 스타일로 다 나와. 근데 실제 현업 코드에서는 Method Syntax가 더 자주 보여. 확장 메서드(Where, Select, OrderBy 등)랑 같이 쓰기 편하거든.

섞어 써도 될까? 어떤 스타일이 좋을까

가능해! 한 프로젝트(심지어 한 쿼리 안에서도) 두 문법을 섞어 쓸 수 있어(근데 좀 이상해 보일 수도 있음). 중요한 건 코드가 뒤죽박죽이 되지 않게 하는 거야. 보통 한 모듈이나 프로젝트 전체에 한 스타일을 정해서 쓰는 게 읽기 편해.

Method Syntax는 연속 변환이나 LINQ 메서드 중 메서드로만 있는 것들(Sum, Count, Any 등) 쓸 때 딱 좋아.

Query Syntaxjoin, group by나 복잡한 조건이 많은 쿼리에서 가독성이 더 좋아.

5. 스타일 변환: 똑같은 걸 다르게 쓰기

C#에서 LINQ는 내부적으로 모든 SQL 스타일 쿼리(Query Syntax)를 메서드 호출 체인(Method Syntax)으로 바꿔. 즉, 뭘 쓰든 결국 컴파일할 때 확장 메서드로 변환돼.

예시 1 — 필터링:

Query Syntax:


var adults = from u in users
             where u.Age >= 18
             select u;

Method Syntax (동일):


var adults = users.Where(u => u.Age >= 18);

예시 2 — 필드 선택(Select):

Query Syntax:


var names = from u in users
            select u.Name;

Method Syntax:


var names = users.Select(u => u.Name);

7. 그룹화와 조인 (join, group by)

새 객체 만들기

우리 예제 앱에 유저를 나이별로 그룹화해서 보여주는 기능을 추가한다고 해보자. 여기서 문법 차이가 확실히 드러나.

Query Syntax (그룹화):


var usersByAge = 
    from u in users
    group u by u.Age into ageGroup
    select new { Age = ageGroup.Key, Users = ageGroup.ToList() };

여기서는 유저를 나이로 그룹화(group u by u.Age)해. into 뒤에 ageGroup이 나오는데, 이게 그룹 자체야.

Method Syntax (동일):


var usersByAge = users
    .GroupBy(u => u.Age)
    .Select(ageGroup => new { Age = ageGroup.Key, Users = ageGroup.ToList() });

더 복잡한 예시: 조인(join)

예를 들어 주문 목록(orders)이랑 유저 목록(users)이 있다고 하자. 유저 이름이랑 주문 금액을 뽑고 싶어.

Query Syntax:


var userOrders =
    from user in users
    join order in orders on user.Id equals order.UserId
    select new { user.Name, order.Amount };

Method Syntax:


var userOrders = users.Join(
    orders,
    user => user.Id,
    order => order.UserId,
    (user, order) => new { user.Name, order.Amount }
);

8. 자주 하는 실수, 함정, 꿀팁

가장 흔한 오해 중 하나: .ToList()를 안 붙이면 결과가 리스트가 아니라 "지연 쿼리"(lazy query)가 돼서, 실제로 처음 순회할 때 실행돼. 이건 편리하지만, 쿼리 작성 후 원본 컬렉션이 바뀌면 예상치 못한 결과가 나올 수 있어. "지연 실행"에 대해서는 LINQ 메서드 배우고 나서 더 자세히 얘기할게.

초보자들이 자주 헷갈리는 게, Query Syntax에서는 모든 LINQ 메서드를 쓸 수 있는 게 아니야. 예를 들어 select sum(u.Age) 이렇게는 못 쓰고, Method Syntax(users.Sum(u => u.Age))로 바꿔야 해.

코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION