login register Sysop! about ME  
qrcode
    최초 작성일 :    2007년 10월 30일
  최종 수정일 :    2007년 11월 12일
  작성자 :    kobukii
  편집자 :    kobukii(김 경균)
  읽음수 :    46,653

강좌 목록으로 돌아가기

필자의 잡담~

이번 강좌는 태오 사이트의 멤버이자, Microsoft MVP인 김 경균님이 제공하는 LINQ에 관한 이야기입니다. 많은 분들이 관심을 가지고 있는 LINQ에 대해 기본적인 개념을 이해할 수 있는 강좌가 될 예정이니 많은 관심을 부탁드립니다.

LINQ란 무엇인가?

LINQ는 Language Integrate Query의 약자로써 통합 질의 언어 라고 말할 수 있습니다..
기존의 Query는 Database의 데이터를 다루기 위해 사용하는 언어쯤으로 여겨 졌습니다. 하지만 LINQ는 컬렉션 형태로 되어있는 모든 데이터에 대해 질의를 할 수 있는 마이크로소프트의 새로운 기술입니다.
예를 들자면 MS-SQL의 데이터를 가져오는데 LINQ를 사용할 수 있는 것은 물론이고 메모리상의 컬렉션 또는 XML에 대해서도 LINQ를 사용할 수 있습니다.
지금부터 이 강력한 통합질의언어인 LINQ에 대해 알아보도록 하겠습니다.

1. Extension Method(확장 메서드)

Extension Method(이하 확장메서드)는 기존의 타입에 매서드를 추가하거나 재컴파일 할 필요 없이 이미 존재하는 CLR타입에 새로운 메서드를 추가할 수 있게 설계된 메서드 입니다.

//static클래스를 생성해야 한다.
public static class KClass
{
    //static메서드로 생성해야 한다.
    public static int isOdd(this int n)
    {
        //홀수일 경우 1을 반환한다.
        if (n % 2 == 1)
            return n;
        return 0;
    }
}

int num = 5;
//int형의 변수 뒤에 isOdd()를 사용할 수 있다.
//num이 5이므로 5를 반환한다.
int oddValue = num.isOdd();

LINQ 와 확장메서는 무슨 관계인가? 확장메서드는 LINQ에서 쿼리를 위한 메서드(Select, Where...)는 확장 메서드로 되어 있기 때문입니다.

위의 캡쳐화면을 보면 분홍색 육면체는 일반 메서드를 나타냅니다. 그 중에서 파란색의 아래방향 화살표가 있는 것이 확장메서드를 나타내는 아이콘인데 위에서는 All, Any, Average등이 있습니다.

LINQ에서는 상당히 많은 수의 확장메서드를 사용합니다. 거의 모든 메서드가 확장메서드라고 봐도 무방할 정도죠. 확장메서드는 LINQ뿐만이 아니라 일반 코드에서도 응용할 수 있기에 이장에서 다루어 보았습니다.

2. Anonymous Type(익명 타입)

Anonymous Type은 타입의 선언을 명확하게 정의하지 않고 코드 내의 CLR타입을 간단하게 정의하는 것이 가능한 C#3.0의 편리한 기능입니다.

public class Tech
{
    public string Upper{ get; set;}
    public string Lower{ get; set;}
}

string[] strs = {"ASp.NeT","AjAx","SilvErLigHt"};
IEnumerable<Tech> techs = from s in strs
                    select new Tech
                    {
                        Upper = s.ToUpper(),
                        Lower = s.ToLower()
                    };
foreach (Tech t in techs)
{
    Response.Write(t.Lower + "," + t.Upper + "");
}

위의 예제는 Query Syntax를 사용합니다. 아직 Query Syntax의 사용법에 대하여 배우지는 않았지만 Anonymous Type에 대햐여 알아보기 위해 간단한 Query Syntax를 사용하였습니다.
우선 Upper와 Lower프로퍼티를 갖는 Tech라는 클래스를 만들었습니다.(이 클래스는 프로퍼티 생성방법이 기존과 약간 다릅니다. 이를 Automatic Propertity라고 합니다.)
strs라는 문자열 배열에는 대소문자가 구분되지 않은 세 개의 문자열이 있습니다. from절에서 strs를 사용하겠다고 명시했고 select절에서는 new Tech키워드를 이용해 앞에서 만들었던 Tech타입으로 개체를 생성합니다. 그리고 각각 Upper와 Lower에 값을 할당합니다.
이를 받는 techs변수는 Tech를 타입매개변수로 하는 IEnumeable형으로 선언합니다.

