이번에 Moq.NET 3.0 버전이 릴리즈 되었습니다. Moq.NET 는 Mocking Object 를 통해 특정 테스트를 진행하고 훨씬 TDD 기반에 근접한 테스팅을 가능하게 합니다. 즉, Mocking Object 는 실제 클래스나 개발이 완료되지 않는 시점에서부터 테스트를 가능하도록 합니다.

그런데 필자는 Moq.NET 를 이해하는 과정에서 내가 알고 있던 것보다 더 깊은 배경이 있었다는 것을 알게 되었습니다. 예를 들어, TDD 외에 BDD 또한 애자일 개발 방법론에 포함된다는 사실과, 조금은 낯설은 BDD-행위 주도 개발을 직접 체험해 보는 과정에서 말입니다. ^^ 

   

왜 TDD (Test-Driven Development) ?

TDD 가 좋으면서 쓰지 않는 이유는 뭘까요? 일반적으로 완벽한 TDD 를 수행하는 과정은 매우 힘듭니다. TDD 에 대한 이론을 들었을때는 확 가슴에 와닿지만, 이것을 몸소 체험하는 과정에서 개발자의 인내력의 한계를 올려놨다 내려놨다 하는 극한을 체험하게 합니다^^; 그러므로 일반적인 TDD 사이클인 Red, Green, Refactor 는 사람을 금방 지치게 만들죠^^; 한 사이클을 마치기 위해서는 많은 시간이 투자되어야 한다는 겁니다.

[그림1] TDD Process

하지만 우리가 TDD 를 수행하는 목적은 이러한 과정에서 코드에 대한 신뢰도를 향상시키고 품질을 향상시키고자 하는 것입니다. 그렇기 때문에 하고자 하는 목적이 보다 나은 품질을 보장하기 위해서라면 TDD 가 필요하다는 것이 머릿속으로만 느낌이 팍팍 옵니다^^;

이제 슬슬 스스로에게 딜레마다 옵니다. 좋은 줄은 알지만 누군가 나에게 TDD 를 강요한다면 아마도 전 "Oh~ No!" 라고 할 것 같네요 -_-;

 

WhiteBox Testing & BlackBox Testing

Moq 를 이야기 하기도 전에 정말 딴소리를 많이 하네요. 일반적으로 테스팅은 크게 WhiteBox Testing 과 BlackBox Testing 으로 구분할 수 있습니다. 이 두 가지 테스팅의 차이는 좁은 범위에서 내부적인 프로세스를 아느냐 모르느냐의 차이고요, 넓은 범위에서는 테스트 레벨의 차이라고 보시면 됩니다.

다음의 그림을 보면 좀 더 이해가 쉬울 겁니다.

[그림2] BlackBox Test 와 WhiteBox Test

즉 BlackBox Test 와 WhiteBox 테스트는 그 목표의 설정이 다르게 됩니다.

BlackBox Test 는 로그인 기능에 대해 요구사항이 있고, 그 기능이 반드시 가져야 할 스팩이 있을 것입니다. 요구사항을 통과하기 위해서는 로그인 기능의 스펙을 만족하면 되고, 실제 단위 테스트 등으로 그런 케이스를 통과를 하면 됩니다. 즉, 내부적으로 어떻게 동작하는지는 알아야 할 필요가 없으므로 수십/수백가지의 테스트 케이스를 통과하여 기능이 정상적으로 동작하는 것을 보장하기 위한 목표입니다.

WhiteBox Test 는 해당 기능에 대해 내부적인 구조를 기반으로 테스트를 진행하게 됩니다. 테스터는 이미 위의 로그인 기능이 내부적으로 어떤 프로세스로 진행되는지 알고 있으며, 예측 가능한 테스트 시나리오를 작성하여 테스트를 진행하게 됩니다. 이 테스트의 목적은 테스트 케이스를 통과하는 BlackBox Test 를 한 단계 뛰어넘어 잠재적인 오류까지 테스트를 통해 잡아내는 것이 목표입니다.
즉, 코드상의 Memory Leak 이나 SQL Injection, Stack Overflow 등 잠재적인 오류를 미리 찾는 경우도 있습니다. 이미 이런 기능은 Visual Studio 2005 이상부터 지원되는 정적 코드 분석(Static Code Analysis) 가 제공이 됩니다. 또, WhiteBox Test 는 코드 커버리지(Code Coverage) 의 수치를 높임으로써 테스트가 안된 코드의 양을 최소화 시키고, 궁극적으로 소프트웨어의 품질을 향상시키는데 있습니다.(Software QA)

Welcome to Dynamic C#(3) - 마음이 넒어진 C#

C# 2009. 6. 26. 08:58 Posted by 알 수 없는 사용자
- 대인배 모드

C#은 점점 더 마음이 넓어지고 있습니다. F#이라는 조금은 독특하지만 머리좋은 친구가 좋은 기능을 소개해주기도 하구요(C# 2.0의 Generics는 F#의 배후에 있는 Don Syme이 제안한거라는 군요), 팬들이 많아지면서 점점 더 넓은 마음을 갖추게 되었습니다. 그리고 대인배 모드에 또 중요한 역할을 해주는게 있는데요 Co- Contravariance입니다.

우선 그다지 친근하지 않은 이름이네요. 이건 대체 뭘까요? 일단 정리해서 말씀드리면, C# 3.0에서 불필요하게 캐스팅을 하면서 해야 했던 작업을 매우 편하게 할 수 있도록 도와주는 C# 4.0의 새로운 기능입니다. C# 3.0에서 못하게 막았던 부분중에서 문제를 일으킬 가능성이 없는 부분에 대해서는 편리하게 사용할 수 있도록 지원해준다는 말인데요. 뭔가 딱 듣기만 해도 대인배스러운 느낌이 들지 않나요 ㅋ. 무슨 이야기 인지 예제를 보면서 확인해보겠습니다. Eric Lippert의 기가막힌 글이 있는데요, 그 글을 참고로 하면서 작성한 글입니다.(링크는 아래 참고자료쪽에!) 


- 예제를 내놓지 않으면 구워먹겠다.

일단, 동물들에게 먹이를 주는 메서드를 통해 알아보도록 하지요. 아래와 같은 코드를 작성합니다.

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

namespace Co_ContraVariance
{
    class Animal
    {
        public bool Hungry { get; set; }

        public override string ToString()
        {
            return "Animal";
        }
    }

    class Mammal : Animal
    {
        public override string ToString()
        {
            return "Mammal";
        }
    }

    class Giraffe : Mammal
    {
        public override string ToString()
        {
            return "Giraffe";
        }
    }

    class Tiger : Mammal
    {
        public override string ToString()
        {
            return "Tiger";
        }
    }

    class Program
    {
        void FeedAnimals(IEnumerable<Animal> animals)
        {
            foreach (Animal animal in animals)
            {
                if (animal.Hungry)
                {
                    Feed(animal);
                }
            }
        }

        private void Feed(Animal animal)
        {
            Console.WriteLine(animal.ToString());
        }

        static void Main(string[] args)
        {
            List<Giraffe> giraffes = new List<Giraffe>{
                new Giraffe{ Hungry = true},
                new Giraffe{Hungry = true},
                new Giraffe{Hungry = false}
            };

            Program program = new Program();
            program.FeedAnimals(giraffes);
        }
    }
}



딱히 잘못된 부분이 보이지 않는 코드입니다. 하지만, vs2008에서는 아래와 같은 에러가 납니다.

 


즉, 다른 타입이므로 메서드를 오버로드하라는 이야기지요. Giraffe는 Animal의 서브타입이므로 문제가 없습니다만, IEnumerable<Giraffe>는 IEnumerable<Animal>과 담고있는 요소의 타입이 다를뿐 어떤 관계도 없습니다. 그래서 IEnumerable<Giraffe>에서 IEnumerable<Animal>로는 형변환이 안되는 것이죠. 그래서 아래와 같은 코드를 통해 간접적으로 형변환을 해줘야 합니다.

program.FeedAnimals(giraffes.Cast<Animal>()); 


 
그런데, 안전한 경우에 한해서 이런게 잘 되게 해주겠다는 게 C#4.0의 이야기입니다. 일단 실행결과를 보시죠.

 

 

C#4.0으로 짠 코드는 잘 실행되는게 보이시죠? 그렇습니다. Covariance를 통해서 코드가 잘 실행된 것입니다. 그러면 이런 Covariance와 Contravariance에 대해서 좀 더 알아보죠.

일단, 간략하게 정의를 한번 내려보도록 하겠습니다.

우선 어떤 타입 T와 U가 있다고 했을때, 다음중 하나는 참이 됩니다.

1. T는 U보다 크다
2. T는 U보다 작다
3. T와 U는 같다
4. T와 U는 서로 관련이 없다.

위의 코드에서 보듯이, Giraffe는 Mammal의 서브타입이므로 Mammal보다 작습니다. 하지만, Giraffe는 Tiger와는 아무관련이 없는 타입이죠. 이런 타입간의 관계에서 어떤 연산을 T와 U에 대해서 수행했을때, 그 결과로 나온 T'와 U'가 T와 U의 관계를 그대로 유지한다면, 그연산은 covariant하다고 이야기 할 수 있으며, 대입의 방향성과 크고작음을 뒤집고 같음과 관계없음만 그대로 유지한다면(위 리스트에서 1,2번을 뒤집고 3,4번만 유지한다면) 이 연산은 contravariant하다고 이야기 할 수 있습니다.


잘 이해가 되시나요? 무슨 꼭 수학의 증명같은 냄새가 나서 거부반응이 일어나신 분들도 있을거 같군요. 그럼, 예제를 통해 차근차근 설명드리도록 하겠습니다.

 

 public interface IEnumerable<T> : IEnumerable
    {
        // 요약:
        //     Returns an enumerator that iterates through the collection.
        //
        // 반환 값:
        //     A System.Collections.Generic.IEnumerator<T> that can be used to iterate through
        //     the collection.
        IEnumerator<T> GetEnumerator();
    }

위 코드는 C#3.0의 IEnumerable의 정의인데요. 이 인터페이스에서 형식매개변수인 T는 GetEnumerator를 통해서 리턴될때만(output position에서만) 사용되는 걸 볼 수 있습니다. 즉, T의 요소를 편집할 방법이 없다는 이야기지요. 이런 경우는 형식매개변수의 대입의 방향성을 유지한 상태에서 IEnumerable<Giraffe>에서 IEnumerable<Animal>같은 형변환을 가능하게 해주겠다는 이야기 입니다.

 

- 대입의 방향성

Giraffe는 Animal의 서브타입입니다. 그렇다면 아래와 같은 코드가 가능하죠.

Animal animal = new Giraffe;

즉, Animal이 Giraffe보다 더 큰(상위) 타입이기 때문에 가능하죠. 하지만 아래의 코드는 컴파일되지 않습니다.

Giraffe giraffe = new Animal();

아래와 같이 하면 컴파일은 문제가 없습니다.

Giraffe giraffe = (Giraffe)new Animal();

하지만, 런타임에서 형변환이 불가능하다고 하면서 예외가 발생되죠. 즉, Animal이 더 크기 때문에, Giraffe는 Animal에 대입될 수 있지만, Animal은 Giraffe에 대입될 수 없습니다. 이게 크고작음에 관련된 대입의 방향성입니다.

단, Giraffe와 Tiger는 둘다 Mammal의 서브타입이지만, 둘사이에는 아무관련이 없습니다.



즉, 이야기를 이어 가자면 Giraffe가 Animal에 대입가능하기 때문에, 형식매개변수가 리턴될때만(output position에서) 사용된다면, 대입의 방향성을 유지한상태에서는 IEnumerable<Giraffe>에서 IEnumerable<Animal>로 변환을 하는것 같이 참조형변환을 지원해주겠다는 이야기 입니다.

 
반대로, Contravariance는 파라미터로 받기만하는 경우에만 사용할 수 있습니다. 그리고 대입의 방향성 역시 반대로 뒤집어 버립니다.

 public interface IComparer<T>
    {
        // 요약:
        //     Compares two objects and returns a value indicating whether one is less than,
        //     equal to, or greater than the other.
        //
        // 매개 변수:
        //   x:
        //     The first object to compare.
        //
        //   y:
        //     The second object to compare.
        //
        // 반환 값:
        //     Value Condition Less than zero x is less than y.  Zero x equals y.  Greater
        //     than zero x is greater than y.
        int Compare(T x, T y);
    }


