본문 바로가기

IT 살이/04. 기술 - 프로그래밍

LINQ 시리즈 00 - 들어가기

Application Block같은 .NET용 개발 프레임웤을 보면 이제 제너릭 정도는 자연스럽게 사용되고 있다. 프레임웤에 대한 공부를 더 진행하기 전에 이쯤해서 C#에 대한 정리를 해야 할 것 같다. 그러나 하는 김에 제너릭뿐만 아니라 C#3.0이상에서 소개하고 있는 표현들에 대한 정리도 해 볼려고 한다. 그러나 필자도 아직 다 공부를 못한 부분이기에 시간이 좀 걸려서 진행될 것 같은 분위기다. 이번 포스트부터도 연재 형태로 갈려고 한다. 최종 목표는 LINQ라는 것의 이해이다. 해서 연재 제목을 이름하여 "LINQ 시리즈"로 정했다.

들어가기 전에 먼저 하나 생각해 보도록 하자. 고객이 여러명 있다. 이 고객들에 대한 정보가 어떤 형태로 있을 수 있을까? 우선 Customer라는 사용자 정의 타입이 있어서 이 타입의 인스턴스들이 컬렉션 구조로 메모리에 있을 수도 있다.  그래서 for문 또는 foreach문으로 각 인스턴스에 접근할 수 있다. 익숙한 방식이다. 그리고  SQL에 저장되어 있을 수도 있고 XML에 저장되어 있을 수도 있다.

그렇다면 고객의 정보가 어디에 있든 상관없이 한방(!)의 쿼리로 필요한 고객에 대한 정보를 검색해서 가져올 수 있는 방법을 찾는다면 발칙한 발상일까? 한방의 쿼리라 함은 개발자는 같은 표현을 사용하더라면 컴파일러든 .NET 프레임웤든 밑단의 인프라가 알아서 해석해서 정보를 조회해 올 수 없냐는 것이다.

그것을 지원하기 위해서 C# 3.0이상의 버전에서는 LINQ라는 이름의 쿼리문을 제공하고 있다. 즉  데이터 저장 장소가 어떻게 되든 LINQ 라는 쿼리문을 사용하면 동일한 표현으로 작성할 수 있다는 것이다. 개발자는 C#용 표현, SQL 표현, XML용 표현을 작성하지 않아도 된다는 것이다.

var query =

                from c in customers

                where c.Discount > 3

                orderby c.Discount

                select new { c.Name, Perc = c.Discount/100 };

from부터 select까지가 LINQ문이다. 여러 고객들중에서 할인(Discount) 서비스를 3 이상으로 받는 고객을 Discount순으로 정렬해서 이름과 할인율을 가져온다는 것으로 대충(!) 해석할 수 있다. 물론 이게 무슨 말인지 아직은 모른다. 우리말을 모르겠다는 것이 아니라 C#표현이 이해가 가지 않는다.

제일 궁금한 것은 select문 이하이다. 일단 select를 하면 여러 건수가 검색될텐데 그럼 컬렉션이 리턴된다는 말인데...음... 그리고 이 건수들의 타입 즉 Name과 Perc를 정보를 갖는 객체가 어떤 타입일지 모르겠다. 그리고 알 수 없는 타입의 객체들의 컬렉션을 받는 query라는 var 타입의 변수의 정체도 모르겠다. Javascript의 Variable변수 var와 비슷해 보여서 어느 정도 감은 있다. 즉 어떤 타입의 객체도 받을 수 있을 것 같긴 한데, 여튼 이것도 미지근한 존재임은 사실이다.

그리고 고객 정보의 컬렉션을 query에 할당했다면 어떻게 각각의 고객의 속성 예를 들어 Name, Perc에 접근할 수 있는지도 궁금하다.

■ 배워야 할 것들!!

그렇다. LINQ의 표현에 대해서 모른다. 그래서 알아보려고 한다. 그러나 사전에 배워야 하는 것들이 많다.  앞의 표현을 C#3.0은 다음처럼 해석한다.

var query = customers

                   .Where ( c => c.Discount > 3 )

                   .OrderBy( c=>c.Discount )

                   .Select ( c=> new { c.Name, Perc = c.Discount /100 } );

이 중에서 "=>" 표시를 사용한 부분을 람다 표현(lamda expression)이라고 한다. 이 람다 표현은 다시 이전 문법의 익명 메소드, 델리게이트 등으로 다시 바꿔 표현할 수 있다. 나중에 보여준다. 지금 말하고 싶은 것은 LINQ 표현은 이렇게 이렇게 정의하자고 해서 단박에 정의된게 아니다라는 것이다.  앞의 from과 select 사이의 표현이 나오기까지는 많은 진화 과정을 거쳤왔다. 그 진화 과정을 이해해야 LINQ 표현을 일고 제대로 해석할 수 있게 되는 것이다.

우선 그 진화 과정에 대한 설명이 1차 목표이다. 표현의 진화 과정을 설명하기 위해서는 C#2.0의 제너릭(generic), 델리게이트(delegate)를 거쳐서 익명 메소드(anonymous method) 그리고 람다 표현(lamda expression), 타입 추론(type inference), 확장 메소드(extension methods) 휴~~ 그리고 기타등등 헉헉~~등 많은 개념들을 알아야 한다.

그리고 나서 이제 본격적으로 LINQ의 연산자들을 정리하게 된다. 앞의 표현에서 from, where, orderby, select등은 LINQ문의 여러가지 연산자중의 일부이다. 그 외에 많은 LINQ 연산자들이 있다. 이미 익숙해있는 SQL문에서 표현할 수 있는 그런 연산자들을 정리한다고 생각하면 된다. Join, Union, Intersect, Distinct 등등.

따라서 진화 과정에 대한 이해만 이뤄지면 LINQ문은 쉽게 정리가 될 것으로 보인다.

■ 포스트 진행 방향

필자도 아직 정리가 되지 않은 새로운 개념들과 표현도 있다. 되도록이면 메뉴얼 냄새가 나지 않도록 풀어서 일상적인 용어와 예를 통해서 설명이 되도록 최선을 다하고 싶다. 그러다 안되면?......말고! 왜? ..... 내 블로그니까!!