Query Syntax를 이용하여 미리 정의된 타입으로 데이터를 쿼리 했습니다. 상당히 명시 적이지만 Tech타입이 범용적으로 쓰이지 않고 현재 코드 부분에서 한시적으로 사용된다면 코드가 많이 복잡해 질 수 있습니다.
이를 좀더 간단하게 사용하기 위해 나온 것이 Anonymous Type입니다.

string[] strs = {"ASp.NeT","AjAx","SilvErLigHt"};
var texts = from s in strs
                select new
                {
                    upper = s.ToUpper(),
                    lower = s.ToLower()
                };
foreach(var t in texts)
{
    Response.Write(t.lower + "," + t.upper + "");
}

위의 코드는 앞의 코드에 비해 상당히 간단해 졌습니다. 일단 Tech클래스 정의가 없어졌습니다. select절을 보면 new키워드 다음 Tech클래스 생성자가 없어진 것을 볼 수 있습니다.
클래스의 생성자 없이 바로 new키워드를 통해 개체를 생성하고 임의로 upper와 lower를 만들어 값을 할당합니다.
이것이 바로 Anonymous Type입니다. 익명으로 타입을 생성한 것입니다.
그래서 이 쿼리 결과는 타입이 명확하지 않기 때문에 IEnumeable<>형으로 받지 않고 var 키워드를 사용하게 됩니다.

다음은 var 키워드에 대해 알아보도록 하겠습니다.

3. var 키워드

c#3.0에서 가장 충격적인 부분이라고 생각하는 var키워드에 대해 알아보겠습니다.
var 키워드는 기존의 인터프리터언어(javascript..)에서 사용되는 형식이 정해지지 않은 어떠한 임의의 변수를 나타냅니다.
C#에서도 드디어 var키워드가 도입 되었는데 기존의 인터프리터언어에서의 var와는 개념이 약간 다릅니다.
기존의 var타입은 프로그램을 실행하는 동안 즉, 런타임 시 타입이 결정되는 반면 C#의 var타입은 컴파일 시에 타입이 결정됩니다.

이제 var키워드로 모든 변수를 대체할 수 있습니다. 타입에 더 이상 신경 쓰지 않고 개발이 가능합니다.
하지만 ASP.NET에서는 사용자가 페이지를 볼 때까지 걸리는 시간에 컴파일 타임이 포함 됩니다. var키워드를 남발하면 컴파일 타임이 늘어나게되어 사용자가 화면을 볼 때까지 걸리는 시간이 길어지므로 짜증날 수도 있기 때문에 var타입은 적절히 필요한 LINQ관련 부분에서 사용하거나 반드시 필요한 부분에서 사용하는 것이 현명한 선택 일 것입니다.

var 타입에 대해 알아 두셔야 할 중요한 체크 포인트가 있습니다.

var 타입은 모든 데이터 타입이 될 수 있습니다. 하지만 초기값을 할당하지 않을 경우 컴파일 타임에 어떠한 타입인지 알 수 없기 때문에 선언과 동시에 값을 할당 해야 합니다.

이 부분이 기존 인터프리터 언어와 다른 가장 중요한 차이점입니다. 비쥬얼스튜디오로 작업할 때 var 타입 변수에 밑줄이 나타나면 초기 값을 할당 했는지 우선 확인해 보세요.

Anonymous Type의 두 번째 예제를 다시 살펴보면 쿼리 한 결과값을 var타입으로 받은 것을 확인 할 수 있습니다.
이는 select절에서 데이터를 가져올 때 new키워드 만을 사용했고 어떠한 타입인지 알 수 없는 Anonymous Type이기 때문에 var키워드를 사용하여 값을 할당 받게 됩니다.
컴파일 타임에 var 타입은 select한 타입을 확인한 다음 특정 타입으로 치환해 주게 되는 것입니다.
그 다음 아래 코드의 foreach문에서도 타입을 정확히 알 수 없기 때문에 var키워드를 사용할 것을 확인할 수 있습니다.

4. Lambda Expression(람다 표현식)

용어사전의 설명에 의하면 Lambda Expression은 '어떤 문제를 해결하기 위한 과정을 수학적 함수를 이용하여 표현한 수식'이라고 설명되어 있습니다.
C#3.0의 Lambda Expression의 기능과 일맥상통하는 부분입니다.

Lambda Expression은 C#2.0에서 도입되었던 Anonymous Delegate(익명 대리자, 무명 메서드)를 좀 더 실용적으로 만든 것으로써 Lambda Expression은 컴파일 과정에서 Delegate(대리자)로 치환됩니다.  간단히 설명하면 Lambda Expression은 컬렉션에 질의를 하기 위해 LINQ에서 사용되는 표현식이라고 알아두시면 될 것 같습니다. 