위 코드는 특정타입에 대해서 비교를 지원해주고 싶을때 구현하는 인터페이스인데요, 여기도 역시 보시면, 형식매개변수인 T는 Compare메서드에서 비교할 인자를 받는 곳(input position)에서만 사용되는 걸 볼 수 있습니다. 예제를 위한 예제가 될 수 도 있지만, IComparer<T>를 통해서 contravariance를 설명해보죠~. 

위에서 작성한 코드에 아래와 같은 코드를 추가합니다. 

    class AnimalComparer : IComparer<Animal>
    {
        public int Compare(Animal x, Animal y)
        {
            return 1; //예제를 위해 ㅋ.
        }
    }

    class GiraffeComparer : IComparer<Giraffe>
    {
        public int Compare(Giraffe x, Giraffe y)
        {
            return 1; //예제를 위해 ㅋ.
        }
    }

.......중략.......

        static void Main(string[] args)
        {
            ........중략.......

            IComparer<Animal> animalComp = new AnimalComparer();
            IComparer<Giraffe> giraffeComp = animalComp;
            Console.WriteLine(giraffeComp.Compare(new Giraffe(), new Giraffe()));
        }



각각 IComparer<Animal>과 IComparer<Giraffe>를 구현한 비교 클래스입니다. 그리고 IComparer<Animal>을 IComparer<Giraffe>에 대입하고 있습니다. 그리고 아무문제없이 컴파일 됩니다. 그리고 실행도 문제없이 됩니다.



Animal은 Giraffe보다 더 큰 데 어떻게 IComparer<Giraffe>에 들어가는 걸까요? 그냥 상식적으로 생각했을때 동물을 비교할 수 있다면, 기린(giraffe)을 비교할 수도 있겠죠? 사람들이 IComparer<Giraffe>에 비교하려고 넣는 객체는 모두 Giraffe타입이겠고 giraffeComp가 실제로 호출하게 되는 Compare메서드는 IComparer<Animal>을 구현한 animalComp의 메서드겠죠. 그래서 방향성이 뒤집혔지만, contravariance로 인해서 실행가능한 코드가 됩니다.

반대로 IComparer<Animal>에다가 IComparer<Giraffe>를 대입하는 경우를 생각해보죠. 그렇다면 사람들은 animalComp를 통해서 Animal을 비교하고 싶어할텐데, 실제로 호출될 메서드는 IComparer<Giraffe>의 Compare메서드겠죠. 그 메서드는 Giraffe타입을 받을 수 있으므로 Animal을 받을 수 없습니다. 그래서 이런 참조형변환은 지원되지 않습니다.

즉, contravariance는 형식인자가 파라미터로 입력되는 부분에서만(input position에서만) 쓰일때, 대입의 방향성을 뒤집는 참조형변환을 지원해주겠다는 이야기 입니다. 일단은 여기까지가 co- contravariance에 대한 간략한 설명입니다. 


- 대인배 만쉐이 ㅋ

암튼, 점점 더 대인배가 되어가는 C#의 모습을 살짝 엿보았습니다. 어떻게 보면, 그냥 직관적으로 할 수 있는 부분들에 대해서 제약을 풀어준 셈이니까 대인배전략에 걸맞는 기능인 거 같습니다. 물론 마냥 낙관적인 것만은 아닙니다만. 성격좋은 사람도 나름의 규칙은 있는 법이니까요. 안전하고 적절할 co- contravariance의 사용은 "들어가는 거(형식매개변수)는 contravariant일 수 있고, 나가는 거(return되는)는 covariant일 수 있다."라는 군요. 그렇지 않은 경우도 있다는 말이겠죠. 제 내공이 허락한다면 이부분에 대해서도 정리해서 올리도록 하겠습니다. 대인배 C# 만쉐이 캬캬캬.

 

- 참고자료

1. http://blogs.msdn.com/ericlippert/archive/2007/10/16/covariance-and-contravariance-in-c-part-one.aspx
2. http://blogs.msdn.com/ericlippert/archive/2007/10/17/covariance-and-contravariance-in-c-part-two-array-covariance.aspx
3. http://blogs.msdn.com/ericlippert/archive/2007/10/19/covariance-and-contravariance-in-c-part-three-member-group-conversion-variance.aspx
4. http://blogs.msdn.com/ericlippert/archive/2007/10/22/covariance-and-contravariance-in-c-part-four-real-delegate-variance.aspx
5. http://blogs.msdn.com/ericlippert/archive/2007/10/26/covariance-and-contravariance-in-c-part-five-interface-variance.aspx
6. New features in C# 4.0, Mads Torgersen

[ASP.NET 4.0] 1. Core Service - Extensible Output Caching

ASP.NET 4.0 2009. 6. 24. 20:03 Posted by 알 수 없는 사용자
Evolution of ASP.NET

.NET Framework 4.0 beta 1와 함께 ASP.NET도 새로운 변화를 시도하였습니다. ASP.NET 2.0의 변화 보다는 덜 파격적이지만, 그 동안 .NET Framework 업데이트가 진행되는 동안 ASP.NET의 변화가 미미했던 것을 감안 한다면, 이번 .NET Framework 4.0 업데이트와 함께 동승한 ASP.NET의 업데이트는 놀라울 만큼 바뀌었습니다.(스캇 구스리 아저씨가 힘좀 쓰셨나 봅니다.ㅋㅋ)
그 중 Core Service 업데이트는 Performance 측면과 기존 ASP.NET Issue를 처리하는데 두드러진 발전을 이루어 냈습니다. 그럼, Core Service의 주요 업데이트 사항을 간략하게 소개하고 넘어가도록 하겠습니다.

1. Extensible Output Caching - 확장 가능한 출력 캐쉬 정도로 직역하겠습니다. 기존에도 있던 페이지 캐싱을 개발자 나름대로 커스트마이징 할 수 있도록 확장 시켜준 기능입니다.
2. Auto-Start Web Application - HTTP Request에 대하여 콜드 스타트 또는 개별 응용프로그램의 재사용에 소모되는 비용을 절감하기 위한 기능인 듯 합니다. 왜 ASP.NET 맨처음 띄우면 밥먹고 담배피고 와야 하잖아요.(오바입니다만...) 그런 비용을 절감 하기 위해 나온 기술인듯합니다. 허나, Windows Server 2008 R2에 탑재 가능한 IIS 7.5에서만 지원되는 기능이라니 OTL이 아닐 수 없습니다. 한 3년동안은 이 기술 볼 수 없을 듯합니다.(회사에서 2008을 깔아야 뭘 하죠? 아직 2000 쓰는 곳도 많이 있는데....)
3. Permanently Redirecting a Page - 영원히 헤어지는 이전 페이지와의 관계, 참 무슨 영화 제목 같 군요. 이전에 이슈가 되었던 Request가 여러번 일어나던 오래된 페이지에서 Redirect를 시킬 경우 HTTP 302 요청 이슈에 대한 대처 방안입니다. 이건 뭐 다들 아실만한 내용이겠네요.
4. The Incredible Shrinking Session State - 깜놀하게하는 세션 상태정보의 감소로 의역(?)하죠. ASP.NET 에서 단일 서버라면 모르지만, 웹팜(Web farm - 모르신다면 당장 찾아 보세요. 롸잇 놔우)에서는 세션 상태 정보를 저장하기 위해서 세션 State Server를 구성하거나 MS SQL을 이용하여 세션 정보를 저장할 수  있도록 저장소를 두는 방법이 있었습니다. 근데, 문제는 두 State Server 다 거의 Raw데이타에 가까운 정보들이 날(Raw)로 저장되어 엥간한 동시접속자 수를 자랑하는 사이트에서는 엄청난 데이터량이 문제였습니다. 데이터 양도 문제지만 Network Traffic도 데이터 양 비례하게 올라가는 문제를 양산하게 됐죠. 이를 해결하기 위해 Gzip Compression을 사용했다는 군요.
그럼, 본격적으로 Extensible Output Caching에 대해 알아 보도록 하겠습니다.



What is Extensible Output Caching?  

말 그대로 확장 가능한 출력 캐쉬 기능입니다. 쉽게 설명 하자면, 엄연히 Caching 기능은 ASP.NET 1.0부터 있었습니다. 페이지나 컨트롤, HTTP Response의 출력물(뭐 쉽게 말하자면 컴파일러에서 html 코드로 완전히 변환된 상태의 코드)을 서버의 메모리 내에 상주시킴으로써 재생산에 드는 비용을 감소 시키는 데에 일조 하던 기능입니다. 하지만, 이것도 만만찮게 다른 문제를 일으키고는 했는데요 저장소는 무조건 메모리로 박치기 하다보니, 다른 웹 어플리케이션과 메모리 선점 전쟁을 하게 되는 문제가 생기고, 서버 자체적으로는 쓰잘때기 없는 것(일명 쓸애기) 까지 메모리 영역을 점령함으로써 서버 리소스를 잡아먹게 되는 문제가 생긴 것이지요.

그래서, 기존에 있던 기능은 살리고~ 살리고~ 살리고 살리고 살리고 커스텀한 Provider만 Implement(구현)하여 대체 저장소를 선택할 수 있도록 한 기능입니다. 물론 MS SQL 서버에도 저장이 되도록 기능을 갖추고 있습니다.

그럼 실전으로 들어가 정확히 뭐하는 기능인지 코드로 살펴 보도록 하겠습니다.

Walkthrough : Step 1. Create a Web Project

웹 프로젝트를 그림 1-1 과 같이 선택하여 생성합니다.

<그림 1-1>

<그림 1-2>

자~! 여기까지는 많이 하셨을 테니 거두 절미 하고, 솔루션에 CustomOutputCacheProvider Class를 추가하기 위해 클래스 라이브러리 프로젝트를 생성하도록 하겠습니다.
                                                                                                                   <그림 1-3>
                                                                                                                                    <그림 1-4>

프로젝트를 생성하셨다면 TestCustomOutputCacheProvider 클래스를 추가 시킵니다. 그리고, CustomOutputCacheProvider 프로젝트에 System.Web과 System.Confihuration을 참조 추가 시키겠습니다. 이제 어느정도 구색이 갖추어졌습니다.

Walkthrough : Step 2. Implement OutputCacheProvider

이번 단계에서는 개발자 특정 저장소를 지정할 수 있도록 커스텀한 CacheProvider를 생성도록 하겠습니다.

<그림 1-5>

그림 1-5와 같이 System.Web.Caching.OutputCacheProvider 추상 클래스를 Implement할 경우 자동으로 오버라이드 메서드가 생성되는 것을 볼수 있습니다.
                                                                                                                           <그림 1-6>

기능 구현에 많은 시간을 할애 할 수 없는 관계로 간단하게 세션에다가 캐싱을 하도록 구현 하겠습니다. 저장소를 선택하고 구현 하는 부분은 각자 구미가 땡기는 대로 구현하여 보세요.

Walkthrough : Step 3. Setting WebSite

먼저 그림 1-7과 같이 Web.Config파일에 caching 섹션을 추가하고 Provider 섹션을 구성하도록 하겠습니다.
<그림 1-7>
 
여기서 부연 설명 드리겠습니다. <outputCache> 섹션의 Attribute인 defaultProvider는 Web Application에 기본적으로 제공할 OutputCacheProvider입니다. 나중에 나올 Global.asax에서 설정해 주지 않는 이상 자동적으로 AspNetInternalProvider를 제공합니다. 그리고 하위 섹션인 <providers> 섹션 이하 섹션에는 개발자가 커스텀 하게 만들어 놓은 Provider를 넣는 부분입니다. 복수 개의 CacheProvider를 제공할 수 있어 좀 더 성능 향상에 기여 할 수 있습니다.(점점 말투가 딱딱해 지고 있습니다. 퇴근 시간이 훌쩍 넘어서 인지 정신적 압박이...)

그리고나서, Global.asax를 추가 시켜보도록 하겠습니다. 그림 1-8과 같이 새로운 아이템 추가 버튼을 클릭하면 대화 상자에서 Global.asax파일을 선택하여 확인 버튼을 선택합니다.
                                                                                                     <그림 1-8>

