작성일 :


LINQ(Language Integrated Queary)

LINQ (“링크”로 발음, Language Integrated Query) 는 2007년 .NET Framework 3.5 의 중요 부분으로 처음 출시 됐다.

SQL 과 비슷하게 질의식의 추가를 통해 언어를 확장하며, 배열, 열거식 클래스, XML, 관계형 DB, 3rd Party Data Source 로부터 데이터를 편리하게 추출하고 가공하기 위해 사용할 수 있다.


기본 개념

LINQ 는 데이터 쿼리를 직관적이고 선언적인 방식으로 작성할 수 있게 해준다.

또한, 다양한 데이터 소스에 대한 쿼리를 통일된 문법으로 작성할 수 있다.
LINQ의 기본 개념 및 특징은 다음과 같이 정리할 수 있다.


  • 통합된 쿼리 언어
    : LINQC# 이나 VB.NET 같은 .NET 프레임워크에 통합되어 있어, 데이터베이스 쿼리를 위한 별도의 언어를 배울 필요가 없다.

  • 다양한 데이터 소스 지원
    : LINQSQL DB, XML, 메모리 내의 컬렉션 등 다양한 데이터 소스에 대한 쿼리를 지원한다.
    따라서, 데이터 소스의 종류에 상관 없이 동일한 쿼리 패턴을 사용할 수 있게 해준다.

  • 필터링, 정렬 및 집계 기능
    : LINQ 쿼리는 SQL과 유사한 다양한 연산자를 제공한다.
    where, select, orderby, groupby 와 같은 연산자를 사용해 데이터를 필터링, 추출, 정렬 및 집계할 수 있다.

  • 객체지향 접근
    : LINQ.NET 의 객체 지향 프로그래밍과 잘 통합되어 있어, 결과를 객체의 컬렉션으로 쉽게 처리할 수 있다.

  • 지연 실행(Lazy Evaluation)
    : LINQ 쿼리는 실행 시점까지 연산을 지연시킨다.
    이는 쿼리를 정의하고 필요할 때까지 실제 데이터 소스에 접근하지 않음을 의미한다.
    이로 인해 성능 최적화가 가능해진다.

  • 익명 타입 및 람다식 지원
    : LINQ 는 람다식과 익명 타입을 통해 쿼리의 가독성과 편의성을 높여준다.
    람다식은 간결하고 직관적인 쿼리 작성을 가능하게 하며, 익명 타입은 복잡한 쿼리 결과를 쉽게 구성할 수 있게 해준다.

  • 확장성
    : LINQ 는 확장 가능하며, 개발자는 자신만의 LINQ 프로바이더를 만들어 특정 데이터 소스에 대한 지원을 추가할 수 있다.


    즉, 깔끔하고 유지보수하기 쉬운 코드 작성을 통해 개발자로 하여금 데이터 처리 작업에 더 집중할 수 있도록 한다.
    또한, LINQ 는 데이터 쿼리와 관련된 일반적인 작업을 단순화하고 표준화함으로써, 코드의 일관성과 효율성을 향상시킨다.



LINQ 의 기본 : from, where, orderby, select

LINQ 에서 from, where, orderby, groupby, select 는 데이터를 쿼리하는 데 사용되는 핵심 키워드이다.

from

from 키워드는 쿼리의 시작점을 정의한다.
즉, 데이터 소스와 범위 변수를 지정하는 데 사용된다.

예시 : Person 리스트에서 각 Person 객체에 접근

1
2
3
4
List<Person> people = GetPeople();

var query = from person in people
            select person;

: from person in peoplepeople 컬렉션의 각 항목에 대해 person 이라는 범위 변수를 사용하여 순회한다는 것을 나타낸다.

where

where 키워드는 조건을 기반으로 데이터를 필터링한다.

예시 : 나이가 30세 이상인 사람들만 선택한다.

1
2
3
var query = from person in people
            where person.Age > 30
            select person;

: where person.Age > 30 는 나이가 30 세 이상인 person 객체만 선택한다.

orderby

orderby 는 결과를 특정 기준에 따라 정렬한다.

예시 : 사람들을 이름순으로 정렬한다.

1
2
3
var query = from person in people
            orderby person.Name
            select person;

: orderby person.Name 쿼리는 people 컬렉션의 각 person 객체들을 Name 에 따라서 정렬한다.

groupby

groupby 는 특정 기준에 따라 데이터를 그룹으로 묶는다.

예시 : 사람들을 도시별로 그룹화하고 각 그룹에 속한 사람의 수를 계산

1
2
3
4
var query = from person in people
            group person by person.City into cityGroup
            select new { City = cityGroup.Key,
                         Count = cityGroup.Count()};

: people 컬렉션을 City 속성에 따라 그룹화하고, 각 도시별로 몇 명의 사람이 속해있는 지를 계산한다.

select

select 는 쿼리 결과의 형태를 지정한다.

예시 : 각 사람의 이름과 나이만을 선택한다.

1
2
var query = from person in people
            select new { person.Name, person.Age };

: 이 예시에서 select 는 쿼리 결과로 person 객체의 NameAge 속성만 포험하는 새로운 익명 타입을 생성한다.


전통 C# 방식과 LINQ 적용 후에 대한 비교

예시 : Person 객체의 리스트에서 특정 조건을 만족하는 사람들을 찾는 상황 가정

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Person {
  public string Name { get; set; }
  public int Age { get; set; }
  public string City { get; set; }
}

// 어딘가에서 Person 객체의 리스트를 가져온다고 가정
List<Person> people = GetPeople();

List<Person> results = new List<Person>();
foreach (var person in people) {
  if (person.Age > 30 && person.City == "Seoul")
    results.Add(person);
}

: people 리스트를 순회하면서, 나이가 30세 이상이고, 도시가 Seoul 인 사람들을 찾아 results 리스트에 추가하는 전통 C# 방식


LINQ 적용 후

1
2
3
var results = people
  .Where(person => person.Age > 30 && person.City == "Seoul")
  .ToList();

: LINQ 를 사용하면 쿼리 자체가 간결해지고 읽기 쉬워진다.
where 메서드는 조건을 만족하는 모든 요소를 선택하고, ToList 는 그 결과를 새로운 리스트로 변환한다.



더 복잡한 예시 : 나이가 30 세 이상인 사람들을 찾아 그들의 이름으로 정렬한 다음, 각 사람의 이름과 도시만을 추출하는 경우

1
2
3
4
5
6
7
8
9
10
11
12
List<Person> filteredPeople = new List<Person>();

foreach (var person in people) {
  if (person.Age > 30)
    filteredPeople.Add(person);
}

filteredPeople.Sort((p1, p2) => p1.Name.CompareTo(p2.Name));

List<(string Name, string City)> result = new List<(string Name, string City)>();
foreach (var person in filteredPeople)
  result.Add((person.Name, person.City));



LINQ 적용 후

1
2
3
4
5
var result = people
  .Where(person => person.Age > 30)
  .OrderBy(person => person.Name)
  .Select(person => (person.Name, person.City))
  .ToList();

: Where 는 필터링을, OrderBy 는 정렬을, 그리고 Select 는 필요한 데이터의 추출 및 변환을 담당한다.