(매개변수들)=>(표현식)

Lambda Expression은 위와 같이 나타낼 수 있습니다. 간단한 Lambda Expression의 예를 살펴보도록 하겠습니다.

int[] numbers = {1,2,3,4,5,6,7,8,9};
1. IEnumerable<int> odds = numbers.Where(n=>n%2==1);
2. IEnumerable<int> odds = numbers.Where((int n)=>n%2==1);
3. IEnumerable<int> odds = numbers.Where(delegate(int n){return n%2==1;});

Where메서드는 C#3.0에서 추가된 IEnumerable<T>의 값에 순차적으로 접근하여 그 값을 필터링 하기 위한 확장메서드 입니다. 확장메서드에 대한 자세한 설명은 뒤에서 하도록 하겠습니다.

Where의 파라미터를 보면 (매개변수들)=>(표현식)과 같은 형태로 되어 있습니다. numbers의 값들을 차례로 이동하며 홀수인 경우 값을 반환하게 됩니다.
1번의 표현식을 좀더 명확하게 나타내면 2번과 같이 n을 int n으로 나타낼 수 도 있습니다.
3번의 경우에는 1번 또는 2번의 표현식이 컴파일 될 때 만들어지는 코드로 Anonymous Delegate형태로 생성되게 됩니다. 처음부터 3번과 같은 방식으로 사용해도 상관 없지만 간결함을 위해 1번과 같은 Lambda Expression을 사용 하는 것을 권장 합니다.

5. Query Syntax

Query Syntax란 표준 LINQ query 연산자를 사용하여 쿼리를 표현하기 위한 선언적 표기 방법입니다.
Query Syntax는 기존의 쿼리처럼 문자열을 이용하는 방식이 아니라 코드상에 기존 코드를 입력하듯이 깔끔하게 쿼리를 작성할 수 있습니다. 또한 정확하게 읽고 쓰는 것이 가능하며 쉽게 그 내용을 확인 할 수 있습니다.
또 하나의 편리한 점은 Visual Studio를 사용 할 경우 완벽한 인텔리센스를 제공하며 컴파일 타임의 체크 또한 지원합니다.
Qyery Syntax 표현은 의미상으로 LINQ 확장메서드와 Lambda Expression을 사용하는 것과 동일합니다.
하지만 사용법 자체가 기존의 Query와 동일하여 개발자는 이에 좀더 쉽게 다가갈 수 있을 것 같습니다.

int[] numbers = {1,2,3,4,5,6,7,8,9};
int[] selNums = from n in numbers
                    where n>5;
                    select n;

위의 Query Syntax는 numbers배열에서 5보다 큰 숫자들을 가져오는 표현식입니다.
기존의 Query와 다른 점이 있다면 각 절의 위치가 기존과는 다르게 form절이 가장 상위에 오고 그 다음 where절 마지막으로 select절이 오는 것을 확인 할 수 있습니다.
처음 Query Syntax를 사용할 경우 적응하기 어려울 수 있지만 자세히 보면 기존의 Query보다 더 명확하게 사용 할 수 있다는 것을 알 수 있습니다.
가장 먼저 어디서 데이터를 가져올 것인지를 정하고(from), 가져온 데이터 중에서 어떤 데이터를 걸러낼 것이며(where), 걸러진 데이터를 어떤 형태로 가져올 것인가(select)를 정의하게 됩니다.

Query Syntax에서 from절은 foreach와 상당히 유사하다는 것을 알 수 있습니다.
n이라고 가정한 변수와 이 변수의 제한 범위를 설정하는 나열될 수 있는 개체 numbers를 지정한 것이 foreach와 상당히 유사하며 이어지는 절(where, select)에서 가정한 변수 n을 사용하는것 또한 상당히 유사합니다.

이어지는 where절과 select절 등은 다음 강좌에서 중점 적으로 설명하도록 하겠습니다.

이번 아티클에서는 LINQ를 사용하기 위해 그 기반이 되는 Lambda Expression, Extension Method, Anonymous Type, var 키워드, Query Syntax 에 대해 알아 보았습니다.
다음 강좌에서는 메모리 상의 컬렉션 개체에 LINQ를 적용하는 방법과 Lamba Expression을 보다 유연하게 사용할 수 있도록 많은 예제를 통해 LINQ에 한걸음 더 깊숙이 들어가 보도록 하겠습니다.
다음 강좌를 기대해 주세요..^^ 감사합니다.


authored by


 
 
.NET과 Java 동영상 기반의 교육사이트

로딩 중입니다...

서버 프레임워크 지원 : NeoDEEX
based on ASP.NET 3.5
Creative Commons License
{5}
{2} 읽음   :{3} ({4})