'c#'에 해당되는 글 39건

  1. 2017.01.23 Language Server Protocol, OmniSharp-Roslyn 빌드 오류 해결
  2. 2016.01.28 [MonoDevelop] 두 번째 한글화 버전 승인완료
  3. 2013.07.02 [퀴즈] 프로그래머를 위한 문제 #1 - 1부터 8만까지 8의 개수 (9)
  4. 2013.05.24 Umc Core IoC 통합 컨테이너 #1
  5. 2013.05.23 Umc.Core 프레임워크 다이나믹 프록시(Dynamic Proxy) #1
  6. 2011.06.17 [Visual Studio 2010 SP1] HTML5, CSS3 지원
  7. 2011.06.16 [Visual Studio 2010 SP1] ASP.NET DEPLOYABLE DEPENDENCIES
  8. 2011.06.14 [Visual Studio 2010 SP1] IIS EXPRESS 기능 추가
  9. 2011.06.13 [Visual Studio 2010 SP1] 실버라이트 성능 프로파일 지원
  10. 2011.01.10 2011년 .NET 개발자의 생존전략 (3)
  11. 2010.11.04 곧 다가올 기술, Microsoft Research [1/2]
  12. 2009.10.06 VSTS 2010 팀 트위터를 오픈하였습니다. (2)
  13. 2009.02.16 [C# 4.0] Parallel Extension - [2] 병렬 처리 아키텍처
  14. 2009.02.12 [C# 4.0] Parallel Extension - [1] 병렬 처리
  15. 2009.01.20 GAC Assembly 를 파일로 복사하는 방법
  16. 2008.08.21 C# 코드로 GAC 어셈블리 등록하기
  17. 2008.03.01 [C# 4.0] Parallel Extension - [3] TPL(Task Parallel Library)
  18. 2007.12.18 실전 event [6] - 취소 가능한 버튼 서버컨트롤 활용
  19. 2007.12.18 실전 event [5] - 취소 가능한 버튼 서버컨트롤 만들기
  20. 2007.12.17 실전 event [4] - 취소 가능한 이벤트 만들기
  21. 2007.12.17 실전 event [3] - 취소 가능한 이벤트란
  22. 2007.12.16 실전 event [2] - 유저컨트롤에서 페이지로 이벤트로 값 전달
  23. 2007.12.16 실전 event [1] - 이벤트 시작하기
  24. 2007.12.04 [C# 3.0] LINQ to Sql 의 쿼리를 로그로 남겨보자
  25. 2007.09.17 LINQ To Sql 의 올바른 사용
  26. 2007.09.12 확장 메서드의 설계(Architect)
  27. 2007.09.09 람다식(Lambda Expressions) 을 이용한 확장 메서드(Extension Methods) 만들기 [2] (1)
  28. 2007.09.08 람다식(Lambda Expressions) 을 이용한 확장 메서드(Extension Methods) 만들기 [1] (1)
  29. 2007.09.04 LINQ 의 OUTER JOIN 작업
  30. 2007.09.04 LINQ to SQL Classes 와 LINQ의 JOIN 작업 (2)

마이크로소프트(Microsoft)는 VSCode 에서 다양한 개발 편의 기능을 제공하기 위한 Language Server Protocol 을 공개했다. 이 프로토콜의 C# 버전이 바로 OmniSharp-Roslyn이 되겠다.

그 외에 다양한 언어의 구현체가 등장했는데, 어떤 개발 언어가 구현 되었는지 아래의 링크에서 확인하기 바란다.

필자는 OmniSharp-Roslyn 을 git clone 하고 빌드하게 되면 다음과 같은 오류를 만났다.

개발환경

  • OS: MacOS Sierra
  • Version: 10.12.2

The type initializer for 'System.Net.Http.CurlHandler' threw an exception.

위의 이슈는 아래와 같이 보고가 되었다.

이 이슈는 다음과 같이 해결하면 된다.

brew update
brew install openssl
ln -s /usr/local/opt/openssl/lib/libcrypto.1.0.0.dylib /usr/local/lib/
ln -s /usr/local/opt/openssl/lib/libssl.1.0.0.dylib /usr/local/lib/


Posted by 땡초 POWERUMC
TAG c#, OmniSharo

댓글을 달아 주세요

최근 MonoDevelop 개발툴의 한글화를 좀 더 고도화(?)하여 Pull Request 를 보냈다. 하루가 지나고 바로 approve 되어 차기 릴리즈 버전에 바로 적용이 가능하리라 생각한다. 또한, Xamarin Studio 에도 더 부드러운 한글화를 만나볼 수 있게 되었다.

필자가 개별적으로 배포하는 곳은 monodevelop.co.kr 에서 받아볼 수 있다.

1차 번역은 오로지 한글화에 목표를 두었다면, 2차 번역은 잘못된 번역과 좀 더 부드러운 번역에 중점을 두었다. 그리고 버전업이 되면서 기존 영문 메시지가 많이 변경이 되었는데, 이 또한 적절하게 수정되었다.

번역 품질에도 조그마한 변화를 느낄 수 있길 바라는데, 가령 "View" 를 번역한다면, 뭐라고 번역해야 할까? "뷰", "보기" 등으로 번역할 수 있는데, 이 "View" 가 어디에 쓰일지에 따라 번역 단어도 바뀌게 된다. 개발툴 안에서 쓰이는 단어라면 "보기"로 번역되는 게 맞을 것이다. 그런데, ASP.NET MVC 에 쓰인다면 "뷰"라고 번역되어야 하는데, 이런 번역들도 적절하게 수정이 되었다.

애매하게 번역되는 단어들이 이 뿐만이 아니다. "Convert", "Change", "Replace". 모두 뭔가로 변경되된다는 의미인데, 이는 각각 일관되도록 "변환", "변경", "바꾸기" 로 번역이 되었다.

현재까지 총 5765개 문장/단어 중 4886개 문장/단어가 번역이 완료되어 84% 번역률을 보인다. 남은 번역은 879개로 조만간에 번역이 완료되었으면 좋겠다.

Posted by 땡초 POWERUMC

댓글을 달아 주세요

프로그래머를 위한 문제

프로그래머라면 알쏭달쏭한 논리적인 문제를 좋아하는 편인 것 같다. 답이 팍~ 나오는 문제보다 역량에 따라 코드의 아름다움이 달라지는 것을 추구하는 프로그래머라면 더욱 그렇다.

문제: 1부터 1만까지 8은 모두 몇 개가 나오나?

문제는 쉽다. 1부터 1만까지 8이라는 문자 개수만 카운팅하면 된다. 그런데 이렇게 간단한 문제를 코딩해 놓고 보면 맘에 안든다. 더 짧게…. 아래의 문제를 각 언어별로 풀어보았는데, 바이트 수는 캐러지 리턴(carriage return) 문자를 모두 제거한 바이트 수이다.

참고로, 이 문제는 ‘닷넷(.NET) 프로그래머 모임’ 에서 처음 본 문제인데, 오래 전의 일이라 게시글의 링크를 도저히 찾기가 힘들어서 링크를 남기지 못했다.

여러분 중 문제를 풀어보려고 한다면, 바로 아래에 답이 있으니 브라우저를 먼저 종료하길 바란다.

파이썬(python)

파이썬을 배운지 얼마 안되던 때에 이 문제를 만나서 파이썬으로 풀어보았다. 누가 짜도 최종적으로 아래의 코드가 될거다. 처음에는 이렇게 짧게 가능한 파이썬이 맘에 안들었지만, 이제는 맘에 든다. ㅋ;

더 이상은 짧게 안되지 싶다.

# 총 38 바이트   
(str(list(range(1,10001))).count('8'))  

C#

C# 코드로 짜면 아래처럼 된다. 아래의 코드는 확장 메서드와 람다 표현식이 전부다.

혹시나 요걸 비트 연산으로 풀어봤는데, 아래 코드보다 길어지더라. 뭐 내가 짠 코드라 길어질 수도 있겠다.

// 총 84 바이트  
Console.WriteLine(Enumerable.Range(1,10000).Sum(o=>o.ToString().Count(n=>n=='8')));   

Java

Java 8 정식이 나오면 Lambda 지원. 다만 C#의 확장 메서드를 언어상 지원하지 않으므로 Where, Select, Take, Skip 과 같은 확장 메서드는 사용하지 못할 것 같다. 어쨋든 Java 로 이 문제를 짧게 풀수 있는 경쟁력이 없으므로 패스!

C++ Update - 2013-07-04

C++에 대해 조예가 깊지 않아서 내 머리로는 더 짧게 안된다. 이 코드는 위의 파이썬과 C#과는 알고리즘(?)이 좀 틀리다. 어쩔 수 없다. 짧게 하려면…

// 총 146 바이트  
vector<int> v(10000);  
auto n=1,s=0;  
generate(v.begin(),v.end(),[&n, &s](){  
auto m=to_string(n);  
s+=count(m.begin(),m.end(),'8');  
return n++;});  
cout<<s;

아래 댓글에 더 짧은 C++ 코드를 올려주신 HATENA [링크] 님께서 올려주신 코드 입니다. Update - 2013-07-04

// 총 94 바이트
int c=0;
for(int i=1;i<10001;i++){
auto s=to_string(i);
c+=count(s.begin(),s.end();'8');}
cout<<c;

JavaScript - Update 2013-07-03

본 코드는 아래 댓글의 ddd 님께서 작성하신 자바스크립트 코드 입니다.

// 총 94 바이트  
var a=[];
for (var i=1;i<10001;i++)
a[i]=i;
console.info(a.join("").replace(/[^8]/gi,"").length);
Posted by 땡초 POWERUMC

댓글을 달아 주세요

  1. 황정현 2013.07.02 09:33 Address Modify/Delete Reply

    예전에 자바스크립트로 한번 풀어봤었네요... 근데 너무 길어요...
    for(var i = 0, len = 10000, count = 0, tmp = ""; i < len; i++){
    var arr = [];
    tmp = (""+i);
    for (var j = 1, len2 = tmp.length; j <= len2; j++)
    {
    arr[j] = tmp.substring((j - 1), j);
    if(arr[j].indexOf("8";) > -1) count++;
    }
    }
    console.log(count);

  2. ddd 2013.07.03 17:53 Address Modify/Delete Reply

    javascript 는 이정도 면 될듯한데
    var a = [];
    for (var i = 1; i < 10001; i++)
    a[i] = i;
    alert(a.join("";).replace(/[^8]/gi, "";).length);

    javascript 는 반복문 안쓸수 없나요 ㄷㄷ

    • 엄준일 2013.07.04 10:28 Address Modify/Delete

      댓글로 적어주신 소스 코드를 제 포스트에 업데이트 했습니다.
      ddd 님 사이트 링크를 남기고 싶었는데,
      링크가 없어서 아쉽네요 ㅠ

  3. HATENA 2013.07.04 11:27 Address Modify/Delete Reply

    항상 블로그 잘 보고 갑니다.
    C++은 vector, generate 안써도 쉽게 풀릴거같은데요 ㅎㅎ.

    int c=0;
    for(int i=1;i<10001;i++){
    auto s=to_string(i);
    c+=count(s.begin(),s.end();'8');}
    cout<<c;

    요거면 100byte 이내로 끝날거같습니다.
    파이선 코드길이 ㅎㄷㄷ하내요 ㄷㄷㄷ

  4. java론 2014.01.07 15:46 Address Modify/Delete Reply

    자바로는 아래처럼....
    int a=0;
    for(int i=0;i<10001;i++) {
    a+=(""+i).replaceAll("[^8]","";).length();
    }

  5. 김인혜 2014.04.06 03:56 Address Modify/Delete Reply

    마이너한 스크립트 언어입니다.
    AutoHotkey

    Loop 10000
    _ .= A_Index
    Msgbox % RegExReplace( _, "8", "", @ ) ? @ :

  6. 지나가다 2015.12.15 15:03 Address Modify/Delete Reply

    만들고 나니 위분거랑 같네요 ㅡㅡ;
    int result = 0;
    for (int i=0; i<=10001; i++) {
    result += String.valueOf(i).replaceAll("[^8]", "";).length();
    }
    return result;

  7. 행인 2016.11.20 15:28 Address Modify/Delete Reply

    Acm 문제에서 간간히 등장하는 유형이네요.
    그 당시 풀때 속도 문제 때문에 reject떠서 수학적으로
    규칙을 찾아서 accept 받았던 기억이 나네요

  8. 재밌네요 2016.11.29 16:02 Address Modify/Delete Reply

    Javascript 좀더 짧게~
    --------------------------------------
    var i,s,r; for (i = 1; i < 10001; i++) s += '' + i; r = s.split('8').length-1;
    console.log(r);

객체지향 프로그래밍 이야기

IoC(Inversion of Contol)[1], 우리말로는 ‘역전제어’라고 한다. 객체지향 프로그래밍의 기본은 만들어진 객체를 잘 쓰는 것 부터 시작한다. 이 경우 개체(Object)를 인스턴스화(Instance)하기 위해 개체(Object)를 직접 참조해야 한다.

개체(Object)는 class 로 선언되는 빌딩의 명세서(설계도?)와 같고, 인스턴스(Instance)는 만들어진 빌딩(Building-건물)을 의미한다. 전자를 개체(Object)라고 부르며, 후자를 객체(Object) 또는 인스턴스라고 부른다.

명세서를 찍어내는 방법은 매우 간단하다. Building b = new Building() 이것이 객체지향에서 개체를 인스턴스화 하는 코드가 되겠다. 그런데 현실에서의 건물은 매우 다양하다. 아파트도 있고, 오피스텔도 있고, 고층빌딩도 있다. 어떤 건물은 지하 주차장이 완비되어 있고, 어떤 건물은 주차장이 옥상에 있다. 물론 없는 건물도 있다. 어떤 건물은 건물 전체가 주차장이다.

하나의 객체로 건물의 모든 기능을 담기란 힘들다. 방, 화장실, 출입문, 엘리베이터 등 각각 작은 객체들을 기능 단위로 쪼개야 나중에 다른 건물을 지을 때도 재사용성이 높아진다. 여러개로 쪼개진 기능을 한대 묶어 복합적으로 배치하면(Complex + Composition) 오피스텔이 되기도 하고, 원룸텔이 될 수 있다. 이 얼마나 아름다운 객체지향의 세계인가.

그런데 어느 엘리베이터 업체가 가장 최신의 기능을 넣기 위해 독자 표준으로 만들었다. 이 엘리베이터는 총 중량도 검사해서 작동 여부가 결정되고, 중량이 넘어서면 목적지 까지 중간에 서지도 않는 똑똑한 지성도 갖추었다. 환풍 설비도 갖추고, 향기도 나고, 내부 벽은 고급스러운 스테인레스로 쫙 깔았다.

공포 영화에나 나올 법한 허름한 구닥다리 병원의 삐그덕 거리는 엘리베이터와는 차원이 다르다. 이 병원 건물은 환상적인 저 엘리베이터 업체의 객체를 샀다. 젠장, 안맞는다. 크기도 국제 표준의 규격과 다르고, 외벽과 연결되는 환풍 설비는 꽉 끼어 찌그러질 판이다. 마치 38인치 바지를 입는 사람이 30인치 바지를 억지로 입으려는 것과 같다.

인터페이스 지향적인 프로그래밍 이야기

이 엘리베이터 업체는 최첨단 기술이 도입되는 건설사의 수주를 받아 개발한 엘리베이터인데, 건설사와 계약이 끝나니 손가락만 빨게 생겼다. 독자 표준의 엘리베이터를 국제 표준에 맞게 다시 만들었고 이제야 다시 매출이 조금씩 오르기 시작했다.

국제 표준 규격에 맞게 정해진 규약을 지켜서 만들었다. (말도 안되는 ISOxxxxElevatorOutputV1 이라는 인터페이스가 규약이라고 치자)

public interface IStarbucksElevator
{  
    ISOxxxxElevatorOutputV1 Open();  
    ISOxxxxElevatorOutputV1 Close();

    ISOxxxxElevatorOutputV1 Up();  
    ISOxxxxElevatorOutputV1 Down();
}  

세상이 변하고 살기 좋아지면서 새로운 기술도 쏟아진다. 국제 표준 기구는 엘리베이터에 범죄 예방을 위해 CCTV 규격을 V2 에 포함시켰고, V3 버전에는 어린이들도 쉽게 버튼을 누를 수 있도록 버튼의 위치와 비상벨의 위치가 매우 낮아졌다.

이 엘리베이터 업체는 모든 최신 규격을 지키기 힘들다. 기술력 확보를 위해 인재도 뽑아야 하고, 최신 표준 규격에 맞는 부품을 수입도 해야하고, 아직 모든 준비는 되지 않았지만, 국제 표쥰은 지킬 수 있다. 이렇게 말이다.

public interface IStarbucksElevator
{  
    ISOxxxxElevatorOutputV1 Open();  
    ISOxxxxElevatorOutputV3 Close();

    ISOxxxxElevatorOutputV1 Up();  
    ISOxxxxElevatorOutputV2 Down();
}  

그리고 국제 표준 인터페이스는 하위 호환을 지켜야 하므로 이렇게 생겨먹었다.

public interface ISOxxxxElevatorOutputV1
{  
    // ... 생략 ...
}  

public interface ISOxxxxElevatorOutputV2 : ISOxxxxElevatorOutputV1
{  
    // ... 생략 ...
}  

public interface ISOxxxxElevatorOutputV3 : ISOxxxxElevatorOutputV2
{  
    // ... 생략 ...
}  

국제 표준을 지키기 때문에 명확하게 인터페이싱이 가능하지만, 이 업체의 내부 구현 코드는 점점 엄망이 되어 간다. 내부적으로 지나치게 코드의 버전이 많아지고, 또 갈리게 된다.

이 업체는 표준 규격에 맞게 제작된 엘리베이터의 종류가 여럿 있다. 소형, 중형, 대형 건물마다 필요한 엘리베이터 버전들이 많다.

이제는 엘리베이터 내부 개발자들은 객체를 생성하는 것이 점점 무서워질 정도다. 가끔 헷갈리기도 하는데, 소형 엘리베이터의 코드에서 return new ISOxxxV1LargeBuildingInternalV2_5 이렇게 대형 건물용 엘리베이터 객체를 반환했다간 아작이 난다.

인터페이스 기반의 프로그래밍은 분명한 장점이 많다. 특히 인터페이스 기반으로 다른 객체를 쓸 때 편하다. 내부적인 코드의 개선이 필요하거나 인터페이스에 살짝 변화가 온다던가, 분석이 필요한 경우 인터페이스 기반으로 구현된 코드를 보면 난독증이 올 지경이다. 특히, 인터페이스나 객체들을 이용하여 다형성을 가지는 개체들은 디버깅 기능이 떨어지는 개발툴(IDE)에서는 거의 시간과 씨름하는 노가다와 같다.

국내의 엘리베이터 적용에 관한 법이 바뀌었다. CCTV 기능이 있는 국제 표준 버전 2(ISOxxxxElevatorOutputV2) 기능이 없으면 대형 건물에 엘리베이터를 설치할 수 없다. 또 구현해서 바꿔야 한다. return eturn new ISOxxxV1LargeBuildingInternalV2_5_RequiredCCTV

객체의 생성과 파괴는 간접적 컨테이너(Container)에 의해

그렇다. 객체를 직접 생성하려고 하면 강하게 응집력이 생긴다. 그래서 인터페이스를 활용하여 응집력을 낮추었다. 근데 매우 복잡한 객체지향적인 코드에서는 인터페이스 기반은 너무 힘들다. 인터페이스가 변하지 않음을 보장하고 인터페이스의 상속의 스택이 없거나 매우 짧다면 쉽지만, 스택이 깊어지면 당연히 더 어려워질 수 밖에 없다. 디버깅 경험을 떠올려 보라. 메서드 안의 메서드(Inner Method), 또 그 안에서 또 다른 메서드 호출이 깊어지면 복잡해질 수 밖에 없다.

그래서 IoC(Inversion of Control-역전 제어)는 직접 개체를 핸들링 하던 것을 간접 참조를 통해 제어 방향을 완전히 반대로 바꾸는 방법이다.

기존의 객체를 직접 핸들링 하던 방식과 인터페이스 기반의 방식을 표현하면 아래와 같이 표현할 수 있겠다.


아래의 그림은 각각의 장점과 단점을 기술한 표이다.

IoC(Inversion of Control)에 대해 필자와 같은 돌팔이가 아닌 ‘집단 지성’의 명쾌하고 깔끔한 정의는 링크를 통해 확인하기 바란다.


Umc Core IoC 통합 컨테이너의 탄생 배경

Umc Core IoC는 여러 개의 서로 다른 프레임워크의 인터페이스와 스키마, 그리고 Dependency & Injection, AOP Weaving 의 인터페이스를 모두 통합한 프레임워크이다.

오픈 소스의 시대이다. 객체를 다루는 트랜드도 바뀌어 이 전에 아티클의 내용인 다이나믹 프록시(Dynamic Proxy) 와 AOP(Aspect Oriented Programming) 등과 같은 기법들을 사용한다.


아래 현재 버전의 오픈 소스가 참조하는 IoC 컨테이너 오픈 소스는 2011년 당시와 다를 수 있음.


문제는 오픈 소스들마다 사용하는 다이나믹 프록시 오픈 소스, IoC 컨테이너 오픈 소스가 제각기 다르다는 문제에서 출발하게 된다. NHibernate, iBatis.NET(현 myBatis.NET)Castle Windsor 프레임워크의 다이나믹 프록시 및 IoC 컨테이너를 사용하고, Enterprise LibraryUnity Application Block 프레임워크를 사용한다.

만약, Enterprise Library를 기반으로 ORM 프레임워크로 NHibernate 조합으로 사용한다고 치자. 내부적으로 객체를 생성하는 곳이 두 군데가 된다. 이 객체의 생명 주기를 관리하는 곳도 두 곳이 된다. 다이나믹 프록시(Dynamic Proxy) 개체가 생성된다면 똑 같은 개체가 두 군데에서 생성하므로 괜한 메모리 공간만 차지하게 된다.

아래의 그림은 2011년 당시 수집한 자료를 기반으로 작성이 되었다.



하나의 응용 프로그램의 레이어(Layer) 안에서 두 개의 컨테이너와 프록시 객체가 생성되는 것도 문제지만, 두 개의 프레임워크가 제공하는 인터페이스도 판이하게 다르다는 것은 코딩 스타일에 문제가 된다. 당연히 응용 프로그램 차원에서는 더 큰 문제로 보아야 된다.

아래의 그림에선 두 개의 IoC 프레임워크가 전혀 다른 XML 스키마와 인터페이스를 제공하는 것을 알 수 있다.



Umc Core IoC 프레임워크의 소스 코드는 https://github.com/powerumc/UmcCore/tree/master/Src/Base%20Frameworks/Src/Core/IoC 에서 먼저 확인할 수 있다.

To be continue #2…


  1. In software engineering, inversion of control (IoC) is a programming technique, expressed here in terms of object-oriented programming, in which object coupling is bound at run time by an assembler object and is typically not known at compile time using static analysis.  ↩

    http://en.wikipedia.org/wiki/Inversion_of_control


'Umc Projects > Umc.Core' 카테고리의 다른 글

Umc Core IoC 통합 컨테이너 #1  (0) 2013.05.24
Umc.Core 프레임워크 다이나믹 프록시(Dynamic Proxy) #1  (0) 2013.05.23
Umc.Core 미공개 Preview  (6) 2008.05.14
Umc.Core 란?  (0) 2007.12.01
Posted by 땡초 POWERUMC

댓글을 달아 주세요

요즘 참 할일도 많은데 할 수 있는 일이 점점 줄어든다. 필자는 블로그 버킷 리스트(bucket list)를 작성하는데 블로그가 사망하기 전에 꼭 해야 할 일을 목록으로 만들어 놓고 하나 하나씩 글을 써 나간다. 근데 할 일이 늘어만 간다. ㅠ

  • 당장 쓸 수 있는 글 39개
    사소한 개발 기술부터 심도있는 내용으로 흐리멍텅한 개념을 글을 쓰면서 잡아 나가는 것들

  • 개발 후 산출물로 쓸 글 37개
    오픈소스로 내놓을 계획, 또는 알고 있는 것들에 대한 증명이 필요하고 그 후에 쓸 수 있는 글

  • 연구개발 11개
    배우고 싶은 것, 하고 싶은 것, 해야 하는 것들이고 공부해야 쓸 수 있는 글들

아무튼 점점 쓸 것들이 늘어만 가지만, 하나 하나 하다보면 쓸게 없어 지는 날이 올거라 믿는다 >.,<

#1 - Umc.Core 프레임워크 다이나믹 프록시(Dynamic Proxy)

다이나믹 프록시(Dynamic Proxy)는 최근 IoC(Inversion of Controls)라는 개념으로 확장되고 객체지향 프로그래밍(OOP)의 효율성을 극대화한다. 다이나믹 프록시 기법은 이미 오래 전부터 존재해 왔다.

C++의 스마트 포인터(Smart Pointer) 처럼 직접 포인터를 건들이지 않고 레퍼런스 카운팅이나 객체의 생명주기를 프록시 개체(Proxy Object)를 통해 관리하는 기법이 있고, RPC(Remote Procedure Call)과 같은 원격 프로시저 호출을 위해 프록시 패턴(Proxy Pattern)이 기반에 깔려 직접 원격 구현을 숨기고 간단한 인터페이스만 제공해 주는 패턴 등 매우 다양하다.

최근의 다이나믹 프록시(Dynamic Proxy)는 IoC(Inversion of Control), DI(Dependency Injection), ORM(Object Relation Mapping), AOP(Aspect Oriented Programming) 등 객체를 다루는 프레임워크에서 기본적으로 채용할 만큼 객체를 다룸에 있어 가장 기본적인 기법 또는 기술에 속한다.

필자가 오늘 다루어 볼 내용은 이런 프록시 패턴(Proxy Pattern)이 기반이 되는 개체 제어를 위한 기법이다.

먼저 다이나믹 프록시(Dynamic Proxy)에 대해 예전에 잠깐 쓴 글을 참고하자.

과거 2009년도 닷넷엑스퍼트 재직 시절에 다이나믹 프록시(Dynamic Proxy)를 만들었다가, 2011년 좀 더 나은 객체 디자인으로 완전히 다시 만든 다이나믹 프록시(Dynamic Proxy) 프레임워크가 지금 설명할 Umc.Core.Dynamic.Proxy 이다.

Umc Core 프레임워크는 오픈 소스로 공개되어 있으며 누구든지 소스 코드를 열람할 수 있다. 현재 소스 코드는 다음의 링크를 통해 제공된다.

그 외에 필자가 공개한 소스 코드도 여럿 있으니 관심있는 분들은 참고하기 바란다.

 

 







#2 - 코드부터 보자.

만약 관리 언어(Managed Language)의 동작 매커니즘을 이해하지 못했다면 마치 마법과도 같은 기법으로 보일 것이다. 아래의 코드는 완벽하게 돌아가는 소스 코드이다.

using System;  
using Umc.Core.Dynamic;  

namespace ConsoleApplication1
{  
public interface IPerson
{
    string Name { get; set; }
    string Email { get; set; }
}  

class Program
{
    static void Main(string[] args)
    {
        var type   = DynamicProxyObject.InterfaceImplementationType<IPerson>();
        var person = (IPerson)Activator.CreateInstance(type);

        person.Name  = "POWERUMC";
        person.Email = "powerumc at 지멜";

        Console.WriteLine("Name : {0}, Email : {1}", person.Name, person.Email);
    }
}
}  

한번 위의 코드를 보자. IPerson 인터페이스는 IPerson을 구현하는 클래스가 반드시 있어야 객체를 생성할 수 있다. 다음과 같이 말이다.

public class Person : IPerson
{
    public string Name { get; set; }
    public string Email { get; set; }
}   

C#의 상식으로 보아도 인터페이스(Interface)는 인스턴스를 생성할 수 없으며, 인스턴스를 생성하기 위해 구현 클래스가 반드시 존재햐여 하는 것 쯤은 알고 있을 것이다. 즉, Person 클래스가 있어야 IPerson person = new Person(); 으로 객체를 생성할 수 있다. 분명, 처음 코드의 DynamicProxyObject.InterfaceImplementationType<IPerson>(); 가 뭔가의 마법을 부리는 것이 확실하다고 보면 된다.

#3 - 다이나믹 프록시(Dynamic Proxy) 의 다른 구현 방법들

방금 언급한 DynamicProxyObject.InterfaceImplementationType<IPerson>(); 코드가 바로 class 로 구현조차 되지 않은 클래스를 동적(Dynamic)으로 런타임에 생성한다. 이 동적 클래스를 런타임에 생성하기 가장 쉬운 방법이 있는데, 그것은 .NET Framework에서 제공하는 CodeDomProvider 이다.

간단히 CodeDomProvider를 언급만 하고 넘어가보자. CodeDomProvider는 C#, VB.NET의 객체 표현을 Code Dom으로 표현할 수 있는데, 각각 CSharp, VB.NET Provider를 제공해 주고, 런타임에 컴파일을 한다. 다만, 컴파일 시간이 동적 객체 생성 기법 중에 가장 느리다.

그리고 C# 3.0부터 지원하는 람다 표현식(Lambda Expression)을 이용하는 방법이다. 이 람다 표현식도 내부적으로 CodeDom과 매우 유사하다. 단점이라면, 객체의 이름(Class Name)과 주소(Namespace) 등을 원하는데로 줄 수 없다. LambdaExpression 클래스의 맴버들이 많은데, 이것들로 모든 구현이 가능하다. 간단한 예제 코드를 보자.

Expression<Func<string, string>> expression = (s) => "Hello " + s;               
var func = expression.Compile();               
var ret = func("POWERUMC");   
Console.WriteLine(ret);

이 코드를 실행하면 “Hello POWERUMC” 라는 결과가 나오는 것을 확인할 수 있다.

이렇게 알게 모르게 이미 .NET Framework에서 다이나믹 프록시(Dynamic Proxy) 기법을 쓰는 곳이 의외로 많다. C# 컴파일러는 익명의 표현식들을 내부적으로 컴파일하면서 메서드로 만들어 버리기도 한다. 이렇게 똑똑한 컴파일러 덕분에 람다 표현식이나 LINQ의 성능이 매우 좋다는 것이다.

이 외에 동적메서드(DynamicMethod) 방법이 있는데, 얘는 그냥 넘어가도 무관하다.

#4 - 다이나믹 프록시(Dynamic Proxy) 개체가 생성되는 일련의 순서

동적 개체가 만들어지려면 어떤 순서가 필요할까?

먼저 객체지향 언어라는 점을 생각해볼때, 객체의 주소(Namespace)와 이름(Type Name)이 필요하다. 필자의 프레임워크 코드 중 Umc.Core.Dynamic.Proxy.Builder 네임스페이스의 ModuleBuilderExtension와 TypeBuilderExtension이 그 역할을 한다.

Type을 생성하기 위해서는 생성자 하나 이상이 반드시 필요한데, Object를 상속하는 타입을 만들어야 한다. 아시다시피 public class Person 클래스는 암묵적으로 public class Person : Object 를 상속하게 된다. 그래서 타입을 생성하고 하나의 생성자를 만들고 나면, 부모 객체인 Object의 생성자(Constructor)를 호출을 해주어야 한다. 당연히 부모가 있어야 자식이 있는 것과 같다.

이 때 반드시 주의해야 하는 것이 있다. 생성자는 인스턴스를 생성하는 생성자가 있고, static 생성자가 있다. 만약 static 생성자인 경우는 부모 객체인 Object 생성자(Constructor)를 호출하면 안된다.

Object 생성자를 타입의 생성자 안에서 호출하려면 다음과 같은 코드를 이용하면 된다.

il.Emit(OpCodes.Ldarg_0);  
l.Emit(OpCodes.Call, typeof(object).GetConstructors([0\]);  

이제 IPerson의 프로퍼티(Property)를 구현한다.

IPerson의 프로퍼티 목록은 리플랙션(Reflection)을 이용하여 쉽게 얻어낼 수 있다. 간단히 typeof(IPerson).GetProperties(); 면 된다. (프레임워크 내부에선 더 복잡할 수 있음)

C#의 프로퍼티는 컴파일을 하게 되면 프로퍼티가 메서드로 치환된다. 예를 들어, public string Name { get; set; } 코드는 다음 처럼 컴파일러가 치환한다.

public string get_Name() { ... }  
public void set_Name(string name) { ... }  

그러므로, 다이나믹 프록시를 구현할 때도 프로퍼티를 선언해 준 후에 get, set 메서드를 구현해 주어야 한다. 이를 Umc.Core에서 다음고 같이 구현하였다.

public ICodeLambda Get()
{  
var type       = new TypeBuilderExtension(null, this.TypeLambda.TypeBuilder);  
var methodAttr = this.TypeLambda.MethodAccessor.MethodAttribute | MethodAttributes.NewSlot | MethodAttributes.Final | MethodAttributes.Virtual | MethodAttributes.SpecialName | MethodAttributes.HideBySig;  
var method     = type.CreateMethod(methodAttr, propertyBuilder.PropertyType, String.Concat("get_", propertyBuilder.Name), Type.EmptyTypes, null, false);  

propertyBuilder.SetGetMethod(method);  

return new CodeLambda(this.TypeLambda, method.GetILGenerator());
}  

public ICodeLambda Set()
{  
var type = new TypeBuilderExtension(null, this.TypeLambda.TypeBuilder);  

var methodAttr = this.TypeLambda.MethodAccessor.MethodAttribute | MethodAttributes.NewSlot | MethodAttributes.Final | MethodAttributes.Virtual | MethodAttributes.SpecialName | MethodAttributes.HideBySig;  
var method     = type.CreateMethod(methodAttr, typeof(void), String.Concat("set_", propertyBuilder.Name), new Type[] { propertyBuilder.PropertyType }, null, false);  
method.DefineParameter(1, ParameterAttributes.HasDefault, "value");  

propertyBuilder.SetSetMethod(method);  

return new CodeLambda(this.TypeLambda, method.GetILGenerator());

}  

그리고 get, set 메서드의 내부 코드는 다음과 같이 구현된다.

public ITypeLambda GetSet()
{  
this.TypeLambda.FieldAccessor.FieldAttribute = FieldAttributes.Private;  
var field = this.TypeLambda.Field(this.propertyBuilder.PropertyType, String.Concat("__", propertyBuilder.Name));  

var get = this.Get();
{
    get.Return(field);
}  

var set = this.Set();
{
    set.IL.Emit(OpCodes.Ldarg_0);
    set.IL.Emit(OpCodes.Ldarg_1);
    set.IL.Emit(OpCodes.Stfld, ( (IValuable<FieldBuilder>)field ).Value);

    set.Return();
}  

return this.TypeLambda;
}  

위의 코드가 그 흔한 프로퍼티의 구현부인 public string Name { get { return this._name; } set { this._name = value; } } 를 구현하는 코드가 되겠다. 별거 아닌 코드지만 내부적으로 프로퍼티와 메서드를 생성하고, 그 구현 코드를 IL 코드로 재구현 하면 역시 조금 난이도가 높아진다.

메모리에서 개체 포인터의 엑세스를 방지하기 완료 방법

지금까지는 메모리에 동적인 코드들을 IL 코드들로 구현하였다. 모든 구현이 완료되었으면 더 이상 메모리에서 IL 코드가 위변조 되거나 .NET 코드 정책에 위배되지 않도록 엑세스 접근을 막아야 한다.

이 코드는 Umc.Core.Dynamic.Proxy.Lambda.TypeLambda 클래스의 CreateType() 메서드가 완료시킨다. 이 코드는 다음과 같이 구현 되었다.

public Type ReleaseType()
{  
if (this.TypeBuilder == null)
{
    throw new NullReferenceException(this.TypeBuilder.GetType().Name);
}  

return this.TypeBuilder.CreateType();
}   

코드 구현의 완료를 알렸다면 이제 동적 타입(Dynamic Type) 개체가 완성이 된다. 즉, 맨 처럼 IPerson 인터페이스를 구현하는 동적 개체(Dynamic Object)인 Person 개체의 타입이 되는 것이다. 즉, 이 Person 개체는 런타임에서 메모리상에 만들어진 것이 되겠다.

이리하여 Activator.CreateInstance(type) 으로 메모리상에 만들어진 Person 클래스를 생성할 수 있게 되는 것이다.

다이나믹 프록시(Dynamic Proxy) 개체의 모습

메모리상에서 만들어진 Person 개체의 타입은 내부적으로 규칙을 정해서 만들었다. Person 객체를 생성하여 이 객체의 타입을 보면 괴상한 이름으로 지어졌다.

var type   = DynamicProxyObject.InterfaceImplementationType<IPerson>();  
var person = (IPerson)Activator.CreateInstance(type);  

// 결과 -> dynamic_46c8ecaab09b41cbaa814511f69f1974

이 타입이 속한 주소(Namespace)와 모듈(Module)을 직접 디스크에 저장할 수도 있는데, 이런 방법을 이용하여 코드 난독화(Code Obfuscation) 처럼 사용할 수도 있다.

또 다이나믹 프록시(Dynamic Proxy)를 활용해 중간에 로깅(Logging)을 하거나 트랜잭션(Transaction) 처리를 할 수 있는 AOP 를 구현할 수도 있는 것이다. (AOP 구현 기법 중 하나이며, 다른 방법이 더 있다.)

또, 사용 편의성을 위해 고안된 것이 체이닝(Chaining) 방법을 이용하여 런타임 코드를 더 쉽게 만드는 방법을 Umc Core 프레임워크에서 제공한다. 다음의 코드를 보면 쉽게 이해가 될 것이다.

using System;  
using System.Linq;  
using System.Reflection;  
using Umc.Core.Dynamic.Proxy.Lambda;  

namespace ConsoleApplication1
{  
internal class Program
{
    private static void Main(string[] args)
    {
        string typeName = Guid.NewGuid().ToString("N");
        string methodName = Guid.NewGuid().ToString("N");

        var assembly = new AssemblyLambda().Assembly();
        {
            var module = assembly.Module();
            {
                var type = module.Public.Class(typeName);
                {
                    var constructor1 = type.Public.Constructor();
                    {
                        constructor1.Emit.EmitWriteLine("This is constructor");
                        constructor1.Return();
                    }

                    var constructor2 = type.Private.Static.Constructor();
                    {
                        constructor2.Emit.EmitWriteLine("This is (private static) constructor");
                        constructor2.Return();
                    }

                    var method = type.Public.Static.Method(methodName);
                    {
                        method.Emit.EmitWriteLine("This is emitted writeline");
                        method.Return();
                    }
                }

                var releaseType = type.ReleaseType();
                var obj = System.Activator.CreateInstance(releaseType);
                var releaseMethod = releaseType.GetMethod(methodName, BindingFlags.Public | BindingFlags.Static);

                Console.WriteLine("Release type is {0}", releaseType.AssemblyQualifiedName);
                Console.WriteLine("Release method is {0}", releaseMethod.Name);

                releaseType.GetMethod(methodName).Invoke(null, null);

                Console.WriteLine("".PadLeft(50, '-'));

                releaseType.GetMethods().ToList().ForEach(m => Console.WriteLine("Method Name is " + m.Name));
            }
        }
    }
}
}



// 결과 ->  
This is (private static) constructor  
This is constructor  
Release type is bdfd27e5e7ed446d8702fe172733d937, 4a8f6dd24e1f4054b551cca95ad0870b, Version=0.0.0.0, Culture=neutral,  PublicKeyToken=null  
Release method is 389b4a43a1ba4dc1b1391b5b06633645  
This is emitted writeline  
Method Name is 389b4a43a1ba4dc1b1391b5b06633645  
Method Name is ToString  
Method Name is Equals  
Method Name is GetHashCode  
Method Name is GetType  

위의 코드와 같이 좀 더 직관적으로 동적 코드를 만드는 방법을 Umc Core에서는 제공해 주고 있다.

재미있는 것은 메서드의 이름이다. 결과 출력 중 Method Name is 389b4a43a1ba4dc1b1391b5b06633645 이 있는데, 놀랍게도 메서드의 이름이 숫자로 시작한다. C# 언어 사양 중 변수의 타입, 변수 등의 이름은 반드시 알파벳 문자로 시작해야 함에도 불구하고, 숫자로 시작하다니…

이는 C#의 언어 사양과 CIL(Common Intermediate Language) 언어의 사양이 다르기 때문이다. 심지어 숫자가 아닌 특수문자로 시작해도 된다. 앞서 말했다시피 이런 방법을 이용하여 코드 난독화(Code Obfuscation) 가 가능하다.

비록 대부분의 Umc Core 소스 코드를 공개하지 않았지만, 미공개 코드 중 코드 난독화 툴도 함께 포함이 되어있고, Junk Assembly를 만드는 툴, AOP based Compile 툴 등도 포함이 되어있다. ㅎㅎㅎ; 아쉽지만 여전히 미공개 분은 공개하지 않을 예정이다. 더불어, 관심있는 독자라면 CIL 언어 스팩의 사양을 살펴보는 것도 좋을 것이다.

결론

지금까지 살펴본 다이나믹 프록시(Dynamic Proxy)를 살펴보았다. 이 기법은 IoC, DI, AOP, ORM 등 최신 객체 제어 기술들의 가장 근간이 되는 기법이다. 여러분들이 최신 기술들로 IoC, DI, AOP 등을 구현하고 싶다면 당장 오픈소스를 이용하면 될 것이다.

아마 필자처럼 .NET 기반으로 다이나믹 프록시(Dynamic Proxy)를 직접 구현해서 쓰는 것은 매우 드문 일이다. 이미 검증된 오픈 소스들도 많기 때문에 굳이 이를 구현해서 쓸 필요는 없다.

하지만 이런 오픈 소스를 이용하여 쓰는 것은 그리 어렵지 않겠지만, 이런 오픈 소스를 이용하여 어떻게 코드를 만드느냐는 성능이나 내부적으로 동작하는 효율성에 영향을 미칠 수 있다. 즉, 자신이 오픈 소스를 이용하여 만든 코드가 효율적인 코드, 그리고 메모리상에서 Clean Code로 동작하느냐는 별개의 문제이다.

필자와 같이 다이나믹 프록시(Dynamic Proxy)를 구현해 보았다면 여러분들이 얼마나 위험한 코드를 많이 만드는지 알 수 있다. 즉, 오픈 소스를 써보기만 했다면 절대로 알 수 없는 고급 기술이다.

ASP.NET MVC 등과 같은 프레임워크에 IoC 등이 통합되면서 내부적으로 이와 유사한 방법을 쓴다. 특히 웹 개발에 있어 IoC와 같은 프레임워크는 굉장히 위험할 수 있다. 설명하자면 지금까지 쓴 내용보다 더 복잡하고 많은 내용으로 설명이 필요할지도 모른다.

만약 관리 언어(Managed Language) 등으로 만들어진(자바도 구현 기법이 유사함) 응용 프로그램의 고성능 튜닝, 트러블 슈팅, .NET 플랫폼에 관심이 많은 독자라면 반드시 이해하고 넘어가야 할 내용들이다. 그리고 오픈 소스를 이용하여 다이나믹 프록시(Dynamic Proxy)를 간접적으로 사용만 한다면 가볍게 읽고 넘어가도 좋다. 소소한 개발 일상의 이야깃 거리도 될 것이다.


필자는 이 외에도 다이나믹 프록시(Dynamic Proxy)를 바탕으로 이를 IoC와 통합하고 AOP, ORM 등을 구현하는 방법도 알아볼 것이다. Umc Core는 오픈 소스로 공개되어 있으며 위키 페이지를 만들겸 하나씩 정리하고자 한다. 

'Umc Projects > Umc.Core' 카테고리의 다른 글

Umc Core IoC 통합 컨테이너 #1  (0) 2013.05.24
Umc.Core 프레임워크 다이나믹 프록시(Dynamic Proxy) #1  (0) 2013.05.23
Umc.Core 미공개 Preview  (6) 2008.05.14
Umc.Core 란?  (0) 2007.12.01
Posted by 땡초 POWERUMC

댓글을 달아 주세요

처음 Visual Studio 2010 릴리즈 되었을 때는 HTML5 기능이 추가가 되지 않았습니다. 그래서 XML Schema 를 이용하는 방법으로 HTML 텍스트 에디터에서 HTML5 구문을 사용하기도 하였습니다. 하지만 이번 Visual Studio 2010 SP1에는 정식으로 HTML5 인텔리센스와 유효성을 검사할 수 있는 기능이 추가가 되었습니다.

이 기능을 활성화하기 위해서 도구->옵션의 텍스트 에디터->HTML->유효성에서 HTML5 유효성 검사를 지정할 수 있습니다.

 

HTML5가 지원하는 여러 구문을 인텔리센스에서 자연스럽게 보여줍니다.

 

더불어 CSS3 를 완벽하게 지원하지는 않지만, 일부분 CSS3를 지원해 줍니다. CSS3 기능은 앞으로 그 기능을 보강할 수 있는 확장 기능으로 Visual Studio Gallery 에서 배포가 되길 기대해봅니다.

Posted by 땡초 POWERUMC

댓글을 달아 주세요

배포 가능한 종속성(Deployable Dependencies) 는 이번 Visual Studio 2010 SP1 에서 새롭게 추가된 기능입니다. 웹 응용 프로그램을 서버로 배포하기 위해서는 필수 구성 요소들이 설치가 되어 있어야 하는데, 배포 가능한 종속성 기능을 이용하면 웹 응용 프로그램이 동작에 필요한 일부 컴포넌트를 바로 배포할 수 있도록 도와줍니다.

웹 응용 프로그램에서 마우스 오른쪽 버튼을 클릭하여 컨텍스트 메뉴를 활성화하면 다음과 같은 메뉴 항목이 추가가 되어 있습니다.

 

메뉴 항목을 선택하면 아래와 같은 창이 나타납니다. 이 창에서는 ASP.NET MVC3 에서 사용하는 Razor 컴포넌트와 SQL Server Compact 를 선택할 수 있습니다.

 

위와 같이 배포 시 포함할 종속된 어셈블리/컴포넌트를 선택하여 확인 버튼을 클릭하면, 다음과 같이 웹 응용 프로그램 프로젝트에 _bin_deployableAssemblies 폴더가 생성이 되고, 이 하위에 관련된 어셈블리가 추가가 됩니다.

 

웹 응용 프로그램을 게시를 하게 되면, 위의 _bin_deployableAssemblies 폴더의 어셈블리는 웹 응용 프로그램의 bin 폴더로 배포가 됩니다.

 

물론, 웹 배포 패키지로 .ZIP 파일로 생성을 하여도 종속성을 추가한 어셈블리는 BIN 폴더에 추가가 되며, 이 패키지를 이용하여 배포할 서버에 컴포넌트의 설치 없이 바로 배포할 수 있습니다.

 

다만 현재는 여러 가지 배포 어셈블리/컴포넌트를 지원하지 않고 아래의 3개지의 컴포넌트만 배포를 지원해 줍니다.

  • ASP.NET Web Pages / Razor
  • SQL Server Compact 4.0
  • ASP.NET MVC 3
Posted by 땡초 POWERUMC

댓글을 달아 주세요

기본적으로 웹 응용 프로그램을 개발할 경우 로컬에서 동작하는 ASP.NET Development Server 가 활성화가 됩니다.

그림 1 로컬 ASP.NET Development Server 가 동작하는 화면

웹을 개발할 때 Visual Studio가 제공하는 로컬에서 동작하는 ASP.NET Development Server 로 충분히 어려움 없이 개발을 할 수 있으나 웹 개발의 여러 가지 상황을 고려해 보면 기능이 충분하지는 않았습니다.

예를 들면, 기존의 로컬에서 동작하는 ASP.NET Development Server는 특정 웹 페이지나 XML 웹 서비스, WCF 서비스가 SSL(Secure Sockets Layer)로 동작한다거나 WCF의 NET.TCP, NET.PIPE 등의 바인딩을 사용할 수 없었습니다.

이런 여러 가지 기능적으로 IIS Express 를 사용할 경우 얻을 수 있는 이점이 많고, 기존 웹 응용 프로그램을 IIS Express에서 동작하도록 변경하기 위한 절차 또한 매우 간단합니다.

IIS Express가 설치되어 있다면, 웹 응용 프로그램에서 마우스 오른쪽 버튼을 클릭하여 IIS Express 사용을 선택하면 즉시 IIS Express 에서 웹 응용 프로그램이 동작하도록 할 수 있습니다.

 

그리고 다음의 확인 메시지에서 '예'를 클릭하면 바로 IIS Express로 웹 응용 프로그램을 개발할 수 있습니다.

 

IIS Express는 윈도우의 알림 영역에서 찾을 수 있으며 이 아이콘을 이용하여 여러 개의 호스팅 되고 있는 웹 응용 프로그램을 관리할 수 있습니다.

 

IIS Express를 사용하여 Visual Studio 2010에서 여러 가지 설정을 즉시 변경해 줄 수 있습니다.

그림 2 IIS Express 설치시 웹 응용 프로그램 속성

그림 3 기존 ASP.NET Development Server 속성

 

 

 

IIS 7과 IIS Express 버전의 비교표:

Area

IIS 7

IIS Express

Shipping mechanism

Ships with the OS.

Ships out-of-band. It is automatically included with WebMatrix but can also be installed separately.

Supported Windows editions

Limited number of Windows Vista and Windows 7 editions

Most editions of Windows Server 2003, 2008 and 2008 R2

All editions of Windows XP, Vista, Windows 7

All editions of Windows Server 2008 and 2008 R2

Supported .NET Framework versions

v2.0 SP1 and above

v2.0 SP1 and above (.NET 4.0 is required).

Supported programming languages

Classic ASP, ASP.NET, and PHP

Classic ASP, ASP.NET, and PHP

Process model

Windows Process Activation Service (WAS) automatically manages configured sites.

User launches and terminates sites.

Hosted WebCore (aka Hostable Web Core) support

Yes

Yes. IIS Express is implemented as a layer over HWC.

Supported protocols

HTTP, FTP, WebDAV, HTTPS, and WCF (including over TCP, Named Pipes, and MSMQ)

HTTP, HTTPS, and WCF over HTTP

Non-admin support

WAS must run with administrator user rights.

A standard user is allowed to complete most tasks.

Multi-developer support

None

Yes. Configuration files, settings, and Web content are maintained on a per-user basis.

Visual Studio support

Yes

VS 2010 SP1 Beta allows IIS Express to be used instead of Cassini. VS 2008 can also be manually configured to use IIS Express.

Runtime extensions

See http://www.iis.net/download/All for a complete list.

URL Rewrite and FastCGI. These extensions are built into IIS Express.

Management tools

IIS Manager, appcmd.exe

Appcmd.exe. Common IIS Express management tasks are also built into WebMatrix and Visual Studio 2010 SP1 Beta.

System tray support

None

Yes

Includes built-in IIS 7x modules for authentication, authorization, compression, etc.

Yes

Yes

 

참고

IIS Express Overview

http://learn.iis.net/page.aspx/868/iis-express-overview/

 

IIS Express를 설치하기 위해 WPI(Web Platform Installer) 다운로드 페이지

http://www.microsoft.com/web/gallery/install.aspx?appid=iisexpress

 

그림 4 Web Platform Installer 초기 설치 화면

 

그림 5 기본적인 구성 요소인 IIS Express 설치 화면

 

Posted by 땡초 POWERUMC

댓글을 달아 주세요

실버라이트 4 이전의 버전에서 Visual Studio에서 성능 프로파일을 지원하지 않은 것은 아닙니다. 다만, 개발 도구에서 지원하지 않았을 뿐이고, Command Line을 이용하여 브라우저를 Attached 하여 성능 프로파일을 할 수 있었습니다.

물론, 예전에도 실버라이트에서 성능 프로파일링을 위해 커맨드 라인으로 프로파일링을 할 수 있었습니다. 아래와 같은 순서대로 커맨드를 실행하면 되었습니다.

  1. VSPerfClrEnv /sampleon
  2. "c:\Program Files (x86)\Internet Explorer\iexplore.exe" C:\Breakout\Breakout\Bin\Release\TestPage.html
  3. VSPerfCmd /start:sample /output:MyFile /attach:<PID of iexplore.exe process>
  4. Run your scenario
  5. VSPerfCmd /detach
  6. VSPerfCmd /shutdown
  7. VSPerfClrEnv /off

 

이번 Visual Studio 2010 SP1에서는 개발 도구에서 직접 성능 프로파일을 지원합니다. 번거로이 Command Line을 사용할 필요 없이, 기존의 성능 프로파일의 사용 경험을 그대로 실버라이트 4에 적용할 수 있습니다.

Visual Studio 2010의 분석->성능 마법사 시작 메뉴를 클릭하여 실버라이트 응용 프로그램을 프로파일링 할 준비를 합니다.

 

아래와 같이 성능 프로파일을 시작하면 성능 마법사 페이지가 실행됩니다.

  • CPU 샘플링
    예를 들어, 많은 데이터 작업이나 UI요소 핸들링에서 CPU에 얼만큼의 부담을 주는지 측정할 수 있는 방법입니다.

  • 계측
    관리되는 응용 프로그램이 런타임에 얼마만큼의 리소스와 실행 시간을 갖는지 측정할 수 있습니다. 모듈/클래스/메서드 수준에서 성능을 측정할 수 있는 방법입니다.

  • .NET 메모리 할당
    관리되는 응용 프로그램이 얼만큼의 메모리를 소비하고, 가비지 컬렉션(Garbage Collection) 되는지 등의 수준 높은 메모리 정보를 제공합니다.

  • 동시성
    운영체제 차원에서 메모리의 교착 및 컨텍스트 스위칭(Context Switching)을 관찰하고 다른 프로세스에 어떤 영향을 받는지 Low Level의 정보를 제공합니다.

     

 
필자는 CPU 샘플링을 선택하였고, 2단계 페이지에서는 어떤 응용 프로그램을 프로파일링 할 지 선택합니다. 만약 솔루션 탐색기에 로드 되지 않은 프로젝트는 실행 파일(.EXE) 형태의 파일을 선택하면 소스 코드 없이 다음 단계로 이동할 수 있습니다.

 

3단계 마법사 페이지는 즉시 프로파일링을 시작할지 여부를 선택합니다. 기본 설정으로 마침을 선택하면 선택한 프로젝트 또는 실행 파일을 실행하고 프로파일링을 시작하게 됩니다.

 

응용 프로그램이 실행되면 다양한 테스트 시나리오로 테스트를 진행하고, 응용 프로그램을 마치면 수집된 프로파일링 정보로 프로파일링 결과 페이지를 볼 수 있습니다.

 

 

화면의 좌측 상단의 뷰를 변경하면서 성능 구간을 다양한 측면에서 분석을 할 수 있습니다.

 

Posted by 땡초 POWERUMC

댓글을 달아 주세요

최근 2년 동안 다양한 개발 분야의 기술들이 물망에 오르는 굉장히 뜻 깊은 해였습니다. 2년 전이면 Microsoft 강성재 차장과 함께 처음으로 "Visual Studio 한국 공식 팀"을 창설하면서 http://vsts2010.net 이 탄생한 시기이군요. 2008년 12월에 팀이 창설되고, 2009년 1월 5일이 팀 블로그 2주년이 되는 날이었군요.

바로 저희 "Visual Studio 한국 공식 팀" 블로그에서 한홀 한홀 정성스럽게 작성된 포스트들이 2년 여간의 기술 흐름을 대변해 주고 있으며, 그리고 2011년의 기술도 짐작해 볼 수 있는 짧지만 굵은 변화의 흐름과 함께 여기까지 온 것 같습니다.

우리 팀이 함께 해왔던 핵심 키워드의 태그는 무엇이었을까요?

  • Visual Studio 2010
  • .NET 4.0, .NET Framework 4.0
  • ASP.NET MVC
  • C# 4.0
  • C++0x, C++/CLI
  • Parallel Computing
  • WCF
  • Cloud
  • Application Lifecycle Management

   

그리고 위의 태그들에 대해 더 자세히 살펴보더라도 생소한 기술과 이름, 아키텍처, 환경 등이 2년 동안 격변을 일으키며 변화를 해왔다는 사실입니다.

2011년 이전까지는 여러분들에게 선택권이었던 것들이, 이제는 필수가 되어야 한다고 해도 과언이 아닐 겁니다. 비즈니스 요구사항의 단면을 보면 업무적인 요인, 시대적인 배경 등인데, 이 시대적인 배경에는 트랜드+시장+기술+… 이 있을테고요. 그리고 '우리가 이 시대적인 배경 중 '기술'에 한 배를 타고 흐르고 있는가…?' 에 다시 한번 생각해 볼만 합니다.

예전 2010년 6월 1일 REMIX10 세미나에서 여러분에게 말씀 드린 마지막 문구가 다시금 생각이 나네요.

http://www.techdays.co.kr/2010spring/remix10/session3_1.html

   

여러분의 생존전력은 바로 아래에 해답이 있습니다. 여러분들에게 필요한 것, 그리고 그 가능성이 있다고 판단하시면 2011년 생존을 위하여 달려보는 것은 매우 멋진 2011년 한 해가 될 것입니다.

   

.NET 프레임워크

.NET Framework .NET 의 과거와 현재, 그리고 미래
.NET Framework .NET Framework 4.0 의 특징
.NET Framework .NET Framework 4.0 마이그레이션 이슈
.NET Framework .NET 스마트클라이언트 한계 극복 [1]
.NET Framework .NET 스마트클라이언트 한계 극복 [2]
CLR 1. Hello 世界
CLR 2. CLR! CLR! CLR!
CLR 3. MSCorLib & Metadata
CLR 4. Assembly
CLR 5. Assembly - Strongly named assemblies
CLR 6. Assembly - GAC(Global Assembly Cache)
CLR 7. System.Object
CLR 8. System.Object (2)
CLR 닷넷4.0에서 네이티브코드와 매나지드코드의 동거 part 1.
CLR 닷넷4.0에서 네이티브코드와 매나지드코드의 동거 part 2-1.
CLR 닷넷4.0에서 네이티브코드와 매나지드코드의 동거 part 2-2. 네이티브 랩퍼 만들기
Managed Extensibility Framework [MEF] 1. Managed Extensibility Framework 이란?
Managed Extensibility Framework [MEF] 2. Parts 와 Contracts 선언
Managed Extensibility Framework [MEF] 3. Export 선언
Managed Extensibility Framework [MEF] 4. Import 선언
Managed Extensibility Framework [MEF] 5. Catalog 사용
Managed Extensibility Framework [MEF] 6. Lazy Exports
Managed Extensibility Framework [MEF] 7. Exports and Metadata
Managed Extensibility Framework [MEF] 8. Strongly Typed Metadata
Managed Extensibility Framework [MEF] 9. Recomposition
Managed Extensibility Framework [MEF] 10. Querying the CompositionContainer
Managed Extensibility Framework MEF Preview 6 공개
Managed Extensibility Framework MEF 는 Generic Type 을 지원하지 않는다!
Managed Extensibility Framework MEF 에 Generic Type 을 지원하기 위해서..?
Managed Extensibility Framework MEFGeneric 코드 플랙스에 공개합니다.

   

애자일 개발

Agile Development [Better Code]TDD의 개념이 완벽히 녹아 들어간 VSTS 2010
Agile Development [Better Code]Visual Studio 2010 Code Analysis Enhancements - 1.개요
Agile Development [Better Code]Visual Studio 2010 Code Analysis Enhancements - 2. Rule Sets Feature
Agile Development [Better Code]PEX, Automated Whitebox Testing for .NET - 1. 개요
Agile Development [Better Code]Visualize Code Relationships
Agile Development [Testing] TDD (Test-Driven Development-테스트 주도 개발)
Agile Development [Testing] BDD (Behavior-Driven Development?행위 주도 개발)
Agile Development [Testing] Moq.NET (T/B Driven Development)
Agile Development [Better Code]Visual Studio Code Analysis Enhancements - 3. Data Flow Rules and Phoenix Engine
Agile Development 애자일에 대한 고찰
Agile Development [ALM-Test] 1. 왜 단위 테스트를 해야 하는가?
Agile Development [ALM-Test] 2. 한국적인 애자일 모델의 필요성
Agile Development [협업 1] 협업 도구의 통일성과 협업 인프라 관리
Agile Development [ALM-Test] 3. 테스터에 대한 오해와 진실
Agile Development [ALM-Test] 4. 테스터(SDET) 의 역할
Agile Development [ALM-Test] 5. 테스트 계획
Agile Development [ALM-Test] 6. Load Runner vs Visual Studio 2010 테스팅 비교 분석 - http://willstory.tistory.com/4 제공
Agile Development [ALM-Test] 7. TDD vs 계약기반 테스트
Architect Development Architect Development ?
Architect Development 몽당연필과 함께하는 VSTS 2010 모델링 0/4
Architect Development 몽당연필과 함께 하는 VSTS 2010 모델링 1/4
Architect Development Windows Server AppFabric - Velocity 란?
Architect Development WCF=SOA 에 대한 고찰

   

ASP.NET 4.0

ASP.NET 4.0 [ASP.NET 4.0] 1. Core Service - Extensible Output Caching
ASP.NET 4.0 [ASP.NET 4.0] 2. AJAX - Declarative Client Template Rendering
ASP.NET 4.0 ASP.NET 4 와 Visual Studio 2010 Web Development Beta 2 Overview - Dynamic Data(1)
ASP.NET 4.0 ASP.NET 4 와 Visual Studio 2010 Web Development Beta 2 Overview - Dynamic Data(2)
ASP.NET 4.0 ASP.NET 4 와 Visual Studio 2010 Web Development Beta 2 Overview - Web Designer & Deployment
ASP.NET 4.0 ASP.NET 4 와 Visual Studio 2010 Web Development Beta 2 Overview - Core Services
ASP.NET 4.0 ASP.NET 4 와 Visual Studio 2010 Web Development Beta 2 Overview - New Features in the Microsoft Ajax Library
ASP.NET 4.0 ASP.NET 4 와 Visual Studio 2010 Web Development Beta 2 Overview - Web Forms(1)
ASP.NET 4.0 Razor in WebMatrix
ASP.NET 4.0 Razor in WebMatrix(2) 코드의 재 사용
ASP.NET 4.0 Razor in WebMatrix(3) ? WebMatrix Helper
ASP.NET 4.0 ASP.NET 4 와 Visual Studio 2010 Web Development Beta 2 Overview - Web Forms(2)
ASP.NET 4.0 ASP.NET 4 와 Visual Studio 2010 Web Development Beta 2 Overview - Web Forms(3)
ASP.NET 4.0 ASP.NET 4 와 Visual Studio 2010 Web Development Beta 2 Overview - Web Forms(4)
ASP.NET 4.0 ASP.NET 4 와 Visual Studio 2010 Web Development Beta 2 Overview - Web Forms(5)
ASP.NET MVC M, V 그리고 C의 각방생활(1) - ASP.NET MVC vs ASP.NET WEB FORM
ASP.NET MVC M, V 그리고 C의 각방생활(2) - ASP.NET MVC와 인사나누기
ASP.NET MVC M, V 그리고 C의 각방생활(3) - 초간단 사이트 만들기(1)
ASP.NET MVC M, V 그리고 C의 각방생활(4) - 유효성 검사
ASP.NET MVC M, V 그리고 C의 각방생활(5) - 초간단 사이트 만들기(2)
ASP.NET MVC M, V 그리고 C의 각방생활(6) - 유효성 검사(2)
ASP.NET MVC M, V 그리고 C의 각방생활(7) - 함께 즐겨요~ jQuery
ASP.NET MVC M, V 그리고 C의 각방생활(8) - jQuery와 탭메뉴 그리고 파샬뷰
ASP.NET MVC M, V 그리고 C의 각방생활(9) - jqGrid 사용해보자
ASP.NET MVC M, V 그리고 C의 각방생활(10) - jqGrid를 이용한 paging과 sorting
ASP.NET MVC ASP.NET MVC 3 Preview 1 이 릴리즈 되었습니다.
ASP.NET MVC M, V 그리고 C의 각방생활(11) - jqGrid로 데이터 추가,편집,삭제해보기
ASP.NET MVC M, V 그리고 C의 각방생활(12) - 테스팅 그거, 아무나 하나?
ASP.NET MVC JailBreak From Controllers and Actions
ASP.NET MVC VSTS2010 에서 Razor 코드 하이라이팅 지원하기

   

C# 4.0

C# [C# 4.0] Named and Optional Parameters
C# [C# 4.0] Duck Typing
C# [C# 4.0] New Extension Method "Zip"
C# [C# 4.0] Generic Covariance And Contra Variance
C# Welcome to Dynamic C#(1) - 첫만남.
C# Welcome to Dynamic C#(2) - Wanna be a polyglot.
C# Welcome to Dynamic C#(3) - 마음이 넒어진 C#
C# Welcome to Dynamic C#(4) - 극과극 비교체험.
C# Welcome to Dynamic C#(5) - Return to Dynamic.
C# Welcome to Dynamic C#(6) - Return to Dynamic (2)
C# Welcome to Dynamic C#(7) - 아낌없이 표현해 주는 나무
C# Welcome to Dynamic C#(8) - DLR이 나무를 사랑하는 이유
C# Welcome to dynamic C# 외전(1) - Generate From Usage.
C# Welcome to dynamic C# 외전(2) - Generic Method.
C# Welcome to dynamic C# 외전(3) - 감시하는 자와 감시당하는 자.
C# Welcome to Dynamic C#(9) - Dynamic Returns Again.
C# Welcome to Dynamic C#(10) - Dynamic Returns Again.(2)
C# Welcome to Dynamic C#(11) - The Phantom of The Dynamic
C# Welcome to Dynamic C#(12) - dynamic은 외로운 아이.
C# Welcome to Dynamic C#(13) - 아직도 가야할 길.
C# Welcome to Dynamic C#(14) - 철지난 만우절에 낚여서 파닥파닥.
C# Welcome to Dynamic C#(15) - A/S for dynamic.
C# Welcome to Dynamic C#(16) - dynamic이라도 이건 안되는 거임.
C# Welcome to Dynamic C#(17) - 필요한 말만 하고 삽시다.
C# Welcome to Dynamic C#(18) - 이름을 붙이면서 벌어진 일들.
C# Welcome to Dynamic C#(19) - 위너 고르기.
C# Welcome to Dynamic C#(20) - 어르신과 대화하는 법.
C# Welcome to Dynamic C#(21) - 인덱스의 힘.
C# Welcome to Asynchronous C#(0) - C#의 전설.
C# Parallel Programming [C# 4.0] Parallel Extension - [1] 병렬 처리
C# Parallel Programming [C# 4.0] Parallel Extension - [2] 병렬 처리 아키텍처
C# Parallel Programming [C# 4.0] Parallel Extension - [3] TPL(Task Parallel Library)
C# Parallel Programming Welcome to Parellel world(1) - Here comes a new challenger!
C# Parallel Programming Welcome to Parallel C#(1) - 굿바이, 그리고 안녕~~?
C# Parallel Programming Welcome to Parallel C#(2) - 계속 되는 개념 찾기.
C# Parallel Programming Welcome to Parallel C#(3) - 작업의 기본.
C# Parallel Programming Welcome to Parallel C#(4) - 작업의 기본 Part 2.
C# Parallel Programming Welcome to Parallel C#(5) - 병렬작업에서 예외가 생기면 어케...?
C# Parallel Programming Welcome to Parallel C#(6) - To be continue...
C# Parallel Programming Welcome to Parallel C#(7) - Excuse me.
C# Parallel Programming Welcome to Parallel C#(8) - 취소 쉽게 하기.
C# Parallel Programming Welcome to Parallel C#(9) - 백지장은 맞들지 말엉.
C# Parallel Programming Welcome to Parallel C#(10) - 이보게, 잠깐 뒤를 돌아보지 않겠나.

   

C++/CLI

C++/CLI C++/CLI는 미운 오리새끼 or 백조
C++/CLI .NET에서의 C++/CLI의 의미
C++/CLI [Step 01] 'C++/CLI가 뭐야?'에 답하기 && 가장 많은 프로그래밍 언어로 만드는 프로그램 만들기
C++/CLI [Step 02-1] 클래스(class), 핸들(^), 그리고 구조체(struct)
C++/CLI [Step.02-2] 클래스(class), 핸들(^), 그리고 구조체(struct)
C++/CLI [step.03] 배열
C++/CLI [Step. 04] nullptr, interior_ptr, pin_ptr
C++/CLI [Step. 05] 관리 코드의 array를 비관리 코드에 포인터로 전달
C++/CLI [Step. 06-1] 관리코드의 문자열과 비관리코드의 문자열 변환
C++/CLI [Step. 06-2] 관리코드의 문자열과 비관리코드의 문자열 변환
C++/CLI [Step. 07] 비관리 클래스에서 관리 클래스를 멤버로, 관리 클래스에서 비관리 클래스를 멤버로
C++/CLI [Step. 08] 프로퍼티 ( property )
C++/CLI [Step. 09] 델리게이트 (delegate)
C++/CLI [Step. 10] 이벤트 ( event )
C++/CLI [Step. 11] 열거형( enum )
C++/CLI [Step. 12] for each
C++/CLI [Step. 13] parameter array
C++/CLI [Step. 15] static 생성자, initonly, literal
C++/CLI [Step. 14] 인터페이스 ( interface )
C++/CLI [Step. 16] array 클래스에 non-CLI 오브젝트 사용
C++/CLI [Step. 17] 델리게이트에 비관리 함수를 할당하기 그리고 다음 예고
C++/CLI [Step. 18] 순수 가상 함수
C++/CLI [Step. 19] char* -> 관리코드, 관리코드 -> char*
C++/CLI [Step. 20] 닷넷에서 HalfNetwork를 사용하자 - 1
C++/CLI [Step. 21] 닷넷에서 HalfNetwork를 사용하자 - 2
C++/CLI [Step. 22] 닷넷에서 HalfNetwork를 사용하자 ? 3
C++/CLI [Step. 23] 닷넷에서 HalfNetwork를 사용하자 ? 4
C++/CLI [Step. 24] 닷넷에서 HalfNetwork를 사용하자 ? 5
C++/CLI [Step. 25] 닷넷에서 HalfNetwork를 사용하자 ? 6(마지막)

   

C++0x

C++0x [VC++] 1. 큰 변화가 기대되는 Visual C++( VC++ )
C++0x [VC++] 2. C++0x의 auto
C++0x [VC++] 3. static_assert
C++0x [VC++] 4. 우측 값 참조( RValue Reference ) - 첫 번째
C++0x [VC++] 5. 우측 값 참조( RValue Reference ) ? 두 번째
C++0x [VC++] 6. 우측 값 참조( RValue Reference ) - 세 번째
C++0x [VC++] 7. 우측 값 참조( RValue Reference ) - 네 번째
C++0x [VC++] 8. 우측 값 참조( RValue Reference ) ? 다섯 번째
C++0x [VC++] 9. Lambda ( 람다 ) - 첫 번째
C++0x [VC++] 11. Lambda - 두 번째
C++0x [VC++] 12. Lambda - 세 번째
C++0x [VC++] 13. Lambda - 네 번째
C++0x [VC++] 14. decltype
C++0x 대용량 파일 조작을 위한 C++0x의 변화
C++0x nullptr
C++0x VC++ 10에 구현된 C++0x의 코어 언어 기능들
C++0x C++0x 관련 책 "Visual C++ 10과 C++0x"
C++0x "Visual C++ 10과 C++0x" pdf 파일
C++0x [Plus C++0x] 람다(Lambda) 이야기 (1)
C++0x [Plus C++0x] 람다(Lambda) 이야기 (2)
C++0x [Plus C++0x] 람다(Lambda) 이야기 (3)
C++0x [Plus C++0x] 람다(Lambda) 이야기 (마지막회)
C++0x [STL] 1. What's new in VC++ 2010?
C++0x [STL] 2. unique_ptr (1/2)
C++0x [STL] 3. unique_ptr (2/2)
C++0x [STL] 4. make_shared
C++0x [STL] 5. 에 추가된 새로운 함수들 (1/5)
C++0x [STL] 6. 에 추가된 새로운 함수들 all_of, any_of, none_of (2/5)
C++0x VS2010에서 nullptr의 알려진 버그
C++0x RValue Reference에 의한 STL의 성능향상 테스트
C++0x [STL] 7. 에 추가된 새로운 함수들 copy_if, copy_n, find_if_not (3/5)
VC++ 10 Concurrency Runtime C++ 개발자를 위한 병렬 프로그래밍 동영상 [0]
VC++ 10 Concurrency Runtime C++ 개발자를 위한 병렬 프로그래밍 동영상 [1]
VC++ 10 Concurrency Runtime C++ 개발자를 위한 병렬 프로그래밍 동영상 [2]
VC++ 10 Concurrency Runtime C++ 개발자를 위한 병렬 프로그래밍 동영상 [3]
VC++ 10 Concurrency Runtime C++ 개발자를 위한 병렬 프로그래밍 동영상 [4]
VC++ 10 Concurrency Runtime C++ 개발자를 위한 병렬 프로그래밍 동영상 [5]
VC++ 10 Concurrency Runtime C++ 개발자를 위한 병렬 프로그래밍 동영상 [6/7] 완결!
VC++ 10 Concurrency Runtime PPL task를 이용한 피보나치 수 계산
VC++ 10 Concurrency Runtime 인사 및 Multi Core, Multi Thread...그리고 VC++ 10
VC++ 10 Concurrency Runtime Concurrency Runtime
VC++ 10 Concurrency Runtime Parallel Patterns Library (PPL)
VC++ 10 Concurrency Runtime 양보할 줄 아는 Concurrency Runtime의 event
VC++ 10 Concurrency Runtime Parallel Patterns Library(PPL) - Task
VC++ 10 Concurrency Runtime Parallel Patterns Library(PPL) - 병렬 알고리즘
VC++ 10 Concurrency Runtime Parallel Patterns Library(PPL) - parallel_for 알고리즘
VC++ 10 Concurrency Runtime Asynchronous Agents Library로 Dining Philosophers 문제 해결하기 - 1
VC++ 10 Concurrency Runtime Parallel Patterns Library(PPL) - parallel_for_each 알고리즘
VC++ 10 Concurrency Runtime Asynchronous Agents Library로 Dining Philosophers 문제 해결하기 - 2
VC++ 10 Concurrency Runtime Parallel Patterns Library(PPL) - parallel_invoke
VC++ 10 Concurrency Runtime Asynchronous Agents Library로 Dining Philosophers 문제 해결하기 - 마지막회
VC++ 10 Concurrency Runtime Parallel Patterns Library(PPL) - combinable
VC++ 10 Concurrency Runtime Parallel Patterns Library(PPL) - task group에서의 병렬 작업 취소 - 1
VC++ 10 Concurrency Runtime Parallel Patterns Library(PPL) - task group에서의 병렬 작업 취소 - 2
VC++ 10 Concurrency Runtime Parallel Patterns Library(PPL) - concurrent_vector - 1
VC++ 10 Concurrency Runtime Parallel Patterns Library(PPL) - concurrent_vector - 2
VC++ 10 Concurrency Runtime Parallel Patterns Library(PPL) - concurrent_queue - 1
VC++ 10 Concurrency Runtime Parallel Patterns Library(PPL) - concurrent_queue - 2
VC++ 10 Concurrency Runtime Concurrency Runtime(ConcRT)의 디버그 모드에서 메모리 leak 문제
VC++ 10 Concurrency Runtime Asynchronous Agents Library 소개
VC++ 10 Concurrency Runtime Asynchronous Agents Library - agent. 1 ( 상태 )
VC++ 10 Concurrency Runtime Asynchronous Agents Library ? agent. 2 ( 기능 )
VC++ 10 Concurrency Runtime Asynchronous Agents Library - message 전달 함수. 1 ( 전송 )
VC++ 10 Concurrency Runtime Asynchronous Agents Library ? message 전달 함수. 2 ( 수신 )
VC++ 10 Concurrency Runtime Asynchronous Agents Library ? message block 1. ( 인터페이스 )
VC++ 10 Concurrency Runtime Asynchronous Agents Library ? message block 2. ( unbounded_buffer )
VC++ 10 Concurrency Runtime Asynchronous Agents Library ? message block 3. ( overwrite_buffer & single_assignment )
VC++ 10 Concurrency Runtime Asynchronous Agents Library ? message block 4. ( call )
VC++ 10 Concurrency Runtime Asynchronous Agents Library ? message block 5. ( transformer )
VC++ 10 Concurrency Runtime Asynchronous Agents Library ? message block 6. ( choice )
VC++ 10 Concurrency Runtime Asynchronous Agents Library ? message block 7. ( join & multitype_join )
VC++ 10 Concurrency Runtime Asynchronous Agents Library ? message block 8. ( timer )
VC++ 10 Concurrency Runtime Concurrency Runtime ? 동기화 객체 1. ( critical_section & reader_writer_lock )
VC++ 10 Concurrency Runtime Concurrency Runtime ? 동기화 객체 2. ( event )
VC++ 10 Concurrency Runtime Asynchronous Agents Library ? message block 9. ( custom )
VC++ 10 Concurrency Runtime Concurrency Runtime - 만델브로트 프랙탈 ( Mandelbrot Fractal ) 예제
VC++ 10 Concurrency Runtime Concurrency Runtime ? Task Scheduler 1. ( Scheduler )
VC++ 10 Concurrency Runtime Concurrency Runtime ? Task Scheduler 2. ( SchedulerPolicy )
VC++ 10 Concurrency Runtime Concurrency Runtime ? Task Scheduler 3. ( ScheduleGroup )
VC++ 10 Concurrency Runtime Concurrency Runtime ? Task Scheduler 4. ( ScheduleTask )
VC++ 10 Concurrency Runtime Concurrency Runtime ? Task Scheduler 5. ( Context blocking )
Visual C++ 10 About Visual C++ 10
Visual C++ 10 디버깅 모드에서 역어셈블리 코드 보기
Visual C++ 10 Visual C++ 10의 변화
Visual C++ 10 [Upgrade to VC++ 10] _WIN32_WINNT 버전 문제
Visual C++ 10 VS2010 C++ 프로젝트의 디렉토리 설정

   

클라우드 컴퓨팅

Cloud 구름 속의 미래 : Windows® Azure™ Platform [1]
Cloud SQL Azure - CTP1
Cloud SQL Azure 알아보기 (1) - 데이터베이스 개체 생성
Cloud SQL Azure 알아보기(2) ? 데이터베이스 스키마 마이그레이션, 데이터 전송
Cloud 구름 속의 미래 : Windows® Azure™ Platform [2]
Cloud SQL Azure 사용 시 주의점(1) - 방화벽 설정
Cloud SQL Azure 알아보기(3) ?SQL Server 2008 R2 Nov CTP
Cloud SQL Azure 알아보기(4) ? SQL Azure Cloud App
Cloud SQL Azure 알아보기 (5)- SQL Azure 이점과 T-SQL 지원
Cloud [MS@클라우드컨퍼런스] MS 클라우드 기술과 플랫폼
Cloud 클라우드 기반 분산 컴퓨팅을 위한 AppFabric (1) : 아하! App 분산!
Cloud Hello Windows Azure / Windows Azure Platform의 이해
Cloud Hello Windows Azure / Gallery of 'Powered by Windows Azure Platform'
Cloud Hello Windows Azure / Windows Azure 개발 환경의 구축
Cloud Hello Windows Azure / Understanding Windows Azure Development Process
Cloud Hello Windows Azure / Windows Azure Tools for Visual Studio 1.2 출시
Cloud Hello Windows Azure / Windows Azure Platform 최신 소식 업데이트 (종합) [수정]
Cloud Hello Windows Azure / Twitter 스타일 방명록 만들기 #1
Cloud Windows Azure Update: Microsoft Project Code-Named "Houston" CTP 1
Cloud SQL Azure와 Excel 2010의 PowerPivot
Cloud Hello Windows Azure / Twitter 스타일 방명록 만들기 #2
Cloud Windows Azure Update: CloudStorageAccount 클래스 사용 시 주의 사항
Cloud SQL Azure Update: Dynamic Management View
Cloud Hello Windows Azure / Twitter 스타일 방명록 만들기 #3
Cloud Windows Azure Update: myAzureStorage
Cloud SQL Azure 와 SQL Reporting Service
Cloud Windows Azure Update: Windows Azure CDN의 활용
Cloud [작업 중] Windows Azure Update: Adaptive Smooth Streaming with Windows Azure Storage

   

게임 개발

Direct3d Mobile [d3dm 기초] 1. wm6.x 개발환경 세팅
Direct3d Mobile .NET 기반에서 공개소스 게임엔진 포팅하기
DirectX 11 [JumpToDX11-1] 사라진 Direct3D 오브젝트를 찾아서...
DirectX 11 [JumpToDX11-2]DeviceContext...넌 누구냣!!
DirectX 11 [JumpToDX11-3] Feature Level
DirectX 11 [JumpToDX11-4] ID3D11View
DirectX 11 [DX11_#1]D3D Buffer( 1 / 2 )
DirectX 11 [DX11_#2]D3D Buffer( 2 / 2 )
DirectX 11 [DX11_#3]기본적인 설정
DirectX 11 [JumpToDX11-5] 새로운 시대를 여는 DirectX11...
DirectX 11 [JumpToDX11-6] 커맨드(Command)...
DirectX 11 [DX11_#4]텍스트, 버튼 출력
DirectX 11 [JumpToDX11-7] 간편해진 리소스 처리.
DirectX 11 [JumpToDX11-8] Deferred Contexts
DirectX 11 [JumpToDX11-9] Multi-threaded Rendering 을 위한 API.
DirectX 11 [JumpToDX11-10] GPGPU 를 위한 DirectCompute.
DirectX 11 [JumpToDX11-11] DirectCompute 를 위한 한걸음!
DirectX 11 [JumpToDX11-12] DirectCompute 의 절차.
DirectX 11 [JumpToDX11-13] Tessellation 등장.
DirectX 11 [DX11_#5]DirectX11의 활용 사례(1/3)
DirectX 11 [JumpToDX11-14] DirectX9 세대의 테셀레이션( ID3DXPatchMesh 편 )
DirectX 11 [JumpToDX11-15] DirectX9 세대의 테셀레이션( IDirect3DDevice9::DrawXXXPatch편 )
DirectX 11 [알콜코더의 미리 배워보는 DirectX 11 - 입문편] 0. 누구를 위한 연재인가
DirectX 11 [알콜코더의 미리 배워보는 DirectX11-입문편] 1.튜터리얼 01 : 다이렉트 3D 기초 #1
DirectX 11 [알콜코더의 미리 배워보는 DirectX11-입문편] 1.튜터리얼 01 : 다이렉트 3D 기초 #2
DirectX 11 [JumpToDX11-16] DirectX9 세대의 테셀레이션( D3DXTessellateNPatches편 )
DirectX 11 [알콜코더의 미리 배워보는 DX11 ? 입문편] DX11에서 무엇이 추가되었나?
DirectX 11 [JumpToDX11-17] DirectX9 세대의 테셀레이션( ATI 라이브러리편 )
DirectX 11 [발표자료] 예제로 느껴보는 다이렉트X 11의 매력
DirectX 11 [JumpToDX11-18] DirectX11의 테셀레이션 ( 테셀레이션을 위한 하드웨어의 등장편 )
DirectX 11 [알콜코더의 미리 배워보는DX11 입문편] DirectX 11의 특징들
DirectX 11 [알콜코더의 미리배워보는 DX11-입문편] 1. 튜터리얼01 : 디바이스와 스왑체인의 생성

   

F#

F# Welcome to F#(1) - 첫만남.
F# Welcome to F#(2) - 두번째 만남.
F# Welcome to F#(3) - 사소한 탐색전.
F# Welcome to F#(4) - 과거와 배경을 좀 더 알고싶어.
F# Welcome to F#(5) - 아주 조금씩 심화되는 탐색전.
F# Welcome to F#(6) - 비교본능.
F# Welcome to F#(7) - 클리프 행어.
F# Welcome to F#(8) - 은총알과 엄친아.
F# Welcome to F#(9) - 메이져 데뷰.
F# Welcome to F#(10) - 인도음식 카레.....?
F# Welcome to F#(11) - 차별을 권장하는 언어인거임?!?!
F# Welcome to F#(12) - 공동작업 좋치아니항가

   

MFC

MFC [MFC] 리스타트 매니저(Restart Manager) - (1/3) : 기능 소개
MFC [MFC] 리스타트 매니저(Restart Manager) - (2/3) : 사용하기
MFC [MFC] 리스타트 매니저(Restart Manager) - (3/3) : 활용하기
MFC [MFC] 태스크 대화상자(Task Dialog) - (1/3) : 기능 소개
MFC [MFC] 태스크 대화상자(Task Dialog) - (2/3) : 사용하기
MFC [MFC] 태스크 대화상자(Task Dialog) - (3/3) : 활용하기
MFC [MFC] 태스크 대화상자(Task Dialog) - 예제 코드 올립니다.
MFC [MFC/윈도우 7 멀티터치] #2 : 제스처(gesture)를 이용한 구현()
MFC [MFC/윈도우 7 멀티터치] #3 : 제스처(gesture)를 이용한 구현()
MFC [MFC/윈도우 7 멀티터치] #4 : WM_TOUCH 메세지를 이용한 구현()
MFC [MFC/윈도우 7 멀티터치] #5 : WM_TOUCH 메세지를 이용한 구현()
MFC [MFC/윈도우 7 멀티터치] #6 : 예제 코드 올립니다

   

RIA

RIA Expression Blend3 preview - 1.인터페이스
RIA Expression Blend3 preview - 2. Photoshop import
RIA Silverlight 3 & Blend 3 RC 공개!!!
RIA Silverlight 4 Beta 공개
RIA .Net Ria Service + IIS6 + Silverlight 4 Troubleshooting!!
RIA 실버라이트 비하인드 코드에서 바인딩하기.
RIA .Net Ria Service 와 Entities 그리고 Stored Procedure 하다가 생긴일..
RIA 실버라이트 프로그래머가 할 수 있는 최소한의 블랜드 디자이너를 위한 배려

   

SharePoint 2010

SharePoint 2010 Visual Studio 2010 에게 바란다 - SharePoint 14 Development
SharePoint 2010 SharePoint 2010 Overview
SharePoint 2010 SharePoint 2010 개발 환경 구성
SharePoint 2010 SharePoint 2010 개발 환경- Hello World 웹 파트 생성 및 배포하기
SharePoint 2010 SharePoint 2010 Web Part 생성
SharePoint 2010 SharePoint 2010 Visual Web Part
SharePoint 2010 SharePoint 2010 Feature
SharePoint 2010 SharePoint 2010 Event Receiver
SharePoint 2010 SharePoint 2010 데이터 기술
SharePoint 2010 SharePoint 2010 Server Object Model
SharePoint 2010 Visual Studio 2010 출시에 따른 SharePoint Developer Tools
SharePoint 2010 SharePoint 2010 LINQ to SharePoint
SharePoint 2010 Client Object Model - .NET
SharePoint 2010 Client Object Model ? Silverlight (1)
SharePoint 2010 Client Object Model ? Silverlight (2)
SharePoint 2010 Client Object Model - Javascript(1)
SharePoint 2010 Client Object Model - Javascript(2)
SharePoint 2010 Client Object Model ? 정리
SharePoint 2010 SharePoint 2010 개발환경 구축 가이드
SharePoint 2010 REST -.NET
SharePoint 2010 REST ? Silverlight
SharePoint 2010 REST - jQuery
SharePoint 2010 SharePoint 2010 프로젝트 디버깅
SharePoint 2010 SharePoint 2010 Developer Dashboard

   

Team Foundation Server

Team Foundation Server Visual Studio Team System 2010 (CTP10) - 작업 항목 링크
Team Foundation Server TFS 2010 설치 하기
Team Foundation Server TFS 2010 Build Service 설치
Team Foundation Server TFS 2010 설치 과정 중에 TF255040 문제
Team Foundation Server Visual Studio 2010을 활용한 ALM (1-5) - ALM 이란 무엇인가
Team Foundation Server Team Foundation 트러블 슈팅 가이드
Team Foundation Server Visual Studio Team Foundation Server 2010 를 설치해보자
Team Foundation Server Visual Studio Team Foundation Server 2010 설치 전 할일
Team Foundation Server VS TFS 2010 설치편 - 설치전 IIS, .NET 설치
Team Foundation Server VS TFS 2010 설치편 - 설치 시작
Team Foundation Server VS TFS 2010 구성편 - 설치 후 TFS 구성으로 점심 얻어먹기 편
Team Foundation Server VS TFS 2010 사용편 - SourceSafe? 버려~
Team Foundation Server [HowTo] Team Foundation Server 의 로컬 매핑 캐시 제거하기
Team Foundation Server [HowTo] SharePoint 2010 Beta 깨끗하게 제거하기
Team Foundation Server [HowTo] SCVMM 의 Install Virtual Guest Service 작업 중 2941 오류
Team Foundation Server [HowTo] TFS2010 의 Tfs_Analysis 웨어하우스 데이터베이스가 망가졌을 경우
Team Foundation Server [PPT] 테스트와 가상화의 만남 - 테스트 가상화(Lab Management)
Team Foundation Server Team Foundation Server 2010으로 업그레이드, 마이그레이션, 동기화
Team Foundation Server Visual Source Safe 사용자를 위한 TFS2010 시리즈

   

Visual Studio 2010

Visual Studio 2010 Visual Studio Team System 2010 CTP 만료 해결하기
Visual Studio 2010 Visual Studio 2010 의 특징
Visual Studio 2010 Visual Studio 2010 내부 빌드 최신 동영상: C# 4.0 Language + IDE + WPF Shell + Editor
Visual Studio 2010 Visual Studio 2010 & .NET 4.0 참고 자료들
Visual Studio 2010 Visual Studio 2010 Beta 1 설치부터 살펴보기
Visual Studio 2010 멀티 모니터 사용
Visual Studio 2010 Visual Studio 2010 Beta 2 출시
Visual Studio 2010 Visual Studio 2010 Beta 2 설치 미리 보기
Visual Studio 2010 VS 2010 Beta 2 설치 과정에서 Silverlight SDK 문제
Visual Studio 2010 VS2010 베타2의 WPF & Silverlight 디자이너 성능 향상 팁
Visual Studio 2010 VS 2010 기능 소개 01 인텔리 센스 기능의 변화
Visual Studio 2010 Visual Studio 2010과 Blend Preview for .NET 4 통합 문제
Visual Studio 2010 VS 2010 기능 소개 02 - IDE의 기능 추가
Visual Studio 2010 VS 2010 기능 소개 03 - IDE의 변화
Visual Studio 2010 Visual Studio 2010 출시 일정
Visual Studio 2010 VS 2010 기능소개 04 - Visual C#&VB 개발자 IDE Tips & Tricks 첫번째
Visual Studio 2010 VS 2010 기능소개 05 - Visual C#&VB 개발자 IDE Tips & Tricks 두번째
Visual Studio 2010 Visual Studio 2010 RC 공개 임박!
Visual Studio 2010 Visual Studio 2010 RC 공개
Visual Studio 2010 C#에서 IntelliSense가 동작하지 않을 때 문제 해결 방법
Visual Studio 2010 똑똑한 검색을 지원하는 VSTS 2010의 "Navigate To" 검색
Visual Studio 2010 실버라이트4 RC와 블렌드 4 베타 공개
Visual Studio 2010 윈도우폰 7 개발환경 공개
Visual Studio 2010 Visual Studio 2010! 나랑 놀아보자 ? 기본편 (2회) - VS IDE
Visual Studio 2010 Visual Studio 2010! 나랑 놀아보자 ? 기본편 (3회) - Box Selection
Visual Studio 2010 Visual Studio 2010! 나랑 놀아보자 ? 기본편 (4회) - Call Hierarchy
Visual Studio 2010 Visual Studio 2010 출시와 완소 정보 총 정리
Visual Studio 2010 Visual Studio 2010 e-book 무료로 다운로드 하세요
Visual Studio 2010 Visual Studio 2010! 나랑 놀아보자 ? 기본편 (5회) - Navigate To
Visual Studio 2010 Visual Studio 2010 RTM 추가 완소 정보
Visual Studio 2010 Visual Studio 2010! 나랑 놀아보자 ? 기본편 (6회) - Generate from Usage
Visual Studio 2010 VS 2010 기능소개 05 - Visual C#&VB 개발자 IDE Tips & Tricks 두번째
Visual Studio 2010 Visual Studio 2010, 2008, 2005 에서 .NET Framework 1.1 개발하기
Visual Studio 2010 Visual Studio 2010, 2008, 2005 에서 .NET Framework 1.1 개발하기
Visual Studio 2010 Just for fun! / Visual Studio Express Edition
Visual Studio 2010 왜 Visual Studio 2010 이여야 하는가?
Visual Studio 2010 Visual Studio 2010 최신 PDF 자료를 MSDN 에서 다운로드 받으세요
Visual Studio 2010 Just for fun! / DreamSpark는 대학생 여러분을 위한 솔루션입니다.
Visual Studio 2010 VS2008 을 VS2010 에서 동시에 개발하기
Visual Studio 2010 VS2008 과 VS2010 동시에 개발하기 : 테스트 프로젝트가 포함 될 경우
Visual Studio 2010 Introducing Visual Studio LightSwitch! - Enjoy your development
Visual Studio 2010 Visual Studio Hotfix List
Visual Studio 2010 곧 다가올 기술, Microsoft Research [1/2]
Visual Studio 2010 곧 다가올 기술, Microsoft Research [2/2]
Visual Studio 2010 Visual Studio 31 (1) - 시작, 그리고 Intellisense
Visual Studio 2010 Visual Studio 31 (2) - Startpage
Visual Studio 2010 Visual Studio 31 (3) - Temp Project
Visual Studio 2010 Visual Studio 31 (4.1) - Visual Studio 2010 Productivity Power Tools, Part 1
VIsual Studio Extensibility [Blueprints] S+S Blueprints
VIsual Studio Extensibility Visual Studio 2010 SDK 와 Readme
VIsual Studio Extensibility Visual Studio 2010 Extension Manager
VIsual Studio Extensibility [VSIX] 1. What is different from before version?
VIsual Studio Extensibility [VSIX] 2-1. How to start VSIX programming
VIsual Studio Extensibility [VSIX] 2-2. How to start VSIX programming
VIsual Studio Extensibility MousePresentationTracker - MEF 세미나 예제
VIsual Studio Extensibility [VSX] 1. Visual Studio Extensibility,, 그 시작
VIsual Studio Extensibility Visual Studio 2010 확장 모델인 VSIX 버그
VIsual Studio Extensibility VSGesture v2.0 for VS2010 is now available for download

   

우리 블로그 소식

VSTS 2010 팀 블로그 Visual Studio Team System 2010 공식 팀 블로그 맴버소개
VSTS 2010 팀 블로그 Visual Studio Team System 2010 팀 블로그 소개
VSTS 2010 팀 블로그 VSTS 2010 팀 블로그/스터디 맴버를 모집합니다.
VSTS 2010 팀 블로그 VSTS 2010 팀 맴버 지원을 마감합니다
VSTS 2010 팀 블로그 Visual Studio Team System 2010 Beta 1 공개
VSTS 2010 팀 블로그 [MSDN 주간 세미나] 발표자료 / .NET Framework와 Visual Studio : 현재와 미래 1, 2
VSTS 2010 팀 블로그 VSTS 2010 팀 3분기 맴버 모집
VSTS 2010 팀 블로그 VSTS 2010 팀 세미나 동영상 - 6월 10일
VSTS 2010 팀 블로그 VSTS 2010 팀 맴버 추가 모집
VSTS 2010 팀 블로그 VSTS 2010 팀 트위터를 오픈하였습니다.
VSTS 2010 팀 블로그 TECH DAY 2009 행사 오픈!!!
VSTS 2010 팀 블로그 VSTS 2010 공식 블로그 Viva 2010팀 멤버 추가 모집 공고
VSTS 2010 팀 블로그 [세미나] 차세대 응용 프로그램 구축 방법 및 사례 소개 세미나
VSTS 2010 팀 블로그 Visual Studio 2010 팀에서 팀원 모집합니다.
VSTS 2010 팀 블로그 한국 Visual Studio 2010 사용자를 위한 트위터 커뮤니케이션
VSTS 2010 팀 블로그 C++ 개발자와 함께하는 Visual Studio 2010
VSTS 2010 팀 블로그 [무료 세미나] ReMIX 10
VSTS 2010 팀 블로그 6월 1일, 대한민국 웹 컨퍼런스의 지존 ReMIX 10가 개최됩니다!
VSTS 2010 팀 블로그 REMIX10 의 VS2010 팀 후기
VSTS 2010 팀 블로그 6월 1일, REMIX10 세미나 세션 공개
VSTS 2010 팀 블로그 [세미나] Visual Studio Camp #1
VSTS 2010 팀 블로그 [세미나 후기] Visual Studio Camp #1
VSTS 2010 팀 블로그 [세미나 발표 자료] Visual Studio Camp #1
VSTS 2010 팀 블로그 [세미나] Visual Studio Seminar #1 / 2010년 9월 28일
VSTS 2010 팀 블로그 9월 13일에 개최하는 KGC에서 강연을 합니다.
VSTS 2010 팀 블로그 KGC10에서의 VS2010 스터디 팀의 활약 모습
VSTS 2010 팀 블로그 [VSKOREA] Visual Studio 2010 정보가 한 눈에…
VSTS 2010 팀 블로그 [세미나 후기] Visual Studio Seminar #1
VSTS 2010 팀 블로그 [세미나 발표 자료] Visual Studio Seminar #1
VSTS 2010 팀 블로그 [후기] C++ & 게임 개발자를 위한 개발 생산성 및 퍼포먼스 향상 전략 세미나

   

WCF

WCF WCF란 무엇인가?
WCF 기본 WCF 프로그래밍 - 첫 WCF 서비스 만들기
WCF 기본 WCF 프로그래밍 - 첫 WCF 서비스 만들기 2
WCF WCF의 기본 - Service Contract
WCF WCF의 기본 - Data Contract
WCF WCF 서비스의 동시성(Concurrency) - 1
WCF WCF 서비스의 동시성(Concurrency) - 2
WCF WCF - Serialization
WCF WCF Hosting - WAS를 이용한 Hosting
WCF 도메인을 여러개 등록했을때 WCF 서비스를 호스팅 할수 없어요 ㅠㅠ
WCF WCF Hosting(2) - ASP.NET 호환성(Compatibility)
WCF WCF Hosting (3) - Windows Service를 이용한 Hosting
WCF WCF Security (1) - SSL을 이용한 전송계층에서의 보안 설정
WCF WCF Security (2) - 전송 계층에서의 메세지 인증 (사용자 지정 인증)
WCF WCF Troubleshooting (1)
WCF WCF Service Configuration Editor
WCF WCF Troubleshooting (2)

Posted by 땡초 POWERUMC

댓글을 달아 주세요

  1. 아크몬드 2011.01.11 00:15 Address Modify/Delete Reply

    대박이군요!

  2. 구조신호 2011.06.03 18:09 Address Modify/Delete Reply

    오 한곳에 다 모여있으니 좋네요~~~~!!!!
    감사합니다!!

Microsoft Research 프로젝트로 알아보는 새로운 세대의 시작

Microsoft Research 프로젝트는 Microsoft 에서 진행하는 오픈된 기술과 연구를 하는 R&D 조직으로, 새로운 비즈니스와 기술을 결합하는 프로젝트입니다. 최근 들어 Microsoft Research 사이트의 프로젝트는 작년과 비교해 엄청나게 늘어났습니다. 작년까지만 해도 불과 10~30개의 오픈된 프로젝트가 현재 수백 개의 프로젝트로 늘어난 것이 굉장히 놀랍니다. 그만큼 기술의 트랜드가 빠르게 변한다는 반증이 되겠지요.

Microsoft Research 프로젝트를 열람해 보는 것은 매우 중요합니다. 왜냐하면 당장 2~3년 내에 현실화되는 기술들도 있으며, 현재의 기술이 작년의 Microsoft Research 프로젝트와 통합된 것이 많기 때문이죠. 앞으로 나와는 상관 없는 것들도 있지만, 간접적으로 영향권에 들게 될거라고 생각합니다. 과연 스마트 폰이 어느샌가 내 호주머니 속에 들어가게 될지 모르는 것 처럼 말이죠^^

그럼 Microsoft Research 프로젝트에서 진행하고 있는 재미있는 프로젝트를 소개해 드립니다. 말씀 드렸다시피 이 프로젝트들은 언제 사라질지 모르는 것들이지만, 가치가 있는 것들은 모조리 비즈니스/웹/개발 영역에 접목이 될 수 있습니다.

   

Microsoft Research 진행 프로젝트 소개

A programming language for composable DNA circuits

http://research.microsoft.com/en-us/projects/dna/

이 프로젝트는 프로그래밍 언어의 핵심 로직을 시각화(Visualization)해 주는 프로젝트입니다. 가령 아래와 같은 로직이 있다고 치면, 참 답답하죠. 왜냐하면 제가 무슨 뜻인지 모르니까요^^

directive sample 20000.0 1000

directive plot <kkks t^ kkksr>; <kkppl t^ kkpp x^>; <kpp t^ kppr>;

<kkk t^ kkkr>; <kkl t^ kk x^>; <k t^ kr>; <kkpl t^ kkp x^>; <kp t^ kpr>

directive scale 10.0

def bind = 0.0003 (* /nM/s *)

def unbind = 0.1126 (* /s *)

def Init = 50

def Low = 1

def Excess = 100

   

new x@ bind,unbind

new t@ bind,unbind

   

def SpeciesL(N,al,a) = N * <al t^ a x^>

def SpeciesR(N,a,ar) = N * <a t^ ar>

def BinaryLRxLR(N,al,a,b,br,cl,c,d,dr) = (* A + B ->{N} C + D *)

new i

( constant N * t^*:[a x^ b]<i cl t^ i t^ dr>:t^*

| constant N * Excess * x^*:[b i]:[cl t^]<c x^>:[i]:<d>[t^ dr]

)

   

new e1l new e1 new kkk new kkkr new kkl new kk new k new kr

new e2l new e2 new kkpase new kkpaser new kpasel new kpase

new kkks new kkksr new kkpl new kkp new kkppl new kkpp

new kp new kpr new kpp new kppr

   

( SpeciesL(1,e1l,e1) (* E1 *)

| SpeciesR(10,kkk,kkkr) (* 10 KKK *)

| SpeciesL(100,kkl,kk) (* 100 KK *)

| SpeciesR(100,k,kr) (* 100 K *)

| SpeciesL(1,e2l,e2) (* E2 *)

| SpeciesR(1,kkpase,kkpaser) (* KKPase *)

| SpeciesL(1,kpasel,kpase) (* KPase *)

| BinaryLRxLR(Init,e1l,e1,kkk,kkkr,e1l,e1,kkks,kkksr) (* E1 + KKK ->{r} E1 + KKKs *)

| BinaryLRxLR(Low,e2l,e2,kkks,kkksr,e2l,e2,kkk,kkkr) (* E2 + KKKs ->{r} E2 + KKK *)

| BinaryLRxLR(Init,kkl,kk,kkks,kkksr,kkpl,kkp,kkks,kkksr) (* KK + KKKs ->{r} KKP + KKKs *)

| BinaryLRxLR(Init,kkpl,kkp,kkks,kkksr,kkppl,kkpp,kkks,kkksr) (* KKP + KKKs ->{r} KKPP + KKKs *)

| BinaryLRxLR(Low,kkppl,kkpp,kkpase,kkpaser,kkpl,kkp,kkpase,kkpaser) (* KKPP + KKPase ->{r} KKP + KKPase *)

| BinaryLRxLR(Low,kkpl,kkp,kkpase,kkpaser,kkl,kk,kkpase,kkpaser) (* KKP + KKPase ->{r} KK + KKPase *)

| BinaryLRxLR(Init,kkppl,kkpp,k,kr,kkppl,kkpp,kp,kpr) (* KKPP + K ->{r} KKPP + KP *)

| BinaryLRxLR(Init,kkppl,kkpp,kp,kpr,kkppl,kkpp,kpp,kppr) (* KKPP + KP ->{r} KKPP + KPP *)

| BinaryLRxLR(Low,kpasel,kpase,kpp,kppr,kpasel,kpase,kp,kpr) (* KPase + KPP ->{r} KPase + KP *)

| BinaryLRxLR(Low,kpasel,kpase,kp,kpr,kpasel,kpase,k,kr) (* KPase + KP ->{r} KPase + K *)

)

어찌되었건 이런 코드는 다양한 방법으로 시각화를 해줍니다. 아래는 제가 시뮬레이션해 보니 이런 결과가 나오네요.

중요한 것은 이런 형태의 시각화(Visualization)은 지속적으로 발전하고 있습니다. 모델링(Modeling) 과 DSL(Domain Specifically Language) 의 중요성과 함께 지속적으로 발전하게 될 테니까요.

이 데모는 실버라이트로 작성되어 웹에서 직접 테스트해 보실 수 있습니다. http://lepton.research.microsoft.com/webdna/

   

   

Ajax View

http://research.microsoft.com/en-us/projects/ajaxview/

AJAX 기술로 직격타를 받고 성장한 것이 바로 Web 2.0 입니다. 그리고 Web 2.0을 넘어 Web 3.0이 언급이 되었고, 더 나아가 SNS(소셜 네트워크 서비스)로 발전한 가운데, 가장 영향력을 미친 기술이 AJAX 입니다. 기술적으로 트래픽의 라운드 트립을 줄이고, 분산 아키텍처에 지대한 영향을 미쳤으며, 더 나아가 브라우징(Browsing) 사용성을 극대화한 기술입니다.

하지만 사실상, AJAX 기술은 불필요한 라운드 트립을 증가시킬 수 있는 가장 적절한 수단이기 때문에 잘 사용하는 것이 어려운 기술이기도 합니다. Ajax(Asynchronous JavaScript and XML) 는 순수한 자바스크립트 기술로써 많은 부분을 클라이언트에 의존하지만 자바스크립트와 더불어 HTML CodeDom, XML, DHTML 까지 확장되어 그 영역이 상당하게 복합된 기술이라고 보셔도 됩니다.

   

그렇다면 과연 AJAX 를 어떻게 잘 쓸 것인가에 대한 고민을 이 Ajax View 프로젝트가 도움을 줄 것 같습니다. 이 기술을 중심으로 파생되어 AJAX Performance Profiling, Monitoring 기술의 기반이 되는 것 같습니다. 자세한 내용은 위의 사이트 링크를 참고하세요.

   

Automated Test Generation (ATG)

일찍이 Microsoft 는 1990년대 이후부터 테스팅 기술에 대한 연구를 꾸준히 해온 정통 소프트웨어 기업입니다. 코드 레벨의 테스트는 물론이며, Windows 95 시절에 지원되기 시작한 Plug-and-Plug(하드웨어를 꽂으면 인식하는 기술) 등 상상하지도 못했던 많은 기능을 자동화 테스팅한 기업이기도 합니다. 지금 우리 세대에서 맛보고 있는 테스팅 기술은 Microsoft 의 실제 내부의 기술과는 매우 격차가 있지요. (인정합니다.^^;)

처음 공식적으로 나온 White Box Automation Test 도구인 PEX 가 Visual Studio 2008 시절부터 나오긴 하였지만, 완성된 기술은 아니며 계속 발전하는 기술입니다. PEX 와 관련하여 온라인 세미나를 찍은 것이 있는데 못찾겠군요.;; 대신 아래의 테스팅과 관련된 내용을 참고 하세요.

[ALM-Test] 6. Load Runner vs Visual Studio 2010 테스팅 비교 분석 - http://willstory.tistory.com/4 제공
[ALM-Test] 5. 테스트 계획
[ALM-Test] 4. 테스터(SDET) 의 역할
[ALM-Test] 3. 테스터에 대한 오해와 진실
[ALM-Test] 2. 왜 단위 테스트를 해야 하는가? [2]
[ALM-Test] 1. 왜 단위 테스트를 해야 하는가? [1]
[Testing] Moq.NET (T/B Driven Development)
[Testing] BDD (Behavior-Driven Development–행위 주도 개발)
[Testing] TDD (Test-Driven Development-테스트 주도 개발)

아무튼 이런 테스팅을 위해서 Dynamic Proxy 기술과 Dynamic MSIL Injection 같은 기술이 필요한데, 이미 이런 부류의 닷넷 기술이 존재하긴 합니다. 그 중에 대표적인 것이 Microsoft.CCI 와 Code Contract, Castle Dynamic Proxy, Mono Cecil, Moles 등등등…

하지만 이번 이 프로젝트는 이 기반 기술 들을 통합하려는 의지를 보이는 것 같습니다. 개인적으로 굉장히 기대를 하고 있는 프로젝트이기도 합니다.

   

Code Contracts

http://research.microsoft.com/en-us/projects/contracts/

Code Contracts 는 이미 유명한 기술입니다. 초기에 Microsoft Research 프로젝트로 진행 중이다가 Visual Studio 2008 시절에 릴리즈가 되었으며, .NET Framework 4.0 와 Visual Studio 2010 에는 아예 탑재 시켜버렸습니다. Code Contract 를 직역하면 코드 계약(Code Contract) 인데, 코드간의 명확한 명세를 코드 레벨에서 작성하는 것입니다. 이것도 예전에 온라인 세미나를 했었는데 못찾겠군요;;

명확한 코드 계약이 왜 필요하냐…? 라고 물으신다면 당시 세미나에서 예시를 든 것이, "당신이 회사를 다닌다면 회사와 계약을 합니다. 계약서에는 연봉 정보도 있고, 근태 규칙도 있고 여러 가지가 있습니다..." 마찬가지로 내가 만든 코드를 누군가 써야 할 때 바로 그 명세가 되는 것이 Code Contract 입니다.

이 기술로 파생될 수 있는 기술은 상당히 많습니다. 명확하게 코드를 계약하게 되면 테스트에 굉장히 용이하며, 더 나아가 자동화 테스트(PEX 와 같은)에서 훨씬 여유로워 집니다. 그리고 정적 분석(Static Analytics) 기술과 접목하여 잠재적인 코드의 계약 관계를 파악하여 미리 경고나 오류를 발생해 줄 수 도 있고요.

하지만 저의 경우는 그리 톡톡히 효과를 보지는 못했습니다. 왜냐하면 명확한 계약은 1:1 계약에서 효과가 있지만, 1:N, N:N 간의 계약에서는 그 계약 조건이 명확해 질 수가 없습니다. 현재 나온 PEX 기술과 Code Contract 를 조합하여 계약을 파생시키는 기술적인 부분이 부족하며, 계약의 제약 조건 등 아직은 적극적으로 사용하기에는 부족해 보입니다.

하지만 이 기술을 근간으로 하여 더 효과적인 많은 방법들이 위의 Automated Test Generation (ATG) 프로젝트 등으로 활발히 연구 중이며, 앞으로도 지속적으로 관심을 가질 기술은 분명합니다.

   

Composable Virtual Earth

http://research.microsoft.com/en-us/projects/cve/

제가 설명드릴 만큼 깊이 이해를 못하고 있기 때문에, 참고하세요^^; 중요한 것은 이미지 프로세싱 등의 기술로 효과적으로 운용을 하고자 하는 것 같습니다.

   

DryadLINQ

http://research.microsoft.com/en-us/projects/dryadlinq/

이 프로젝트는 C#의 LINQ+Parallel 기술을 접목하여 분산된 데이터의 접근성을 극대화한 기술입니다. 이미 잘 알고 있는 LINQ 와 .NET 4.0부터 제공되는 TPL(Task Parallel Library)를 이용하여 단순한 분산 데이터에 접근하는 방법입니다. 기존의 LINQ to SQL, Entity Framework 과 같이 단일 데이터 소스가 아닌 클러스터링 된 분산 데이터에 대상이 됩니다.

이 프로젝트는 기존에 존재하는 기술을 접목하여 새로운 기술의 탄생의 근원이기도 합니다. 하지만 생각해보면 분산된, 클러스터링된 데이터를 왜 DryadLINQ 를 써야 할까. 그만큼 대규모의 데이터면 '데이터베이스 관리자를 따로 둘텐데' 말이죠.

제 짧은 소견으로는 분명히 이 기술은 Microsoft Cloud 기술인 Azure 에 접목될 가능성이 농후합니다. 즉, Azure 기반의 클라우드 기술을 엔터프라이즈(Enterprise) 급으로 끌어올릴 수 있는 전략적인 기술이기도 합니다. 이런 부분에서 아직 Azure 는 완성된 기술은 아닙니다. 계속 발전하는 기술이지…

   

Doloto

http://research.microsoft.com/en-us/projects/doloto/

이 프로젝트는 정말인지 기대가 됩니다. 아까 말씀 드린 'Ajax View' 프로젝트와 연관이 있어 보이지만, 이 프로젝트는 나름대로 효과를 톡톡히 보여줄 것 같습니다.

문제는 Web 2.0 은 말씀 드린대로 AJAX 기술과 떨어질 수 없는 관계이기도 합니다. 그런데 데이터 처리를 서버&클라이언트로 분산하면서 결국은 서버를 거치게 되고, 원치않던 라운드 트립은 증가하게 되고, 결국은 사용자의 사용성(광범위한…)은 저하될 수 있습니다. 뭐가 문제일까요? AJAX 가 문제일까, Web 2.0 이 문제일까, 코드가 문제일까, 시스템이 문제일까….

Doloto 는 과분하게도 이런 문제를 큰 고민 없이 해결해 줍니다. 아래는 그래프는 Doloto 를 적용하면 대략 50%에 근사하게 성능이 개선되는 수치입니다. 성능을 개선하기 위해 특별히 코드를 변경할 필요도 없다고 합니다. 그렇다면 연관된 기술은 서버 코드/클라이언트 코드 분석 기술 이외에 캐싱(Caching) 일 텐데…

일단 기대가 됩니다.

   

ExtendedReflection - Dynamic Analysis Framework for .NET

http://research.microsoft.com/en-us/projects/extendedreflection/

이 기술은 'Automated Test Generation (ATG)' 과 없지 않아 연관이 될 수 있을 것 같습니다. 여기에서는 분석 도구라고 설명하지만, 이런 Low-Level의 구현이 가장 잘 되어 있는 프레임워크는 Mono.Cecil입니다. 그러고 보면 약간은 중복성이 있어 보이는 프로젝트이기도 합니다.

적어도 Microsoft.CCI 는 그렇다쳐도 Microsoft.Unity.ObjectBuilder, Castle.DynamicProxy와 Mono.Cecil은 .NET 오픈 소스 중에 가장 대표적인 Dynamic Proxy 및 MSIL 기술인데, 어찌될지 그냥 지켜보고 있습니다.

단순히 기존 존재하는 오픈 소스 대체용도인지, 다양한 기술을 접목하고자 하는 진정한 프레임워크 기반 기술인지는 두고 볼 일입니다.

   

F#

http://research.microsoft.com/en-us/projects/fsharpproj/

깜놀하셨죠? 바로 F# 도 Microsoft Research 에서 태생한 언어입니다. 그냥 그렇다구요^^

   

Graphical tools for text analysis

특별히 아래의 그림만으로 이해하시리라 믿고, 패스!

   

HD View

예전에 Silverlight 의 딥줌(DeepZoom) 을 기억하십니까? 저는 사실 결과물에 대해 다른 것은 없지만, 뭔가 이미지 프로세싱 측면에서 다른 접근 방식을 가지고 가는 것 같습니다. 워낙 자료도 적어서 뭐라고 설명 드리기는 힘들 것 같아요.

다만, 아래의 그림을 보시면 딥줌과 유사하지만, 그래도 유사할 것 같아요^^… 어떤 알고리즘인지가 궁금할 뿐;;

   

HD View SL

위의 'HD View' 의 실버라이트 버전입니다. 참고^^

   

   

정리

Microsoft 는 소프트웨어 개발 기업으로 세계에서 1위 기업입니다. 그 중, Microsoft Research 프로젝트는 여러분들에게 오픈된 프로젝트일 뿐이며, 내부적으로 더 많은 연구가 계속되고 있습니다. 예를 들어, http://codeplex.com 은 여러분들에게 공개된 오픈 소스 커뮤니티지만, Microsoft 내부에는 더 많은 프로젝트들이 수백 개씩 오픈 되어 있습니다. (제가 어떻게 아냐구요? Microsoft 직원이 쓴 책에 그렇다고 말하더군요^^)

다만, 그 중에서 저희에게 오픈된 기술 R&D 영역이 Microsoft Research 프로젝트입니다. 그리고 관심이 없으셔도 상관은 없답니다. 최근 기술 트랜드는 너무나도 빨리 나오고, 변하기 때문에 모두 따라가기가 벅차기도 합니다. 그리고 이 모든 것을 자세하게 알 수 없게 되었습니다. 중요한 것은 내가, 여러분들이 받아들일 기술/트랜드를 준비할 수 있겠지요. 모르고 아는 것과 알고 아는 것은 상당히 다릅니다.

직접적으로 이런 기술들이 나에게는 관련이 없지만, Microsoft 는 비즈니스/웹/시각화/클라우드에 지속적으로 시도를 하는 것을 알 수 있으며, 장차 알게 모르게 도움이 될 거라고 믿습니다. 그리고 이 서비스/기술을 이용하는 사람은 여러분들이 될 수도….^^

Posted by 땡초 POWERUMC

댓글을 달아 주세요

안녕하세요. VSTS 2010 공식 팀에서 Twitter 를 시작했습니다. Twitter 를 통해 차마 시간이 없어 정리하지 못한 정보나 알아두면 좋은 팁과 정보 등을 단문 메시지로 여러분들에게 전달해 드릴 예정입니다.

차세대 플랫폼인 Visual Studio / Team System 2010 등 관심 있는 분들의 많은 Following 을 부탁 드립니다.

http://twitter.com/vsts2010

   

 

   

Posted by 땡초 POWERUMC

댓글을 달아 주세요

  1. 하나둘넷 2009.10.06 23:42 Address Modify/Delete Reply

    트위터에 좋은 내용들이 짧게 올라오네용.. 잘 보고 가요~^^

    • 땡초 2009.10.07 09:17 Address Modify/Delete

      저는 트위터를 twhirl 이라는 클라이언트 어플케이션으로 사용하고 있답니다.
      제가 써 본 것중에는 제일 편하네요.
      http://www.twhirl.org/download

지난 포스트에서 Parallel Extension 과 LINQ 를 이용한 PLINQ 에 대해서 살펴보았습니다. 지난번에 얘기했듯이 Manual Parallelism 는 Parallel Extension 의 성능을 절대 따라올 수 없다고 하였습니다. 왜냐하면, Parallel Extension 은 Manual Parallelism 의 병렬 처리 방식보다 더 복잡하고 정밀한 병렬 처리 알고리즘으로 처리하기 때문입니다.
 
Parallel Extension 이란?
 
Parallel Extension 은 전혀 새로운 것이 아닙니다. C# 3.0 의 LINQ 는 LINQ 쿼리식을 제공하기 위해 새로운 컴파일러(Compiler) 가 필요했습니다. 정확히 말하자면 C# 의 Language Service 의 버전이 업그레이드 되었고, LINQ 쿼리식을 편하게 쓸 수 있도록 Visual Studio 2008 을 사용해야 했습니다. 다시 말하자면, LINQ 쿼리식이 아닌 확장 메서드(Extension Methods) 만으로 쿼리가 가능했다는 것이 이것을 증명해 줍니다. 확장 메서드(Extension Methods) 는 결국 IL 레벨에서는 정적(Static) 인 인스턴스(Instance) 에 불과하니까요.
 
Parallel Extension 은 새로운 컴파일러(Compiler) 가 필요하지 않습니다. .NET 의 기본적인 코어(Core) 인 mscorelib.dll, System.dll, System.Core.dll 만을 사용하여 구현이 되었습니다. 그리고, 기존의 ThreadPool 을 개선하였고, LINQ 와 통합하여 선언적으로 Parallel Extension 을 사용할 수도 있게 되었죠.
 
Task Parallel Library 를 통해 데이터 처리와 어떤 작업(Task)에 대해서도 병렬 처리도 가능해 졌습니다. 이제는 데이터의 병렬 처리뿐만 아니라, 작업(Task) 단위로서도 Task Parallel Library 로 병렬 처리가 가능합니다.
 
이제는 병렬 처리가 된다는 것이 중요한 게 아니라, 병렬 처리의 내부적인 예외 핸들링이나 Visual Studio 에서 디버깅(Debugging) 이 가능합니다. 이러한 새로운 매커니즘으로 내부적으로는 새로운 예외 핸들링 모델(Exception Handling Model)이 필요했습니다.
 
또한 .NET Framework 4.0 의 Parallel Extension 은 다양한 언어를 지원합니다. C#, VB.NET, C++, F# 그리고 .NET 컴파일러(Compiler) 로 컴파일(Compile) 되는 언어라면 상관없습니다. RoR/PHP 라도 .NET 컴파일러(Compiler)에 의해 컴파일(Compile) 된다면 Parallel Extension 을 사용하는데 전혀 문제가 없습니다.
 
 
Parallel Extension 아키텍처
 
 
[그림1] Parallel Extension 아키텍처 (클릭하면 확대)
 
Parallel Extension 의 병렬 처리는 .NET 컴파일러(Compiler) 로 컴파일(Compile) 되는 어떤 언어든 차별을 두지 않고, 병렬 처리 기능을 사용할 수 있습니다. PLINQ 로 작성된 쿼리(Query)는 별도의 PLINQ Provider 의 엔진(Engine) 에서 쿼리를 분석하는 과정을 거치게 됩니다. 쿼리 분석(Query Analysis) 에 의해 선언된 LINQ 쿼리식을 분석하여 최적의 알고리즘으로 각각의 작업을 배치하게 됩니다.
 

[그림2] Parallel Extension 작업 분할
 
각각 분배되는 작업은 쓰레드 큐(Thread Queue) 에 쌓이고, 이 큐에 쌓이는 작업(Task) 는 실제 작업자 쓰레드(Worker Thread) 에 할당이 됩니다. 하지만, Parallel Extension 은 단지 쓰레드에 할당하는 것으로 작업이 마치기를 기다리지 않습니다. 만약, 작업을 분배하는 것은 Manual Parallel 과 크게 다르지 않기 때문이죠.
 

[그림3] Parallel Extension 작업 분할
 
Parallel Extension Library 는 병렬 처리의 작업을 지속적으로 최적의 상태를 감시합니다. 예를 들어, A 의 작업이 Task 1, Task 2, Task 3 인데, B 의 작업은 모두 마친 상태라고 할 때, Parallel Extension Library 는 A 의 작업을 놀고 있는 B 에게 또 다시 분배합니다. 이러한 반복적으로 병렬 처리의 작업이 최적화 될 수 있도록 하여, 병렬 처리의 성능을 극한으로 끌어올립니다.
 
LINQ 만 알면 난 병렬 처리 개발자
 
Parallel Extension 은 LINQ 와 통합하기 위한 프로바이더(Provider) 를 제공합니다. 아직 LINQ 잘 모르신다구요? 30분만 투자하시면 LINQ 를 사용하는데 큰 지장이 없습니다. 그리고 그만큼 쉽습니다. LINQ 를 이해하기 위해 제네릭(Generic), 확장 메서드(Extension Methods), 익명 타입(Anonymous Methods) 도 함께 공부하시면 좋습니다.
 
예전에 이런 광고도 있었죠.
“비트 박스를 잘하려면?” “북치기, 박치기만 잘하면 됩니다”
 
“그럼 PLINQ 개발자가 되기 위해서는?” “AsParallel() 만 잘하면 됩니다.”
 
맞습니다. Parallel Extension Library 의 AsParallel() 확장 메서드(Extension Methods) 만 알면 당신도 이제 병렬 처리 개발자입니다. 이전 포스트의 PLINQ 예제에서 처럼 AsParallel() 만 붙이면 그것을 PLINQ 라고 부릅니다^^ (병렬 처리를 위한 확장 메서드와 옵션은 더 많이 존재합니다 )
 
아래는 AsParallel() 의 예 입니다.
private static void ParallelSort(List<Person> people)
{
       var resultPerson = from person in people.AsParallel()
                                    where person.Age >= 50
                                    orderby person.Age ascending
                                    select person;
 
       foreach (var item in resultPeople) { }
}
 
하지만, 무조건적인 병렬 처리는 오히려 성능을 저하시킬 수 있습니다. 특히 PLINQ 를 사용하는 병렬 처리는 .NET Framework 내부적으로 쿼리 분석(Query Analysis) 과정을 거치게 됩니다. 각각 프로세서(Processor) 에 분배된 데이터는 또 분배되고, 최적화가 가능할 때까지 계속적으로 분배됩니다. 마치 세포 분할이 일어나는 것처럼 말이죠.
 
최소한 병렬 처리를 위해서 데이터에 대한 이해와 추측이 가능해야 합니다.
 
1.     추측 가능한 데이터의 양
2.     추측 가능한 데이터의 내용
3.     추측 가능한 데이터 처리 시간
 
이러한 최소한의 예측 작업을 하지 않는다면, 오히려 PLINQ 를 이용할 때 성능은 저하될 수 있습니다. 예를 들어, 평균 데이터의 양이 2개라고 가정한다면, PLINQ 의 쿼리 분석(Query Analysis) 작업은 오히려 성능 저하의 요인이 됩니다. PLINQ 쿼리 분석(Query Analysis) 에 의해 두 번째 프로세서(Processor) 의 사용량이 많다고 판단된다면, 병렬 작업은 의미가 없어지고 오히려 성능을 저하시킬 테니까요. ‘쿼리 분석(Query Analysis) 작업이 눈 깜빡 거리는 시간(1/40(0.025)초) 이라고 가정한다면, 만 건의 쿼리 분석(Query Analysis) 작업 시간은 250초’가 될 테니까요.

Posted by 땡초 POWERUMC

댓글을 달아 주세요

최근 대부분의 사용자들의 컴퓨터의 사양이 코어2 로 업그레이드 되고 있습니다. CPU 제품에 따라 코어에 대한 아키텍처가 다르지만, 기본적으로 이들 제품은 하나의 컴퓨터에 CPU 가 두 개인 제품들입니다. 인간과 비교하자면 뇌가 두 개인 사람인데 그다지 상상해서 떠올리고 싶지 않네요^^.

컴퓨터는 CPU 두 개를 보다 효율적으로 이용하기 위해 바로 Parallelism Processing(병렬 처리)를 하게 됩니다. 하나의 CPU 의 성능을 향상시키는 방법이 아닌, 두 개의 CPU 에게 작업을 할당함으로써 데이터의 처리 성능을 극대화 시키게 됩니다. 우리에게 익숙한 운영체제인 윈도우(Windows) 의 멀티 쓰레딩(Multi Threading) 을 생각하면 병렬 처리(Parallelism Processing) 는 그렇게 어려운 개념은 아닙니다.
 
[그림1] 어쨌든 뇌가 두 개 (여기에서 참조)
 
원래 오픈 소스 프로젝트로 Parallel Extension 프로젝트를 CodePlex 에서 본 기억이 있는데, 지금은 링크의 주소를 찾을 수 가 없네요. 구글을 통해 “Parallel Extension” 을 검색하시면, .NET 에서의 Parallel Programming 의 흔적을 찾아볼 수 있습니다.
 
우선 아래의 Person 클래스를 작성하여 테스트에 사용할 것입니다.
 
class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}
 
 
General~
 
코어(Core) 하나로 작업할 경우, 개발자는 아무것도 염려 하지 않아도 됩니다. 그 동안 우리가 배웠던 대로 코드를 작성하기만 하면 됩니다. 병렬 처리에 대한 고민을 하지 않고 개발한 코드라면 모두 이 범주에 속하겠네요. 이러한 방법은 가장 보편적으로 작성할 수 있습니다.
 
private static void GeneralSort(List<Person> people)
{
       List<Person> resultPeople = new List<Person>();
       foreach (Person person in people)
       {
             if (person.Age >= 50)
                    resultPeople.Add(person);
       }
 
       resultPeople.Sort((p1, p2) => p1.Age.CompareTo(p2.Age));
 
       foreach (var item in resultPeople) { }
}
 
List<Person> 개체를 파라메터로 넘겨주고, Person 중에 Age 가 50이 넘는 개체를 정렬하는 코드입니다.
바로 이 코드를 병렬 처리를 하고자 합니다. 이 코드를 병렬 처리를 하고자 한다면 코드의 양은 훨씬 늘어나고, 복잡한 처리를 해야 합니다.
 
 
Manual Parallelism
 
일반적으로 데이터의 처리를 병렬 처리로 전환하기 위해서는 쓰레드(Thread) 를 사용합니다. 쓰레드(Thread) 가 생성이 되면 커널 또는 물리적인 프로세서에 의해 의해 유휴 상태 또는 처리가 가능한 코어(Core) 로 작업이 할당되어 다중 작업(Multi Process) 을 가능하게 됩니다.
 
이러한 방법의 병렬 처리는 프로세서(Processor) 개수만큼 쓰레드(Thread) 를 생성하여 비동기 작업을 합니다.
 
private static void ThreadSort(List<Person> people)
{
       var resultPeople = new List<Person>();
       int partitionsCount = Environment.ProcessorCount;
       int remainingCount = partitionsCount;
       var enumerator = (IEnumerator<Person>)people.GetEnumerator();
       try
       {
             using (var done = new ManualResetEvent(false))
             {
                    for (int i = 0; i < partitionsCount; i++)
                    {
                           ThreadPool.QueueUserWorkItem(delegate
                           {
                                 var partialResults = new List<Person>();
                                 while (true)
                                 {
                                        Person baby;
                                        lock (enumerator)
                                        {
                                              if (!enumerator.MoveNext()) break;
                                              baby = enumerator.Current;
                                        }
                                        if (baby.Age >= 50)
                                        {
                                              partialResults.Add(baby);
                                        }
                                 }
                                 lock (resultPeople) resultPeople.AddRange(partialResults);
                                 if (Interlocked.Decrement(ref remainingCount) == 0) done.Set();
                           });
                    }
                    done.WaitOne();
                    resultPeople.Sort((p1, p2) => p1.Age.CompareTo(p2.Age));
             }
       }
       finally
       {
             if (enumerator is IDisposable) ((IDisposable)enumerator).Dispose();
       }
 
       foreach (var item in resultPeople) { }
}
 
중요한 부분은 추출된 데이터의 정렬(Sort) 작업입니다. 이 작업을 하기 위해서는 모든 쓰레드(Thread) 의 작업이 끝나야 합니다. 만약 모든 쓰레드(Thread) 가 종료되지 않은 시점에서 정렬 작업을 하게 되면, 과연 정렬된 데이터를 신뢰할 수 있을까요?? ( 왜 그런지는 여러분의 상상에 맡기도록 합니다. )
 
정렬 작업을 하기 전 ManualResetEvent 의 WaitOne() 메서드를 호출하여 모든 쓰레드(Thread) 의 WaitHandle 이 작업이 신호를 받을 때까지(동기화 작업) 기다려야 합니다. 예를 들어, 두 개의 쓰레드(Thread) 가 생성 되고 첫 번째 쓰레드는 이미 작업을 종료하였지만, 두 번째 쓰레드는 아직 작업이 완료되지 않았다면, 작업을 마친 모든 쓰레드(Thread) 는 가장 늦게 처리가 완료되는 쓰레드를 기다려야 정렬 작업을 진행할 수 있습니다.
 
마지막으로, 위의 코드의 병렬 처리 작업은 성능에 한계가 있습니다. 프로세서(Processor) 개수만큼 쓰레드(Thread) 를 생성하여 작업을 분배하는 방식이기 때문에, 병렬 처리 작업의 성능은 곧 프로세서(Processor) 개수가 될테니까요!
 
 
Parallel Extension
 
C# 4.0 은 병렬 처리를 하기 위해 코드의 양을 획기적으로 줄일 수 있습니다.
 
private static void ParallelSort(List<Person> people)
{
       var resultPerson = from person in people.AsParallel()
                                    where person.Age >= 50
                                    orderby person.Age ascending
                                    select person;
 
       foreach (var item in resultPeople) { }
}
 
LINQ 식을 사용하여 데이터 처리와 정렬 작업을 간단하게 할 수 있습니다. 감격이네요^^ 바로, .NET Framework 4.0 의 Parallel Extension 을 사용하여 LINQ 처럼 사용하는 것을 PLINQ 라고 합니다.
 
Q : foreach (var item in resultPeople) { } 코드를넣었나요?
 
A: 동일한 테스트를 하기 위함입니다. LINQ 식은 내부 구조의 특성상 “쿼리식”에 불과합니다.
보다 자세한 내용은 필자의 블로그를 참고하세요.
 
Parallel Extension 은 Manual Parallelism 보다 더 복잡하고 좋은 성능을 낼 수 있는 알고리즘으로 구현이 되어 있습니다. 그렇기 때문에 아무리 많은 코어를 가진 컴퓨터에서 동일한 테스트를 한다고 하여도 결코 Manual Parallelism 은 Parallel Extension 의 병렬 처리 성능을 기대할 수 없습니다.
 
이제 살며시 그 내부 구조도 궁금해 집니다. (다음에 계속…)
Posted by 땡초 POWERUMC

댓글을 달아 주세요

가끔씩 GAC 에 등록되어 있는 Assembly 의 DLL 이 필요할 수 있습니다. 하지만 일반적으로 윈도우 탐색기를 통해 GAC 폴더를 탐색하게 되면, 파일을 복사할 수 없는 형태의 View 가 뜨게 됩니다.
 
[그림1] 윈도우 탐색기를 통해 보는 GAC Assembly 목록
 
이런 경우엔 Visual Studio 에서 GAC Assembly 를 참조하고, 파일 복사(File Copy) 옵션을 “예(Yes)” 로 주시면, GAC 의 DLL 의 복사본이 떨어지긴 합니다. 하지만, 매우 번거로운 작업입니다.
 
GAC Assembly 폴더는 어디에 있나요??
%WINDIR%\Assembly 폴더에 있습니다.
 
하지만, 간단하게 레지스트리의 값을 수정하여 GAC Assembly 의 폴더를 구조적으로 탐색할 수 있네요.
 
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Fusion\DisableCacheViewer=1 (DWORD)
 
위와 같이 레지스트리를 추가하시고 GAC Assembly 폴더를 열면, GAC Assembly 를 윈도우 탐색기를 통해 Assembly 별, Version 별로 탐색이 가능합니다.
 
[그림2] 윈도우 탐색기를 통해 GAC Assembly 탐색
 
아무튼 이런 숨은 옵션들이 왜이리 많은지 ^^; 이런 숨은 옵션 가이드 문서는 어디 없나?? 시간 나면 찾아봐야겠습니다. ^^
 
References
 

Posted by 땡초 POWERUMC
TAG c#, GAC

댓글을 달아 주세요

C# 코드로 GAC 어셈블리 등록하기
 
예전에 MSDN Forum 에 자료를 찾던 중에 “C# 코드를 이용하여 GAC 에 어셈블리를 등록할 수 없나요?” 라는 질문을 본적이 있었습니다.
아마, 그때 답변은 엉뚱한 답변들이었죠. 물론, 저도 오늘의 이 코드를 보기 전까지 말이죠^^;
 
희미하게 기억이 날듯 말듯 합니다만, 그때 답변중의 내용이 RegisterAssembly 였던 것 같기도 합니다. 이 메서드는 COM Interop 에 등록하는 메서드인데 말이죠.. ㅎㅎ
 
그래서 혼자 생각했었습니다.
배포 시에 GAC 에 어셈블리를 등록할 경우가 생긴다면,,
1.      GacUtil 을 리소스에 포함한다.
2.      Deploy Project 에서 리소스를 파일로 복원하여, Command Prompt(Process.Start) 를 통해 GACUTIL 로 등록하고,
3.      배포를 종료한다
 
이런 시나리오를 머리 속으로 그렸던 적이 있었습니다.
하지만 오늘 단 한 줄이 이 코드를 보고, ‘정말 어리석었구나’ 느꼈답니다.
 
뭐 긴말 없이, 코드를 보시죠.
 
new System.EnterpriseServices.Internal.Publish()
.GacInstall(@”...Path...\ClassLibrary1.dll");
 
이렇게 한 줄로, GAC 에 어셈블리를 등록할 수 있었답니다. ( 두 줄이라고 우기지 마세요 -_-; )
 
아마 저처럼 테스트 해 보실 분도 계실 거라고 생각합니다. 10의 2~3명은 “어!! 안되는데요!!” 라고 하실겁니다.
Strong Key 를 주시고, 다시 해보세요^.^
( 훔… Strong Key 로 서명이 안되어 있어도, 오류는 없더군요 )
 
머.. 뒷북이라면 당신은 대략 “지못미!!”
 
Reference
 

Posted by 땡초 POWERUMC
TAG c#, GAC

댓글을 달아 주세요

Task Parallel Library
 
Parallel Extension 은 PLINQ 와 더불어 확장 가능한 Task Parallel Library 를 제공합니다. Task Parallel Library 는 PLINQ 를 이용하지 않고 개별적이고 수동적인 병렬 처리 작업을 위해 사용할 수 있습니다.
 
Task Parallel Library 는 크게 세 가지 방법으로 병렬 처리를 위한 Library 를 제공합니다.
 
Loops
 
[그림1] Parallel.For 를 이용한 병렬 처리
 
[그림2] Parallel.Foreach 를 이용한 병렬 처리
 
Task Parallel Extension 으로 병렬 처리를 쉽게 처리할 수 있으며, 병렬 처리로 인자값을 넘기거나 하는 작업을 쉽게 할 수 있습니다.
 
Statements
 
 
[그림3] Parallel.Invoke 를 이용한 병렬 처리
 
 
Task
 
특히 Parallel Extension Library 에서 Task 는 수동적으로 병렬 처리를 하기 위해 다양한 기능을 지원합니다. 정교하게 스레드(Thread) 를 처리했던 것에 비하면 심플하고도 직관적으로 병렬 작업을 처리할 수 있습니다.
 
Task 는 보다 정교하게 병렬 처리 작업을 할 수 있습니다.
l 대기
l 취소
l 연장
l 상하(부모/자식) 간의 관계
l 디버그 지원
 
아래는 ThreadPool.QueueUserWorkItem 처럼 바로 작업을 시작하도록 합니다.
 
Task.StartNew(…);
 
아래는 Task 에 대해 대기 및 취소 작업을 진행하도록 합니다.
 
Task t1 = Task.StartNew(…);
t1.Wait();
t1.Cancel();
Task t2 = t1.ContinueWith(…);
 
아래는 작업에 대해 지속적인 병렬 처리를 가능하도록 합니다.
 
var p = Task.StartNew(() => {
    var c = Task.StartNew(…);
}
 
아래는 특정 작업의 결과를 받아 올 수 있습니다.
 
var p =
 Future.StartNew(() => C());
int result = p.Value;
 
 
 
Coordination Data Structures
 
병렬 처리 작업은 PLINQ 와 TPL(Task Parallel Library) 를 지원하기 위해 기존의 데이터 컬렉션 등이 등장하였습니다. 내부적으로 동기화를 지원하지 않았던 문제들을 지원하게 되었고, 특히 오늘날 멀티 코어(Multi Core) 프로세스를 위해 많은 동기적인 문제를 고민해야 했습니다. .NET Framework 4.0 은 이러한 공통적인 문제들을 해결하기 할 수 있습니다.
 
l Thread-safe collections
       ConcurrentStack<T>
       ConcurrentQueue<T>
       ConcurrentDictionary<TKey,TValue>
      
l Work exchange
       BlockingCollection<T>
       IProducerConsumerCollection<T>
l Phased Operation
       CountdownEvent
       Barrier
l Locks
       ManualResetEventSlim
       SemaphoreSlim
       SpinLock
       SpinWait
l Initialization
       LazyInit<T>
       WriteOnce<T>

Posted by 땡초 POWERUMC

댓글을 달아 주세요




 
 
ButtonEx 컨트롤의 활용
5회차에서 빡시게 ButtonEx 서버 컨트롤을 만들어 보았습니다. 취소 가능한 이벤트를 통해 만든 서버 컨트롤을 활용할 수 있는 샘플을 보도록 하겠습니다.
 
여기서 만들어 볼 샘플은 유효성체크(Validate Check) 입니다. TextBox 컨트롤에 입력된 문자가 숫자인지 판별하는 간략한 샘플이지만, 어떻게 Before/After 이벤트를 분리하여 구현하는지 잘 보여주는 샘플이라고 생각합니다.

[그림1] 웹 폼 구성
 
아래의 소스는 int.Parse 메서드를 통해 숫자가 아닐 경우 Cancel = true 를 통해 After 이벤트를 취소하는 예제입니다.
namespace WebApplication4
{
        public partial class _Default : System.Web.UI.Page
        {
 
               protected void Page_Load(object sender, EventArgs e)
               {
               }
 
               protected void ButtonEx1_BeforeClick(object
sender,Sample.ButtonEx.BeforeClickEventArgs e)
               {
                       try
                       {
                              int.Parse( TextBox1.Text ); // 입력한값이숫자가아니라면 Exception 발생하겠죠?
                              Response.Write( TextBox1.Text + " 입력하였습니다<br/>");
                       }
                       catch
                       {
                              Response.Write("숫자만입력하세요");
                              e.Cancel = true;
                       }
               }
 
               protected void ButtonEx1_AfterClick(object sender,
Sample.ButtonEx.AfterClickEventArgs e)
               {
                       Response.Write("입력한값은숫자가맞습니다");
               }
        }
}
 
[그림2] 실행 결과
 
어떤가요? .NET Framework 은 이벤트 프로그래밍이라는 말이 과언이 아니라고 생각합니다. 이벤트는 .NET 프로그래밍에 있어서 굉장히 유용한 것 같네요. 두서 없이 아티클을 적어 보긴 했지만, 이미 필요한 분에게 많은 도움이 되었을 거라 생각합니다. 그럼 안녕^^//
Posted by 땡초 POWERUMC
TAG c#, Event

댓글을 달아 주세요




 
 
실전 취소 가능한 버튼 컨트롤 만들기
 
Umc.Core.EventHandlerDictionary 클래스
이 클래스는 Umc.Core 프로젝트에 포함된 클래스 입니다. 이 클래스의 이름에서 알 수 있듯이 이벤트를 사전(Dictionary)로 관리하도록 하기 위한 클래스 입니다.
 
namespace Umc.Core
{
        ///<summary>
        /// Umc.Core<br/>
        /// Delegate 담는 EventHandlerDictionary 컬렉션
        ///</summary>
        public class EventHandlerDictionary : IDisposable
        {
               ///<summary>
               /// Umc.Core<br/>
               /// Event 담는컬렉션
               ///</summary>
               private Dictionary<object,Delegate> eventDictionary = new Dictionary<object,Delegate>();
 
               ///<summary>
               /// Umc.Core<br/>
               /// EventHandlerDictionary EventHandler 추가한다.
               ///</summary>
               ///<param name="key">키값</param>
               ///<param name="value">Delegate</param>
               public void AddHandler(object key, Delegate value)
               {
                       if ( eventDictionary.ContainsKey(key) )
                       {
                              eventDictionary[key] = Delegate.Combine(eventDictionary[key], value);
                       }
                       else
                       {
                              eventDictionary[key] = value;
                       }
               }
 
               ///<summary>
               /// Umc.Core<br/>
               /// EventHandlerDictionary EventHandler 제거한다.
               ///</summary>
               ///<param name="key">키값</param>
               ///<param name="value">Delegate</param>
               public void RemoveHandler(object key, Delegate value)
               {
                       if ( eventDictionary.ContainsKey(key) )
                       {
                              eventDictionary[key] = Delegate.Remove(eventDictionary[key], value);
                       }
               }
 
               public bool Contains(object key)
               {
                       return this.eventDictionary.ContainsKey(key);
               }
 
               ///<summary>
               /// Umc.Core<br/>
               /// EventHandlerDictionary 인덱서
               ///</summary>
               ///<param name="key"></param>
               ///<returns></returns>
               public Delegate this[object key]
               {
                       get { return eventDictionary[key]; }
                       set { eventDictionary[key] = value; }
               }
 
               #region IDisposable 멤버
               ///<summary>
               /// Umc.Core<br/>
                /// EventHandlerDictionary 자원을해제한다.
               ///</summary>
               public void Dispose()
               {
                       if( eventDictionary != null )
                              eventDictionary.Clear();
 
                       eventDictionary = null;
               }
               #endregion
        }
}
 
클래스 내부에는 Dictionary 제네릭 클래스의 오브젝트를 생성하여, AddHandler(), RemoveHandler() 를 통해 이벤트를 사전에 추가/삭제 하는 로직이 들어있습니다.
 
 
ButtonEx 네임스페이스
Click 이벤트 전/후에 발생할 이벤트의 인자를 전달한 EventArgs 클래스 입니다. 이미 지난 회차를 보신 분이라면 그렇게 생소하지 않을 것입니다.
///<summary>
/// Before 이벤트가발생할전달될이벤트인자클래스입니다.
///</summary>
public class BeforeClickEventArgs : CancelEventArgs
{
        public string Reason { get; set; }
}
 
///<summary>
/// After 이벤트가발생할전달될이벤트인자클래스입니다.
///</summary>
public class AfterClickEventArgs : EventArgs { }
 
또한, 직관적인 코딩을 위해 Before/After 이벤트를 위한 델리게이트를 선언하였습니다. 특별한 변경된 EventArgs 와 같은 인자가 없다면 기존 EventHandler 를 활용해도 되지만, 언제든 추후에 확장될 가능성은 충분하다고 생각합니다. 그렇기 때문에 델리게이트를 선언해 주었답니다.
///<summary>
/// BeforeClick 이벤트를캡슐화하는델리게이트입니다.
///</summary>
///<param name="sender"></param>
///<param name="e"></param>
public delegate void BeforeClickEventHandler(object sender, BeforeClickEventArgs e);
///<summary>
/// AfterClick 이벤트를캡슐화하는델리게이트입니다.
///</summary>
///<param name="sender"></param>
///<param name="e"></param>
public delegate void AfterClickEventHandler(object sender, AfterClickEventArgs e);
 
여기서 이벤트는 사전(Dictionary) 을 통해 이벤트를 관리하게 됩니다. Umc.Core 프로젝트에 사용되는 EventHandlerDictionary 클래스의 일부를 직접 예제 클래스에 포함한 것입니다. 이 EventHandlerDictionary 에 접근하기 위한 Events 프로퍼티를 선언하였습니다.
private EventHandlerDictionary events;
///<summary>
/// EventHandlerDictionary 통해이벤트를관리합니다.
///</summary>
protected EventHandlerDictionary Events
{
        get
        {
               if( events == null )
                       events = new EventHandlerDictionary();
 
               return events;
        }
}
 
여기에서 선언된 이벤트는 EventHandlerDictionary 클래스에서 관리하게 될 것이기 때문에, event 선언에 대해 커스트마이징(?)이 필요합니다. 즉, 이벤트의 추가/삭제에 대한 액션을 변경할 필요가 있습니다.
private object EVENT_BEFORE_CLICK     = new object(); // BeforeClick 이벤트오브젝트
private object EVENT_AFTER_CLICK      = new object(); // AfterClick 이벤트오브젝트
 
///<summary>
/// BeforeClick 이벤트입니다. Click 이벤트가발생하기전에발생합니다.
///</summary>
[Description("Click 이벤트가발생하기전에발생합니다")]
public event BeforeClickEventHandler BeforeClick
{
        add
        {
               this.Events.AddHandler(EVENT_BEFORE_CLICK, value);
        }
        remove
        {
               this.Events.RemoveHandler(EVENT_BEFORE_CLICK, value);
        }
}
 
///<summary>
/// AfterClick 이벤트입니다. Click 이벤트가발생한발생합니다.
///</summary>
[Description("Click 이벤트가발생후에발생합니다")]
public event AfterClickEventHandler AfterClick
{
        add
        {
               this.Events.AddHandler(EVENT_AFTER_CLICK, value);
        }
        remove
        {
               this.Events.RemoveHandler(EVENT_AFTER_CLICK, value);
        }
}
 
여기는 각각의 Before/After 이벤트를 발생하는 메서드와 CancelEventArgs 의 Cancel 프로퍼티를 검사하는 메서드가 존재합니다. OnEventsFire() 메서드를 눈여겨 보시면 될 것 같습니다.
///<summary>
/// BeforeClick 이벤트를발생합니다.
///</summary>
///<param name="sender"></param>
///<param name="e"></param>
protected virtual void OnBeforeClick(object sender, BeforeClickEventArgs e)
{
        if( !this.Events.Contains( EVENT_BEFORE_CLICK ) ) return;
 
        BeforeClickEventHandler handler       =
this.Events[ EVENT_BEFORE_CLICK ] as BeforeClickEventHandler;
        if( handler != null )
               handler(sender, e);
}
 
///<summary>
/// AfterClick 이벤트를발생합니다.
///</summary>
///<param name="sender"></param>
///<param name="e"></param>
protected virtual void OnAfterClick(object sender, AfterClickEventArgs e)
{
        if( !this.Events.Contains(EVENT_AFTER_CLICK) ) return;
 
        AfterClickEventHandler handler =
this.Events[ EVENT_AFTER_CLICK ] as AfterClickEventHandler;
        if( handler != null )
               handler(sender, e);
}
 
///<summary>
/// Click 이벤트가발생할경우 BeforeClick/AfterClick 이벤트를발생합니다.
///</summary>
///<param name="sender"></param>
protected virtual void OnEventsFire( object sender )
{
        BeforeClickEventArgs beforeArgs       = new BeforeClickEventArgs();
        OnBeforeClick( sender, beforeArgs );
 
        if( beforeArgs.Cancel ) return;
 
        AfterClickEventArgs afterArgs = new AfterClickEventArgs();
        OnAfterClick( sender, afterArgs );
}
 
[Obsolete("ButtonEx 컨트롤에서는 Click 이벤트를사용하지않도록합니다. 대신 AfterClick 이벤트를사용하세요")]
protected override void OnInit(EventArgs e)
{
        base.OnInit(e);
        this.Click += new EventHandler(ServerControl1_Click);
}
 
private void ServerControl1_Click(object sender, EventArgs e)
{
        OnEventsFire(sender);
}
 
이제 간략한 소스 코드 설명은 끝났네요. 힘들게 만든 ButtonEx 서버 컨트롤을 어떻게 활용하면 될지 다음 회차를 참고하세요.
Posted by 땡초 POWERUMC
TAG c#, Event

댓글을 달아 주세요




 
 
CancelEventArgs 클래스
CancelEventArgs 는 .NET Framework 이 제공하는 클래스 입니다. 이 클래스는 특정한 기능의 구현이 된 것이 아니라, 몇 가지 프로퍼티가 제공이 되는 것 뿐입니다.
 
CancelEventArgs 클래스의 메타 데이터를 보면 두 개의 생성자와 Cancel 프로퍼티를 제공하는 것을 알 수 있습니다.
 
[그림1] CancelEventArgs 클래스 메타데이타
 
 
예제
그럼 한번 취소 가능한 이벤트를 작성해 보겠습니다.
 
우선 이벤트가 사용할 대리자를 선언해 보았습니다. AfterEventHandler 의 경우 특별히 지정하지 않아도 되지만, 직관적으로 코딩이 나름대로 편하기 때문에 선언해 보았답니다.
public delegate CancelEventHandler BeforeEventHandler(object sender, CancelEventArgs e);
public delegate EventHandler AfterEventHandler(object sender, EventHandler e);
 
다음은 Sample 클래스의 모든 소스를 한번에 보도록 하겠습니다.
 
public class Sample
{
        private object EVENT_BEFORE_EVENT     = null; // Before 이벤트객체
        private object EVENT_AFTER_EVENT      = null; // After 이벤트객체
 
        // 이벤트의수가많아경우, 대부분의이벤트가사용되지않을것이라고예상될경우유용한방법이다.
        // 다음회차에자세히알아보자.
        public event CancelEventHandler BeforeEvent
        {
               add
               {
                       EVENT_BEFORE_EVENT     =
(CancelEventHandler)EVENT_BEFORE_EVENT + value;
               }
               remove
               {
                       EVENT_BEFORE_EVENT     =
(CancelEventHandler)EVENT_BEFORE_EVENT - value;
               }
        }
 
        public event EventHandler AfterEvent
        {
               add
               {
                       EVENT_AFTER_EVENT      = (EventHandler)EVENT_AFTER_EVENT + value;
               }
               remove
               {
                       EVENT_AFTER_EVENT      = (EventHandler)EVENT_AFTER_EVENT - value;
               }
        }
 
        // Before 이벤트를발생한다. private 메서드에주의
        private void OnBefore(object sender, CancelEventArgs e)
        {
               CancelEventHandler handler = (CancelEventHandler)EVENT_BEFORE_EVENT;
 
               if( handler != null )
                       handler(sender, e);
        }
 
        // After 이벤트를발생한다. private 메서드에주의
        private void OnAfter(object sender, EventArgs e)
        {
               EventHandler handler          = (EventHandler)EVENT_AFTER_EVENT;
 
               if( handler != null )
                       handler( sender, e);
        }
 
        // Before, After 이벤트를발생하여 Before 이벤트의 Cancel 여부를판단한다.
        public void OnFire(object sender)
        {
               CancelEventArgs args          = new CancelEventArgs();
               this.OnBefore(sender, args);
 
               if( args.Cancel ) return;
 
               this.OnAfter(sender, EventArgs.Empty);
        }
}
 
여기서 event 를 선언하는 코드가 약간 생소하네요.
 
public event CancelEventHandler BeforeEvent { add; remove; }
 
이 구문은 대부분의 이벤트가 사용하지 않을 것으로 예상될 경우 이벤트의 추가/삭제를 커스트마이징 할 수 있기 때문에 굉장히 효율적인 방법입니다. 여기에서 이벤트는
 
EVENT_BEFORE_EVENT
 
오브젝트(object) 를 통해 추가/삭제 되는 것을 알 수 있습니다. 즉, EVENT_BEFORE_EVENT 오브젝트는 이벤트의 키 값이라고 보셔도 무방할 것 같네요.
 
OnBefore(), OnAfter() 와 같이 실제로 이벤트를 발생하는 메서드는 이미 1,2 회차에서 자주 보셨을 거라 생각합니다. 실제로 가장 중요한 구문은 OnFire() 메서드 입니다. OnFire() 메서드는 참조 타입(클래스)인 CancelEventArgs 클래스의 인스턴스를 생성하여 OnBefore() 메서드에게 넘겨주고 있습니다. Before 이벤트의 실제 구현부가 실행되고 CancelEventArgs 의 Cancel 프로퍼티가 True 가 될 경우 조건문에 의해 더 이상 After 이벤트가 실행되지 않도록 return 이 된답니다.
 
소스 코드에 주석을 잘 보시면서 차근차근 생각하시면 이해가 되실 겁니다.
 
Default.aspx.cs
[그림2] default.aspx 실행결과
 
만약, Before 이벤트 중 이벤트의 진행을 취소하고 싶다면 Cancel 프로퍼티를 True 설정하는 것만으로 이벤트의 진행의 취소가 가능합니다.
 
[그림3] Cancel 프로퍼티를 True 로 설정한 실행결과

Posted by 땡초 POWERUMC
TAG c#, Event

댓글을 달아 주세요


 
 
1,2 회 이벤트에 대해 잘 알아 보셨는지요. 이번 3회차 에서는 1,2회차에 비해 난이도가 월등히 높아지게 됩니다. 반드시 이벤트를 정복하고자 한다면 1,2 회차를 직접 코드로 작성해 보며 이벤트에 대한 감각을 익히세요.
 
취소 가능한 이벤트
아마도 윈폼을 조금이라도 해 보신 분이라면, FormClosing/FormClosed 이벤트를 보신적이 있을 것입니다. 이 이벤트 중 FormClosing 은 폼이 닫히기 전에 발생하는 이벤트로 FormClosed 이벤트가 발생하는 것을 방지할 수 도 있답니다. 바로 이것이 취소 가능한 이벤트 입니다.(제가 붙혀서 부르는 것임 +_+)
 
아래의 간략한 윈폼 소스를 보면 알 수 있을 것입니다.
 
[그림1] FormClosing/FormClosed 예제
 
FormClosing 과 FormClosed 는 폼이 닫힐 때 차례로 발생하는 것을 알 수 있습니다.
 
[그림2] FormClosing/FormClosed 이벤트
 
하지만, 만약 CancelEventArgs 에서 제공하는 Cancel 프로퍼티를 True 로 설정할 경우 FormClosing 이후 FormClosed 이벤트를 실행되지 않습니다.
 
[그림3] CancelEventArgs 의 Cancel 프로퍼티를 True 로 설정한 경우
 
위와 같이 Cancel 프로퍼티를 True 로 설정한 경우 더 이상 FormClosed 이벤트는 발생하지 않게 되며, 폼 또한 종료하게 되지 않습니다.
 
[그림4] FormClosed 가 발생하지 않는 예제
 
이렇게 특정 이벤트가 발생하기 위해 Before/After(전후) 의 처리가 필요한 이벤트의 경우 After 이벤트를 발생하지 않도록 함으로써 Before 이벤트의 활용도가 많아진다.
 
이러한 Before 이벤트는 여러 가지 용도로 사용할 수 있습니다.
l 하나의 이벤트 구현에 들어갈 내용을 Before/After 단계로 구분하여 작성할 수 있습니다.
l Before 이벤트에서 유효성 검사를 실시하여, 이벤트의 진행/취소 유무를 결정할 수 있습니다.
 
대략 위 두 가지 정도가 가장 많이 활용될 수 있을 것 같습니다.
 
실제로 여러 상용 컨트롤에서는 위와 같은 Before/After 와 같은 굉장히 방대한 이벤트를 제공해 줍니다. 하나의 이벤트로 처리될 것이 두 개의 Before/After 이벤트로 제어할 수 있게 되면 보다 직관적이고 구현을 분리하여 작성하는데 도움이 됩니다.
 
다음 회차에 이러한 취소 가능한 이벤트를 만들어 보도록 하겠습니다.
Posted by 땡초 POWERUMC
TAG c#, Event

댓글을 달아 주세요



 
 
우리는 전편에서 이벤트의 간략한 소개와 예제를 통해 이벤트의 사용 방법을 익혀보았습니다. 이번편 부터는 이벤트를 활용할 수 있는 예제들을 중심으로 소개하려고 합니다. 아마 그동안 이벤트가 뭉게구름처럼 정확하게 머리 속에 그려지지 않았다면, 이번 예제들을 통해 확실히 이벤트의 개념에 대해 알 수 있을 것 같습니다.
 
 
유저컨트롤에서 페이지로 값 전달
1편에서 선언부와 구현부의 분리로 점차적으로 프로그램을 보다 융통성 있게 만들 수 있다고 하였습니다.  페이지로 값을 이벤트를 통해 전달하는 방법을 살펴보겠습니다.
 
우선 우리가 사용할 이벤트 인자를 넘길 ReceiveEventArgs 클래스를 만들 것입니다. 이 ReceiveEventArgs 는 이벤트가 발생할 때 이벤트가 전달하는 Argument(인자)를 전달받을 수 있기 위함입니다.
 
받을 인자는 간단한 string 값으로 하겠습니다.
 
ReceiveEventArgs.cs
public class ReceiveEventArgs : EventArgs
{
        public string Item { get; set; }
}
 
유저컨트롤을 만들기 전에 UserControlBase 를 만들 것입니다. 이 UserControlBase 에는 기본적인 델리게이트와 이벤트를 선언하고 이벤트를 발생시키는 메서드가 포함이 됩니다.
 
UserControlBase.cs


public delegate void ReceiveEventHandler(object sender, ReceiveEventArgs e);
 
public class UserControlBase : System.Web.UI.UserControl
{
        public event ReceiveEventHandler ReceiveEvent;
 
        protected void OnRecevieEvent(object sender, ReceiveEventArgs e)
        {
               if( ReceiveEvent != null )
                       ReceiveEvent( sender, e);
        }
}
 
복잡하게 생각할 것 없이, 1편에서 보던 간략한 예제를 클래스 별로 분리하였다고 보시면 됩니다.
 
그럼 이제 유저컨트롤을 만들어 보겠습니다. 유저컨트롤에는 RadioButtonList 를 두고 아이템을 선택 후 전달 버튼을 누르면 이벤트를 발생하는 부분이 포함될 것입니다.
 
WebUserControl1.ascx.cs
public partial class WebUserControl1 : UserControlBase
{
        protected void Page_Load(object sender, EventArgs e) { }
 
        protected void Button1_Click(object sender, EventArgs e)
        {
               OnRecevieEvent(sender,
new ReceiveEventArgs{ Item=RadioButtonList1.SelectedItem.Text });
        }
}
 
보시는 것과 같이 버튼을 클릭하였을 때, OnReceiveEvent 를 발생하는 메서드를 호출하여 RadioButtonList 에서 선택된 아이템의 텍스트를 인자 값으로 전달합니다.
 
이제 default.aspx.cs 를 만들어 보겠습니다. 여기의 코드도 무척 심플하네요.
 
Default.aspx.cs
public partial class _Default : System.Web.UI.Page
{
        protected void Page_Load(object sender, EventArgs e)
        {
               this.ucWebUserControl1.ReceiveEvent +=
new ReceiveEventHandler(ucWebUserControl1_ReceiveEvent);
        }
 
        void ucWebUserControl1_ReceiveEvent(object sender, ReceiveEventArgs e)
        {
               string msg     = string.Format("선택된아이템은 {0} 입니다",e.Item);
               lbl.Text       = msg;
        }
}
 
 
결과 화면을 보겠습니다.
[그림2] 실행화면
 
글 만으로 잘 이해가 안되시면 첨부 파일을 다운로드 하여 한번 살펴보시면 좋을 것 같습니다.
Posted by 땡초 POWERUMC
TAG c#, Event

댓글을 달아 주세요



실전 event 목차
 
 
이벤트란 무엇인가?
이벤트는 간단히 말하자면 특정 사건이 발생했음을 알리는데 사용됩니다. Page_Load 되었을때 Page_Load 이벤트가 발생할 것이고, 버튼을 클릭했을 경우 _Click 이벤트가 발생할 것입니다. 예를 들어, 내 여자친구의 생일날이 오면 생일 이벤트가 발생할 것이고, 12월 25일 크리스마스가 오면 크리스마스 이벤트가 발생할 것입니다.
 
점차적으로 프로그램의 복잡성이 증가함에 따라 이벤트를 굉장히 유용하게 사용될 수 있습니다. 대리자를 통해 메서드의 형식을 캡슐화할 수 있기 때문에, 선언부와 구현부를 따로 분리할 수 있기 때문입니다. 단지, 우리는 이벤트의 발생을 알리기만 하면 될 뿐이니까요.
 
 
이벤트 만들기
이벤트는 대리자(Delegate) 와 떨어질 수 없는 관계입니다. 바로 이벤트는 이 대리자를 통해 메서드의 구현을 실행시키게 되는 것이기 때문입니다. 하지만 이곳에서는 대리자에 대한 설명은 하지 않을 것입니다^^;
 
이벤트는 선언을 하는 것만으로 하나의 이벤트가 완성됩니다.
 
event EventHandler Event;
 
굉장히 간단하지 않습니까? 이벤트의 선언은 위와 같이
 
event 키워드 + 대리자 + 이벤트 이름
 
이렇게 3가지만 알고 있으면 이벤트가 완성됩니다.
 
참고 : EventHandler 대리자는 다음과 같이 정의 되었습니다.
public delegate void EventHandler(object sender, EventArgs e);
 
 
실전 기초 예제
그럼 어디서나 볼 수 있는 간단한 예제를 한번 만들어 보겠습니다.
 
우선 폼에 버튼을 하나 올려 놓았습니다.

[그림1] 웹폼에 버튼 컨트롤을 올림.
 
아래 소스는 Delegate 와 event 를 선언하고 이벤트를 발생하는 모든 과정을 구현한 것입니다. 별거 아니죠??
 
public partial class _Default : System.Web.UI.Page
{
        delegate void MyEventHandler();
        event MyEventHandler MyEvent;
 
        void OnMyEvent()
        {
               if( MyEvent != null )
                       MyEvent();
        }
 
        protected void Page_Load(object sender, EventArgs e)
        {
               this.MyEvent += new MyEventHandler(_Default_MyEvent);
        }
 
        protected void Button1_Click(object sender, EventArgs e)
        {
               OnMyEvent();
        }
 
        void _Default_MyEvent()
        {
               Response.Write("MyEvent 발생하였습니다");
        }
}
 
실행결과는 더욱 더 별거 아닙니다.
 
[그림2] 실행결과
 
만약 위 소스가 이해가 안되신다면, 절대로 다음 회차를 보지 마시고, 다음의 사이트를 통해 대리자와 이벤트에 대한 기초 문법을 더 익히시기 바랍니다.
 
소설 같은 자바
http://www.jabook.org/
 
훈스 닷넷
http://www.hoons.kr/Lectureview.aspx?key=Lecture&LECCATE_IDX=7&ref=1&lecture_idx=208
http://www.hoons.kr/Lectureview.aspx?key=Lecture&LECCATE_IDX=7&ref=1&lecture_idx=209
Posted by 땡초 POWERUMC
TAG c#, Event

댓글을 달아 주세요

이미 C# 3.0 에서 LINQ to Sql 란 말은 자주 들어 보았을 것이다. 많은 세미나 또는 블로그 포스트에서 LINQ to Sql 의 쿼리가 MSSQL 프로필러를 통해 실행되는 모습을 익히 보았을 것이다.
하지만 LINQ to Sql 을 이용하여 쿼리가 되는 것을 기록할 필요가 있다. 쿼리가 수행되는 시간, 쿼리 되는 빈도나 부하 등을 유지보수 하기 위해서 반드시 이 쿼리들이 로그에 기록되어야 한다.
 
그럼 오늘은 이 LINQ to Sql 이 어떻게 로그를 남기고 어떻게 로그에 기록하면 될지 알아보자.
 
먼저 콘솔 프로젝트를 만들어보자.
우선 LINQ to Sql 항목을 추가하고, [그림1] 과 같이 서버탐색기를 통해서 데이터베이스의 테이블을 끌어놓자. 여기서 사용하는 테이블은 UmcBlog 실제 웹서버 테이블을 끌어놓아 보았다 +_+
 
[
그림1] 서버탐색기를 통해 테이블을 추가함.
 
콘솔 프로젝트의 소스는 아래와 같이 무척 간단하다.
 
[
그림2] 콘솔 프로젝트 소스
 
그리고 데이터베이스의 DataContext 객체를 생성하면, 위와 같이 Log 프로퍼티가 제공될 것이다. Log 프로퍼티는 Stream 을 받을 수 있는 프로퍼티이다. Console.Out 을 통해 Console Output Stream 을 넣어보았다.
 
[
그림3] 콘솔 프로젝트 실행 결과
 
Console Output Stream 을 통해 LINQ to Sql 쿼리는 SQL Server 의 프로필러로 보내지는 쿼리를 콘솔에서도 확인할 수 있다.
 
그렇다면 이 Stream 을 텍스트 파일로 Log 를 남기는 것은 생각보다 간단하다.
아래는 웹 프로젝트로 만든 소스이다.
 
[
그림4] 웹 프로젝트 소스
 
[
그림5] 웹 프로젝트 실행 결과
 
[
그림6] Log.txt 에 LOG 가 남겨진다.
 
 
서버가 실행되는 위치에 StreamWriter 객체를 이용해 “Log.txt” 라는 텍스트 파일로 남길 수가 있다.
 
writer.Close()
 
라는 맨 마지막 줄의 빨간 밑줄이 보일것이다. 바로, Stream 을 반드시 닫아 주어야 한다. 그렇지 않으면 로그 파일을 열려있는 채로 프로세서가 잡아놓고 있을 테니 말이다.
UmcBlogDataContext 와 리플랙터로 DataContext 를 확인한 결과 Log 프로퍼티로 제공되는 Stream 은 닫혀지지 않기 때문에 반드시 Stream 을 닫아 주어야 한다.
 
그렇다면 개발자는 매번 이 Stream 을 생성하고 닫아주는 코드를 작성해야 하는 것일까? 그렇지 않다.
이 로그를 자동화 하는 방법이 있다.
 
[
그림7] UmcBlogDataContext 의 Base Class 지정하는 속성창
 
위와 같이 친절하게도 LINQ to Sql 디자이너는 생성된 DataContext 개체의 Base Class 를 지정할 수 있도록 되어 있다. 그럼 우리는 Base DataContext 가 될 수 있는 클래스를 이곳에서 상속받아 로그의 기록을 자동화 하도록 만들면 된다. 

음.. 다음에 기회가 된다면 DataContext 를 상속받아 로깅하는 간단한 예제를 만들어 보도록 하자. 텨텨텨 =3=3=3

Posted by 땡초 POWERUMC

댓글을 달아 주세요

LINQ TO Sql 은 데이터베이스를 엑세스 하고 쿼리하는데 데이터베이스와 어플케이션간에 많은 장벽을 없애버렸다. 바로 어플케이션에서 쉽게 SQL 쿼리를 사용할 수 있기 때문이다.
하지만, 이와 같이 장벽이 사라진 만큼 데이터베이스와 어플케이션의 더욱 더 깊은 이해가 요구 되어야 더욱 더 섬세하고 좋은 성능을 낼 수가 있을 것이다.
 
 
일반적인 데이터엑세스 과정
 
 
대략 위와 같은 논리적인(또는 물리적인) 3 Layer 형태가 갖추어 질 것이다.(위 그림 정말 못그렸다.;;)
그렇다면 LINQ TO Sql 의 사용은 Data Access Layer 가 가장 적절할 것 같다.
LINQ TO Sql 클래스를 만들어, 비쥬얼하게 멋진 다이어그램과 사용할 프로시져를 끌어다 놓는 것 만으로 SqlParameter 를 만드는 귀찮은 작업은 생략될 수 있을 것이다.
 
그렇다면 왜 Data Access 에서만 LINQ TO Sql 을 사용해야 할까
 
이유는 간단하다. 바로 디스어셈블러 때문이다.
데이터베이스의 ConnectionString 은 자동으로 app.config 에 기어 들어간다고 쳐도, 데이터베이스의 테이블 스키마와 관계 등이 그대로 노출 될 수 있다.

다음은 LINQ TO Sql 이 만들어 주는 Entity 클래스의 일부이다.
 
 
아래는 LINQ 쿼리가 어떻게 디스어셈블리 되는지 보여준다.
 
var joinList = from c in db.Comments
              group c by c.ArticleNo into g_c
              join a in db.Articles on g_c.Key equals a.ArticleNo
              orderby g_c.Key ascending
              select new
              {
                        g_c.Key,
                        a.Title,
                        CommentCount = g_c.Count()
              };
var joinList = db.Comments.GroupBy<Comment, int>(Expression.Lambda<Func<Comment, int>>(Expression.Property(CS$0$0000 = Expression.Parameter(typeof(Comment), "c"), (MethodInfo) methodof(Comment.get_ArticleNo)), new ParameterExpression[] { CS$0$0000 })).Join(db.Articles, Expression.Lambda<Func<IGrouping<int, Comment>, int>>(Expression.Property(CS$0$0000 = Expression.Parameter(typeof(IGrouping<int, Comment>), "g_c"), (MethodInfo) methodof(IGrouping<int, Comment>.get_Key, IGrouping<int, Comment>)), new ParameterExpression[] { CS$0$0000 }), Expression.Lambda<Func<Article, int>>(Expression.Property(CS$0$0000 = Expression.Parameter(typeof(Article), "a"), (MethodInfo) methodof(Article.get_ArticleNo)), new ParameterExpression[] { CS$0$0000 }), Expression.Lambda(Expression.New((ConstructorInfo) methodof(<>f__AnonymousType0<IGrouping<int, Comment>, Article>..ctor, <>f__AnonymousType0<IGrouping<int, Comment>, Article>), new Expression[] { CS$0$0000 = Expression.Parameter(typeof(IGrouping<int, Comment>), "g_c"), CS$0$0002 = Expression.Parameter(typeof(Article), "a") }, new MethodInfo[] { (MethodInfo) methodof(<>f__AnonymousType0<IGrouping<int, Comment>, Article>.get_g_c, <>f__AnonymousType0<IGrouping<int, Comment>, Article>), (MethodInfo) methodof(<>f__AnonymousType0<IGrouping<int, Comment>, Article>.get_a, <>f__AnonymousType0<IGrouping<int, Comment>, Article>) }), new ParameterExpression[] { CS$0$0000, CS$0$0002 })).OrderBy(Expression.Lambda(Expression.Property(Expression.Property(CS$0$0000 = Expression.Parameter(typeof(<>f__AnonymousType0<IGrouping<int, Comment>, Article>), "<>h__TransparentIdentifier0"), (MethodInfo) methodof(<>f__AnonymousType0<IGrouping<int, Comment>, Article>.get_g_c, <>f__AnonymousType0<IGrouping<int, Comment>, Article>)), (MethodInfo) methodof(IGrouping<int, Comment>.get_Key, IGrouping<int, Comment>)), new ParameterExpression[] { CS$0$0000 })).Select(Expression.Lambda(Expression.New((ConstructorInfo) methodof(<>f__AnonymousType1<int, string, int>..ctor, <>f__AnonymousType1<int, string, int>), new Expression[] { Expression.Property(Expression.Property(CS$0$0000 = Expression.Parameter(typeof(<>f__AnonymousType0<IGrouping<int, Comment>, Article>), "<>h__TransparentIdentifier0"), (MethodInfo) methodof(<>f__AnonymousType0<IGrouping<int, Comment>, Article>.get_g_c, <>f__AnonymousType0<IGrouping<int, Comment>, Article>)), (MethodInfo) methodof(IGrouping<int, Comment>.get_Key, IGrouping<int, Comment>)), Expression.Property(Expression.Property(CS$0$0000, (MethodInfo) methodof(<>f__AnonymousType0<IGrouping<int, Comment>, Article>.get_a, <>f__AnonymousType0<IGrouping<int, Comment>, Article>)), (MethodInfo) methodof(Article.get_Title)), Expression.Call(null, (MethodInfo) methodof(Enumerable.Count), new Expression[] { Expression.Property(CS$0$0000, (MethodInfo) methodof(<>f__AnonymousType0<IGrouping<int, Comment>, Article>.get_g_c, <>f__AnonymousType0<IGrouping<int, Comment>, Article>)) }) }, new MethodInfo[] { (MethodInfo) methodof(<>f__AnonymousType1<int, string, int>.get_Key, <>f__AnonymousType1<int, string, int>), (MethodInfo) methodof(<>f__AnonymousType1<int, string, int>.get_Title, <>f__AnonymousType1<int, string, int>), (MethodInfo) methodof(<>f__AnonymousType1<int, string, int>.get_CommentCount, <>f__AnonymousType1<int, string, int>) }), new ParameterExpression[] { CS$0$0000 }));
 
일일이 탭도 맞추고 정렬한 후에야 비로소 볼만 하겠지만, 조막만한 쿼리가 어쨌든 알아보긴 힘들지만 역어셈블리가 되었다.
그렇다면 충분히 어셈블리의 IL 코드를 조작하여, 원하는 데이터를 리턴시키기엔 충분할 것이다. (쉽지 않겠지만^^;)
 
위의 무지막지한 디스어셈브리 코드를 보면, LINQ TO Sql 의 성능마저 궁금하게 만든다.
하지만, 성능 테스트는 다음으로 슬쩍 미루도록 해야겠다. (음하하;;)
왜냐하면 난 소중하니까 ^^
Posted by 땡초 POWERUMC

댓글을 달아 주세요

우리는 C# 3.0 에 확장 메서드(Extension Methods) 가 언어적으로 지원된다는 말은 수없이도 들어보았다. 확장 메서드는 기존 C# 2.0 에 비해 굉장히 파격적이다. 추후 확장 프로퍼티와 확장 이벤트 등도 지원된다고 하니, 가히 언어적으로 파격적이다.
 
 
확장 메서드의 문제점
 
확장 메서드는 굉장히 파격적이다. 내가 C# 2.0 을 하면서 감히 이런 언어적 지원이 가능하리라곤 상상도 못했으니 그 아이디어 적이 면만으로도 충분히 놀랄만 하다.
확장 메서드는 원본 타입의 Type 에 따라 지원된다.
하지만, 자주 사용되는 string, int, bool 등과 같은 타입에 확장 메서드를 추가하게 되고, 프레임웍이 커짐에 따라 이런 확장 메서드의 양도 무한대(?)로 커질 가능성이 충분히 있다.
 
확장 메서드는 기본적으로 자신이 속한 namespace 에 한해 Intelisense 에 표시된다. 즉, 다른 namespace 의 확장 메서드를 사용하고 싶다면 using 문을 추가하면 된다.
바로, 여기에서 문제점이 도출된다.
기존 Utility 성격의 메서드나 해당 namespace 에 존재하는 많은 메서드들이 확장 메서드로 마이그레이션이 가능하다는 것이다.
C# 에서는 수많은 namespace 가 존재하고, 수많은 클래스가 존재한다. 만약, using 문을 추가해 다른 namespace 의 확장메서드를 사용하려 했으나, 중복되는 경우도 생길것이며, 구현하려는 기능이 일반 static 메서드였는지, 확장 메서드였는지 조차 기억하기엔 너무나도 번거로운 작업이 될 것이다.
 
일반적인 확정 메서드가 구현되는 상황을 보도록 하자.
 
class Program
    {
        static void Main(string[] args)
        {
                     string encrypt = "AAA".Encrypt();
 
                     Console.WriteLine(encrypt);
        }
    }
 
static class MyExtender
{
           public static string Encrypt(this string arg)
           {
                     return arg + "는 암호화 됨.(MyExtender)";
           }
}
 
Encrypt 메서드는 특정 문자열을 암호화 하는 확장 메서드이다. (암호화 코드가 있다는 가정임)
 
즉, 해당 클래스가 속해있는 namespace 에 한해 확장 메서드를 구현하고, 만약 다른 namespace 의 확장 메서드가 필요하게 되면 using 네임스페이스; 구문을 추가하여 다른 namespace 영역의 확장 메서드를 끌어다 쓰면 되는 것이다.
 
만약, using 문이 추가되면 될수록 우리가 기억 해야할 확장 메서드의 양은 얼마만큼 많아 지게 될지 알 수 없다.
 
수많은 고민을 통해 “모든 확장 메서드는 하나의 namespace 안에서 관리하자” 라는 생각을 해보았다. 즉, 확장 메서드가 필요하면 using 구문 하나만으로 모든 확장 메서드를 호출할 수 있도록 하는 구성이다.
하지만, 여기에 결정적인 단점이 있다. 이 부분은 뒷부분에 다시 설명 하도록 하겠다.
 
 
 
확장 메서드(Extension Methods) 설계
 
 
위 그림과 같이 확장 메서드를 지원하는 별도의 폴더와 namespace 를 만들었다.
이 namespace 는 솔루션 또는 프레임웍이 사용하는 모든 확장 메서드를 한군데에 모아 놓기 위한 namespace 이다.
 
즉,
 
using Umc.Core.Extender;
 
구문 하나만으로 모든 확장 메서드를 활용할 수 있다.
 
그럼 SecurityExtender.cs 파일과 TextExtender.cs 파일을 연속으로 보도록 하자.
본 소스는 예제용으로 제공되는 소스이니 크게 비중을 두지 말고 보도록 하자.
 
namespace Umc.Core.Extender
{
           public static partial class SecurityExtender
           {
                     public static Security.Security Security(this string arg)
                     {
                                return new Umc.Core.Security.Security(arg);
                     }
           }
}
 
namespace Umc.Core.Extender
{
           public static partial class TextExtender
           {
                     public static Umc.Core.Text.Text Text(this string arg)
                     {
                                return new Umc.Core.Text.Text(arg);
                     }
           }
}
 
위 두 클래스는 동일한 namespace 안에 존재하게 되며, 특히 partial 클래스로 선언되어 언제 어디서든 동일한 namespace 와 class 명을 갖게 된다면 확장 및 기능 추가가 가능하도록 했다.
 
아직 리턴 타입의 클래스 구현을 확인하진 못했지만, 어느정도 객체지향 프로그램을 해 본 사람이라면 일찌감치 감을 잡았을 것이라고 생각한다.
 
위 두 클래스가 지원하는 확장 메서드의 원본 타입은 string 이 되며, 해당 확장 메서드의 리턴 타입은 또 다른 인스턴트형의 클래스이다.
 
위처럼 구현한 이유는 확장 메서드를 쩜(.)을 찍고 구현할 수 있도록 소위 Depth(깊이)를 준 것이다. 여기에서 말하는 소위 Depth 라고 함은 다음의 그림을 보면 쉽게 이해가 갈 것이다.
 

 
위와 같이 해당 확장 메서드에서 쩜(.) 을 누르는 순간 새로운 메서드들이 Intelisense 에 나타나게 된다.
 
 
개발자 입장에서는 이렇게 직감적으로 코딩을 가능하게 하는 것도 “사용자 경험(UX)” 라고 말하고 싶다.
 
이렇게 설계가 가능하다면, 다음과 같이 최소한의 확장 메서드로 다양한 기능을 추가할 수 있다는 것이다.
 
그럼, Security 와 Text 클래스가 어떻게 구현되었는지 연속적으로 보도록 하자.
 
namespace Umc.Core.Security
{
           public class Security
           {
                     // SourceString 이 private 이므로 Object Initializer 를 사용할 수 없다.
                     public Security(string str)
                     {
                                this.SourceString = str;
                     }
 
                     // 암호화할 문자열
                     private string SourceString { get; set; }
 
                     public string Encrypt()
                     {
                                // 암호화 알고리즘이라고 가정.
                                return SourceString + "는 암호화 됨.";
                     }
 
                     public string Decrypt()
                     {
                                // 복호화 알고리즘이라고 가정.
                                return SourceString + "는 복호화 됨.";
                     }
           }
}
 
namespace Umc.Core.Text
{
           public class Text
           {
                     public Text(string str)
                     {
                                this.SourceString = str;
                     }
 
                     private string SourceString { get; set; }
 
                     public string Left(int len)
                     {
                                return SourceString.Substring(0, len);
                     }
 
                     public string Right(int len)
                     {
                                return SourceString.Substring(SourceString.Length - len , len);
                     }
 
                     // 기존 확장메서드 방식으로 인스턴스를 리턴하여 호출할 방법이 없음.
                     public static string Test()
                     {
                                return string.Empty;
                     }
           }
}
 
 
 
특히나 interface 를 통한 확장 메서드의 구현은 그 진가를 십분 발휘하게 될 것임이 분명하다.
그렇지만, 이러한 편리한 설계임에도 불구하고 단점이 존재하게 된다.
 
 
확장 메서드 설계의 문제점
 
바로 static 메서드로 구현된 메서드는 호출할 뾰족한 방법이 없다.
위의 확장 메서드의 설계 에서 보듯이, 구현된 클래스는 반드시 인스턴스를 생성하여 사용할 수 있도록 구성되었다.
 
아래와 같이
 
 
처럼 static 으로 구현된 메서드는 인스턴스를 생성하여도 호출할 방법이 없다.
우리가 설계한 확장 메서드는 생성자에 인자값을 전달하는 형식이지만, 더군다나 static 메서드는 생성자에 인자값을 전달한다고 하더라도, 생성자가 전달한 인자값을 활용할 방법이 없다는 것이다. 아마도 이 부분은 확장 프로퍼티라는 개념이 C# 3.0 정식 버젼에서 지원하느냐, 어떻게 지원하느냐가 관건이 될 것 같다.
 
 
마치며
 
C# 3.0 의 Lambda, LINQ, Extension Methods 는 새로 등장하는 시스템의 설계에 엄청난 파장을 불러 일으킬만한 이슈이다. 아직 완벽하게 완성된 C# 3.0 은 아니지만, 분명한 것은 수많은 Language(언어) 들의 표본이 C# 3.0 이 될 것이 분명하다.(이렇게 말하니 무슨 홍보대사 같네 ㅋ)
정식 C# 3.0 의 모습을 기대하면서 이만 ^^//
Posted by 땡초 POWERUMC

댓글을 달아 주세요

[.NET/C# 3.0] - 람다식(Lambda Expressions) 을 이용한 확장 메서드(Extension Methods) 만들기 [1]
[.NET/C# 3.0] - 람다식(Lambda Expressions) 을 이용한 확장 메서드(Extension Methods) 만들기 [2]
 
 
 
지난 아티클에서 우리는 List<> 컬렉션에 특정 요소를 탐색하기 위해 delegate 와, 익명 메서드, 람다식을 이용한 방법을 알아보았다.
 
List<> 컬렉션의 Find와 FindAll 메서드는 List<> 클래스가 제공하는 메서드지만, 이와 비슷한 확장 메서드를 손수 구현해 보도록 할 것이다.
 
 
이번에도 다음의 List<> 컬렉션의 데이터를 가지고 예제를 만들어 볼 것이다.
 
List<int> arr = new List<int>();
arr.Add(1);
arr.Add(2);
arr.Add(3);
arr.Add(4);
 
지난 강좌에서 보듯 다음과 같이 List<> 클래스의 Find 메서드를 이용하여 특정 요소를 탐색한다.
 
int result = arr.Find(o => o == 2);
Console.WriteLine(result);
 
 
 
List<Int>.Find 메서드를 확장 메서드로 구현
 
확장 메서드를 구현하기 위해 MyExtension 이라는 클래스를 만들고 UmcFind 라는 메서드를 만들자.
 
static class MyExtension
{
           public static int UmcFind(this IEnumerable<int> arr, Predicate<int> p)
           {
                     List<int> ret = new List<int>();
                     foreach (var v in arr)
                     {
                                if (p(v))
                                          return v;
                     }
 
                     return 0;
           }
}
 
위 확장 메서드는 다음과 같이 호출이 가능하다.
 
int result = arr.UmcFind(o => o == 2);
Console.WriteLine(result);
 
 
Public static int UmcFind(this IEnumerable<int> arr, Predicate<int> p)
 
의 선언을 보자.
 
인자값에 오는 this 는 확장메서드를 지원할 원본 객체의 타입이다. 즉, 우리는 List<int> 에 대한 객체에만 확장 메서드를 지원하게 된다.
 
Predicate<Int> p
 
는 .NET Framework 에서 선언된 bool 을 리턴하는 델리게이트이다.
 
즉, o => o == 2 람다식의 “ o == 2 “ 의 구현부는 Predicate 델리게이트에게 위임된 것이다.
때문에,
 
if( p( v ) )
 
와 같이 Predicate 의 리턴이 bool 이므로 람다식의 조건을 True/False 로 리턴 받을 수 있다.
 
 
 
List<Int>.FindAll 메서드를 확장 메서드로 구현
 
아래와 같이 사용되는 List<int>.FindAll 메서드를 확장 메서드로 구현해 보자.
 
List<int> result = arr.FindAll(o => o >= 2 && o <= 3);
result.ForEach(o => Console.WriteLine(o));
 
 
이번에는 .NET Framework 가 제공하는 델리게이트를 사용하지 않고, 직접 델리게이트를 선언해 볼 것이다.
 
delegate TResult FindAllHandler<T, TResult>(T t);
 
FindAll 확장 메서드를 구현하기 위해 제네릭 델리게이트를 선언해 보았다.
첫번째 T 는 받을 인자 타입이고, 두번째 TResult 는 리턴 타입이 된다.
 
그럼 UmcFindAll 이라는 확장 메서드를 만들어 보자.
 
static class MyExtension
{
           public static List<int> UmcFindAll(
            this IEnumerable<int> arr, FindAllHandler<int,bool> p)
           {
                     List<int> result = new List<int>();
 
                     foreach (var v in arr)
                     {
                                if( p(v) )
                                          result.Add( v );
                     }
                     return result;
           }
}
 
위의 확장 메서드는 다음 처럼 사용이 가능하다.
 
List<int> list = arr.UmcFindAll(o => o >= 2 && o <= 3);
list.ForEach(o => Console.WriteLine(o));
 
 
 
보시는 바와 같이 List<> 클래스가 제공하는 FindAll 메서드와 동일한 기능을 하는 확장 메서드를 만들어보았다.
 
UmcFindAll 확장 메서드는 제네릭 델리게이트를 선언하여 예제를 만들어 보았지만, UmcFind 확장메서드를 유심히 본 독자라면 보는데 큰 어려움이 없을 것 같다.
 
 
이것으로. 람다식의 간략한 이용 방법과 람다식을 사용하는 확장 메서드에 대해서 알아 보았다.
Posted by 땡초 POWERUMC

댓글을 달아 주세요

  1. 상준 2011.03.24 14:17 Address Modify/Delete Reply

    글 너무 너무 잘봤습니다.
    하지만 이해하기 너무 힘드네요...
    실례지만 해당 소스코드도 있었으면..
    더좋은 글이 되지 안을까 생각합니다..

[.NET/C# 3.0] - 람다식(Lambda Expressions) 을 이용한 확장 메서드(Extension Methods) 만들기 [1]
[.NET/C# 3.0] - 람다식(Lambda Expressions) 을 이용한 확장 메서드(Extension Methods) 만들기 [2]



C# 3.0 에서 LINQ 를 위해 많은 언어적 개념이 도입되었다.
확장 메서드(Extension Methods)와 Lambda Expression 등이 바로 그것이다.
그중 Lambda Expression(이하 람다식) 은 Ruby 에서 먼저 나왔다고 하지만, C# 3.0 에서의 람다식은 LINQ 와 확장 메서드와 굉장히 사슬처럼 엮여 있는 듯한 모습이다.
 
람다식은 대리자(Delegate)와 제네릭 메서드의 복잡한 식을 간결하게 줄여줄 수 있다.
 
=>
 
연산자를 이용하여, 익명 메서드(Anonymous Method) 의 여러줄의 코드를 단 한줄의 코드로 줄여줄 수 가 있다.
 
좀더 자세한 설명히 필요하다면 다음을 참고 하도록 하자.
http://msdn.microsoft.com/msdnmag/issues/07/09/BasicInstincts/Default.aspx?loc=ko
 
 
우리가 사용할 예제는 다음의 List<int> 컬렉션을 사용할 것이다.
 

List<int> arr = new List<int>();
arr.Add(1);
arr.Add(2);
arr.Add(3);
arr.Add(4);

 
 
List<> 컬렉션은 Find 라는 메서드를 제공한다. ( 확장 메서드가 아님 )
이 메서드는 컬렉션의 특정 요소를 찾기 위해 사용되어 지는데, C# 이 제공하는 Predicate<> 델리게이트를 통해 True/False 를 반환하는 델리게이트이다.
 
그럼 List<> 컬렉션의 특정 요소를 찾기 위해 다음과 같이 사용된다.
 

static void Main(string[] args)
{
           List<int> arr = new List<int>();
           arr.Add(1);
           arr.Add(2);
           arr.Add(3);
           arr.Add(4);
 
           Predicate<int> p = new Predicate<int>(Compare);
           int result = arr.Find(p);
           Console.WriteLine(result);
}
static bool Compare(int i)
{
           return i == 2;
}

 
 
Predicate<int> p = new Predicate<int>(Compare);
 
Predicate<> 대리자는 Compare 메서드에게 일거리를 할당한 것을 볼 수 있다.
 
그럼, 가상 메서드를 이용하여 코드양을 줄여 보도록 하자.
 

int result = arr.Find(new Predicate<int>(
                                delegate(int i)
                                {
                                          return i == 2;
                                }
                     ));
Console.WriteLine(result);

 
 
위와 같이 당연히 결과는 “2” 가 나타났다.
델리게이트를 통해 i==2 라는 요소를 찾기위해 int 인자와 bool 을 리턴하는 메서드를 만들어야 하지만, 위의 delegate 키워드의 구문은 가상 메서드를 만들게 됨으로써 코드양이 많이 줄어 들게 되었다.
 
하지만, 람다식을 이용하여 더 줄여보도록 하자.
 

Console.WriteLine(arr.Find(o => o == 2));

 
 
위 7개 라인을 단 한줄로 해결하였다.

 
사실 이 구문이 선듯 이해가 가지 않는 필자는 무진장 머리를 굴려보았다.
잘 이해를 하기 위해 람다식을 마치 메서드가 있는 구문이라고 머리속으로 상상해보기 바란다.
 
 
 
=> 연산자를 기준으로 왼쪽은 넘길 인자값이 되는 것이고, 오른쪽은 내용이 되는 것이다.
 
그래도 잘 이해가 안된다면 마치 메서드가 존재한다는 상상 훈련을 해보면 그리 오래 걸리지 않고 쉽게 이해가 될 것 같다.
다음 2편에서는 제네릭 대리자를 통해 람다식이 가능한 확장 메서드를 만들어 보도록 하자
Posted by 땡초 POWERUMC

댓글을 달아 주세요

  1. 지송 2010.06.17 12:57 Address Modify/Delete Reply

    람다식 찾다왔는데 역시 이해가 쉽게 써놓으셨네요.

    좋은 하루 되세요 !

LINQ 의 OUTER JOIN 작업

.NET/C# 2007. 9. 4. 00:24 |
LINQ 를 이용한 OUTER JOIN 을 해보자.
이번 강좌를 지난 강좌에 이어 LINQ to SQL Classes 항목을 추가 하여야 한다.
이부분에 대해서는 다음의 URL 을 참고하기 바란다.
 
[.NET/C# 3.0] - LINQ to SQL Classes 와 LINQ의 JOIN 작업
http://umc.pe.kr/article/2007/09/02/LINQ-to-SQL-Classes-AND-LINQ-JOIN.aspx
 
 
우선 우리가 원하는 SQL 쿼리식을 보자
 
SELECT A.ArticleNo, C.Content, C.InsertDate
FROM Article A
LEFT OUTER JOIN Comment C ON C.ArticleNo = A.ArticleNo
ORDER BY C.InsertDate DESC
 
아주 간단한 OUTER JOIN 의 예이다.
이 쿼리의 결과는 다음과 같다.
 
 
위 그림은 보시다시피 결과 데이터의 중하단 쯤에 나온 결과이다.
쿼리를 보듯 NULL 값이 주루룩 있다. 당연히 INNER JOIN 되지 않은 데이터는 NULL 값이 표시될 것이다.
 
 
그럼 LINQ 의 확장 메서드를 통한 OUTER JOIN 을 해보자.
 
var joinList = db.Articles.GroupJoin(
             db.Comments,
             _article => _article.ArticleNo,
             _comment => _comment.ArticleNo,
             (_article, c) => c.DefaultIfEmpty().Select(
                    _comment => new
                    {
                           ArticleNo = _article == null ? -1 : _article.ArticleNo,
                           CommentContent = _comment.Content ?? string.Empty,
                           InsertDate = _comment.InsertDate.ToString() ?? string.Empty
                    }
             )
             ).SelectMany(obj => obj)
             .OrderByDescending(o => o.InsertDate);
 
 
위 식을 INNER JOIN 식과 비교해 보았을 때, 좀 더 부가적인 작업이 필요하다.
 
c.DefaultIfEmpty()
 
을 통해 JOIN 가능한 키가 없을 경우에 따로 처리를 해주어야 한다.
 
또한, 키가 없을 경우의 데이터 또한 nullable 의 ?? operator 를 통해 null 데이터에 대한 경우에 대한 작업을 해야한다.
 
SelectMany(obj => obj)
 
확장 메서드를 통해 반복이 가능한 순환자(열거자) 에 대한 키(Key)값을 모두 반환한다.
 
아무리 람다식을 이용해 코딩양을 줄였다고 하더라고, 사실 벅찬 감이 무척 많다..
두개의 테이블이지만, 3-4 개의 테이블이라고 생각하면, 아마도 SQL 쿼리를 이용하는 것이 나을 것이다.
 
 
그렇지만 다음의 LINQ 식을 이용한 쿼리를 보도록 하자.
 
var joinList = from a in db.Articles
             join c in db.Comments on a.ArticleNo equals c.ArticleNo into _c
             from c in _c.DefaultIfEmpty()
             orderby c.InsertDate descending
             select new
             {
                       ArticleNo = a.ArticleNo,
                       CommentContent = c.Content,
                       InsertDate = c.InsertDate.ToString()
             };
 
개체를 이용한 쿼리식에 비해 무척이나 SQL 쿼리와 가까워 졌다.
 
join c in db.Comments on a.ArticleNo equals c.ArticleNo into _c
from c in _c.DefaultIfEmpty()
 
를 보면, into 키워드를 통해 join 데이터를 _c 컬렉션에 담고
다시 _c.DefaultIfEmpty() 를 통해 null 데이터를 처리하고 있다.
 
into 키워드는 LINQ 의 출연과 함께, 쿼리식 뿐만 아니라 통계 쿼리에도 자주 등장하게 될 키워드이다.
 
그럼, 다음 아티클을 스스로 기대하며 이만^^
Posted by 땡초 POWERUMC

댓글을 달아 주세요

LINQ 의 JOIN
 
기존 C# 2.0 의 Typed DataSet 의 개념과 LINQ 가 결합하여 LINQ to SQL Classes 라는
이름으로 굉장히 강력한 기능을 제공한다.
 
LINQ, 람다식, 익명 형식에 대한 내용은 다음의 URL 을 참고 하세요.
 
2009-06-20 아래의 경로로 접속할 수 없습니다.
LINQ의 발전과 C# 설계에 미치는 영향

 
LINQ to SQL Classes 항목 만들기
 


[새 항목 만들기] 에서 LINQ to SQL Classes 를 만든다.
그럼 .dbml 확장자를 가진 몇가지 파일과 디자이너 화면이 나타나게 된다.
 
여기서 사용하게 될 데이터베이스는 UmcBlog 소스와 함께 공개된 데이터베이스를 사용할 것이다.
 
 
Article 테이블은 블로그의 아티클을 저장할 테이블이다.
Comment 테이블은 아티클에 대한 댓글을 저장하는 테이블이다.


 

디자이너는 두 테이블간 관계가 맺어져 있다면, 이 두 테이블 간의 RULE 과 Key 등이
자동으로 매핑되는 것을 볼 수 있다.
 
 
 
DataBase 쿼리와 LINQ 를 이용한 JOIN 작업
 
SELECT A.ArticleNo, C.Content, C.InsertDate
FROM Article A
INNER JOIN Comment C ON A.ArticleNo=C.ArticleNo
Article, Comment 테이블의 JOIN 쿼리
 
간단하게 JOIN 하는 쿼리를 작성해 보았다.
결과는 다음과 같을 것이다.
 
 
Comment 테이블의 댓글의 ArticleNo 를 Article 테이블과 조인하여 나온 결과이다.



그렇다면 LINQ 를 이용한 JOIN 작업을 보자.

위에서 LINQ to SQL Classes 를 다음과 같이 객체를 생성한다.

 
UmcBlogDataContext db = new UmcBlogDataContext();
 
 
// INNER JOIN
var joinList = db.Articles.Join(db.Comments,
                           _article => _article.ArticleNo,
                           _comment => _comment.ArticleNo,
                           (a, c) => new
                           {
                               ArticleNo             = a.ArticleNo,
                               CommentContent = c.Content,
                               InsertDate            = c.InsertDate
                           }
                    ).OrderByDescending( o => o.InsertDate );
 
SQL 쿼리와 비교해 볼 때 다소 복잡해 보이는 감이 없지 않다.
C# 2.0 의 익명 메서드를 이용와 비교해볼 때 위와 같이 람다식 을 이용하여 그나마 짧게
작성한 코드이다.

 
물론 위와 같이 불편하게 쿼리를 작성하지 않아도 된다.
LINQ 의 쿼리식을 이용하여 마치 SQL 쿼리를 작성하듯 쿼리를 완성할 수 있다.

 
LINQ 식을 이용한 JOIN
 
var joinList = from a in db.Articles
                      from c in db.Comments
                      where a.ArticleNo == c.ArticleNo
      orderby c.InsertDate descending
                      select new {
                              ArticleNo = a.ArticleNo,
                              CommentContent = c.Content,
                              InsertDate            = c.InsertDate
                       };
 
위의 예제를 보면 from 절이 두개가 오는 것을 알 수 있다.
마치 PL/SQL 의 from Article A, Comment C 와 같이 사용하듯 하다.
 
물론 ANSI SQL 과 같은 방법으로 JOIN 이 가능하다.
그럼 아래의 구문을 보자.
 
// INNER JOIN 3
var joinList = from a in db.Articles
                       join c in db.Comments on a.ArticleNo equals c.ArticleNo
                      orderby c.InsertDate descending
                      select new {
                              ArticleNo            = a.ArticleNo,
                              CommentContent       = c.Content,
                              InsertDate           = c.InsertDate
                       };
 
위와 같이 join 문과 함께 on 뒤에 두개의 테이블을 조인을 하게 된다.
On 과 함께 ==(Equals) 을 사용할 수 없기 때문에 “equals” 을 통해 두 테이블을 조인하게 된다.
 
 
위의 예제를 보듯, 객체를 이용한 쿼리와 SQL 쿼리식과 같은 쿼리가 모두 가능하다는 것을
알 수 있다.
하지만, outer join 은 기존 방법과는 약간 다른 방법으로 조인을 하게된다.
다음시간에 LINQ 의 outer join 을 알아보도록 하자.
Posted by 땡초 POWERUMC

댓글을 달아 주세요

  1. 엔돌슨 2012.09.04 17:23 신고 Address Modify/Delete Reply

    궁금한것이 있습니다.
    join c in db.Comments on a.ArticleNo equals c.ArticleNo
    이렇게 조인되면 키가 1개만 매치되는 데 2건이상이면 어떻게 해야하나요?

    조인을 할때 조인되는 키가 여러개의 경우 어떻게 처리해야 하나요?

    • 땡초 POWERUMC 2012.09.06 00:40 신고 Address Modify/Delete

      JOIN 구문을 이렇게 사용하셔도 됩니다.
      http://social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/thread/a8bf3932-611f-44d2-b4d8-6cac83b30406/

      또는 where 절을 이용하셔도 됩니다.
      from n1 in new[] { "Tom", "Dick", "Harry" }
      from n2 in new[] { "A", "B", "Tom", "Dick" }
      where n1 == n2 && n1.Length >= 3
      select n2