추가된 Global.asax 파일을 열고 그림 1-9의 코드를 추가 시켜 줍니다.
                                                                                                                       <그림 1-9>

 
GetOutputCacheProviderName 메서드는 Web.config 파일에 <caching>섹션이 추가 되어 있어야만 호출 되는 메서드 입니다. 그리고 코드를 보면 특정 페이지 에만 "SessionCache"라는 Provider명을 리턴하게 되어 있는데 이 부분은 Web.config의 <provider> 하위 노드의 Name Attribute와 매핑되는 키값입니다. 즉, 특정 페이지에 접근 시 개발자가 원하는 CacheProvider에 접근하여 커스텀한 저장소에 저장하게 하는 기능의 Entry Point 라고 보셔도 무방합니다.

그리고 UserControl을 생성하여 간단한 컨트롤을 작성하여 보겠습니다. 그리고 UserControl 선언적 구문 페이지 상단에는 <%@ OutputCache Duration="60" VaryByParam="None" providerName="SessionCache" %>
을 기입하여 줍니다. Duration의 의미는 소멸되기 까지 대기 시간으로 60초이고 VaryByParam은 Post든 QuerString이든 파라미터가 넘어오는 건마다 페이지를 저장시킬지의 여부를 선택합니다. 그리고 providerName은 해당 UserControl에서 제공할 Provider를 선택하는 Attribute입니다다.
그리고, 한가지 재미 있는점은 여러개의 Provider를 구현 하고 Web.config에 등록 시킨 후 각각 UserControl에 다른 Provider를 등록 시키면 Global.asax에서 한가지 ProviderName을 리턴 하더라도 각각의 Provider 저장소에 저장이 된다는 것입니다.

이제 마지막으로 웹 프로젝트에 CustomOutputCacheProvider 프로젝트를 참조한다. 그림 1-10r과 같이 전체적인 Test 솔루션 구성이 끝이 났습니다.

                                                                                                   <그림 1-10>

Walkthrough : Step 4. Running Web Application and Result

이제 마지막 단계 Test Application을 구동하고 값을 확인하는 작업만 남겨두고 있습니다. F5를 눌러 빌드를 한 후 정상적으로 빌드 성공이 되면 Web browser가 화면에 나타날 것 입니다. 제가 값을 확인 하기 위해 몇개 중단점을 찍어 값을 확인 하는 것으로 이번 아티클을 마무리 할까 합니다.

맨 처음 브라우저가 화면에 나타나고 그림 1-11처럼 Global.asax의 GetOutputCacheProviderName메서드에 중단 점이 걸리는 것을 확인 할 수 있습니다.
                                                                                                                              <그림 1-11>
그 다음 F5를 다시한번 눌러 다음 중단점으로 이동하면  우리가 만들어 놓은 TestCustomOutputCacheProvider 클래스의 Set메서드를 호출하는 것을 확인 할 수 있습니다.

                                                                                                                              <그림 1-12>
Text Visualizer로 값을 확인한 결과 그림 1-13과 같이 렌더된 Html 태그값이 저장소에 저장되는 것을 확인 할 수 있습니다.

                                                                                                         <그림 1-13>
마지막으로 인위적으로 포스트 백을 일으켜 저장소에 저장된 값을 가지고 오는 과정을 확인 하도록 하겠습니다. 화면에 버튼 이벤트를 일으키면 서버 쪽 Global.asax의 GetOutputCacheProviderName메서드를 재 호출 하여 페이지에 할당된 ProviderName을 리턴받은 후 TestCustomOutputCacheProvider 클래스의 Get메서드를 호출하는 것을 확인 할 수 있습니다. Get메서드에서는 이미 저장소에 캐싱된 Html 값이 반환 되어 사용자에게 전달되는 것을 확인 할 수 있습니다.

<그림 1-14>

정말 오늘 길게도 썼습니다. 씁씁후후~ 어떤 메카니즘을 가지고 동작하는지 대충 이해하셨을 듯 합니다. 그럼 다음에도 ASP.NET 4.0에 다른 기능에 대하여 알아보도록 하겠습니다.

[VSIX] 2-1. How to start VSIX programming

VIsual Studio Extensibility 2009. 6. 23. 13:35 Posted by 알 수 없는 사용자

VSIX 시작하기

본격적으로 VSIX 프로그래밍에 대하여 알아 보도록 하겠습니다. 일단 VSIX의 개념 부터 짚고 넘어가는 것이 순리일듯 합니다. 일단 이미 이전에 엄준일씨에게서 포스팅 된 Visual Studio 2010 Extension Manager를 참고하는 편이 나을 것입니다.
VSIX는 뭐의 줄임말일까요? Visual Studio 2010에서 새롭게 선보인 VSIX는 언뜻 Visual Studio Extensibility와 관련 있는 듯 하나 VSIX는 인스톨러와 관련이 있으므로 Visual Studio Installer Extension의 의미일 듯 합니다.(이건 필자의 생각은 아닙니다. 머리나쁜 필자가 저런 의미심장한(?) 단어를 생각해 낼 일이 없기 때문에)

앞서서 1. What is different from before version에서 포스팅한 내용에 추가적으로 이전 버전과는 다른 Deployment Packaging을 지원하기 시작하였습니다. 이전에는 Packaging을 하기 위해서는 Setup 프로젝트를 생성하고 Regpkg.exe를 통해 Package 등록에 필요한 일련의 과정들을 설정하여 Deployment하는 복잡한 과정을 거쳐야 하였습니다.


하지만, 이제 상황은 달라졌습니다. VSIX가 나오므로 해서 패키징과 배포가 아주 아주 용이해졌을 뿐이나라 Extension Manager를 통하여 설치된 VSX 목록을 관리 할 수 있는 편리함도 함께 추가 되었습니다.

VSIX는 일종의 범용적인 Package로써 .zip의 OPC(Open Packaging Convention)가 적용된 형태라고 볼 수 있습니다. 그럼 심심한데 압축을 풀어 볼까요. 실제 압축이 풀리는지 막 궁금하지 않습니까? 필자만 궁금한가? 필자만 변태인가? 흐흐

<그림 1-1>

테스트로 프로젝트를 생성하고 빌드를 한 상태로 Debug 폴더로 들어가 보겠습니다. 그림 1-1과 같은 화면이 눈앞에 보일 것입니다. 뭐 별다른건 없어 보이는군요. Manifest파일과 .vsix 파일 말고는 우리가 자주 보던 어셈블리와 디버그 파일입니다. 그러나 .vsix의 압축을 풀어 보겠습니다.

<그림 1-2>
그림 1-2와 같이 .vsix 파일명과 같은 폴더가 생성된 것을 볼 수 있습니다. (아~ 그래픽 툴에 상당히(?) 익숙하고 디자인 감각이 있는 필자는 <~요기 라고 표현함으로써 직관성과 예술성을 감미하였습니다.)
그럼 해당 폴더로 들어가 보겠습니다.

 
<그림 1-3>

역시나 기대 했던것 처럼 .vsixmanifest파일과 해당 어셈블리가 위치되어 있습니다. 근데, [Content_Type].xml은 뭥미? 그래서 까봤습니다.(궁금한건 못참는 이 죽일놈에 개발자 습성 때문에)
<그림 1-4>

역시나 .vsix 내부의 파일 타입이 OPC API 요건 대로 아주 잘 정리되어 있는것 을 볼 수 있습니다.
그럼, .vsix 컨텐츠 목록을 정리해보겠습니다.
 [Content_Type].xml  컨텐츠의 알려진 파일에 대한 정보 수집 장소
 extension.vsixmanifest  Extension의 정보를 담고 있는 manifest정도로 이해
 하면 될듯?. 일종의 config파일과 비슷(?) 오바일까요?
 Assembly file  우리가 개발한 어셈블리 파일
 나머지 듣보잡  기타 아이콘, 이미지 기타 등등 파일들
<표 1-1>
 이상으로 .vsix를 까발리는 행위를 마치고 순수 VSIX를 개발하기 위한 일련의 과정들을 설명하기로 하겠습니다.

[VSIX] 1. What is different from before version?

VIsual Studio Extensibility 2009. 6. 23. 02:30 Posted by 알 수 없는 사용자
VSX ( Visual Studio Extensibility ) 란?
Visual Studio Extensibility (이하 VSX )는 예전 부터 우리가 쓰고 있는 Visual Studio와 통합하여 개발 생산성을 높이고자 기존에 제공 되던 IDE환경에서 보다 커스트마이징한 환경을 구축하는 것을 말합니다.
이미 Third-party 솔루션을 제공하는 회사는 널리고 널렸으며, 회사 자체 Framework을 구축하고 있는 곳은, 자체적으로 개발 생산성 향상을 위하여 VSX를 제공하고 있는 것을 흔히 볼수 있을 것입니다.


 
이미 Visual Studio 2005 와 Visual Studio 2008에서 그 기능을 강력하게 지원하고 있으며, 기본적으로 Visual Studio SDK를 설치 하지 않아도 제공되는 Add-In Templete은 쉽게(?) 원하는 Application을 작성할 수 있도록 도와 주고 있습니다.

주로 VSX 종류는 3가지로 나눌 수 있습니다.

1. Visual Studio Add-In
우리가 쉽게 할 수 있는 Add-In은 그 자체만으로 강력한 기능을 제공합니다. Visual Studio의 오브젝트 모델에 접근 할 수 있고, 사용자 인터페이스를 추가하고, 여러 옵션 툴바, 메뉴 등의 IDE 요소에 접근하여 컨트롤할 수 있게 제공하고 있습니다. 주로 Add-In으로 Package보다는 간단하지만 그 기능만은 간단하지 않은 기능들을 선보이고 있으므로 충분히 이것으로도 원하는 산출물을 내놓을 수 있다고 생각하고 있는 바이지만, 이 아티클을 쓰는 이유와는 좀 다르므로 일단 패스하고 추후, 필자의 블로그를 통해 간단하게 나마 소개해보고자 합니다.(필자 엄청난 귀차니즘으로 그날이 언제쯤 올런지.... 쯧쯧)

2. Visual Studio Macro
아~ 매크로 이름만들어도 귀에 팍팍 꽂히는 소리가 들리는군요? MS Office Excel의 기능을 화려하게 만들어 주는 이놈이 Visual Studio에도 있었습니다.(실제 쓰는 사람은 몇 보지 못한 1人) Package보다 쉽고 Add-In 보다 쉽다라고 자부하는 매크로는 주로 아주 반복적인 작업에 많이 쓰입니다. 하지만 우리가 원하는 커스트마이징과 퐌타스틱한 Application에는 조금 아쉬운듯한 새로운 기능 추가 조건에는 맞지 않습니다. 하지만, 오토메이션 업무에는 뛰어난 발군의 기능(?)을 제공하고 있으니 무시할 수는 없는 노릇입니다.

3. Visual Studio Package
드디어 나왔군요 Package. 총 3가지 중 Visual Studio의 활용성과 기능 추가성에 대해서는 Package만한 놈이없을 정도로 그 기능적인 확장성을 인정 받습니다. Package는 Unmanaged 즉 Native언어로 구현 가능하며, 또한 C#, VB와 같이 CLR에서 동작할 수 있는 Managed Language로도 구현이 가능하다니, 필자와 같은 C# 개발자에게는 좋은 IDE를 제공하여 주는 셈입니다. 

이렇게 VSX를 이루고 있는 아이들을 살펴 보았습니다. 그럼, 과연 Visual Studio 2010과 이전 버전 (이하 Visual Studio 2008 또는 2005)과는 무엇이 틀린지 살펴 보도록 하겠습니다.(필자 생전 태어나서 처음 아티클 이란 것을 써서 그런지 몰라도 벌써 퇴근의 압박과 고질적인 손가락 관절염이 도지고 있네요.)

What is different?

