GDG Busan 2017, 야밤의 Meetup #2

LINQ를 배워보다!

이번에 C#을 스터디를 하면서 가장 인상적이고 놀라웠던 기능 중 하나입니다(LINQ를 기능이라고 해야할지 망설여지는데 제 생각에는 데이터를 처리하는 방법론?이라 느껴집니다).

LINQLanguage-Integrated Query의 약자로 거의 모든 자료를 SQL 형식을 차용한 문법을 사용하여 다룰 수 있도록 설계되었습니다. DB에서 많이 사용되는 SQL을 차용했다는 기술적 측면보다 데이타를 '구조화된 질의어'라는 단일 인터페이스를 통해 거의 모든 자료를 다룰 수 있도록 설계했다는 점이 놀라웠습니다.

LINQ의 기본 인터페이스를 통해 데이터를 조작할 수 있기 때문에 LINQ에서 지원하지 않는 새로운 형태의 데이터가 있다고 해도 인터페이스 규약만 준수한다면 얼마든지 개발자가 확장할 수 있고, LINQ 인터페이스를 사용하기 때문에 일관성을 유지할 수 있다는 점이 장점입니다.

LINQ 101

  • C# 3.0과 .Net Framework 3.5에 도입
  • 임의의 컬렉션(미술 켈렉션 아님, 그 컬렉션임)과 XML DOM(당연히 JSON도 됨)에 질의(Query)를 수행
  • 원격 자료 저장소(a.k.a RDBMS)에 대한 질의도 가능
  • {정적 형식 점검, 동적 질의 작성} 두 가지 모두를 제공

첫걸음

  • LINQ의 기본적인 자료 단위는 SequenceElement
  • SequenceIEnumerable<T>를 구현하는 임의의 객체, Element는 순차열에 들어있는 항목
  • 메모리 내부에 있는 객체들을 지역 컬렉션이라하고, 내부의 SequenceLocal Query이라 함
  • Query operator는 순차열에 어떠한 변환(transformation) 연산을 적용하는 메서드
    • System.LinqEnumerable클래스에 약 40개의 Query Operator 연산자가 있는데, 대부분이 정적 확장 메서드로 구현되어 있고 이들을 통틀어 Standard Query Operators(표준 질의 연산자)라 부름
  • LINQ = Sequence + Query Operator

Fluent Syntax

  • Fluent Syntax가 더 유연하고 확장가능함
  • 예제1
// 배열에서 영문자 "a"가 포함된 모든 이름 추출

using System;  
using System.Collections.Generic;  
using System.Linq;

namespace LinqDemo  
{
    class Program
    {
        static void Main(string[] args)
        {
            string[] names = { "Tom", "Dick", "Harry" };

            IEnumerable<string> filteredNames = names.Where(n => n.Contains("a"));
            foreach (string name in filteredNames)
            {
                Console.WriteLine(name);
            }
        }
    }
}
  • Chaning을 사용해서 좀 더 복잡한 질의를 만드는 방법도 가능
  • 예제2
// 배열에서 영문자 "a"가 포함된 모든 이름 추출
using System;  
using System.Collections.Generic;  
using System.Linq;

namespace LinqDemo  
{
    class Program
    {
        static void Main(string[] args)
        {
            string[] names = { "Tom", "Dick", "Harry", "Mary", "Jay" };

            IEnumerable<string> filteredNames = names
                .Where(n => n.Contains("a"))
                .OrderBy(n => n.Length)
                .Select(n => n.ToUpper());
            foreach (string name in filteredNames)
            {
                Console.WriteLine(name);
            }
        }
    }
}
  • WhereOrderBy, Select는 표준 질의 연산자
  • 한 연산자의 출력 순차열이 그 다음 연산자의 입력 순차열로 사용
    • 질의 연산자의 인수로 지정하는 람다식의 용도는 질의 연산자마다 다름

Query Expressions

  • 질의를 좀 더 간결하게 표기할 수 있는 단축 구문을 지원하는데, 이것을 Query Expressions이라 함
  • 예제
using System;  
using System.Collections.Generic;  
using System.Linq;

namespace LinqDemo  
{
    class Program
    {
        static void Main(string[] args)
        {
            string[] names = { "Tom", "Dick", "Harry", "Mary", "Jay" };

            IEnumerable<string> filteredNames =
                from n in names
                where n.Contains("a")
                orderby n.Length
                select n.ToUpper();
            foreach (string name in filteredNames)
            {
                Console.WriteLine(name);
            }
        }
    }
}

101 LINQ

코드 수준의 자세한 내용은 101 LINQ Samples을 참고해보시면 좋을 것 같습니다.

이젠 dotNET 차레!

다음 시간엔 dotNET을 진행하도록 하겠습니다. LINQ를 좀 더 'dark'하게 연구해보고 싶지만, dotNET에서 LINQ는 얼마나 큰 파괴력을 보여줄지 사뭇 기대됩니다!