가중 눈에 띄게 달라진점을 꼽으라면 역시나 .NET Framework 4.0 부터 지원하는 MEF일 것입니다. (필자 MEF 땜에 VSIX 테스트 프로젝트 생성하고 안돌아가 똥줄 좀 탔습니다.)
MEF에 대해서 머리에 물음표가 그려지는 개발자 여러분께서는 엄준일씨(땡초)가 고생 고생해서 써놓은 아티클을 참고 하길 바랍니다. (친절한 필자는 링크도 남겨주는 군화. http://www.vsts2010.net/13)
MEF 즉 단위 컴포넌트 별로 쪼개어 개발될 뿐만 아니라, 의존성 또한 약화 되어버리니 이건 Visual Studio에서 그토록 기다리고 기다리던 기능이 아닐까 합니다. (아무래도 이전 버전에서 패키지를 관리하기에는 좀 어려움이 있기는 했습니다.)
그리고, MEF는 필자 개인적인 생각이고 UI측면에서는 WPF로 바뀐 Editor라고 할까나... .NET Framework 3.0 부터 지원하던 WPF가 드디어 IDE에 녹여지게 되었고, 추가적인 Editor 기능 역시 WPF로 구현이 가능하게 되어 개발하면서 움직이는 화면을 보는 재미가 쏠쏠하지 않을까 합니다.(필자 UX 개발자가 아니어서 저런 기능까지 구현할까라는 의구심이 들기도 합니다. 만들어 놓으면 그림판만 WPF지 윈폼 컨트롤 못지 않는 딱딱함을 지원할것이 100%입니다.) 그리고 Package프로젝트 생성 시 이전 버전과는 달리 Editor Templete이 분리 되어 있는 것을 볼 수 있을 것입니다. 아마도 MS는 이번 2010의 Editor에 사활을 거는듯 합니다. 왜냐하면 Editor의 Architecture를 눈에 띄게 변경시켜 놓았으니 말입니다. 이번 Framework 변경사항과도 일맥 상통하게 확장성이 화두인듯 합니다.


What is Next?
  
 
다음 번부터는 Tutorial 형식으로 하나하나 따라해 볼 수 있도록 구성해볼 생각입니다. 설치에서 부터 간단한 어플리케이션 작성 그리고 개인적으로는 Azure 도 붙여 보고자 합니다. 아주 재미 있을 것 같지 않습니까? 필자 엉덩이가 들썩 들썩하는 소리가 들려 오는 군요.
참고로 국내에서는 VSX 개발에 대한 리소스가 충분치 않는 것이 사실입니다. 필자의 검색능력이 부족하여서 인지도 모르겠으나, 많은 관심을 가지고 본다면, 정말 재미있는 영역이 될것입니다.

지난 2009 6 10 MSDN 주간 세미나를 통해 VSTS 2010 팀의 세미나를 진행하였습니다. 새로워진 Visual Studio 2010 .NET Framework 4.0 등에 많은 분들이 관심을 주셨던 같습니다.

 

참여하고 싶었지만 참석 못하신 분들 또는 다시 보고 싶으신 분은 I am a developer 사이트에서 세미나 동영상을 있고, 발표 자료를 다운로드 받을 있습니다.

 

강보람 - C#연대기 -C#의 Before/After.

 

 

 

공성의 - VSTS2010에서의 소프트웨어 품질 관리

 

 

김병진 - VSTS 2010 Architecture & UML

 


 

엄준일 - Managed Extensibility Framework

 

 

 

최흥배 - Visual C++ 10, C++0x 그리고 Concurrency Runtime

 


Visual Studio 2010 Beta 1 설치부터 살펴보기

Visual Studio 2010 2009. 6. 15. 17:30 Posted by 알 수 없는 사용자

Visual Studio 2010 Beta 1이 일반에 공개된지도 벌써 한달이 다 되갑니다.
미래의 Visual Studio의 모습을 보기 위해 설치 해서 사용을 해보신 분들도 있으시겠지만 시간이 없거나 아직 Beta 1 단계라서 완성되지 않은 부분이 있어서 다음 기회에 사용 해보시려는 분들도 있으실겁니다.
설치 과정을 보면서 어떠한 구성요소가 업데이트 되었고 설치가 되는지 알아보고 기본적으로 변화된 IDE의 모습을 살펴보겠습니다.



먼저 오토런 화면입니다.
첫번째 인스톨 메뉴를 선택하고 설치를 시작 해 보겠습니다.



기본적인 설치 파일 작업이 끝나고 다음으로 넘어갑니다.



현재 설치되어 있는 구성 요소를 체크 하고 설치 될 요소를 알려줍니다.
VC 런타임이 9.0과 10.0 두개가 모두 설치되는 것을 볼 수 있습니다.
그리고 핵심이 되는 .NET Framework 4 Beta 1과 Visual Studio 2010 Beta 1 등이 설치 되는 것을 알 수 있습니다.
그럼 라이센스에 동의를 하고 다음으로 넘어갑니다.



지금까지는 이전과 별 다를건 없었는데 여기서 약간 달라집니다.
기존에는 전체 구성요소가 트리 구조로 한번에 나왔는데 이제 바로 나오지 않고
.NET 개발 환경과 C++ 개발 환경으로 나뉘어져 있습니다.
자신의 개발 환경에 맞게 선택을 할 수 있고 체크를 한 후 아래 보이는 Customize 버튼을 누르면 세부 선택이 가능합니다.



보시는 것처럼 이전과 같이 트리 구조로 선택 할 수 있게 나오게 되고 원하는 형태로 설치가 가능합니다.
그리고 SQL Server 2008 Express 버전이 기본적으로 선택이 됩니다.
Install 버튼을 눌러 설치를 시작하겠습니다.



.NET Framework 4 Beta 1이 설치되면 재부팅을 요구합니다. 재부팅을 하고나면 나머지 설치 과정을 이어서 진행합니다.



드디어 설치가 완료되었습니다. Windows Server 2008 SP2 VPC에서 설치를 진행했는데 중간에 디지털 서명 관련 에러가 나서 재부팅하고 다시 하니 잘 설치되었습니다.
혹시 비슷한 에러나 나면 참고하세요.

그리고 설치되는 MSDN은 베타1에 포함되지 않았습니다. 온라인 MSDN 라이브러리에서 2010에 관련된 내용을 확인 할 수 있습니다.


제어판에서 설치된 목록을 보면 다음과 같습니다.
현재 베타1 단계에서는 이정도가 설치되고 앞으로 베타2 이후에는 변화 될 수도 있습니다.



시작 메뉴에 등록된 프로그램은 다음과 같습니다. Microsoft Test and Lab Manager 등 새롭게 추가된 요소를 볼 수 있습니다.




VS2010 베타1을 실행 해 보면 시작 페이지가 많이 달라진것을 볼 수 있습니다.
전체적인 IDE에도 색도 들어가고 화려한 모습을 보여주고 있습니다.




About 메뉴에서 구성 요소를 다시 한번 보면 Silverlight도 기본으로 추가된것을 볼 수 있고 F# 등 새로운 언어도 포함되었습니다.


새 프로젝트를 열어보면 이전과 조금 다른 형태가 보입니다.
2008에서 처럼 멀티 타겟팅을 지원하고 업그레이드 된 .NET Framework 4.0도 보입니다.



F# 프로젝트 템플릿은 다음과 같습니다. .NET Framework 4.0에서 새롭게 지원하는 것이므로 3.5 이하를 선택하면 나타나지 않습니다.



새롭게 추가된 온라인 템플릿 탭을 선택하면 기본 템플릿 외에 다양한 템플릿을 추가 할 수 있습니다.



WPF 프로젝트를 생성 해 보았습니다. 전체적인 IDE가 푸른색을 기본으로 새롭게 변화되었고 WPF로 구성되었다는걸 느낄 수 있습니다.
그런데 WPF에서 폰트 처리 문제때문에 좀 뿌옇게 보이는 경향이 있는데 앞으로 개선될거라 예상됩니다.



Visual Studio 2010에서는 멀티 모니터를 지원 한다고 하는데 보시는 것처럼 탭으로 분류된 창을 분리 할 수 있습니다. 창을 드래그 해서 다른 모니터로 옮겨서 여러 모니터에서 작업을 할 수 있습니다.

지금까지 설치부터 IDE의 모습까지 간략히 살펴보았는데 여러가지 향상된 점이 많다는 것을 알 수 있습니다.
관심 있으신 분들은 설치해서 사용 해보시가 여건이 안되신다면 궁금한 점을 말씀하시면 더 자세히 알려드리도록 하겠습니다.

여섯번째입니다.

이미징 데모 설명과 시연을 끝내고 전체 요약 후 질답 세션으로 넘어갑니다.


혹 자막이 안보이시는 분은 유투브 플레이어에서 CC(Turn on Captions)를 활성화해주시면 보일겁니다.
(임베드 태그에서 기본으로 보이도록 설정했는데 왜 기본으로 안나오는지 모르겠군요;)

Welcome to F#(9) - 메이져 데뷰.

F# 2009. 6. 12. 16:25 Posted by 알 수 없는 사용자
-뒷북이냐

어느덧 비주얼스튜디오 2010 베타1이 나온지도 거의 한달이 다되어 가네요. 그동안 뭐가 바뀌었는지 간략한 소개도 못드렸었군요. 뒷북이라 느끼실 수도 있겠지만, 간략하게 비주얼스튜디오 2010 베타1에서 F#이 어떻게 무명시절의 설움을 딛고 일어서고 있는지 소개해드리려고 합니다.




-메이저데뷰

개인적으로 가장 중요하다고 생각하는 점은 F#이 무명시절의 설움을 딛고 메이져데뷰를 했다는 거죠. 이제 당당하게 비주얼 스튜디오 시작시에 나오는 스플래시 화면에도 이름을 올리고, 비주얼 스튜디오를 깔고 처음실행하면 나오는 기본개발환경설정 선택창에서도 Visual F#을 보실 수 있습니다.




캬. 그리고 새 프로젝트를 눌러서 들어가보면 Visual F#이 메인에 나오고요 C#과 VB.NET은 "Other Languages" 카테고리로 분류가 됩니다. 좋네요. 참고로 F# Interactive도 기본으로 뜹니다. 


그리고 비주얼 스튜디오 2010 베타1에 포함된 F#은 약간 버전업이 되었는데요(1.9.6.2 -> 1.9.6.16) 아래 그림을 비교해보시면, F#의 버전과 닷넷프레임워크 버전이 바뀌었음을 확인해볼 수 있습니다.

(2008)
(2010)


그리고 이번버전부터 PowerPack을 따로 받아서 깔도록 바뀌었습니다. 그래서 F# Interactive에서 #r 해서 PowerPack.dll을 로드하려고 해도 dll을 찾아오지를 못하는데요, 그래서 따로 다운을 받아서 복사를 해줘야 합니다.  여기에서 받을 수 있구요~ "C:\Program Files\Microsoft F#\v4.0" 이 경로에 복사해서 넣어주면, F# Interactive에서 기존처럼 #r "FSharp.PowerPack.dll";; 구문으로 추가할때도 자동으로 찾아서 추가해줄 수 있습니다. 그리고 기존처럼 비주얼스튜디오 2008에서도 베타1에 추가된 1.9.6.16버전을 사용할 수 있는데요, 여기에서 다운받으실 수 있습니다.


그동안 6개월동안 커뮤니티의 피드백을 받아서 F#언어와 컴파일러의 버그를 잡고 구조와 성능을 개선하는데 집중했다고 합니다. #light가 이제는 기본으로 설정되는 것과 .NET 4.0의 BingInteger와 연동이 잘되고, params타입을 사용하는 메서드를 호출하거나 만들수있게 되었고, 라이브러리의 이름이나 표현을 표준에 맞게 수정하면서 타입파라미터가 대문자로 바뀌는 등의 변화가 있었습니다.


(소문자였던 타입 파라미터가)

(대문자로 바뀌었음)



-이게 다야?

사실, 더 자세하게 하나하나 분석해드릴 수 있으면 좋으련만, 공부한지 얼마 안되는지라 뭐가 자세하게 바뀐건지 감은 잡혀도 확실하게 설명드리지 못하는 점이 조금은 죄송스럽군요;;;
여기에서 추가되거나 바뀐 내용들을 자세하게 보실 수 있습니다.

F#이 도대체 왜 비주얼스튜디오에 정식으로 추가된 걸까요? 기존에도 J#등과 같은 언어가 추가되었다가 소리소문없이 사라지기도 했었습니다만, F#도 그런걸까요? 사실 저는 함수형언어에 기존의 언어들이 갖지 못한 장점들이 있고 C#이나 VB.NET이 멀티패러다임을 지향하면서 함수형,동적 언어들의 장점을 취합하고 있지만 함수형언어 고유의 영역을 제대로 커버하는건 힘든게 아닌가 싶었습니다. 그래서 F#이 추가되는 걸 그런 점에서 봤었습니다만, 스터디를 이끌고 계시는 K님의 말씀을 듣던 중 새로운 점을 하나 발견하게 됐습니다.

패션쇼를 예를 들어주셨는데요, 제대로 옮기는지는 확실치 않지만 대략 '패션쇼에서 독특한 옷들 입고 나와서 모델들이 걸어다닌다고 해서 그 옷이 바로 백화점이나 옷가게 진열장에 걸리는건 아니다, 앞으로의 가능성과 방향을 제시하는 의미가 있는거다' 같은 말씀이였습니다. 그리고 함수형언어가 그런면이 있어서 그동안 함수형언어의 발전적인 개념들이 현업에서 쓰는 언어에 하나씩 추가되기도 하는거라고 말이죠(LINQ같이).

이 말을 듣고 나닌 Paul Graham이 왜 그토록 Lisp을 최고로 치면서 시간이 지나면 사라질 언어말고 언어계층의 뿌리에 해당하는, 그래서 시간이 지나도 가치가 변하지 않을 Lisp같은 언어에 집중하라고 말을 했는지 알것 같기도 했습니다.

F#이 메이져 데뷰를 하면서 그걸통해 닷넷프레임워크에서 돌아가고 서로간에 호환이 가능한 함수형언어를 확보하는 동시에, F#을 통해서 시험적인 요소들의 가능성도 보고 닷넷을 더 발전적인 형태로 가져가기 위한 시도가 아닌가 하는 생각이 들었습니다.

제대로 설명한건지는 확신이 안서지만 어쨌든, 기존의 함수형언어의 팬들이 F#을 통해 뭔가를 많이 시도하고 즐긴다면 닷넷이 더욱 풍성해지는 거겠죠~~~~.

-참고자료
1. http://blogs.msdn.com/dsyme/default.aspx

다섯번째입니다. 이제 끝이 보이네요;
많이 늦었죠? 죄송합니다. 출장 때문에 한 2주동안 바빴습니다.

이번 회에서는 Asynchronous Agents Library에 대해 더 자세히 살펴보고 실제 적용 예를 보여줍니다.


그 사이 VS2010 베타1의 발표와 함께 많을 자료들이 쏟아져 나왔는데요. AAL 관련해서도 유용한 글들이 보이더군요.



AAL로 액터 기반 병렬 프로그래밍을 경험해보세요! 

새롭게 추가된 Extension Manager

이번 Visual Studio 2010 에서는 새로운 Visual Studio 확장 가능한 기능을 제공합니다. 이전의 Visual Studio Extensibility(VSX) 는 그 개발하기 위한 환경을 갖추는 것도 힘들었지만, 아마도 좋은 확장 기능을 찾는 것이 더 힘들었었지요.

이러한 Visual Studio 확장 기능과 Industry Partner 의 제품을 소개하고 검색할 수 있는 Visual Studio Gallery 웹 사이트가 아마도 가장 신뢰할 수 있고 유일한 곳이었습니다. 지금 보이는 웹 사이트는 Visual Studio 2010 과 서비스를 통합하기 위하여 얼마 전에 개편이 되었습니다. 그리고 새롭게 확장된 기능들로 카테고리도 새롭게 정비하고 추가가 되었네요.

[그림1] Visual Studio Gallery 웹 사이트 리뉴얼

 

새로운 표준적인 배포 패키징

그리고 Visual Studio 2010 은 확장 기능을 신뢰할 수 있고, 쉽게 배포하고 사용할 수 있는 배포 방법으로 VSIX 배포 패키징을 지원하게 되었습니다. VSIX 는 .NET Framework 에서 제공하는 패키징 방법으로 System.IO.Packaging 으로 신뢰할 수 있고 범용적인 ZIP 압축 방법을 통한 패키징 방법입니다.

System.IO.Packaging 은 .NET Framework 3.0 부터 지원하는 XPS Document 를 배포하기 위해 지원이 되었고 최근에는 실버라이트의 XAP 에도 표준적인 패키징 기술이 적용된 것으로 알고 있습니다.

System.IO.Packaging 은 아래의 링크를 통해 자세한 내용을 확인하세요.

A New Standard For Packaging Your Data
http://msdn.microsoft.com/en-us/magazine/cc163372.aspx

 

Visual Studio Extension Manager

Visual Studio 2010 에서는 확장 기능을 개발하기 위해 MEF Component 를 제공합니다. 개발자가 Visual Studio 의 코드 편집기를 가장 많이 사용하고, 그래서인지 Visual Studio 2010 의 WPF 기술은 코드 편집기가 주 타겟이 되었던 것 같습니다. 그래서 코드 편집기는 WPF 를 통해 화려한 모습으로 변신하였고 내부적인 코드 편집기의 아키텍처링도 완전히 바뀐 모습입니다.

새로운 코드 편집기는 기존의 인터페이스를 모두 버리고, Wpf 접두어가 붙힌 IWpfTextView 등의 인터페이스가 대거 등장하게 되었습니다. 그리고 대부분의 확장 기능은 코드 편집기를 쉽게 확장할 수 있는 인터페이스를 제공합니다. 여기에 MEF(Managed Extensibility Framework) 를 사용하여 인터페이스가 원하는 표준적인 메타데이터(Metadata) 만 선언해 주면 쉽게 확장 기능을 개발도 할 수 있습니다.

사설은 여기까지 마치고 Visual Studio 2010 의 Extension Manager 를 구경해 볼까요?

[그림2] Tools>Extension Manager

   

[그림3] 쉬운 확장 기능 검색과 설치

Online Gallery 를 통해 Visual Studio Gallery 사이트에 등록된 Visual Studio 2010 을 지원하는 컴포넌트를 자동으로 검색하고 DownLoad 버튼을 누르면 바로 설치를 할 수 있습니다.

[그림4] Demo Dashboard 확장 기능을 설치한 모습

아직은 많은 확장 기능 컴포넌트가 등록되지 않았지만, Beta 1 버전이 출시가 된지 몇 일 안된것을 고려한다면 그리 적은 양은 아닌 것 같네요. 현재까지 제공되는 확장 기능을 가지고 노는 것만으로 쏠쏠한 재미가 될 듯 하네요...

   

Visual Studio 2010 SDK 와 Readme

VIsual Studio Extensibility 2009. 5. 22. 09:30 Posted by POWERUMC
Visual Studio 2010 Beta 1 이 Microsoft MVP 에게 공개되는 것을 시점으로 지난 20일에는 일반인들에게도 공개가 되었습니다. 이미 구글 검색을 해보면 알겠지만 이번 Beta 1 릴리즈에 대한 소식이 미어 터질 정도로 쏟아져 나오고 있습니다.
 
Visual Studio 2010 Beta 1 SDK 도 Microsoft Download Center 에서 Shell-Integrated 만을 먼저 공개하였습니다. SDK 까지 내놓았다는 것은 이미 Visual Studio 2010 Beta 1 버전임에도 왠만한 IDE 의 아키텍트는 구현이 되었다는 증거겠죠?
 
Visual Studio 2010 SDK Beta 1
 
 
Microsoft MVP 에게는 이번 Beta 1 버전이 나오기 전에 신청자에 한해서 이와 유사한 버전이 공개가 되었었습니다. 이번 Beta 1 과는 빌드 버전이 크게 차이는 없습니다만 이번 Beta 1 에서는 내부적으로 훨씬 많은 기능 향상이 있었습니다. Parallel Debugging 도 완성이 되었고 Visual Studio Gallery 의 리뉴얼과 함께 Extension Manager 도 정상적으로 가동이 되는 듯 합니다.
 
특히나 이유 없이 뻗어버리던 거센 반항은 이번 Beta 1 에서는 겪어보지 못했습니다. (MSDN Forum 에서는 Hang 하신 분들이 몇 분 계시더군요)
 
그런데 문제는 내부적으로 크게 변화된 점은 눈에 띄지 않습니다만, VSX 쪽에서는 미미하게, 그리고 많은 폭으로 (도대체 무슨 의미? -_-) 변화가 찾아왔습니다. 이번 Visual Studio 2010 Beta 1 는 Managed Extensibility Framework 의 Plugin Architect 로 만들어졌으며 Managed Extensibility Framework 을 모르고서는 Visual Studio 2010 을 안다고도 할 수 없어졌습니다. 이미 Beta 1 의 상당한 확장 기능은 MEF 로 구현되었고 이번에 새롭게 추가된 Extension Manager 의 확장 기능도 MEF 가 그 기본이 되고 있기 때문입니다.
 
 
어쨌든 기존의 Visual Studio 2008 의 Package 들을 Visual Studio 2010 으로 마이그레이션 하면서 파악하기 힘든 오류를 턱턱 뱉어냈는데 다행히도 아래의 링크에서 그 문제 해결 방법을 가이드하고 있네요.
 
[그림1] Visual Studio 2008 Package 마이그레이션 오류
 
Visual Studio 2010 SDK Beta 1 Readme
 
 
일단 Visual Studio 2010 의 출발은 굉장히 시원시원 한 것 같습니다. 아직은 기존의 Visual Studio 2008 버전의 대부분이 Visual Studio 2010 으로 컨버팅 된 수준입니다만 2010 버전을 시점으로 IDE 도 Managed 환경으로 탈바꿈 할 준비를 하려는 모양입니다.
 
약간의 거부 반응을 일으켰던 2010 버전의 UI 도 이제는 포근해져가네요. 얼른 기존의 프로젝트를 2010 버전으로 변환해야겠네요^^
 
알아 두면 피가 되고 살이 되는 닷넷엑스퍼트 사람들의 포스트
 
기타 참고
 


Querying the CompositionContainer
 
CompositionContainer 의 Exported 구성 요소를 취득하기 위해서는 컨테이너에 하나의 구성 요소만이 존재해야 합니다. 쿼리(Query) 를 통해 이러한 객체들이 여러 개 존재할 경우 MEF 는 예외를 발생하게 됩니다.
 
바로 아래와 같은 경우이죠.
l 하나의 인스턴스를 요청할 때, 인스턴스를 찾지 못했을 경우
l 하나의 인스턴스를 요청할 때, 인스턴스가 여러 개일 경우
 
GetExportedObject
 
일반적으로 ExportAttribute 에 인자가 전달되지 않은 경우는 클래스의 타입이 키 값이 되어, 아래와 같이 구성 요소를 취득할 수 있습니다.
 
class Program
{
        static void Main(string[] args)
        {
               var container = new CompositionContainer(new AssemblyCatalog(Assembly.GetExecutingAssembly()));
              
               var export = container.GetExportedObject<Export1>();
               export.Say();
 
               Console.ReadKey();
        }
}
 
[Export]
class Export1
{
        public void Say()
        {
               Console.WriteLine("Export1 Say..");
        }
}
 
 
만약, ExportAttribute 에 Contract Name 이 선언이 될 경우는 클래스의 타입 정보와 Contract Name 이 일치해야 구성요소를 취득할 수 있습니다.
 
class Program
{
        static void Main(string[] args)
        {
               var container = new CompositionContainer(new AssemblyCatalog(Assembly.GetExecutingAssembly()));
              
               var export = container.GetExportedObject<Export2>("export2");
               export.Say();
 
               Console.ReadKey();
        }
}
 
[Export("export2")]
public class Export2
{
        public void Say()
        {
               Console.WriteLine("Export2 Say..");
        }
}
 
 
GetExport
 
만약 여러 개의 구성 요소의 인스턴스가 필요하다면 GetExport 메서드를 통해 Export 의 구성 정보를 가져오면 됩니다.
 
var exports = container.GetExport<Export1>();
exports.GetExportedObject().Say();
 
필요하다면 ExportAttribute 의 Contract Name 으로 질의(Query) 할 수 있습니다.
 
var exports = container.GetExport<Export2>("export2");
exports.GetExportedObject().Say();
 
아쉽게도 MEF Preview 4 까지 지원하던 C# 3.0 의 Expression 을 통해 질의하는 방법은 MEF Preview 5 이후 없어진 것이 아쉽네요.
 
GetExportedObjectOrDefault
 
일반적으로 MEF 에서는 질의(Query) 결과가 없을 경우 예외를 발생하게 되는데, GetExportedObjectOrDefault 메서드를 통해 결과가 없을 경우 Null 값으로 대체할 수 있습니다.
 
var obj = container.GetExportedObjectOrDefault<Export1>("A");
if( obj != null )
        obj.Say();
 
 

'Managed Extensibility Framework' 카테고리의 다른 글

MEF 는 Generic Type 을 지원하지 않는다!  (0) 2010.01.29
MEF Preview 6 공개  (0) 2009.07.20
[MEF] 9. Recomposition  (1) 2009.04.19
[MEF] 8. Strongly Typed Metadata  (0) 2009.04.16
[MEF] 7. Exports and Metadata  (0) 2009.04.16

Welcome to Dynamic C#(2) - Wanna be a polyglot.

C# 2009. 5. 17. 16:25 Posted by 알 수 없는 사용자

- 자넨 왜 그렇게 언어에 집착하는고?

넵, 확실히 저는 언어에 쫌 집착하는 편이긴 합니다. 우리가 말하고 쓰는언어도 꽤나 집착하는 편입니다. 언어를 제대로 배우려고 노력하다보면, 더 재밌는 걸 많이 접할 수 있게 되고 그 언어뿐만 아니라 언어를 쓰는 사람들의 사고방식도 아주 조금씩 이해하게 되기 때문이죠. 뭔가 보고싶은게 있는데 그게 제가 모르는 언어로 되어 있어서 못보는건 조금 슬픈일인거 같습니다. 개인적으로 부족한 실력이지만, 미드&일드를 아주 재밌게 즐기고 있습니다.

프로그래밍 언어도 비슷한 의미에서 집착하게 되는게 아닐까 싶습니다. 프로그래밍 언어에는 그 언어를 만들고 지지하는 사람들의 사고방식도 같이 배울 수 있게 되고, 점점 재밌게 할수 있는게 늘어나기 때문이죠. 최근에 언어에 대해서 아주 부족한 의견이지만 글을 썼던 적이 있습니다. 관심있으신 분은 보시고 따쓰한 피드백 주시면 완전 감사하겠습니다. 

아무튼 그런의미에서 F#에 C#에 Axum까지 건드려보고 있는거지요. 줏대가 없다거나 바람기가 있다거나 뭐 그런건 아닙니다. 그럼 본론으로 들어가서, 지난번엔 동적C#에 대한 이야기를 조금 드렸었습니다. 하지만 정작 알고 싶은건 dynamic키워드란게 생겼고 대충 오리꽥꽥 어쩌구 저쩌구 하는건 알겠는데, 어디다 써먹는거란 말이더냐? 뭐 그런거겠죠. 그래서 쌩초보이지만, 최대한 그런관점에서 접근해보고자 합니다. 그 첫번째가 실제로 프로젝트를 하다가 하나 느낀게 있어서 그걸 적어보고자 합니다. 



- 시나리오
(제가 모르는 해결방법이 있을수도 있습니다. 그럴땐 따쓰한 피드백을!)

LINQ to SQL(이하 L2S)로 프로젝트를 진행중입니다만, 데이터가 추가되거나, 수정되거나 삭제될때 그 값들의 이전/이후 데이터를 포함해서 그 데이터의 고유번호(seq)를 같이 저장하는 뭐 그런 시나리오입니다. 그래서 L2S에서는 아래와 같은 방법을 제공합니다.

 

ChangeSet changeSet = db.GetChangeSet();

foreach (Customer c in changeSet.Inserts)
{
	.......
}

 

하지만, 위와 같은 코드는 한번의 SubmitChanges로 변경이 일어나는 대상 테이블이 하나라면 Generic파라미터로 처리할 수도 있겠지만(ChangeSet에서 리턴되는 객체의 타입이 object입니다), 주문과 상세주문같이 한번에 여러개의 테이블에 변경이 일어난다면, 그닥 친절하지 못한 시나리오가 되겠습니다. 그래서 그때 들었던 생각이 "아 이거 dynamic키워드를 이용해서 오리꽥꽥타이핑(duck typing)을 이용하면, 쫌 쉽게 될거 같은뎅..." 였습니다. 그래서 한번 살짝 구현해봤습니다.

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;

namespace FirstDynamic
{
    class Customer
    {
        public int Seq{get; set;}
        public string Name {get; set;}        
    }

    class Company
    {
        public int Seq{get; set;}
        public string Name{get; set;}
    }

    class Project
    {
        public int Seq{get; set;}
        public string Name{get; set;}
    }

    class NoneSeqThing
    {
        public string Name{get; set;}
    }

    class Logger
    {
        public void WriteLog(dynamic entity)
        {
            try{
                Console.WriteLine(entity.Seq);
            }
            catch(Microsoft.CSharp.RuntimeBinder.RuntimeBinderException ex)
            {
                Console.WriteLine("Exception : " + ex.Message);
            }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {            
            Logger logger = new Logger();

            Customer customer = new Customer
            {
                Seq = 1,
                Name = "Boram"
            };

            Company company = new Company
            {
                Seq = 6,
                Name = "NanoSoft"
            };

            Project project = new Project
            {
                Seq = 108,
                Name = ".NET 99.9"
            };

            NoneSeqThing noneSeqThing = new NoneSeqThing
            {
                Name = "None Seq Thing"
            };

            object[] entities = new object[] { customer, company, project, noneSeqThing };

            foreach (object entity in entities)
            {
                logger.WriteLog(entity);
            }
        }
    }
}

 

위에서는 몇가지 객체를 선언해서 DTO를 흉내냈고, Seq가 있는 타입과 없는 타입이 있는 것을 볼 수 있습니다. 그리고 ChangeSet에서 반환되는 객체를 그냥 dynamic으로 Logger에게 넘겨주고 있습니다. 그리고 Seq멤버변수가 있으면 남기고 없으면 안남기는 식으로 다른 처리를 해주고 있습니다. 그리고 결과는 아래와 같습니다.



그렇습니다, 이런식으로 dynamic을 이용한다면 지난 포스트에서 Paul Graham아자씨가 이야기 했던 나이들고 엄한 이모 컴파일러와 좀더 편하게 대화할 수 있는 법이죠. 써놓고 보니깐 포스트가 별거 없네요. 기분 탓이 아니라 제 내공 탓이겠죠. 여담이지만, 제가 해결한 방식은 리플렉션으로 Seq프로퍼티를 검색해서 유/무를 판별하는 방식을 이용했습니다. 확실히 손이 좀더 많이 가는 방법이죠.

이렇게 여러가지 패러다임에 익숙해지고 잘 활용할 수 있게 되면, 점점 더 빠르고 경쾌한 리듬으로 코드를 작성하는 일도 가능하지 않을까 생각해봅니다. 이제 프로그래밍을 하시는 분들도 세계화에 발맞추는 속도에 걸맞게 프로그래밍언어에 대해서도  ployglot이 되어야 하지 않을까 생각합니다. 다만, 제 생각엔 그러한 노력은 프로그래머에게 족쇄를 채우는게 아니라 오히려 더 큰 자유를 주는 일이라고 생각합니다. 그럼, 또 개발하다가 dynamic의 헬프가 필요한 순간이 오면 나누도록 하겠습니다.

여담이지만, polyglot하니깐 중학교때 "핸들 이빠이 돌려"라는 한문장으로 3개국어를 자유자재로 구사하시던 한문선생님이 떠오르는 군요. ㅋ


-참고자료
1. Pro LINQ: Language Integrated Query in C# 2008, Joseph C. Rattz, Jr. , APRESS.

Welcome to Parellel world(1) - Here comes a new challenger!

C# Parallel Programming 2009. 5. 16. 16:04 Posted by 알 수 없는 사용자

-신 캐릭터의 등장.

언제나 새로운 캐릭터의 등장은 가슴을 설레이게 하는거 같습니다. 디아블로 같은 액션 RPG도, 스타크래프트같은 전략시뮬에서도, 미연시에서...... 그리고 비주얼스튜디오에서도 말이죠. Axum은 딱히 비주얼스튜디오 2010에 포함되기로 이야기 되는 언어는 아닙니다만, 왠지 2010이나 그 이후버전에선 정식으로 편입되어서 중요한 역할을 할 것같은 느낌이 들어서 아주 조금씩 소개를 드려볼까 합니다. 물론 Welcome to Parallel world에서는 Axum만 다루진 않을 거구요 기타 다른 병렬프로그래밍에 대한 이슈들을 쌩초보의 입장에서 공부하면서 정리해보고자 합니다. 신기한게 보이면 그냥 못지나치는 성격이라 시간은 부족해지는데 일은 계속해서 늘리고 있군요. 아무튼, 관심있는분들의 많은 따쓰한 피드백을 기다리며 시작해보겠습니다. 

-Axum????

Axum은 위에서 설명드린것 처럼 딱히 아직 구체적인 계획은 없고 그저 실험적으로 개발되고 있는 새로운 언어입니다. 가이드문서에서는 아래와 같이 설명을 하고 있군요.

Writing a parallel program typically requires partitioning the solution into a number of parallel tasks. Some problems are easily amenable to parallelization because the tasks can run independently of each other. In other problems the tasks have interdependencies and require coordination. ......... With Axum, we offer a language that allows programmers to arrange coordination between components in a way that is close to their natural conception of the solution. In other words, if you can model your solution in terms of interactive components, encoding it in Axum will be straightforward, and you will likely avoid many common concurrency-related bugs. 

병렬 프로그램을 작성하려면, 프로그램을 여러개의 작은 병렬작업들로 쪼개는 작업이 필요합니다. 몇가지 문제들은 애초에 서로 독립적으로 수행될 수 있으니깐 쉽게 병렬화시킬 수 있습니다. 다른 몇가지 문제들은 서로 연관되어 있기 때문에 순서를 잘 정해줘야 합니다. .... Axum은 그러한 수행순서등을 솔루션이 원래 동작해야 하는 시나리오에 근접하게 잘 정리하도록 도와주는 새로운 언어입니다. 부연 설명을 하자면, 문제해결을 위한 솔루션을 컴포넌트들의 상호작용모델로 그려낼 수 있다면, 이런 솔루션을 Axum으로 표현하는 작업은 매우 직관적이고 쉬울 것입니다. 그래서 프로그래머들은 매우 흔히 발생하는 동시성과 관련된 버그를 피할 수 있게 되는 것이죠.


즉, 병렬프로그래밍을 지원하기 위한 새로운 DSL이라고 생각하면 될 것 같기도 하군요. Axum은 C#과 비슷한 점이 많기도 하고 틀린점도 있는데 대강정리해보면 아래와 같습니다.

-C#과 Axum이 가진 공통점은 :
      모든 C# 3.0의 람다와 LINQ쿼리 같은 표현식들
      모든 C# 3.0의 yield와 yield break같은 구문들
      메서드와 필드 정의들
      델리게이트와 이뉴머레이션 타입들 

-Axum에서 볼 수 없는 C#의 요소들
      클래스, 인터페이스와 구조체
      연산자 정의들
      프로퍼티
      상수 필드와 상수지역변수
      정적 필드와 정적 메서드 

-Axum에서만 볼 수 있는 요소들
      에이전트 와 도메인
      채널
      스키마
      네트워크
      Interleaved control flow


그렇다는 하는 군요. 아무튼, 정리해보면 'Axum은 C#과 비슷한 점도 있고 틀린점도 있으며 병렬프로그래밍을 지원하기 위해서 새롭게 실험적으로 개발되고 있는 DSL이다' 정도가 되려나요?

DSL이라는 말은 제가 붙인겁니다만, 아무튼 모냥을 보니 병렬프로그래밍이라는 부분에 특화된 모습을 보이면서 class정의는 C#, F#, Managed C++, Visual Basic.NET등의 언어를 통해서 하거나 C#을 통해 직접 정의할 수 있다는 걸로 봐서는 DSL이라고 보는게 맞는거 같기도 하군요. 여담이지만 위에서 언급한 4개의 언어의 순서는 제 맘대로 한건 아니구요 문서에 있는 순서를 그대로 언급한 겁니다. F#도 이제 MS내에서도 중요하게 생각하고 있다는 걸까요? 왠지 급흐뭇해 지는 군요.
(찾아보니 이전에 Maestro라는 코드네임으로 개발되던 언어였고 DSL이 맞군요 ㅋ)


여담2 이지만 이런 구절도 있었습니다. "Axum is a .NET language and can use libraries written in other .NET language such as C#, Visual Basic or F#." 이제 F#도 C#과 VB.NET으로 대표되는 주요언어에 포함되는 느낌이로군요 캬캬캬.

아무튼, Axum은 여기서 받으실 수 있습니다. 그리고 그 사이트에서 문서도 보실 수 있구요. 좀 더 자세한 이야기는 다음포스트로 넘기기로 할까요?

-나만 몰랐던가? concurrency와 parallel은 다른 것이다!

일단, 사전적 정의를 보자면 아래과 같습니다.

concurrent - 무언가가 시간적으로 동시에 일어나는 이미지
parallel - 무언가 동일한게 시간&공간적으로 다른곳에 존재하는 이미지

그리고 여기에 대한 좋은 설명이 있어서 참고해봤는데요, 싱글코어 CPU에서 실행되는 두개의 concurrent한 스레드는 concurrent하지만, parallel하지는 않다는 이야기이고... parallel은 멀티코어, 멀티CPU, 분산환경에서 얻을 수 있는 장점이라는 이야기더군요 즉, concurrent하다고 해서, parallel한것은 아니라는 것입니다.

 

- 참고자료

1. Axum Programmer's Guide, Microsoft Corporation
2. AXUM LANGUAGE OVERVIEW, Niklas Gustafsson
3. http://blogs.sun.com/yuanlin/entry/concurrency_vs_parallelism_concurrent_programming


Visual Studio Team System 2010 Beta 1 이 다가오는 월요일(2009-05-18) 에 MSDN 을 통해 공개가 되고 다운로드 할 수 있다고 합니다. 단, 일반인들에게는 20일에 다운로드가 가능하다고 합니다.
 
 
 
Visual Studio Platform 팀에서 개발 리드를 담당하고 있는 Pedro Silva 씨는 블로그에 이번 Beta 1 에는 Visual Studio SDK 도 포함이 된다고 합니다. SDK 도 포함이 된 것으로 추정하면 대부분의 Visual Studio 2010 의 기능은 이전 버전보다 완성도가 상당히 높아졌으리라 생각합니다. 이전 버전에서는 Visual Studio 2010 이 이전 버전과의 비호환적인 부분이 많았는데 어떻게 변했을지 더욱 궁금해지네요.
 
Visual Studio 2010 에 대한 공식 Product 는 여기 에서 참고하시면 됩니다.
 
References
 
 


네번째입니다.

Combinable에 대해 자세히 다루고 PPL을 마무리한 뒤, Asynchronous Agents Library가 소개됩니다.


잘못된 번역이나 부족한 부분 있으면 알려주세요. ^^

Welcome to F#(8) - 은총알과 엄친아.

F# 2009. 5. 10. 20:56 Posted by 알 수 없는 사용자
-넌 제목이 왜 맨날 이 모냥이냐.

은총알과 엄친아. 과연 전 무슨생각으로 제목을 맨날 이렇게 짓는 걸까요? 개인적으로 포스트에서 이야기 하고자 하는걸 비유적으로 설명하는걸 좋아합니다. 그래서 일까요? 늘 글을 쓰기 전에 이야기 하고자 하는 내용을 심사숙고합니다. 그렇게 해서 나오는게 고작 요정도 인거죠.

은총알. 은초딩도 아니고 이건 뭘까요? 들어보신분들도 많으시겠지만, 소프트웨어 공학에서 이야기하는 모든 문제가 이거하나면 해결된다고 하는 그런 어떤 경우에도 쓸 수 있는 만능의 해결책? 그정도 느낌을 생각하시면 될거 같습니다. 즉, 많은 사람들을 파닥파닥 낚이게 만드는 주범이지요. 엄친아도 못하는게 없는 만능의 엄마친구아들을 뜻하죠. 적어도 프로그래밍 세계에선 은총알이나 엄친아 같은 프로그래밍언어는 없는거 같습니다. 아무리 C#이 발전했다 한들, 하자면 할 수 있지만 어색한 부분이 있다는 거죠. 그럼 오늘은 거기에 대해서 좀 이야기 해보겠습니다.


- 이거슨 F# 코드!

아래 코드는 Expert F#에 나오는 코드입니다.

open System.Collections.Generic

let devideIntoEquivalenceClasses keyf seq =
    let dict = new Dictionary<'key, ResizeArray<'a>>()
    
    seq |> Seq.iter(fun v ->
        let key = keyf v
        let ok, prev = dict.TryGetValue(key)
        if ok then prev.Add(v)
        else 
            let prev = new ResizeArray<'a>()
            dict.[key] <- prev
            prev.Add(v))
            
    dict |> Seq.map(fun group -> group.Key, Seq.readonly group.Value)

즉, 어떤 데이터의 집합과 그 데이터에 대해 수행할 함수를 받아서 각각의 데이터에 대해 그 함수를 수행합니다. 그리고 같은 결과 끼리 집합을 만들어서, 결과값과 결과값이 같은 데이터들의 집합을 Dictionary로 만들어서 리턴해주는 프로그램이죠. 즉, 함수형언어의 장점이 잘 드러나는 데이터처리부분의 예제입니다. 실행결과는 아래와 같습니다. 

> devideIntoEquivalenceClasses (fun x -> x % 3) [1..10];;
val it : seq<int * seq<int>>
= seq [(1, seq [1; 4; 7; 10]); (2, seq [2; 5; 8]); (0, seq [3; 6; 9])]

숫자를 3으로 나눈나머지를 구하는 함수와, 1부터 10까지의 숫자를 넘겨주면, 이렇게 나머지값이 같은 숫자별로 그룹을 지어서 리턴해줍니다. 여기서 Dictionary는 닷넷의 클래스를 그대로 사용한 거구요, ResizeArray는 닷넷에서의 System.Collections.Generic.List<T>의 줄임말입입니다. 이름그대로 mutable한, 사이즈를 조절가능한 Array라는 거죠. 

코드를 보면, 전체데이터를 포함할 dict라는 Dictionary를 선언하구요, 입력으로 들어온 seq의 각요소에 대해서 사용자가 넘겨준 함수(keyf)를 수행합니다. 그리고 그 결과값이 이미 존재하는지 확인해서 존재한다면, 그 결과값을 key로 하는 ResizeArray에 숫자값을 추가하고 존재하지 않는다면, 새로운 ResizeArray를 만들어서 숫자를 추가하고, 그 ResizeArray를 dict에 추가해주는 방식입니다.

그리곤 마지막으로 key에 해당하는 ResizeArray를 읽기전용인 시퀀스로 만들어서 리턴해주고 있습니다. 이 예제는 어떤 함수에서 내부적으로는 side-effect를 가진 자료구조를 쓰더라도 그 side-effect를 오직 내부에서만 나타나게 격리한다면, 그 함수는 pure하고 functional한 함수라는 이야기를 하면서 나온 예제입니다. 그래서 마지막에 읽기전용 시퀀스로 리턴을 해주고 있는거지요. 


- 이거슨 C#코드!

이 코드를 C# 3.0버전으로 그대로 옮겨 보겠습니다. 

class Program
    {
        public Dictionary<T2, List<T1>> DivideIntoEquivalenceClasses<T1, T2>>(Func<T1,T2> func, List<T1> list)
        {
            Dictionary<T2, List<T1>> dict = new Dictionary<T2, List<T1>>();

            list.ForEach(l => {
                T2 key = func(l);
                if (dict.ContainsKey(key))
                {
                    dict[key].Add(l);
                }
                else
                {
                    List<T1> prev = new List<T1>();
                    dict[key] = prev;
                    prev.Add(l);
                }
            });

            return dict;
        }

        static void Main(string[] args)
        {
            Program program = new Program();

            var dict = program.DivideIntoEquivalenceClasses((x => x % 3), new List<INT> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 });

            var resultSet = dict.Select(item => new { item.Key, item.Value });

            foreach (var result in resultSet)
            {                
                Console.Write("{0},", result.Key);
                result.Value.ForEach(item => Console.Write(" {0} ", item));
                Console.WriteLine();
            }
        }
    }

실행결과는 아래과 같구요.



역시 func<>를 이용한 higher-order와 LINQ덕분에 코드의 길이자체가 별로 차이가 없고, 오히려 C#의 문법에 익숙해서 그런지 더 깔끔해 보이는 부분도 있네요. 다만, 눈에 상당히 거슬리는게 있다면, T1,T2를 비롯한 파라미터타입과 리턴타입등을 명시한 부분이 상당히 거슬리는군요. 사실 짜면서도 아직 익숙하지 않아서 일까 좀 헷갈렸습니다. F#에서는 Type inference가 제대로 적용되어서 파라미터에도 타입을 명시할 필요가 없죠. 물론 C#에서도 변수수준에서는 var타입을 이용해서 Type inference를 지원하지만, 파라미터와 리턴타입에 대해서는 지원하지 않기 때문에 쫌 복잡해질 수 있습니다. 함수형 프로그래밍을 C#에서 하느라 복잡해지는 모냥은 여기에서도 확인하실 수 있습니다. @_@.

 
아래구절은 Expert F#에서 인용한 구절인데요, 제가 설명하려는 바를 아주 잘 요약해주시고 있습니다.

 A key feature of F# is the automatic generalization of code. The combination of automatic
generalization and type inference makes many programs simpler, more succinct, and more

general. It also greatly enhances code reuse. Languages without automatic generalization force programmers to compute and explicitly write down the most general type of their functions, and often this is so tedious that programmers do not take the time to abstract common patterns of data manipulation and control.

F#의 핵심기능중의 하나가 바로 코드를 자동으로 일반화시켜주는 것이다. 자동일반화와 타입유추를 조합하게 되면 많은 프로그램을 간단하고, 좀더 명확하게 그리고 좀 더 일반화시켜서 작성할 수 있다. 당연히 코드 재사용도 아주 편리해 진다. 자동일반화를 지원하지 않는 언어는 프로그래머가 명시적으로 일반적인 타입을 계산해서 명시해야 만 한다. 그리고 이런 것들은 데이터처리와 그 처리의 흐름을 공통적인 부분을 묶어서 추상화하는 작업을 매우 손이 많이가고 짜증나는 작업으로 만든다.



- 그래서~?

즉, LINQ를 통해 C#에서의 데이터처리와 흐름의 추상화가 가능해졌으며, 그 덕에 C#으로도 부분적으로 함수형언어와 버금가는 생산성을 내는일이 가능해졌습니다. 하지만, 명령형 언어의 한계점이 이런부분일까요? 일반화를 하기 위해서 무척이나 까다롭게 인자들의 타입을 잘 명시해줘야 하는거죠. 물론, 저렇게 하는게 옳은지에 대해서는 잘 모르겠습니다. 개인적으로는 저런부분을 굳이 C#을 이용해서 구현하려고 애쓰기 보다는 F#을 이용해서 조합하는게 더 옳지 않나 싶습니다. 사실 F#을 닷넷에 편입시키려는 의도도 그런부분을 가장 기대하는게 아닌가 싶기도 하구요. 


- 참고자료

1. Expert F#, Don Syme, Adam Granicz, Antonio Cisternino, APRESS
2. http://weblogs.asp.net/podwysocki/archive/2009/04/26/functional-c-forward-functional-composition.aspx

 

세번째입니다.

관련 디버깅 유틸과 PPL 지원 알고리즘, 이미징 예제 병렬화, 동기화 개체자료구조 등이 소개됩니다.


잘못된 번역이나 부족한 부분 있으면 알려주세요. ^^

Welcome to Dynamic C#(1) - 첫만남.

C# 2009. 5. 4. 14:37 Posted by 알 수 없는 사용자

-너 F#쓰던 넘이자나, Dynamic C#은 뭐냐.

안녕하세요. Welcome to F#이라는 앞뒤도 안맞고 내용도 부실하며, 불친절한 포스트를 남발하고 있는 강보람(워너비)입니다. 원래 하던거에 약간 시들해지면, 새로운 자극을 찾는다고 하던가요. F#의 포스트를 쓰는게 점점 벽에 부딛히니 C#과 자극적인 외도를..... 생각하는건 아닙니다. 하지만, 의문이 생기니 그걸 찾아보고자 하는 호기심이 생기고, 그 호기심을 오래잠재워두면 없어질거 같아서 일단 시리즈를 시작해보자! 해서 일단 무작정 Welcome to Dynamic C#이라는 시리즈를 시작해볼까 합니다. 기존에 동적언어에 대한 경험이 일천하다보니 이 시리즈의 내용역시 상당히 불친절할걸로 예상되지만, 관심있으신 분들께선 따쓰한 피드백을 주시기 바랍니다. 이제 날씨가 더워지는데 따쓰한 피드백을 주면 제가 열사병으로 죽지는 않을까 하는 염려는 고이접어 간직하시고 따쓰한 피드백을....-_-


-Paul Graham아저씨와 실용주의 아저씨들?

Paul Graham을 아십니까? "Hackers and Painters"의 저자이며, 논쟁을 불러일으킬만한 말을 참 많이도 하는 Lisp빠돌이죠. 오랜만에 Hackers and Painter를 읽다가 아래와 같은 구절을 읽고는 '이 책에 이런구절이 있었나~?' 하면서 C# 4.0의 dynamic과 DLR이 떠올랐습니다. 

A programming language is for thinking of programs, not for expressing programs you've already thought of. It should be a pencil, not a pen. Static typing would be a fine idea if people actually did write programs the way they taught me to in college. But that's not how any of the hackers I know write programs. We need a language that lets us scribble and smudge and smear, not a language where you have to sit with a teacup of types balanced on your knee and make polite conversation with a strict old aunt of a complier. 

프로그래밍언어는 프로그램에 대해서 생각해나가기 위한 것이지, 이미 머리속에 짜여져있는 프로그램을 표현하기 위한 것이 아닙니다. 프로그래밍언어는 펜이 아니라 연필이어야 합니다. 정적타입은 제가 학교에서 배우던 것 처럼만 프로그램을 짠다면 괜찮은 아이이디어 일지도 모르겠습니다. 하지만 제가 아는 해커들중에 그렇게 짜는 사람은 한명도 없더군요. 우리는 명확하지 않은 아이디어를 흐릿한 형태 그대로 빠르게 묘사할 수 있게 해주는 언어가 필요합니다. 무릎에 타입이라는 찻잔을 떨어지지 않게 올려놓고, 나이많고 엄격하신 이모님이랑 공손하게 대화하려고 애쓰는 것 처럼 컴파일러와 대화할 필요가 없다는 거죠.


그리고는 예전에 사두었던 "Programming Ruby"를 꺼내서 읽어봤습니다. "실용주의 프로그래머"를 읽으면서 실용주의 학파로 유명한 데이비드 토머스와 앤디 헌트가  펄에서 루비로 관심사를 옮겼다는 사실은 알고 있었지만, 이 책을 읽으면서 이들의 동적언어에 대한 사랑이 확실하게 드러나더군요.

반면에 루비를 잠깐이라도 사용해본다면, 동적 타입을 갖는 변수가 많은 점에서 실질적으로 생산성을 향상시킴을 알게 될 것이다. 오랜 기간 실행되는 커다란 루비 프로그램이 중요한 작업을 수행하면서도, 타입과 관련된 오류는 하나도 던지지 않고 잘 돌아간다. 왜 일까? ..... 결론적으로 말해 '타입 안전성'에서 말하는 '안전성'이란 대개 허상에 불과하며, 루비 같은 동적 언어로 개발하는 것은 안전하면서도 생산적이다.

이런 호기심이 생기자, F#때문에 미뤄오던 C#4.0의 dynamic에 대한 탐구를 더 이상 미룰 수 없다는 생각이 들었습니다. 그래서 가끔 생각날때 마다 dynamic에 대한 생각을 정리해서 올리려고 지금 포석을 깔고자 하는 것이죠. 대뜸 F#에 대해서 쓰다가 C#으로 옮겨가면, 읽으시는 분들도 혼란을 느끼시지 않을까 해서 말이죠. 물론 그런분덜 한분도 없을거 압니다-_-. 


-반갑다! dynamic! 

일단, dynamic에 대해서 조금 알아보도록 하겠습니다. dynamic은 말 그대로 동적이라는 거구요, 타입체크를 컴파일 타임이 아니라 수행순간에 즉, 런타임에서 하겠다는 말이 됩니다. 여기서 Duck typing이라는 개념이 들어가게 되는데요, Duck typing은 객체의 타입에 따라서 가능여부를 결정하는 게 아니라, 그저 요건을 갖추고 있다면 모두다 가능하다고 보는 거죠. 즉, 비유를 하나 하자면 조선시대의 어떤 모임을 생각해 보겠습니다.

이 모임에서 양반집의 지체높은 어르신들과 그 어르신들의 자제들만 회원으로 받아준다면 이 모임은 정적타입검사(Static type check)를 하고 있는셈입니다. 특정 계급(Type)만 들여보내주기 때문이죠. 타입이 틀리면 아예들어갈 수가 없습니다. 하지만, 어떤 모임에서는 그림에 관심이 있는 사람이라면, 양반이나 상놈 가리지 않고 모두다 받아들여줬습니다. 이 모임은 바로 Duck typing을 충실히 따르고 있는셈입니다. 계급(타입)에 상관없이 그저 공통점(그림을 사랑하는 뜨거운 가슴!)만 있으면 들여보내주기 때문이죠. Duck typing은 이처럼 타입으로 가르지 않고, 요건을 갖췄다면 모두 묻지도 따지지도 않고 받아들여주는 걸 이야기 합니다.(Duck이 들어가 있는 이유는 애초에 이 개념을 설명하신 분께서 오리처럼 걷고 꽥거리면 전부다 오리로 봐주자고 말씀하셨기 때문이죠. 제가 안그랬습니다-_-. 오히려 제가 만들었다면, '동호회 타이핑' 같은용어를 썼을거 같은데... 제가 안만든게 다행이군요.) 

그럼 첫 예제를 한번 볼까요? 

static void Main(string[] args)
{
            dynamic num = 4;

            Console.WriteLine(num);
 

            Type type = num.GetType();
            MethodInfo method = type.GetMethod("ToString", new Type[] {});

            if (method != null)
            {
                Console.WriteLine(method.ToString());
            }
} 

위 예제는 dynamic타입의 num에 숫자인 4를 입력하고, 출력을 합니다. 그리고 WriteLine에 의해서 불려지는 ToString메서드의 유무를 검사하기 위해서, 타입에서 ToString메서드를 찾아서 출력하는 프로그램입니다. 결과는 아래와 같습니다. 



WriteLine에선 출력할 객체의 ToString을 호출하죠. 그래서 num의 값이 출력되는 것을 보면 런타임에 num이 ToString을 가지고 있는지 확인해서 있으니까 출력을 했다고 볼 수 있습니다. 그리고 확인을 위해서 dynamic타입인 num의 타입에서 ToString메서드를 찾아서 해당 메서드를 출력해봅니다. 결과를 보면 ToString이 있는 것을 볼 수 있습니다. 그리고 WriteLine의 오버로딩중에서 dynamic타입을 인자로 받아들이는 오버로딩이 없는걸로 봐서는, 런타임에 해당 dynamic객체가 ToString을 가지고 있는지 봐서 있으면 출력하고, 없으면 Microsoft.CSharp.RuntimeBinder.RuntimeBinderException을 발생시키는 것을 유추할 수 있습니다.


-양반과 상놈의 이야기 

그럼 위에서 이야기 했던, 양반과 상놈의 이야기를 한번 구현해볼까요? 

class Yangban
    {
        public string Name {get; set;}

        public void YangbanSound()
        {
            Console.WriteLine("Yo, it's the yangban sound, baby :) ");
        }
    }

    class YangbanChild : Yangban
    {
        public void ILikeDrawing()
        {
            Console.WriteLine("I like Drawing");
        }
    }

    class Sangnom
    {
        public string Name { get; set; }

        public void SangnomSound()
        {
            Console.WriteLine("Yo, it's the sangnom sound, baby ;) ");
        }

        public void ILikeDrawing()
        {
            Console.WriteLine("I like Drawing");
        }
    }

    class Program
    {
        public void EnteringYangbanClub(Yangban yangban)
        {
            Console.WriteLine("Welcome yangban {0}!", yangban.Name);
        }

        public void EnteringDrawingClub(dynamic person)
        {
            try
            {
                person.ILikeDrawing();
                Console.WriteLine("Welcome {0}! who like drawing",person.Name);
            }
            catch (Microsoft.CSharp.RuntimeBinder.RuntimeBinderException you_do_not_like_drawing)
            {
                Console.WriteLine("{0}. You can't come in. I'm sorry about that :)", person.Name);
            }
        }

        static void Main(string[] args)
        {
            Yangban yangban1 = new Yangban { Name = "chulsoo" };
            YangbanChild yangbanChild1 = new YangbanChild { Name = "chulsooAdeul" };
            Sangnom sangnom1 = new Sangnom { Name = "boram" };

            Program program = new Program();
            program.EnteringDrawingClub(yangban1);
            program.EnteringDrawingClub(yangbanChild1);
            program.EnteringDrawingClub(sangnom1);
        }
    }

위 코드를 보시면, 양반과 양반자식, 상놈이 있죠? 모두 이름을 가지고 있구요, 양반은 간지나는 양반사운드를 구사하며, 상놈은 상놈사운드 그리고 양반자식과 상놈은 자기가 그림그리는걸 좋아한다고 합니다. 그리고 두개의 클럽이 있습니다. 하나는 양반만 들어갈 수 있는 클럽이구요, 하나는 그림을 좋아하는 사람이 들어갈 수 있는 클럽입니다. 자 그럼, 양반과 양반자식인 철수와 철수아들, 상놈인 보람을 데리고 이야기를 해보겠습니다. 양반클럽에 철수와 철수아들, 보람 이렇게 셋이 들어가려고 합니다. 그런데, 양반클럽은 양반이거나 양반의 자제가 아니면 못들가게 엄격하게 막아놨습니다. 그래서 일까요? 아래 그림을 보면, 들어가고 싶다는 의사표시조차도 허용되지 않는 슬픈 모습입니다. 

뭐, 계급으로 딱 막혀있기 때문에 들어가는거 자체가 불가능하니까요. 이렇게 타입으로 조건을 걸게되면, 해당타입이거나 해당타입을 상속한 타입이 아니면 안됩니다. 그러면, 그림애호가 클럽에 들어가보도록 하겠습니다. 그림애호가클럽은 일단 다 들여보내주는 군요. 하지만, 들어가게되면 그림을 좋아하는지 크게 외쳐보라고 시킵니다. 근데, 철수는 그림을 좋아하지 않는군요. 그래서 철수는 쫓겨나고 철수아들과 보람은 환영받습니다. 실행결과는 아래와 같죠.


그렇습니다. 계급으로 나누것이 아니라 무엇을 할 수 있는지에 따라 니편 내편을 나누니깐 철수는 못들어가고 보람은 들어가게 되는 것이죠.


-근데 dynamic이거 어따 쓰면 조으까? 

도대체 이걸로 무엇을 할 수 있다는 걸까요? 왜 Paul Graham아저씨는 그토록 다이나믹을 부르짖었으며, 실용주의 아저씨들은 또 왜그랬을까요? 불행히도 저는 그동안 정적인 명령형 언어만 다뤄봤기 때문에 잘 모르겠습니다. 뭐 좀 알아보려고 하는데, 그 과정에서 느끼는 점들을 이곳을 통해 나눠보려고 하는거구요. 그럼 F#뿐만 아니라 C#을 통해서 최대한 자주 찾아뵙겠습니다.


-참고자료

1. Hackers and Painters, Paul Graham, O'Reilly
2. Programming Ruby, 데이비드 토머스, 앤디 헌트, 차드파울러, 인사이트
3. http://code.msdn.microsoft.com/Project/Download/FileDownload.aspx?ProjectName=csharpfuture&DownloadId=3550