Parallel Patterns Library(PPL) - concurrent_queue - 2

VC++ 10 Concurrency Runtime 2010. 1. 16. 09:00 Posted by 알 수 없는 사용자

concurrent_queue는 사용 용도가 concurrent_vector 보다 더 많을 것 같아서 좀 더 자세하게 설명하겠습니다.

 

온라인 서버 애플리케이션의 경우 Producer-Consumer 모델이나 이와 비슷한 모델로 네트웍을 통해서 받은 패킷을 처리합니다. 즉 스레드 A는 네트웍을 통해서 패킷을 받으면 Queue에 넣습니다. 그리고 스레드 B Queue에서 패킷을 꺼내와서 처리합니다. 이 때 Queue는 스레드 A B가 같이 사용하므로 공유 객체입니다. 공유 객체이므로 패킷을 넣고 뺄 때 크리티컬섹션과 같은 동기 객체로 동기화를 해야 합니다. 이런 곳에 concurrent_queue를 사용하면 아주 좋습니다.

 

 

concurrent_queue를 사용하기 위한 준비 단계

 

너무 당연하듯이 헤더 파일과 네임스페이스를 선언해야 합니다.

 

헤더파일

#include <concurrent_queue.h>

 

네임스페이스

using namespace Concurrency;

을 선언합니다.

 

이제 사전 준비는 끝났습니다. concurrent_queue를 선언한 후 사용하면 됩니다.

concurrent_queue< int > queue1;

 

 


concurrent_queue에 데이터 추가

 

concurrent_queue에 새로운 데이터를 넣을 때는 push 라는 멤버를 사용합니다.

 

원형

void push( const _Ty& _Src );

 

STL deque push_back과 같은 사용 방법과 기능도 같습니다. 다만 스레스 세이프 하다는 것이 다릅니다. concurrent_queue는 앞 회에서 이야기 했듯이 스레드 세이프한 컨테이너이므로 제약이 있습니다. 그래서 deque 와 다르게 제일 뒤로만 새로운 데이터를 넣을 수 있습니다.

 

concurrent_queue< int > queue1;

queue1.push( 11 );

 

 

 

concurrent_queue에서 데이터 가져오기

 

데이터를 가져올 때는 try_pop 멤버를 사용합니다. 앞의 push의 경우는 STL deque와 비슷했지만 try_pop은 꽤 다릅니다.

 

원형

bool try_pop( _Ty& _Dest );

 

try_pop을 호출 했을 때 concurrent_queue에 데이터가 있다면 true를 반환하고 _Dest에 데이터가 담기며 concurrent_queue에 있는 해당 데이터는 삭제됩니다. 그러나 concurrent_queue에 데이터가 없다면 false를 즉시 반환하고 _Dest에는 호출했을 때의 그대로 됩니다.

 

concurrent_queue< int > queue1;

 

queue1.push( 12 );

queue1.push( 14 );

 

int Value = 0;

 

if( queue1.try_pop( Value ) )

{

           // queue1에서 데이터를 가져왔음

}

else

{

           // queue1은 비어 있었음.

}

 

 

 

concurrent_queue가 비어 있는지 검사

 

concurrent_queue가 비어 있는지 알고 싶을 때는 empty()를 사용합니다. 이것은 STL deque와 같습니다.

 

원형

bool empty() const;

 

비어 있을 때는 true를 반환하고 비어 있지 않을 때는 false를 반환합니다. 다만 empty를 호출할 때 비어 있는지 검사하므로 100% 정확하지 않습니다. 100% 정확하지 않다라는 것은 empty push, try_pop 이 셋은 스레드 세이프하여 동시에 사용될 수 있으므로 empty를 호출할 시점에는 데이터가 있어서 false를 반환했지만 바로 직후에 다른 스레드에서 try_pop으로 삭제를 해버렸다면 empty 호출 후 false를 반환했어 try_pop을 호출했는데 false가 반환 될 수 있습니다.

 

 

 

concurrent_queue에 있는 데이터의 개수를 알고 싶을 때

 

concurrent_queue에 있는 데이터의 개수를 알고 싶을 때는 unsafe_size 멤버를 사용합니다.

 

원형

size_type unsafe_size() const;

 

이것은 이름에서도 알 수 있듯이 스레드 세이프 하지 않습니다. 그래서 unsafe_size를 호출할 때 push try_pop이 호출되면 unsafe_size를 통해서 얻은 결과는 올바르지 않습니다.

 

 


concurrent_queue에 있는 데이터 순차 접근

 

concurrent_queue에 있는 데이터를 모두 순차적으로 접근하고 싶을 때는 unsafe_begin unsafe_end를 사용합니다.

 

원형

iterator unsafe_begin();

const_iterator unsafe_begin() const;

 

iterator unsafe_end();

const_iterator unsafe_end() const;

 

unsafe_begin을 사용하여 선두 위치를 얻고, unsafe_end를 사용하여 마지막 다음 위치(미 사용 영역)를 얻을 수 있습니다. 이것도 이름에 나와 있듯이 스레드 세이프 하지 않습니다.

 

 

 

모든 데이터 삭제


모든 데이터를 삭제할 때는 clear를 사용합니다. 이것은 이름에 unsafe라는 것이 없지만 스레드 세이프 하지 않습니다.

 

원형

template< typename _Ty, class _Ax >

void concurrent_queue<_Ty,_Ax>::clear();

 

 

 

제 글을 보는 분들은 C++을 알고 있다는 가정하고 있기 때문에 STL을 알고 있다고 생각하여 아주 간단하게 concurrent_queue를 설명 하였습니다.

 

concurrent_queue 정말 간단하지 않습니까? 전체적으로 STL deque와 비슷해서 어렵지 않을 것입니다. 다만 스레드 세이프 하지 않은 것들이 있기 때문에 이것들을 사용할 때는 조심해야 된다는 것만 유의하면 됩니다.

 

이것으로 Concurrency Runtime PPL에 대한 설명은 일단락 되었습니다.

이후에는 Concurrency Runtime의 다른 부분을 설명할지 아니면 Beta2에서 새로 추가된 C++0x의 기능이나 또는 이전에 설명한 것들을 더 깊게 설명할지 고민을 한 후 다시 찾아 뵙겠습니다.^^

 

 


참고

Producer-Consumer 모델 : 자바워크님의 http://javawork.egloos.com/2397148

MSDN concurrent_queue :

http://msdn.microsoft.com/en-us/library/dd504906(VS.100).aspx#queue

 

4. Assembly

CLR 2010. 1. 15. 09:00 Posted by 알 수 없는 사용자
Assembly 라고 하면 맨 처음 생각 나는게 뭔가요? 저는 Assembly 언어가 생각이 납니다. 기계어와 Assembly 언어. 요사이는 Assembly 언어로 프로그램을 작성하는 분이 거의 없을 거라고 보지만 예전에 PC 사양이 많이 안 좋았던 시절에는 컴파일러의 최적화 성능도 그리 좋지 않았기 때문에 최적화된 코드로 빠른 속도를 내기 위해서 많은 부분을 직접 Assembly 언어로 구현했다는 이야기를 많이 들었었지요. 참 대단합니다. ㅎㅎ

아.. 이야기가 딴 길로 샙니다. 지난 주에 Metadata를 까보면서 넘어갔던 부분이 몇 개 있었는데요. 그 중의 하나가 Assembly 였지요. 오늘은 이 Assembly에 대해 공부해 보려고 합니다. 

Assembly?

Assembly 는 뭔가요? 지난 주에 저희가 만들었던 hi.exe 도 어셈블리입니다. 그럼 어셈블리는 실행 파일인가요? 틀린 말은 아니지만 좀 더 정확히 정의하자면 Assembly는 타입이나 리소스를 포함한 하나 이상의 파일들이 모인 파일의 컬렉션 이라고 CLR Via c# 2nd 한글판에서는 이야기하고 있습니다. 물론 일반적으론 하나의 파일로 구성되는 경우가 대부분입니다. Assembly를 논리적인 DLL 또는 EXE 파일로 이해하면 될 것 같습니다.

이 Assembly 파일이 갖고 있는 정보 중의 하나는 Manifest라고 하는데 이 Manifest에는 Assembly의 버전과 컬처, 배포자, public 형태의 타입, Assembly를 구성하는 모든 파일의 정보를 갖고 있습니다. CLR은 이 Assembly를 로드하여 지난주에 살펴본 Metadata 테이블을 읽은 후, Manifest에 있는 다른 파일들의 정보를 읽게 됩니다.

좀 어렵네요. 왜 이런 Assembly를 사용하는가. 를 먼저 살펴봅시다. Assembly는 다음과 같은 특징을 갖습니다.

* 개발된 코드를 여러 파일로 분산하여 실행 시 최소한의 파일로 구성한 다음, 필요한 파일이 생길 경우 인터넷 상으로 다운로드하는 식의 효과적인 배포가 가능합니다. (어플리케이션 설정 파일의 codebase 항목에서 설정된 곳을 통해 필요한 Assembly를 다운로드 할 수 있도록 설정이 가능합니다.)

* Assembly에 리소스나 데이터 파일을 추가할 수 있습니다. 이 데이터 파일의 형식은 어플리케이션이 파싱하여 이해할 수 있는 파일이라면 제약이 없습니다.(예 : 오피스 워드 파일, 엑셀 파일 등등)

* 서로 다른 언어로 구현된 타입(클래스)의 구성으로 Assembly를 생성하는 것이 가능합니다. 전체 모듈 중 일부는 C#으로 다른 일부는 Visual Basic으로 구현하는 것이 가능합니다. 어떤 언어로 작성되었던 컴파일 하게 되면 같은 IL코드로 생성이 되어 있으며 Assembly 테이블을 참조하면 해당 모듈을 재사용하는데 필요한 모든 정보를 얻을 수 있기 때문입니다.


Assembly는 Manifest Metadata 테이블이라는 것을 가지고 있습니다. 테이블 리스트는 다음과 같습니다.

 테이블 이름 설명 
 Assembly Assembly를 식별하는 단일 엔트리를 가집니다. 이 엔트리에는 어셈블리의 이름, 버전, 컬처, 플래그, 해시 알고리즘, 발행자의 공용키를 포함합니다. 
 File Assembly의 부분인 각 PE 파일과 리소스 파일을 위한 항목을 갖고 있습니다. 엔트리에는 파일의 이름, 확장자, 해시, 플래그를 포함합니다. 만일 Assembly가 오직 자신 하나의 파일만으로 구성된다면 이 테이블이 갖고 있는 엔트리는 없습니다. 
 ManifestResource 각 리소스를 위한 항목을 가집니다. 엔트리는 리소스 이름, 플래그(public, private)를 포함합니다.  
 ExportedTypes Assembly의 PE 모듈로부터 노출된 각 공용 타입을 위한 항목을 가집니다. 엔트리는 타입 이름, File 테이블의 인덱스,  그리고 TypeDef 테이블의 인덱스를 포함합니다.

이러한 manifest를 정의함으로써 Assembly의 파일 구성에 대한 정보를 제공하는 것이 가능하고 어셈블리 스스로 설명하는 것이 가능해집니다.

컴파일러 옵션에서 /t 의 값으로 /t[arget]:exe, /t[arget]:winexe, /t[arget]:library 를 주게 되면 컴파일러는 manifest정보를 포함한 단일 파일의 Assembly를 생성하게 됩니다. 이는 각각 CUI 실행 파일, GUI 실행 파일, DLL 라이브러리 입니다.

이외에도 /t[arget]:module 이라는 옵션도 있습니다. 이 옵션을 사용하게 되면 컴파일러는 manifest와 metadata를 포함하지 않은 PE파일을 생성하게 됩니다. 이 파일은 기본적으로 .netmodule 의 확장자를 가지게 되며 다중 파일로 구성된 Assembly를 구성할 때 사용하게 됩니다. 이 타입의 모듈을 CLR이 이용하기 위해서는 항상 이 해당 모듈이 Assembly에 포함되어 있어야 합니다. 이렇게 .netmodule 형식의 파일을 생성해 놓음으로써 자주 사용하는 메소드와 그렇지 않은 메소드를 구분하여 분리해서 파일 구성을 할 수도 있겠군요.

다음과 같은 코드를 컴파일 하려고 합니다.

코드 1) Hellovb.vb
NameSpace Hello
Public Class HelloWorld
Overloads Shared Sub PrintHello()
System.Console.WriteLine("HELLO!!")
End Sub
End Class
End NameSpace 

코드 2) Test.cs
using Hello;
public sealed class Program
{
public static void Main()
{
System.Console.WriteLine("Hi");
HelloWorld.PrintHello();
}

코드 1은 VB.NET용 소스 파일이며 코드 2는 C#용 소스 파일입니다.

코드 1은 .netModule로 컴파일을 해 봅시다.


코드 2 는 코드 1에서 정의된 HelloWorld 클래스의 PrintHello 메소드를 이용하고 있습니다. 방금 생성한 hellovb.netModule을 끌어와야 정상적으로 컴파일이 되겠지요. 생성하려는 Assembly에 모듈을 추가하려고 할 때는 /addmodule 이라는 옵션을 사용하면 됩니다.


test.exe라는 Assembly를 만들고 실행을 시키자 코드대로 잘 실행이 됩니다. Assembly의 특징 중 하나인 서로 다른 언어로 구현된 타입(클래스)의 구성으로 Assembly를 생성하는 것이 정말 가능하네요. :)

자 이제 우리는 생성된 Hellovb.netmodule 과 test.exe 파일을 열어봐서 앞에서 살펴본 내용을 확인해 보면 되겠습니다.

먼저 Hellovb.netmodule의 Metadata 엔트리를 봅니다.


앞에서 /t[arget]:module 이라는 옵션을 이용하여 PE파일을 생성하게 되면 컴파일러는 Manifest 정보를 포함하지 않는 PE 파일을 생성한다고 했습니다. 정말 manifest 정보가 없네요.

아 여기에 보이는 AssemblyRef 테이블은 현재 파일이 참조한 모든 참조 어셈블리 파일의 목록을 갖고 있습니다. 이 목록을 이용하여 Assembly의 다른 파일들을 열지 않고도 참조된 어셈블리가 어떤 것들인지 확인 할 수가 있는 것입니다. 이 파일은 기본 모듈인 mscorlib과 Visual Basic으로 만들어진 모듈이기에 Microsoft.VisualBasic이라는 Assembly를 참조하고 있다고 표현하고 있네요.

자 이제는 test.exe을 살펴봅시다.


테이블이 많이 보이네요. 앞에서 언급한 Assembly, FIle, ExportedTypes 테이블이 보입니다. ManifestResource는 없네요. 이 파일엔 리소스가 없거든요 :(
하나하나 살펴봅니다. 먼저 Assembly 테이블을 보니 이름(Name), 버전(Major, Minor, Build, Revision), Culture, Flag, 해시 알고리즘(hashAlgId), 발행자의 공용키(PublicKey) 값이 보입니다.


이번에는 File 테이블입니다. Test.exe Assembly의 부분인 다른 PE 파일의 정보가 들어있네요. 이름(Name : Hellovb.netmodule), 플래그(Flags : 이 파일은 리소스 파일이 아님을 알 수 있습니다.) 등을 확인할 수 있습니다.

마지막으로 ExportedType 테이블입니다. 타입의 이름(TypeName : HelloWorld), File테이블의 인덱스(Implementation)등을 확인 할 수 있습니다. TypeDefID 값이 0200002라고 적혀 있네요. Ildsam.exe 를 이용해서 hellovb.netmodule을 찾아보니(TypeName이 HelloWorld고 Namespace가 Hello니까요) 다음과 같이 ID를 확인할 수가 있군요.

아 복잡하네요. 간단히 말하자면 컴파일러는 컴파일을 하면서 Assembly를 생성하게 되며 이 Assembly들의 내부 Manifest정보와 Metadata정보 덕분에 Assembly 스스로 자신에 대한 설명이 가능하므로 어디서든지 쉽게 재 사용이 가능하구나! 라고 이해하면 될 것 같습니다.

Assembly 구성에 대해 좀 더 알아봅시다. 다음의 코드를 컴파일하여 Assembly 구성을 하되 DLL 라이브러리로 구성합니다.

코드 3) Test2.cs

using Hello;

public class GoodbyeWorld
{
public static void PrintGoodbye()
{
System.Console.WriteLine("Goodbye World");
}
}

public sealed class Program
{
public static void Main()
{
System.Console.WriteLine("Hi");
HelloWorld.PrintHello();
GoodbyeWorld.PrintGoodbye();
}

}

컴파일을 하니 test2.dll 이라는 라이브러리 모듈이 생성되었네요. 

이 라이브러리는 그렇다면 다른 곳에서 어떻게 사용하면 될까요? 물론 지금 해왔던 것 처럼 컴파일 시mscorlib.dll을 /r[eference] 옵션을 이용하여 추가해 컴파일 했던 것 처럼 /r[eference] 옵션을 이용하여 이 모듈을 사용할 수 있을 것입니다.

앞으로 우리가 개발할 때 사용할 툴인 Visual Studio IDE에서는 어떻게 사용하나요? 물론 다 알고 계시겠지만 프로젝트에서 참조 추가(Add Referece) 메뉴를 이용하면 쉽게 이 라이브러리를 사용할 수 있습니다.
우리가 구현했던 메소드들이 잘 보이네요 :)

컴파일러말고도 Assembly를 생성할 수 있는 방법이 또 있습니다. Assembly Linker(AL.exe)를 이용해서 생성할 수 있다고 합니다. Assembly Linker는 서로 다른 컴파일러에 의해서 빌드된 모듈들로 구성된 어셈블리를 만들 때 사용됩니다.

test3.cs 에서 Hellovb에서 사용되었던 코드를 제외하여 test4.cs를 만들고 이걸 netmodule로 컴파일을 하겠습니다.
public class GoodbyeWorld
{
public static void PrintGoodbye()
{
System.Console.WriteLine("Goodbye World");
}
}

public sealed class Program
{
public static void Main()
{
System.Console.WriteLine("Hi");
GoodbyeWorld.PrintGoodbye();
}

}

그리고 앞에서 생성했던 VB.NET의 Hellovb.netmodule과 지금 생성한 C#으로 만든 test3.netmodule을 AL.exe를 이용하여 Assembly로 만들어 봅니다.

잘 생성되었습니다. :)

AL.exe를 이용해서 Assembly에 리소스를 추가할 수가 있습니다. 리소스를 추가하게 되면 앞에서 살펴본 ManifestResource 테이블이 생성되겠지요.

다음과 같이 AL.exe를 이용하여 DLL을 생성합니다.
그리고 테이블을 살펴보니

ManifestResource 테이블에 kara.jpg 이미지 리소스가 추가되어 있네요!! 물론 csc.exe나 vbc.exe 같은 각 언어의 컴파일러에서도 /resource 옵션을 이용하여 리소스 추가가 가능합니다.



휴- 정신없네요. 한숨 돌립시다. @_@




우리가 생성한 test.dll 파일을 보니까 뭔가 썰렁합니다. 파일 정보를 보니 버전 리소스 정보가 하나도 없네요!
물론 Visual Studio IDE를 이용하여 프로젝트를 생성하면 C#의 경우는 AssemblyInfo.cs 라는 파일이 자동으로 추가되면서 이 파일을 통해 생성하려는 Assembly의 파일 정보를 구성할 수 있습니다. 그렇다면 AL.exe나 csc.exe, vbs.exe의 컴파일러를 이용하여 Assembly를 생성하려는 경우 파일 정보는 어떻게 추가 할 수 있을까요?

using System.Reflection;

[assembly: AssemblyTitle("Test Library")]
[assembly: AssemblyDescription("Test")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("VSTS2010")]
[assembly: AssemblyProduct("Test Library")]
[assembly: AssemblyCopyright("Copyleft ©  2010")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]


public class GoodbyeWorld
{
public static void PrintGoodbye()
{
System.Console.WriteLine("Goodbye World");
}
}

public sealed class Program
{
public static void Main()
{
System.Console.WriteLine("Hi");
GoodbyeWorld.PrintGoodbye();
}

}

위의 코드를 다음과 같이 컴파일 합니다.

그러면 생성된 test.dll 에는 파일 정보가 포함되게 됩니다.


오늘 너무 많은 것을 하네요. 하지만 다음 주 진도를 위해 몇 가지를 더 짚고 넘어가야 합니다. 앞에서 버전 번호를 보면 알겠지만 버전 번호는 다음과 같은 형식을 갖고 있습니다.

주 번호(Major) / 부 버전 번호(Minor) / 빌드 번호(Build) / 리비전 번호(Revision)

Test.dll의 버전은 1.0.0.0 이라고 되어 있습니다. 앞의 1.0은 공식적으로 사용되는 버전의 숫자입니다. 보통 .NET FrameWork 2.0 , 3.5 이런 식으로 이야기 할 때의 버전 번호입니다.

세번 째의 빌드 번호는 말 그대로 빌드 할 때마다 증가하는 번호를 의미합니다. 만약 Test.dll이 32번째 빌드된 버전이라면 2.0.32.0 으로 버전 번호가 매겨지겠지요. 마지막 번호는 빌드의 수정을 의미합니다. 만약 32번째 빌드된 버전에 문제가 있어서 그날 다시 빌드를 해야 한다면 마지막 번호가 증가를 하게 됩니다.

이 버전 구성 방식은 꼭 지켜야 하는 규칙은 아닙니다. 하지만 Microsoft를 포함한 일반적인 소프트웨어 회사에서는 위와 같은 버전 구성 방식을 사용하고 있습니다.

그런데 위의 소스에서 보면 Assembly와 관련된 버전 정보가 하나가 아님을 알 수 있습니다.

[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

이 두 개 말고도 [assembly:AssemblyInformationVersion] 이라는 항목도 있습니다.  결국 Version과 관련된 항목이 3개가 있는데 CLR에서 사용하는 버전 정보는 [assembly: AssemblyVersion] 입니다. 이 버전 정보는 CLR에서 굉장히 중요합니다. 뒤에서 배우게 될 Strongly named assemblies를 바인딩 할 때 사용되는 버전 정보입니다. 이 버전 번호가 Assembly의 metadata 테이블 정보 중 AssemblyRef 테이블 항목에 기록이 됩니다.

버전 정보와 함께 Assembly는 Culture(언어) 라는 항목을 가집니다. 이 항목의 값에 따라 사용자는 영어 버전, 일본어 버전, 한국어 버전등의 Assembly를 가질 수 있게 됩니다. Culture에 들어가는 문자열은 주태그 - 부가태그의 형식으로(표준 RFC1766) 표현됩니다.

de-AT Austrian German
en-GB British English
en-US U.S. English

일반적으로는 코드가 포함된 Assembly에는 Culture를 지정하지 않습니다. 코드가 언어에 종속적으로 실행되어야 할 이유가 없기 때문이지요. 대신에 다국어를 지원하기 위한 어플리케이션을 만들 경우 Culture와 관련된 전용 리소스만을 포함한 Assembly를 만들어서 빌드를 하게 됩니다.(이를 satellite assembly - 위성 어셈블리 라고 합니다.) 이렇게 포함된 리소스는 System.Resources.ResourceManager 클래스를 이용하여 사용하게 됩니다.



오늘은 여기까지! 다음주에 계속됩니다!! :)

참고 자료
CLR Via C# 2nd.

'CLR' 카테고리의 다른 글

6. Assembly - GAC(Global Assembly Cache)  (2) 2010.02.02
5. Assembly - Strongly named assemblies  (0) 2010.01.26
3. MSCorLib & Metadata  (4) 2010.01.06
2. CLR! CLR! CLR!  (3) 2009.12.30
1. Hello 世界  (0) 2009.12.23
안녕하세요. 아직 떨린 마음을 감추지 못하는 팀블로그 새내기 박세식입니다. 너무나 오랜만에 포스팅을 하게되네요. 제 개인사까지 다 말씀드릴 필요는 없겠지만, 여러분 모두 새해에는 하시는일 모두 잘되었으면 좋겠습니다. 진심으로요ㅠㅠ 늦었지만 새해 복 많이 받으세요^^

이번 시간은 ASP.NET MVC와 인사를 나눠보는 시간을 갖도록 하겠습니다. 반갑게 만나보도록 하죠^^

M, V, C의 각방생활

먼저 프로젝트를 생성합니다. 새 프로젝트 열기에서


ASP.NET MVC 2 Web Applicatoin 을 선택하고, 이름은 HelloMVC 로 하겠습니다. OK를 클릭하면 다음과 같이 유닛 테스트 프로젝트를 생성할 것인지 묻는 창이 뜹니다. (이게 ASP.NET MVC의 장점이라는 겁니다. 프로젝트 자체에서 유닛 테스트를 지원해주고 있습니다. 이 창에서 Yes 를 선택하면 간단하게 유닛테스트 프로젝트를 생성할 수 있습니다.) 이 시간은 유닛테스트와는 전혀 상관이 없는 관계로 No를 선택하도록 하겠습니다.


그러면, 다음과 같은 구조의 프로젝트가 생성된 것을 확인하실 수 있습니다.


Controllers, Models, Views 폴더가 각각 분리되어 생성되었습니다. 지나가는 얘기로, 저의 한가지 꿈이 여러개의 방이 있는 집을 갖는건데요.^^; 하나는 서재실, 또 하나는 음악실, 나머지 하나는 침실 뭐 이런거죠. 정말 각각의 방 안에서의 할일이란 명확합니다. 각각의 방에서 할일들을 한 방에서 하게 된다면... 잠시 상상해보겠습니다. 한쪽에서는 드럼과 피아노와 일렉기타의 절묘한 하모니의 시끄러움(?)이, 다른 한쪽에서는 책과 씨름하며, 또 다른 한쪽에서는 코를 곯며 자는 모습... 상상이 가십니까? 음악실에서는 음악을 연주하며 맘껏 소리높여 노래도 부르고, 서재실에서는 조용한 가운데 책도 보며 교양을 쌓고, 침실에서는 자면되는거죠. 모델, 뷰 그리고 컨트롤러 또한 각자의 할 일이 뚜렷하기 때문에 한 방에 같이 있을 수가 없습니다. 각방을 써야하는거죠^^ 

프로젝트가 생성될때 샘플페이지도 같이 생성이 됩니다. F5를 눌러서 확인해보겠습니다. 클릭하시면 디버깅을 할 수 있도록 Web.config 파일을 수정한다는 팝업창이 뜨는데요, OK하고 넘어가도록 합니다.


자, Welcome to ASP.NET MVC! 가 출력되는 것을 확인하실 수 있습니다. 우리를 먼저 반갑게 맞이해주는데요.^^ 기분좋네요~ 가만히 있을 순 없죠. 저도 인사를 해보도록 하겠습니다.

Hello! ASP.NET MVC!!!

먼저, 컨트롤러 폴더의 HomeController 클래스의 Index() 메쏘드를 다음과 같이 수정하겠습니다.

public ActionResult Index()
{
    ViewData["Message"] = "Hello! ASP.NET MVC!!!";
    return View();
}

소스 1 - /Controllers/HomeController.cs

컨트롤러는 ViewData 를 통해서 뷰에 데이터를 전달할 수 있습니다. 뷰에서는 인라인 코드로 ViewData에 접근할 수 있습니다. (자세한건 여기에서 'ViewData로 뷰에 전달하기'를 봐주세요) 수정한 내용은 F5 로 실행하여 확인할 수 있습니다.


그런데 주소를 보니 http://localhost:1589/로 되어있는데도 원하는 결과를 확인할 수 있습니다. ASP.NET MVC는 기존 웹폼에서처럼 직접적인 페이지 호출이 아닌 라우팅 룰에 의해 호출이 됩니다. ASP.NET MVC 애플리케이션이 처음 시작되면 Global.asax.cs 에 있는 Application_Start() 메쏘드가 호출되고 이는 라우트 테이블을 생성합니다.


소스 2 - Global.asax.cs

라우트 테이블은 들어오는 웹 요청을 3부분으로 나눕니다. 처음은 컨트롤러 이름과 매핑이되고, 두번째는 액션메쏘드와 매핑이 되고, 세번째는 그 메쏘드에 전달될 파라미터와 매핑이 됩니다. 예를들어, /Product/Detail/3 과 같이 요청이 들어오면 다음과 같이 나뉩니다.

Controller  = ProductController
Acton = Detail
Id = 3

예제에서 주소가 http://localhost:1589/  이렇게 되어도 라우트 테이블의 디폴트값인 HomeController의 Index 액션메쏘드를 호출하기 때문에 우리가 원하는 결과를 볼수 있었던 거죠^^

이제 인사는 나누었는데 처음 만남에 인사만 나누기는 섭섭하죠? ^^; 커피라도 한잔하며 얘기 나눠보
는게 좋겠죠? 흠.. 이번시간은 간단히 인사만 나누고 끝내려고 했는데요. 너무 금방 헤어지면 정말 아쉬울것 같아서 더 진행하는 것이니 간단하게 해보도록 하겠습니다. 아무쪼록 저의 허접함을 탓하지 마옵소서...(저 스스로 분발하도록 하겠습니다^^;)

우리 차라도 한잔?

먼저 차한잔 마실거니까요 Index.aspx 를 수정해서 차 마시러 가보도록 하죠^^

<h2><%= Html.Encode(ViewData["Message"]) %></h2>
<br />
차라도 한잔 하실래요?
<%= Html.ActionLink("네", "../Menu/MenuForm") %>

소스 3 - /Views/Home/Index.aspx

Html.ActionLink() 메쏘드는 A 태그를 만듭니다. 링크를 MenuForm으로 하네요. 물론 실행해 보면 에러가 나겠죠. 메뉴컨트롤러와 해당 액션메쏘드가 없기 때문이죠. 그러면 컨트롤러를 생성해보도록 하겠습니다.

using HelloMVC.Models;

namespace HelloMVC.Controllers
{
    public class MenuController : Controller
    {
        //
        // GET: /Menu/
        public ActionResult MenuForm()
        {
            List<Menu> MenuList = new List<Menu>();

            MenuList.Add(new Menu { Id = 1, Name = "커피", Price = "4000" });
            MenuList.Add(new Menu { Id = 2, Name = "레몬에이드", Price = "5000" });

            return View(MenuList);   
        }
    }
}

소스 4 - /Controllers/MenuController.cs

요란한 밑줄이 보이는 Menu 클래스도 생성하겠습니다.

public class Menu
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Price { get; set; }
}

소스 5 - /Models/Menu.cs

모델 클래스의 경우 생성을 하신 후에 꼭! 꼭! 꼭! 빌드를 하셔야합니다. 그래야 아래 보이는 Add View를 하실때 원하는 모델 클래스를 선택하실 수 있습니다.

ViewResult로 MenuList 모델을 파라미터로 뷰페이지로 리턴합니다. 액션메쏘드에 아무데서나 마우스 오른쪽 버튼을 클릭하여 뷰페이지를 생성하도록 하겠습니다.


Add View를 클릭하면 다음과 같은 팝업이 뜹니다. 먼저 저희가 컨트롤러에서 메뉴를 추가한 리스트를 확인해보기 위해서 다음과 같이 세팅하도록 하겠습니다.


Create a stringly-typed view를 선택하고(뷰를 생성할때 모델과 강력한 결합을 이끌게 되면 직접적으로 모델의 애트리뷰트들을 액세스할수 있게 됩니다.), View data class 를 Menu클래스로 선택합니다(여기서 Menu 클래스가 안보이시면 빌드를 안하신거에요. 빌드하셔야죠!). 마스터 페이지의 체크를 해제하도록 합니다. Add 버튼을 클릭하시면 MenuForm 페이지가 생성되는 것을 확인하실 수 있습니다. 바로 실행을 해보시면,


잘나오네요. 그러면 소스를 조금(?) 수정하도록 하겠습니다.

<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<IEnumerable<HelloMVC.Models.Menu>>" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
    <title>MenuForm</title>
</head>
<script type="text/javascript">
    var menuList = new Array();
    function Menu() {
        this.id;
        this.name;
        this.price;
        this.quantity = 0;
        this.cPrice;
    }
    function addMenu(id, name, price) {
        var menuNum = -1;
        for (var k = 0; k < menuList.length; k++) {
            if (id == menuList[k].id) {
                menuNum = k;
                break;
            }
        }
        if (menuNum == -1) {
            var mn = new Menu();
            mn.id = id;
            mn.name = name;
            mn.price = price;
            mn.quantity++;
            mn.cPrice = price;
            menuList.push(mn);
        }
        else {
            menuList[k].quantity++;
            menuList[k].cPrice = menuList[k].quantity * parseInt(menuList[k].price);
        }

        var str = "";
        var totalPrice = 0;
        for (var i = 0; i < menuList.length; i++) {
            str += menuList[i].name + " " + menuList[i].quantity + "잔 " + menuList[i].cPrice + "<br />";
            totalPrice += parseInt(menuList[i].cPrice);
        }
        document.getElementById("divMenuList").innerHTML =
str + "<br /> 돈부터 내시죠~ 여긴 선불!! " + totalPrice + "원 되겠습니다~~^^";
    }
</script>
<body>
    <h2>Menu</h2>
    <table width="400px" cellspacing="1" style="background-color:#CCCCCC">
    <% foreach (var menu in Model) { %>
    <tr>
        <td style="background-color:#EEEEEE"><%= Html.Encode(menu.Name) %></td>
        <td style="background-color:#AAAAAA" align="center"><%= Html.Encode(menu.Price) %></td>
        <td style="background-color:#BBBBBB">
<a href="javascript:addMenu('<%= menu.Id %>', '<%= menu.Name %>', '<%= menu.Price %>');"><%= Html.Encode(menu.Name)%> 추가요</a></td>
    </tr>  
    <% } %>       
    </table><br />
    =================== 주문서 ===================<br /><br />      
    <div id="divMenuList" style="border:1px solid #E3E3E3; width:400px; height:200px" ></div>
</body>
</html>

소스 6 - /Views/Menu/MenuForm.aspx

이상하게 복잡스럽게 보이지만(죄송합니다__) 수정된것은 테이블에 색깔준것과 주문추가 이벤트, 주문서네요.
결과물을 보면


추가 이벤트를 일으킬때마다 주문서가 수정되는 간단한 예제를 보고 계십니다.^^

마무리요

마지막의 결과물은 간단한데 너무 복잡하게 표현한건 아닌지 심히 걱정이 됩니다. 제 실력이 여기까지인지라..다음 포스팅때는 더 깔끔하고 세련된 코드로, 더 나아진 모습으로 찾아뵙도록 하겠습니다.


참고자료 :
http://www.techbubbles.com/aspnet/aspnet-35-mvc-application/

Welcome to Dynamic C#(11) - The Phantom of The Dynamic

C# 2010. 1. 14. 09:00 Posted by 알 수 없는 사용자
  이 포스트에서 소개해드리는 유령메서드는 정식버전에서는 없어진 개념입니다. 너무나도 복잡한 과정을 거쳐야 하기 때문에, 과정을 단순화 시키느라고 기존에 논의하던 개념들을 채택하지 않았다고 하는데요. 이 포스트는 예전에 이런 내용이 논의되었었다하는 정도로 봐주시구요. 실제 dynamic과 관계된 메서드 오버로딩 판별에 대해서는 이 글을 참조해주시기 바랍니다.

- 빙산의 일각!


사실 처음에는 그냥 단순히.. dynamic이란게 추가됐으니, '아 이거 쵸낸 신기하구나', '아 난 귀찮은 거 싫어하는데 이거 때매 이런거 편해지겠구나'하는 생각으로 접근을 했었는데요. dynamic이라는 키워드가 하나 추가되면서 생긴 많은 양의 추가사항들과 이야기들이 빙산 아래쪽으로 숨어 있었네요. 근데, 개인적인 게으름으로 아직 제대로 이야기 드리지 못하는거에 대해서 죄송하게 생각하구요-_- 일단, 원문을 한번 걸러서 약간의 창작을 보태는 수준에 불과하지만 계속해서 최선을 다해서 전달해드리고자 합니다.(저도 궁금하긴 하거든요-_-) 따쓰한 피드백!! 크하하하-_-


- 유령...뭐...?

유령 메서드(the phantom method)는 이 포스트시리즈의 바탕이 되는 Sam Ng의 포스트에서 언급이 되는 용어인데요. 컴파일러가 초기 바인딩단계에서 정적으로 해결할 수 없는 동적 바인딩을 해야하는 경우 사용하는 메서드를 말합니다. 즉, 실체는 없지만 컴파일러 내부에서 문제해결을 위해서 사용한다고 볼 수 있겠죠.

public class C
{
    public void Foo(int x)
    {
    }
   
    static void Main(string[] args)
    {
        dynamic d = 10;
        C c = new C();
        c.Foo(d);
    }
}

위와 같은 코드가 있다고 할때요, Foo의 호출을 바인드하기 위해서 컴파일러는 오버로드 판별 알고리즘을 통해서 C.Foo(int x)같이 딱들어맞는 후보메서드가 포함되어 있을 후보군을 만듭니다. 그리고 매개변수가 변환가능한지를 판단합니다. 그런데, 아직 dynamic의 변환가능성에 대해서는 이야기를 해본적이 없으므로~ 일단, 그거에 대해서 먼저 이야기 해보도록 하겠습니다.

우선, 빠르고 간단하게 정의를 내려보자면, "모든 타입은 dynamic으로 변환이 가능하고, dynamic은 어떤 타입으로도 형변환 할 수 없습니다." 말이 안된다고 생각하실 수 있습니다. 그럼 그 의문을 풀기 위해서 형변환을 고려할 수 있는 상황들을 생각해보기로 하죠.
(주석) 원문에서 "everything is convertible to dynamic, and dynamic is not convertible to anything"이라고 하고 있는데요, 조금 알아보니 Sam Ng가 이야기한 건 아마 암시적 형변환을 두고 이야기 한 것 같습니다. dynamic에서 다른 타입으로 명시적 형변환은 가능합니다. 그리고 이에 대해서 다음 포스트에서 좀 더 자세하게 말씀 드리겠습니다. 

우선, c를 정적인 타입이라고 하고, d를 동적인 타입의 표현식이라고 했을때요, 형변환에 대해서 고려해볼 수 있는 상황은 아래와 같습니다.

1. 오버로드 판별 - c.Foo(d)
2. 대입 형변환 - C c = d
3. 조건문 - if(d)
4. using절 - using(dynamic d = ..)
5. foreach - foreach(var c in d)

일단, 이번 포스트에서는 1번에 대해서 살펴보도록 하구요, 나머지는 다음기회로 미루겠습니다.


- 오버로드 판별의 경우

일단 매개변수 변환가능성으로 돌아가서 생각해보겠습니다. dynamic은 어떤 타입으로도 형변환 할 수 없기 때문에, d는 int로 형변환이 불가능합니다. 하지만, 모처럼 dynamic타입인 매개변수를 썼으니 오버로드 판별도 동적으로 일어났으면 합니다. 그래서 여기서 유령 메서드가 등장합니다.

유령메서드는 오버로드 판별의 후보군에 슬쩍 추가되는데요, 파라미터개수가 똑같고 모든 파라미터가 dynamic타입인 메서드입니다.

즉, 후보군에 Foo(int x, int y), Foo(string x, string y)가 있다면, 유령메서드는 Foo(dynamic x, dynamic y)처럼 생겼겠죠.

유령 메서드가 후보군에 끼어들게되면, 당연하겠지만, 다른 후보군 메서드와 똑같이 취급됩니다. '모든 타입은 dynamic으로 형변환이 되지만, dynamic은 어떤 타입으로도 형변환이 안된다.'는 명제를 다시 한번 떠올려 볼 때입니다. 아주 적절한 타이밍이죠. 이 말은 dynamic타입의 매개변수가 주어진 상황에서 다른 모든 오버로드 후보군은 판별을 통과하지 못하지만, 유령 메서드는 유유히 판별을 통과할 수 있다는 말입니다.

서두에서 제시했던 예제를 다시 보시면, 한개의 dynamic타입을 매개변수로 받습니다. 이 상황에서 오버로드는 두개인거죠. Foo(int)와 유령 메서드인 Foo(dynamic). 전자는 판별을 통과하지 못합니다. dynamic은 int로 형변환이 안되기 때문이죠. 하지만 후자는 성공합니다. 그래서 그 메서드에 호출을 바인드하게 되는거죠.

그리고 호출이 유령 메서드에 바인드 되면, 컴파일러는 DLR을 통해서 런타임에 호출이 제대로 이루어 지도록 조치를 취하는 거죠.

그럼, 한가지 의문이 남는데요. 유령 메서드는 언제 끼어들게 되는 걸까요?


- 유령이 끼어드는 그 순간

컴파일러가 오버로드 판별을 할때, 초기 후보군을 놓고 고심을 합니다. 메서드 호출에 dynamic 매개변수가 있다면, 컴파일러는 후보군을 찬찬히 살펴보면서 유령 메서드를 소환해야 하는지 고심합니다. 유령 메서드가 끼어드는 상황은 아래와 같습니다.

1. dynamic이 아닌 모든 매개변수는 후보군에 있는 파라미터로 형변환이 가능하다.
2. 최소한 한개 이상의 dynamic매개변수가 후보군에 있는 파라미터로 형변환이 불가능하다.

일전에, dynamic타입인 매개변수가 포함된 메서드 호출이라도 정적으로 바인드될 수 있다고 말씀을 드렸었는데요. 이 경우가 2번으로 설명이 됩니다. dynamic매개변수와 일치하는 dynamic파라미터를 갖는 후보메서드가 있다면, 호출은 그 메서드로 정적 바인딩이 됩니다.

public class C
{
    public void Foo(int x, dynamic y)
    {
    }
   
    static void Main(string[] args)
    {
        C c = new C();
        dynamic d = 10;           
        c.Foo(10, d);
    }
}

위와 같은 경우, 오버로드 후보군에 정확하게 Foo호출의 매개변수인 int와 dynamic타입에 일치하는 메서드가 있기 때문에, 정적으로 바인딩되고, dynamic lookup이 발생하지 않습니다. 즉, 오버로드 판별시에 후보군을 한번 쭉 훑었는데도 유령 메서드가 끼어들지 않았다면, 비록 dynamic타입의 매개변수가 있다고 하더라도 원래 하던대로 오버로드 판별을 진행하는 거죠.


- 유령메서드를 통한 할당과 dynamic receiver를 통한 할당은 뭐가 틀린거냐

dynamic receiver의 경우는 런타임 바인더가 실제 런타임시의 receiver의 타입을 기준으로 오버로드 판별을 하려고 합니다. 하지만 유령메서드가 끼어든 할당의 경우는 컴파일타임의 receiver의 타입을 기준으로 진행되는 거죠.

그냥 직관적으로 생각해봤을때, receiver를 컴파일타임에 알 수 있다면, 매개변수에 dynamic타입이 있다고 하더라도 오버로드 판별의 후보군은 컴파일 타임에 밝혀져야 하는 거겠죠.


- 마치면서

사실, 이 부분에 대해서 좀 더 언급할 사항들이 있습니다. 나머지 형변환 케이스에 대해서 더 나아가기 전에, dynamic의 형변환에 대한 부분과 오버로드에 대한 이야기를 좀 더 하려고 하는데요. 여러분과 제가 가진 의문이 조금씩 더 해결됐으면 하는 생각입니다.


- 참고자료

1. http://blogs.msdn.com/samng/archive/2008/11/09/dynamic-in-c-iv-the-phantom-method.aspx



개발 환경이 제대로 구성되었는지를 확인하면서 가장 기본 웹 파트를 생성해서 배포하는 방법을 알아보도록 하겠습니다.

 

1.     SharePoint 프로젝트 템플릿 중에서 맨 위의 Empty SharePoint Project를 선택하고 Name Hello 로 입력 합니다.



위와 같은 프로젝트 템플릿은 SharePoint 2010 없이 Visual Studio 2010 만 설치해도 볼 수 있지만 SharePoint 개발 환경 위에서가 아니면 아래와 같은 메시지를 볼 수 있습니다.



2.     SharePoint 사이트를 입력하고 “Deploy as a farm solution” 을 선택합니다.


3.     잠시 후 Solution Explorer를 확인할 수 있으며 빈 솔루션이므로 새 항목 추가에서 Web Part를 선택하고 이름은 “HJ” 라고 입력 합니다.


4.     생성된 웹 파트에 대한 Solution Explorer 모습은 아래 그림과 같습니다.


5. 이제 코드 창에서 간단한 코드를 작성해봅니다
HJ.cs
코드에 이미 생성되어 있는 CreateChildControls 메서드에 아래와 같은 코드를 입력합니다.   단순 Hello World 라는 글자를 표시해주는 코드 입니다.


6.     작성이 완료되었다면 Solution Explorer 에서 Hello를 오른쪽 클릭하여 배포(Deploy)를 선택합니다. 2번 단계에서 선택한 Farm Solution으로 배포됩니다.

 

7. 배포되었는지 확인하기 위해 SharePoint 사이트를 열어 웹 파트를 추가해봅니다. 알고 계시다시피 SharePoint 2010 사이트는 리본으로 구성되어 있으며 사이트의 첫 페이지에서 Page 탭에서 Edit를 선택합니다. 그럼 아래 그림과 같이 Insert 탭에서 Web Part를 선택할 수 있습니다.


8.     Web Part 추가를 선택하면 별도 설정 하지 않았기 때문에 Custom HJ 라는 웹 파트를 아래 그림에서 확인할 수 있습니다. Add 를 선택해서 웹 파트를 추가합니다.



9.     이전 버전과 달리 웹 파트 영역에 대한 부분은 안보이고 기존 콘텐트 부분에 추가할 수 있습니다. Page 탭을 선택하고 Save 메뉴를 눌러 편집에서 빠져 나옵니다.

그럼 아래 그림과 같이 웹 파트가 추가되어 있는 것을 알 수 있습니다.



개발 환경이 완료되었는지 확인하기 위해 이번 버전과 유사하게 웹 파트를 생성하고 배포, 확인해보았습니다.

 

VS 2010 프로젝트 템플릿에서 보듯이 여러 템플릿을 이용해서 SharePoint 2010을 개발할 수 있습니다.


 

[JumpToDX11-9] Multi-threaded Rendering 을 위한 API.

DirectX 11 2010. 1. 11. 09:00 Posted by 알 수 없는 사용자



이번 시간에는 Multi-threaded Rendering 을 위한 API 들에 대해서 살펴보겠습니다.
기능 위주의 설명을 위해서 인자들에 대한 명시는 생략했습니다.
이점 주의해주시기 바랍니다.

ID3D11Device::CreateDeferredContext()

가장 먼저 살펴볼 것은 DeferredContext 의 생성입니다.
DeferredContext 는 스레드당 하나씩 생성되어질 수 있음을 앞선 시간을 통해서 언급했습니다.
또한 이 DeferredContext 는 Command List 들을 생성해서 가지고 있습니다.
즉, 렌더링이 가능한 상태라는 것입니다.
그런 기능을 우리는 Device 인터페이스를 통해서 생성합니다.
이것은 역시 Free thread 한 작업이기 때문에 Device 인터페이스를 이용합니다.

하나의 DeferredContext 는 thread-safe 합니다.
즉, 스레드 상에서 DeferredContext 가 관련 Command 들을 기록하는 것은 안전한 작업입니다.

간단한 사용 방법은 아래와 같습니다.
ID3D11DeviceContext* pDeferredContext = NULL;
hr = g_pd3dDevice->CreateDeferredContext(0, &pDeferredContext);


ID3D11DeviceContext::FinishCommandList()

신기하게도 우리는 이 API 호출 한번으로 CommandList 들을 기록하고 생성할 수 있습니다.
API 이름이 Finish 여서 Start나 Begin 계열의 API 를 검색해 보았지만, 없었습니다.^^
각각의 DeferredContext 별로 호출되기 때문에 DeviceContext 의 멤버함수로 되어 있습니다.
앞선 시간을 통해서 DeviceContext 는 ImmeidateContext 와 DeferredContext 로
분리될 수 있다고 언급했었습니다.
두 Context 모두 ID3D11DeviceContext 인터페이스를 사용하기 때문에 오해의 소지가 약간 있습니다.
FinishCommandList 는 DeferredContext 를 위한 API 임을 유념하시기 바랍니다.

간단한 사용 방법은 다음과 같습니다.
ID3D11CommandList* pd3dCommandList = NULL;
hr = pDeferredContext->FinishCommandList( FALSE, &pd3dCommandList );


ID3D11DeviceContext::ExecuteCommandList()

이 API는 DeferredContext 에 의해서 생성된 CommandList 들을 실행합니다.
역시나 ID3D11DeviceContext 의 멤버함수이기 때문에 혼란스러울 수 있습니다.
과연 ImmediateContext 가 이 함수를 호출할까요? 아니면, DeferredContext 일까요?

지난 시간들을 통해서 우리는 실제로 Multi-threaded Rendering 이라는 것은
CommandList 생성을 Multi-thread 기반으로 하는 것이라고 언급했었습니다.
그 이후에 실제 그래픽 카드로의 전송은 하나의 스레드만 할 수 있다고 했었습니다.
바로 그 사실입니다.
이 함수는 ImmediateContext 에 의해서 호출됩니다.
즉, 이 API 는 그래픽 카드로 해당 CommandList 들을 전송하는 것입니다.

간단한 사용 방법은 아래와 같습니다.
g_pImmediateContext->ExecuteCommandList( g_pd3dCommandList, TRUE );


이상 3가지 API 에 대해서 살펴보았습니다.
믿기지 않으시겠지만(?)
Multi-threaded Rendering 작업은 이 세가지 API로 할 수 있습니다.
나머지는 스레드 생성과 제어를 위한 작업이 결합되어야 할 것입니다.
일반적인 스레드 프로그래밍과 관련된 내용이라 이곳에서는 배제를 했습니다.
현재 DirectX SDK Sample 에는 'MultithreadedRendering11' 라는 것이 있습니다.( 2009 August 버전 기준 )
이것과 관련된 소스가 있으니 참고해서 보시면 좋을 것 같습니다.

이상으로 Multi-threaded Rendering 의 기본 개념 설명을 마치고자 합니다.
이 부분과 관련된 내용은 앞으로 정리가 되는대로 추가하거나 수정이 되어질 수 있을 것입니다.
다음 시간부터는 DirectX11 의 다른 주제를 가지고 돌아오겠습니다.^^
 

Welcome to Dynamic C#(10) - Dynamic Returns Again.(2)

C# 2010. 1. 11. 09:00 Posted by 알 수 없는 사용자

- 살림살이 좀 나아시졌습니까.

날씨가 계속 춥네요. 난데없이 목이 부어서 지난 금요일에는 조퇴를 했습니다-_-. 다들 건강 조심하시구요. 날씨가 추워서 그런가 여기저기서 어려움을 호소하는 목소리가 들리는 거 같습니다. 다들 하시는 일 잘되고 살림살이 좀 나아지셨으면 좋겠네여!


- 이어서 이어서!

지난포스트에서 보셨던 예제를 다시한번 보시죠.

dynamic d = 10;
C c = new C();

d.foo();
d.SomeProp = 10;
d[10] = 10;

c.Foo(d);
C.StaticMethod(d);
c.SomeProp = d;

지난 포스트에서는 위쪽 그룹에 대해서 다뤘었는데요, 이번 포스트에서는 위 두 그룹중에서 아래쪽 그룹에 대해서 설명드려 보겠습니다. 우선, 가장 간단한 부분부터 다뤄보려고 하는데요, 아래와 같은 코드가 있다고 가정해보죠.

public class C
{
    public void Foo(decimal x) { ... }
    public void Foo(string x) { ... }
    static void Main(string[] args)
    {
        C c = new C();
        dynamic d = 10;
        c.Foo(d);
    }
}

이 코드가 실행되면 어떤일이 벌어질까요? 직관적으로 생각해봤을때... 지역변수c의 타입이 C라는 걸 알 수 있으니깐, C의 오버로드 2개중에 하나가 실행될거라고 생각해볼 수 있습니다. 근데, d의 타입이 dynamic이라는 것도 위 소스코드에서 알 수 있는데요, 그렇다는 이야기는 d의 실제 타입은 런타임에서 알 수 있으므로 컴파일러는 어떤 오버로드를 호출해야 하는지 판단할 수가 없습니다.

그래서 이렇게 생각해볼 수 있습니다. 컴파일러는 호출가능한 후보군을 추출해서 집합을 만들고, 런타임에 실제로 오버로드 판별을 통해서 적합한 메서드를 호출한다고 말이죠. 위의 경우에는 d의 값이 10이므로, 아마도 호환이 안되는 string보다는 decimal을 인자로 받는 오버로드가 호출될거라고 예측해볼 수 있습니다. 그러면, 좀 더 구체적으로 이야기 해보면서 뭐가 예측이랑 다르게 돌아가는지에 대해서 이야기 해보죠.

public class C
{
    public void Foo(decimal x) { ... }
    public void Foo(string x) { ... }
    static void Main(string[] args)
    {
        C c = new D();
        dynamic d = 10;
        c.Foo(d);
    }
}

public class D : C
{
    public void Foo(int x) {...}
}


클래스 D를 C로 부터 상속했고, c를 D의 생성자로 생성한 게 차이점인데요. 그리고 런타임에 c의 타입은 D일텐고, D에는 C가 가진 모든 오버로드보다 더 이 경우에 적합한 int형 파라미터를 가진 Foo가 있습니다. 10은 int형으로 간주될테니, D의 Foo가 가장 적합한 선택이 되겠죠.

그런데, 결과는 어떨까요? 이 부분에 대해서 잘 아시는 분이나 코드를 작성하다가 이상한 점을 발견하신 분이라면 대답하실 수 있으실텐데요. 아래의 그림에서 확인을..


네. 분명히 오버로드가 총 3개여야 할텐데, 두개 밖에 안 나옵니다. 그래서 분명히 D의 Foo가 가장 좋은 선택임에도 불구하고 계속해서 C의 Foo(decimal x)가 호출이 됩니다. 하지만, c를 생성할때 "D c = new D();"나 "dynamic c = new D()"처럼 생성하면, D의 Foo(int x)가 호출이 됩니다. 왜 그럴까요?


- 내가 알면 이글 보고 있겠냐.

dynamic과 관련된 동적 바인딩을 설계할때, 최대한 동적바인딩이 기존의 컴파일러가 정적바인딩에서 하던 짓을 비슷하게 하게끔 유지했다고 합니다. 그래서 그 결과로 dynamic이라고 명시된 매개변수나 receiver가 아니라면, 컴파일타임에 확인할 수 있는 타입을 그 변수의 타입으로 간주한다고 합니다. 즉, 위의 예제에서 c.Foo의 오버로드로 D.Foo(int x)가 포함이 안된 이유는, "C c = new D();"의 결과로 c가 런타임에 가질 타입은 D겠지만, 컴파일타임에서는 C라고 간주한다는 겁니다. 그래서 아무리 인텔리센스를 뒤져봐도 D의 Foo를 발견할 수 없으며 호출도 할 수 없는 거죠.

하지만, "D c = new D();"나 "dynamic c = new D()"처럼 생성하면, 전자의 경우는 컴파일 타임의 c의 타입을 D로 간주하므로 오버로드 3개모두를 인텔리센스에서 확인하실 수 있구요, 후자의 경우는 동적 바인딩을 통해서 c의 런타임 타입이 D임을 알기때문에, 오버로드 후보군에서 Foo(int x)를 골라낼 수 있습니다. 예제를 하나 더 보면요.

public class C
{
    public void Foo(int x, object o)
    {
        Console.WriteLine("Foo(int x, object o)");
    }

    static void Main(string[] args)
    {
        C c = new D();
        dynamic d = 10;
        c.Foo(d, c);
    }
}

public class D : C
{
    public void Foo(int x, D d)
    {
        Console.WriteLine("int x, D d");
    }
}

위의 경우와 마찬가지로, C.Foo(int x, object o)가 호출됩니다. 같은 이유로 말이죠.


- 마치면서

사실 이번 포스트는 좀 애로사항이 있었는데요. 제 실력부족으로 참고했던 원문이 잘 이해가 안가서 말이죠. 그래서 제 나름대로 이런저런 실험을 해보다가 결론을 내렸습니다. 바로 이럴때가 고수님들의 나눔이 필요한 시점입니다. 혹시 더 자세하게 아시는 분이 있다면, 따쓰한 피드백으로 풍성하게 해주시기 바랍니다. "따쓰한" 잊지마세염^^;;;


-참고자료

1. http://blogs.msdn.com/samng/archive/2008/11/06/dynamic-in-c-iii-a-slight-twist.aspx


SharePoint 2010 개발 환경 구성

SharePoint 2010 2010. 1. 11. 08:30 Posted by 알 수 없는 사용자

SharePoint 2010 개발을 하기 위해 SharePoint 2010, Visual Studio 2010를 설치해서 개발 환경을 구성해보도록 하겠습니다. 구체적인 화면 하나하나는 생략하고 간단하게 개발 환경 구성을 정리했습니다.

 

1.     Windows 2008 R2 64비트 설치합니다.

2.     Windows 2008 R2 64비트 역할을 아래와 같이 추가합니다.

가.   웹 서버 역할

 

나.   .NET Framework 3.5 SP1

3.     Litwareinc.com 으로 Active Directory를 구성합니다.

4.     SQL Server 2008 R2를 설치합니다. R2를 설치하는 이유는 PowerPivot등을 테스트하기 위해서 위해서입니다.

 

5.     SharePoint 2010 설치 미디어를 실행합니다.



6. Software prerequisites
설치합니다. 인터넷으로 다운로드 받기 때문에 인터넷이 연결되어야 합니다.


7.    
SharePoint Server를 설치합니다.

  가.   SharePoint Server 설치 시작

  나.   Server Farm 선택


다.  
Configuration 마법사


   라.   중앙 관리 사이트에서 Farm 구성


  마.   SharePoint 사이트 생성


몇몇 구성은 아직 하지 않았지만 이상으로 SharePoint 2010 설치가 완료되었습니다.

 

8.     Office 2010을 설치합니다.

9.     Visual Studio 2010 설치하여 새 프로젝트에서 SharePoint 를 클릭해서 보시면 아래와 같은 화면을 보실 수 있습니다



다음 블로그에서 간단한 웹 파트를 생성해서 개발 환경 구성이 완료되었는지 확인해보도록 하겠습니다.

기본 WCF 프로그래밍 - 첫 WCF 서비스 만들기

WCF 2010. 1. 8. 09:00 Posted by 알 수 없는 사용자
새해가 밝았습니다. (조금 늦었지만,, ;;;;)
올해는 60년 만에 찾아 온  백 호랑이의 해라고 하죠~ 
식상한 멘트일 것 같지만, 백 호랑이의 기운을 받아 올 한해 모두 바라는 일 이루시길 바라겠습니다. ^^

오늘은 WCF 두 번째 시간으로 WCF의 기본에 대해 알아보고, 간단한 WCF 서비스를 만들어보도록 하겠습니다.

지난 포스팅에서 WCF가 웹 서비스와 비슷하게, 분산 어플리케이션을 쉽게 개발할 수 있는 .NET 기술이라고 설명했었습니다.
분산 어플리케이션은 많은 분들이 아시겠지만, 특정 기능을 수행하는 서버 프로그램과 그리고 이 서버 프로그램을 호출하는 클라이언트로 이루어져 있는 이러한 구조를 가집니다. (쉽게 웹 서비스를 사용하는 어플리케이션 구조를 생각하면 될 것 같습니다.)

물론, WCF도 예외는 아닙니다. WCF는 크게 클라이언트와 서버 프로그램,, 그러니깐 WCF 서비스로 나눌 수 있습니다. (이제부터는 서버 쪽 WCF 프로그램을 WCF 서비스(또는 서비스)라고 지칭하겠습니다.) 

이러한 구조에서 클라이언트와 서비스는 메세지를 주고 받기 위해 아래 그림과 같이 Endpoint 를 제공합니다.


Endpoint라,, 약간 생소한 단어죠? ㅎ,,  endpoint는 WCF 에서 새롭게 정의되어진 단어로서 서비스에 접근할 수 있는 interface라 생각하면 될 것 같습니다. Endpoint를 "종단점"이라고 해석하던데, 개인적으로는 종단점보다는 엔드포인트(endpoint)가 더 와닿는 것 같아서 잘 안씁니다 ㅎ

엔드포인트는 Address, Binding, Contract 세가지의 구성 요소로 이루어집니다. (이를 "WCF 서비스의 ABC" 라고 기억하시면 됩니다.)

그럼, 각 요소들에 대해 좀 더 자세한 설명을 해보겠습니다.

  • Address (Where) : Address는 말 그대로 주소입니다. 서비스가 어디에 있는지에 대한 정보를 나타내는 것으로 메세지가 보내어져야 하는 곳을 말합니다. 메세지 전송을 위해 HTTP 프로토콜을 사용한다면 address는 "http://myserver/myservice/" 와 같은 모습을 할 것이며, 만약, TCP 프로토콜을 사용한다면 "net.tcp://myserver:8080/myservice" 와 같이 표현될 수 있습니다.
  • Binding (How)BindingChannel을 정의합니다. Channel이란 메시지를 주고 받기 위한 여러 프로토콜을 명세하는 것을 말하는데, 여기에는 메시지를 전송하기 위한 전송 프로토콜, 보안의 적용 여부 그리고, 트랜잭션의 지원 여부 등이 포함됩니다. 전송 프로토콜의경우 HTTP, TCP, Named Pipes, MSMQ 등을 지원하여 서비스의 목적이나 환경에 따라서 적절하게 사용할 수 있다는 장점이 있습니다.
  • Contract (What)Contract는 서비스의 operation에 필요한 메시지의 포맷을 정의합니다. 좀 더 쉽게 설명하자면, 메시지의 포맷이란 결국 서비스에서 제공하는 메소드와 이 메소드의 매개변수를 정의한 것입니다.(서비스가 제공하는 기능들을 정의한 것이라고 볼 수도 있겠네요~^^) 실제로, 이후에 WCF 서비스를 만들어보면 알겠지만 이 Contract에는 서비스가 제공하는 메소드를 정의한 인터페이스가 매핑되는 것을 볼 수 있을 것입니다.

위의 그림을 조금 발전시킨 그림입니다. WCF 서비스와 클라이언트는 특수한 상황이 아닌 경우 양방향 통신을 하기 때문에 클라이언트 역시 엔드포인트를 가지고 있어야 합니다. 물론, 서비스와 클라이언트의 엔드포인트는 각각 A,B,C를 정의해야 겠죠~!!

서비스를 개발하고, 엔드포인트까지 정의가 끝이 나고 나면, 이제 이 서비스를 호스팅(Hosting)해야 합니다. 마지막으로 호스팅 작업을 해줘야 서비스는 외부에서 접근할 수 있는 상태가 됩니다.

WCF는 서비스를 호스팅 하기 위해 여러 가지의 방법을 제공합니다. 가장 보편적인 방법으로 IIS Hosting이 있구요, 이 외에 Windows Service를 이용한 Hosting과 윈폼 또는 콘솔 어플리케이션을 이용해서 호스팅을 수행할 수도 있습니다
(호스팅 부분만 다루더라도 내용이 많기 때문에 여기서는 간단하게 설명하고 넘어가도록 하겠습니다. 물론, 차후에 이 주제로 포스팅을 할 예정이니 Don’t worry about that~!! ^^;;)

여기서도 WCF의 장점이 팍팍 느껴지지 않으시나요? ^^ 
기존 웹 서비스의 경우에는 항상 IIS를 사용해야 했었고, 그 덕분에 http 프로토콜 만을 이용할 수 밖에 없었죠. 하지만, WCF 서비스는 여러 방식을 통해 호스팅 할 수 있는 장점을 가짐으로써, 적시적소에 서비스를 적용할 수 있는 큰 장점을 제공해 주는 것입니다. 더군다나, 이러한 것들을 개발자가 쉽게 개발할 수 있도록 해주었다는 것 역시 WCF의 큰 장점입니다. (보면 볼수록 너무나도 매력적인 플랫폼이에요~ ^^*)

일단, 기본적인 사항은 여기까지 설명을 하구요, 나머지는 실제로 간단한 WCF 서비스를 만들어보면서 추가적으로 설명을 하겠습니다.
다음으로 넘어가기 전에, 아래와 같은 내용을 다시 한번 되새김질(?) 하고 넘어가도록 하죠~ ^^

서비스를 개발하기 위해선,,
  • 서비스가 제공하는 기능들을 정의 한 Contract 가 존재해야 한다.
  • 서비스에 접근하기 위한 엔드포인트가 필요하며, 엔드포인트는 Address, Binding, Contract 로 구성되어 있다.
  • 서비스를 노출하기 위해 서비스를 호스트 해야하며, WCF는 호스팅을 수행하기 위한 여러가지 방식을 제공해 준다.

이제~ 간단한 WCF 서비스를 개발해 볼까요? 


간단한 WCF 서비스 개발하기

앞에서도 설명을 했었지만, WCF 서비스는 호스팅을 위한 여러 방법이 존재합니다. 처음으로 만드는 이 WCF 서비스는 여러 방법 중 Console 어플리케이션을 이용한 방법으로 간단하게 만들어볼까 합니다. (이 방법이 가장 심플하니깐요~ 흣,,)
여기서는 아주*10000 간단한 서비스를 만들어볼꺼구요, “WCF 서비스가 어떤 모습을 하고 있는지,,” 정도만 알고 넘어가시면 될 듯 합니다.

우선, VS2010에서 Console Application 프로젝트를 생성합니다. (아,, 개발 언어는 C#을 사용할 것입니다. 앞으로도 쭈~욱~~ )
그리고, 프로젝트에 아래 그림과 같이 각각 IProductService.cs, ProductService.cs 라는 이름을 가진  두 개의 파일을 추가 하였습니다.


IProductService는 인터페이스며, 서비스의 계약을 정의합니다. 서비스의 계약은 한마디로 서비스가 제공하는 여러 메소드를 정의하는 인터페이스라고 생각하시면 됩니다. 그리고, ProductService는 IProductService를 상속받아 실제 메소드를 구현하는 클래스입니다.

파일을 추가한 후에, 프로젝트에 System.ServiceModel.dll 어셈블리를 참조 추가합니다.
(System.ServiceModel.dll 에 WCF 서비스를 위한 대부분의 클래스들이 포함되어 있습니다. 앞으로도 계속 쓰이게 될 중요한 어셈블리죠~ ^^)

이제, 서비스를 개발 할 준비가 다 되었습니다. 먼저, IProductService 인터페이스 부터 구현해보겠습니다. 
(아래 코드에는 생략되었지만, using 문을 사용하여 System.ServiceModel 네임스페이스를 사용하도록 해주는 것도 잊지 마세요~)

[ServiceContract]
interface IProductService
{
    [OperationContract]
    string GetFirstName(string empID);
}

너무 간단한가요? ㅎ,, 
서비스의 계약을 정의해 주는 일은 봐서 알겠지만 아주 쉽습니다. 클래스에 "ServiceContract" 특성을 지정하고, 그 메소드에는 "OperationContract" 특성을 지정해 주는 것만으로도 계약을 정의해 줄 수 있습니다.이 외에 여러 옵션들을 줄 수 있지만, 차후에 다루게 될 것이니 이것만으로 넘어가겠습니다.
(다시 한번 강조하지만, 이번 WCF 서비스는 아주 간단한 서비스라는거~ 아시죠?? ^^)

다음으로 ProductService 클래스를 구현해보겠습니다.

class ProductService: IProductService
{
    public string GetFirstName(string empID)
    {
        return"Steve";
    }
}


음,, ProductService도 아주 아주 간단합니다. (제가 민망할 정도로,,~ ^^;;)
차후에 이 서비스를 수정해서 쓰긴 하겠지만, 지금은 별 다른 기능없이 단순하게 "Steve" 라는 문자열을 반환해주는 메소드를 구현하였습니다.
사실, 구현 부분은 지금 상황에서 그렇게 중요하지 않습니다.

서비스의 계약과 관련한 구현은 다 되었습니다. 이제 해야할 작업은 이 서비스를 호스팅하는 일이죠~
Console 어플리케이션을 이용하여 호스팅을 하기 위해서 Program.cs 에 관련 코드를 다음과 같이 추가 하였습니다.

using System.ServiceModel;
using System.ServiceModel.Description;

namespace MyService
{
    class Program
    {
        static void Main(string[]args)
        {
            Uri baseUri = new Uri("http://localhost:8000/ProductService");
            using(ServiceHost serviceHost = new ServiceHost(typeof(ProductService), baseUri))
            {
               //Add Service Endpoint
               serviceHost.AddServiceEndpoint(typeof(IProductService), new BasicHttpBinding(), "");
               
               //Add Metadata Behavior
               ServiceMetadataBehavior mexBehavior = new ServiceMetadataBehavior();
               mexBehavior.HttpGetEnabled = true;
               serviceHost.Description.Behaviors.Add(mexBehavior);

               //Add Metadata Exchange Endpoint
               serviceHost.AddServiceEndpoint(typeof(IMetadataExchange), 
                                              MetadataExchangeBindings.CreateMexHttpBinding(),"mex");
               serviceHost.Open();


               Console.WriteLine("Press <ENTER> to terminate WCFService.\n");
               Console.ReadLine();
            }
        }
    }
}

호스트 구현은 조금 코드가 길죠,, ^^;
사실, 서비스 자체만 호스팅 하는 코드는 그렇게 길지 않습니다. 하지만, 서비스에 Metadata Exchange Endpoint를 추가하려다 보니 코드가 조금 길어졌습니다. 

이 코드에서의 핵심은 ServiceHost 클래스입니다. ServiceHost 객체를 이용하면, WCF 서비스를 호스팅 할 수 있다는 사실을 마음 속 아니, 머리 속 깊이 넣어주세요~

ServiceHost 클래스의 생성자는 두 개의 파라미터를 받습니다.  첫번째 파라미터는 호스팅 하려는 클래스의 타입이며, 두번째 파라미터는 Base Uri 입니다. Base Uri는 말 그대로 서비스의 기본 주소(address)를 나타냅니다.

ServiceHost 객체를 생성한 후에는 이 개체에 AddServiceEndpoint 메소드를 이용하여 endpoint를 추가하여 줍니다.
AddServiceEndpoint 메소드는 기본적으로 세 개의 파라미터를 필요로 하는데, 이 파라미터가 앞에서 설명했던 Address, Binding, Contract 입니다.

Contract는 서비스의 계약을 정의 했던 IProductService 인터페이스를 지정하구요, BindingBasicHttpBinding 클래스를 사용하였습니다. BasicHttpBinding 클래스는 WCF에서 기본적으로 제공하는 여러 Binding 개체 중에 하나로 이름에서 알 수 있듯이 기본적인 Http 프로토콜을 사용합니다. 그리고, 마지막 Address 는 빈 문자열을 주었습니다. 이렇게 빈 문자열을 주게 되면 endpoint의 주소는 ServiceHost 개체를 만들 때 사용했던 Base Uri와 동일한 값을 가지게 됩니다.

Endpoint 추가까지 끝이 나면 호스트를 수행할 준비가 모두 끝납니다. 이제 ServiceHost 개체의 Open 메소드를 사용하여 서비스를 시작할 수 있는데, Open 메소드는 각 채널에 맞는 리스너(listener)를 별도의 스레드로 수행을 하여 클라이언트의 요청을 처리할 수 있게 합니다.

(혹시,, 제가 Metadata Exchange Endpoint 에 대한 설명은 살짝 넘어갈려고 한 걸 눈치 채셨나요? ^^;; MEX 에 대해선 다음 포스팅 때 꼭 설명을 하도록 할께요~ 한번만 눈 감아주시길,, ㅋ)

서비스 구현은 모두 끝이 났습니다. 한번 실행해 볼께요~

실행을 하면 다음과 같은 Console 창이 뜹니다.


이 창이 무사히 뜨면, 서비스가 아무 탈 없이 잘 동작하고 있다는 말입니다.
음,, 이것만 봐서는 믿음이 안 갈 수 있으니, 한번 검증해 보죠~ ㅎ,, 

이 콘솔 창을 그대로 띄워 놓은 상태에서 브라우저를 열고 주소창에 http://localhost:8000/ProductService (이 주소는 ServiceHost 개체를 생성할 때 입력했던 Base Uri 인거,, 기억하시죠? ^^) 를 입력해보겠습니다~
다음과 같은 내용을 확인할 수 있습니다. 짜잔~


이 화면은 어디서 많이 본 것 같죠?? 네,, 예전 .NET 웹 서비스를 만든 후 실행했을 때의 화면과 비스무리(??) 합니다~ ^^
(서비스가 잘 동작하고 있군요,, ㅎ)

이로써, 첫 WCF 서비스 만들기가 끝이 났습니다. 유후~~

이제 Client를 만들어야 되는데,,(흠,,) 글이 너무 길어진 것 같은,,;;;;; 
어쩔 수 없군요~ Client 구현은 다음으로,, (MEX 설명과 함께~ ㅎㅎ)

빠른 시일 내에 다음 포스팅을 올리도록 할테니, 너무 노여워 하지 말아주세요~ (기다리시는 분이 있을 것 같진 않지만,, ^^;;)

또 다시 강조하지만, 이번 포스팅의 목적은 "WCF 서비스는 어떤 식으로 구현하는가?" 에 있습니다.
따라서, WCF에 대해 전체적인 그림(?)을 그릴 수 있는 내용이 되었으면 해서 Binding 이나 Behavior 등 자세한 설명은 하지 않았습니다.
세부적인 설명들은 앞으로 차차 하게 될 것이니깐요,, (가야 할 길은 멀고도 험하죠,, ^^;;)

어쨌든 이 자료가 WCF를 시작하는 분들께 많은 도움이 되었으면 합니다.
그럼 다음 포스팅때 뵙겠습니다~ ^^

Welcome to Dynamic C#(9) - Dynamic Returns Again.

C# 2010. 1. 7. 09:00 Posted by 알 수 없는 사용자

- 정말 오랜만에 다시 Dynamic이군요.

안녕하세요~! 눈 때문에, 어떤 사람들은 로맨틱한 겨울이고, 어떤 사람들은 악마의 똥가루의 냄새에 신음하고, 어떤 사람들은 방에 콕처박혀 있고 뭐 아주 버라이어티한 겨울입니다. 겨울이 버라이어티 정신이 충만하네요. 연예대상같은거라도 하나 받고 싶은 가봐요. ㅋㅋ 아무튼! 정말 오랜만에 다시 dynamic시리즈를 쓰게 되네요. 워낙 한 내용도 없이 중간에 끊어서 좀 그랬습니다;;; 물론, 기다리신 분이 얼마나 있을지는 미지수지만요-_- 그럼. 한번 이야기를 시작해볼까요? dynamic에 대해서 조금씩 자세하게 들어가 보겠습니다.


- 어서내놔 dynamic

우선 예제를 하나 보시죠.

dynamic d = 10;
C c = new C();

//위쪽 그룹 
d.foo();
d.SomeProp = 10;
d[10] = 10;

//아래쪽 그룹 
c.Foo(d);
C.StaticMethod(d);
c.SomeProp = d;




위 그룹과 아래 그룹의 차이점은 뭘까요? 네~! Give that man a cigar!(누가 정답을 말했을때 하는 말이라네요) 위 그룹은 액션을 받는 객체가 동적인 객체, 즉 dynamic receiver이구요. 아래 그룹은 static receiver와 static method가 바로 차이점입니다.

위 그룹은 동적인 표현식(expression)속에서 직접적으로 동적인 행위가 일어나고, 아래그룹은 직접적으로  동적표현식은 아닙니다. 각각의 연산의 매개변수로 동적인 타입이 들어가면서, 전체적인 표현식을 간접적으로 동적으로 만들고 있는거죠. 이런 경우에는 컴파일러가 동적인 바인딩과 정적인 바인딩을 섞어서 수행하는데요. 예를 들어서 동적타입을 매개변수로 받는 오버로드가 있을 경우에, 어떤 멤버집합(member set)을 오버로드해야 할지 결정할때는 정적인 타입을 사용해서 판단할테구요, 실제로 오버로드를 판별(resolution)할때는 매개변수의 런타임 타입을 사용할 것이기 때문이죠.

컴파일러가 dynamic타입인 표현식을 보게되면, 그 안에 포함된 연산들을 동적 연산처럼 처리하게 됩니다. 즉, 표현식이 인덱스를 통한 접근이든 메서드호출이든 상관없이 그 표현식의 결과로 나오는 타입은 런타임에 결정될거라는 거죠. 그 결과로 컴파일 타임에 동적인 표현식의 결과로 나오는 타입은 dynamic이겠죠.

컴파일러는 이런 모든 동적인 연산들을 DLR을 통해서 dynamic call site라는 걸로 변환을 합니다. 지지지난 포스트에서 설명을 드렸던거 같은데요, 제네릭한 델리게이트를 가지고 있는 정적 필드입니다. 어떤 연산에 대한 호출을 가지고 있다가, 추후에 같은 타입의 연산이 호출되면 다시 call site를 생성할 필요없이 정적필드에 저장된 델리게이트를 호출해서 실행에 필요한 부하를 최대한 줄이는데 도움을 주는 친구죠. call site가 만들어지면, 컴파일러는 그 call site에 저장된 델리게이트를 호출할 코드를 생성하구요, 거기에다가 매개변수를 넘겨줍니다.

만약에, 호출한 객체가 IDynamicObject를 구현해서 스스로 동적 연산을 어떻게 처리할지 아는 객체가 아니거나, 미리 저장된 델리게이트와 타입이 안맞아서 캐시가 불발이 나면, call site와 같이 생성된 CallSiteBinder가 호출됩니다. CallSiteBinder는 call site에 필요한 바인딩을 어떻게 처리해야 하는지 알고 있는 객체인데요, C#은 이 CallSiteBinder에서 상속한 바인더를 갖고 있습니다. 이 C# CallSiteBinder가 적절한 바인딩을 통해서 DLR의 call site가 갖고 있는 델리게이트에 저장될 내용을 expression tree형태로 만들어서 리턴합니다. 이 내용역시 전전, 전포스트에서 다뤘었쬬? 못봤다고 하시면!!!! 제가 절대 가만있을수는 없는 문제고! 링크를 드..드리겠습니다. 전포스트, 전전포스트. 친절하죠?-_-


- 캐시되는 과정은 어떠냥

공개된 문서를 통해 볼 수 있는 현재의 캐시 방식은 그냥 단순히 매개변수들의 타입이 일치하는지 검사하는겁니다.  만약에.. 이런 호출이 있다고 할때...

args0.M(arg1, arg2, ...);

그리고, 이전에 args0이 C라는 타입이며, 매개변수 arg1과 arg2가 모두 int인 호출이 있었다고 해보면요, 캐시를 체크하는 코드는 대략아래와 같습니다.

if (args0.GetType() == typeof(C) &&
    arg1.GetType() == typeof(int) &&
    arg2.GetType() == typeof(int) &&
    ...
    )
{
    //CallSiteBinder의 바인드 결과는 여기에 계속 통합되구요
}
    ......//캐시 검사는 좀 더 많을 수도 있구요
else
{
    //여기서 CallSiteBinder의 bind메서드를 호출하고, 캐시를 업데이트 합니다.
}

지금까지 간단하게 알아본 내용을 그래도 마무리 하려면, C# CallSiteBinder가 뭘 어떻게 하는지를 알면 되겠네요. 서두에 두그룹의 연산중에 위 그룹의 연산을 보면요, 메서드 호출, 속성 접근, 인덱서 호출등 3가지 연산이 있었죠. 일단 모든 연산은요 표준 C# runtime binder를 통해서 생성되고, C# runtime binder가 걔네들을 데이터 객체로 사용합니다. 그 데이터객체는 바운드되야할 액션을 설명하는데요, 그런 객체를 C# payload라고 부른다고 합니다. 

C# runtime binder는 쉽게 작은 컴파일러라고 생각하면 되는데요, 얘가 일반적인 컴파일러가 갖고 있는 심볼테이블이나 타입시스템, 오버로드 판별 및 타입 교체같은 기능을 갖고 있기 때문입니다. 간단하게 d.Foo(1)을 예로 생각해보죠.

runtime binder가 호출되면, 현재 call site에 대한 payload과 call site에 대한 런타임 매개변수를 갖습니다. 그리고 dynamic receiver를 포함해서 그 모든 런타임 매개변수와 타입을 모아서는 그 타입에 대한 심볼테이블을 만듭니다.(심볼테이블에 대한 간략한 설명은 여기를 참조하세영!) 그리곤 payload꾸러미를 풀어헤쳐서 수행하려고 하는 연산의 이름을 꺼냅니다.(Foo) 그리고 d의 타입에서 리플렉션을 사용해서 Foo라는 이름을 갖는 모든 멤버를 뽑아냅니다. 그리고 걔네들도 심볼테이블에 적어넣죠. 말로 설명하니깐 깝깝하시죠? 설명하는 저도 깝깝하네여-_-;;; 제가 상상력을 동원해서 부연설명을 드리면요,

d.Foo(1)에서 먼저 매개변수의 타입과 d의 타입을 갖고와서 심볼테이블에 적어두고요.

주소     타입            이름
서울시   int             익명(= 1)

수원시   dynamic      d

그리고 리플렉션으로 d의 타입에서 Foo를 모두 찾아냈는데 대략 아래와 같다고 해보죠.
Foo(int a)
Foo(double b)
Foo(string c)

그리고 얘네들도 따로 심볼테이블에 집어넣으면?

-call site에 대한 심볼테이블
주소     타입            이름
서울시   int            익명(= 1)
수원시   dynamic      d

-d의 멤버중에 Foo라는 동명이인들
주소      타입        이름
부산시   void     Foo(int a)
창원시   void     Foo(double b)
안양시   void     Foo(string c)

그러면, 타입을 찬찬히 들여다보면, 어떤 Foo가 호출되야 할지 명확하게 보입니다. d.Foo(1)호출에서 매개변수의 런타임타입이 int이므로 Foo(int a)가 호출이 되겠죠. 이건 그냥 제가 설명을 위해서 상상력을 동원해본거니깐요 믿지는 마시기 바랍니다. 예비군 동원 무쟈게 귀찮으시져? 상상력도 무쟈게 귀찮아 하네요-_-. 어서 집에 보내고 다시 설명을 이어 가겠습니다.

위에서 설명드린 runtime binder를 설계할때 세웠던 한가지 원칙은 "runtime binder는 정적 컴파일러가 하는 짓을 똑같은 의미로 할 수 있어야 한다."였다고 하는데요. 그래서 에러메세지 역시 동일한 에러메세지를 뱉어낸다고 합니다.

위의 바인딩의 결과로 바인딩이 성공적일 경우에 수행할 동작을 표현한 expression tree가 만들어집니다. 그렇게 안되는 경우에는 runtime binder exception을 던진다고 하네요. 결과로 만들어진 expression tree는 DLR의 캐시에 포함되고 호출되면서 원래의 호출을 성공적으로 완료합니다.


- 약간의 제약사항?

그런데, 위에서 정적 컴파일러와 똑같은 짓을 하게 만들려고 했지만, 아마도 예산과 시간때문에 선택과 집중을 해야 하니깐 몇가지 못집어 넣은게 있다고 합니다. 람다식과 확장 메서드, 메서드 그룹(델리게이트)에 대한 이야기 인데요. 현재로서는 바인딩 안된 람다식을 런타임에서 표현할 방법이 없다고 합니다. 개발하다가 디버깅을 할때 브레이크 포인트를 잡고 그 상태에서 현재 상태의 객체에 값을 가져온다거나 메서드를 호출하고 값을 확인할 수 있잖아요? 근데, 람다식은 그런식으로 디버깅이 안됐던거 같은데, 아마 그문제가 계속 이어지는 거 같습니다.

그리고 메서드 그룹역시 런타임에 표현할 수 있는 방법이 없다고 합니다. 예를 들면,

delegate void D();
public class C
{
     static void Main(string[] agrs)
     {
        dynamic d = 10;
        D del = d.Foo; //뭐 이렇게는 안된다고 하네요. 그래서 런타임 익셉션이 난다고 합니다.
     }
}

그리고 확장 메서드 역시 using절과 범위를 바인딩없이 넘겨줄 방법이 없기때문에, 확장메서드역시 안된다고 하구요.


- 마물!

무척 오랜만의 포스팅인데요, 갈증이 조금이라도 해소가 되셨으면 좋겠네요. 제 실력이 바닥을 기다보니 원문의 내용을 한번 걸러서 드리는 정도밖에 못드리는 면이 많은데요. 뭐-_- 내공이 부족하니 한계가 명확하네요. 그럼 다음 포스트에서 뵙져~!!!!!!!


- 참고자료

1. http://blogs.msdn.com/samng/archive/2008/11/02/dynamic-in-c-ii-basics.aspx


3. MSCorLib & Metadata

CLR 2010. 1. 6. 09:00 Posted by 알 수 없는 사용자
어서 빨리 System.Object로 시작해서 CLR을 배우고 싶지만 .NET Framework 환경의 CLR의 기반에 대해 좀 더 자세히 짚고 넘어가야 할 것 같습니다. 그래서 이번엔 이 부분에 대해서 정리를 하면서 공부를 해보려고 합니다.

MSCorLib.dll

public sealed class Program
{
  public static void Main()
  {
    System.Console.WriteLine("Hi");
   }
}

이런 코드를 하나 만들어 봅시다. C# 코드입니다. 우리는 CLR을 공부하려고 하는 것이지 C#을 공부하려는 건 아니지만 앞으로 C#을 이용하여 많은 코드를 작성할 예정입니다. 암튼 빌드 해봐야겠죠. 워워- VS 2010 IDE 아직 띄우지 마세요. 훌륭한 개발툴 깔아놓고서도 쓰지 않는게 억울하긴 하지만 지난번과 같이 Visual Studio Command Prompt를 실행해서 빌드를 해 봅시다.

csc.exe /out:hi.exe /t:exe /r:MSCorLib.dll hi.cs


.exe의 실행파일이 생성되고 실행 해 보면 Hi 라고 문자열을 출력합니다.

csc는 C#컴파일러 입니다. 인자를 살펴보면 /out 은 생성될 실행파일명을 지정하는 것이고 /t는 Target의 약자로 exe로 지정되었다는 것은 Win32 어플리케이션을 생성하겠다는 의미입니다. 그리고 /r은 Reference의 약자인데 코드에서 사용된 외부에서 정의된 타입의 참조를 어떤 모듈을 이용하여 해결하겠다는 의미입니다. 마지막으로 hi.cs는 컴파일할 소스 파일이지요.

여기서 우리가 자세히 살펴봐야 할 부분은 /r의 인자인 MSCorLib.dll 입니다.

우선 소스를 다시 한번 살펴 봅시다. 소스에서는 System.Console.WriteLine이라는 메서드를 사용하고 있습니다. 여기서 System.Console 이라는 타입은 C# 컴파일러에서는 정의되어 있는 타입이 아니기 때문에 위에서 보면 MSCorLib.dll이라는 어셈블리 모듈을 참조하여 컴파일을 하고 있습니다.

MSCorLib.dll은 특별한 파일로서 모든 기본 타입을 제공하고 있습니다. Byte, Char등의 타입부터 그 외에 기본적으로 사용하는 많은 타입들을 포함한 어셈블리입니다. 그야말로 핵심 모듈이지요. 그렇기 때문에 C#등의 컴파일러에서는 /r의 인자로 MSCorLib.dll 만큼은 생략해도 기본적으로 이 모듈은 참조하여 컴파일을 하게 됩니다.
결국

csc.exe /out:hi.exe /t:exe hi.cs

라고 해도 정상적으로 컴파일은 된다는 말이지요. /out 옵션과 /t옵션의 기본값도 원래는 소스파일명(확장자 제외한).exe 이고 /t도 기본이 exe이므로 본래는

csc.exe hi.cs

라고 해도 컴파일은 문제없이 잘 됩니다. csc 컴파일러의 인자 중에서는 기본 라이브러리 모듈은 MSCorLib.dll을 참조하지 말라고 지시하는 인자가 있는데 바로 /nostdlib 입니다.

만약에 hi.cs 를 /nostdlib 인자를 주어서 컴파일을 하면 어떻게 될까요.


당연히 컴파일이 실패합니다. 'System.Object' 타입을 찾을 수 없다고 하면서 말이지요. System.Object는 모든 타입의 기본입니다. 모든 타입은 System.Object로부터 파생이 됩니다. 기본 라이브러리 모듈을 참조하지 않았으니 모든 타입의 기본이 되는 System.Object 타입을 찾지 못하는 건 당연한 결과지요. 다시 말하지만 MSCorLib.dll 은 .NET Framework의 핵심 모듈입니다.

Metadata

자 우리는 hi.exe 라는 작은 프로그램을 생성하였습니다. 이제 이 생성된 파일을 좀 까봐야겠습니다. 지난번에 실행파일은 IL코드와 메타데이터가 포함되어 있다고 배웠습니다. 좀 더 정확히 말하자면 PE32(또는 PE32+)헤더와 CLR헤더 IL코드 그리고 메타데이터가 포함되어 있습니다. 한번 살펴봐야죠.

.NET에서 생성하는 PE32 포맷의 실행파일은 기존의 PE32 형식의 실행 파일과 거의 동일합니다. 거기에 .NET Metadata 관련 섹션 정보가 추가되어 있는 형식입니다.


생성된 파일의 Metadata 정보를 확인하기 전에 Metadata의 구조는 어떤식으로 되어 있는지 확인해 봐야겠습니다. Metadata의 구조는 Microsoft SDK에 포함되어 있는 CorHdr.h 라는 헤더 파일에 IMAGE_COR20_HEADER 라는 구조체로 정의가 되어 있습니다.

typedef struct IMAGE_COR20_HEADER
{
    // Header versioning
    DWORD                   cb;             
    WORD                    MajorRuntimeVersion;
    WORD                    MinorRuntimeVersion;
   
    // Symbol table and startup information
    IMAGE_DATA_DIRECTORY    MetaData;       
    DWORD                   Flags;          
 
 // The main program if it is an EXE (not used if a DLL?)
    // If COMIMAGE_FLAGS_NATIVE_ENTRYPOINT is not set, EntryPointToken represents a managed entrypoint.
 // If COMIMAGE_FLAGS_NATIVE_ENTRYPOINT is set, EntryPointRVA represents an RVA to a native entrypoint
 // (depricated for DLLs, use modules constructors intead).
    union {
        DWORD               EntryPointToken;
        DWORD               EntryPointRVA;
    };
   
    // This is the blob of managed resources. Fetched using code:AssemblyNative.GetResource and
    // code:PEFile.GetResource and accessible from managed code from
 // System.Assembly.GetManifestResourceStream.  The meta data has a table that maps names to offsets into
 // this blob, so logically the blob is a set of resources.
    IMAGE_DATA_DIRECTORY    Resources;
 // IL assemblies can be signed with a public-private key to validate who created it.  The signature goes
 // here if this feature is used.
    IMAGE_DATA_DIRECTORY    StrongNameSignature;
    IMAGE_DATA_DIRECTORY    CodeManagerTable;   // Depricated, not used
 // Used for manged codee that has unmaanaged code inside it (or exports methods as unmanaged entry points)
    IMAGE_DATA_DIRECTORY    VTableFixups;
    IMAGE_DATA_DIRECTORY    ExportAddressTableJumps;
 // null for ordinary IL images.  NGEN images it points at a code:CORCOMPILE_HEADER structure
    IMAGE_DATA_DIRECTORY    ManagedNativeHeader;
   
} IMAGE_COR20_HEADER, *PIMAGE_COR20_HEADER;


좀 보기 힘들긴 하지만 위에서부터 하나하나 확인해보죠. 우리가 위에서 생성한 hi.exe 파일을 대상으로 확인하려고 합니다. 직접 헤더를 분석하는 툴을 만들어도 좋겠지만(^-^;;) CFF Explorer 라는 툴을 이용하여 헤더를 확인해 보기로 합니다.


CFF Explorer로 확인해 보면 .NET Directory 섹션부터 위의 헤더 정보와 동일한 이름의 정보들이 순차적으로 기록되어 있는 것을 확인할 수 있습니다. 굉장히 많은 정보 중에서 우리가 짚고 넘어가야 할 정보들은 메타데이터 정의 테이블과 메타데이터 참조 테이블입니다.

Corhdr.h 파일에서 메타 데이터 정의 테이블과 참조 테이블 리스트들의 이름들을 확인해 볼 수 있습니다.   

// Token  definitions

typedef mdToken mdModule;               // Module token (roughly, a scope)
typedef mdToken mdTypeRef;              // TypeRef reference (this or other scope)
typedef mdToken mdTypeDef;              // TypeDef in this scope
typedef mdToken mdFieldDef;             // Field in this scope
typedef mdToken mdMethodDef;            // Method in this scope
typedef mdToken mdParamDef;             // param token
typedef mdToken mdInterfaceImpl;        // interface implementation token

typedef mdToken mdMemberRef;            // MemberRef (this or other scope)
typedef mdToken mdCustomAttribute;      // attribute token
typedef mdToken mdPermission;           // DeclSecurity

typedef mdToken mdSignature;            // Signature object
typedef mdToken mdEvent;                // event token
typedef mdToken mdProperty;             // property token

typedef mdToken mdModuleRef;            // Module reference (for the imported modules)

여기서 확인해 봐야 할 테이블들은 다음과 같습니다.

메타 데이터 정의 테이블 리스트
 메타 데이터 정의 테이블 이름 설명 
 ModuleDef 모듈을 식별하기 위한 항목
 TypeDef 모듈 내의 정의된 각 타입을 위한 항목
 ModuleDef 모듈 내에 정의된 각 메서드를 위한 항목
 FieldDef 모듈 내에 정의된 모든 필드를 위한 항목
 ParamDef 모듈 내에 정의된 각 파라미터를 위한 항목  
 PropertyDef 모듈 내에 정의된 각 속성을 위한 항목 
 EventDef 모듈 내에 정의된 각 이벤트를 위한 항목 

메타 데이터 참조 테이블 리스트
 메타 데이터 참조 테이블 이름 설명
 AssemblyRef 모듈이 참조하는 각 어셈블리를 위한 항목 
 ModuleRef 모듈이 참조하는 타입을 구현하는 각 PE 모듈을 위한 항목 
 TypeRef 모듈이 참조하는 각 타입을 위한 항목 
 MemberRef 모듈이 참조하는 각 멤버(필드 메서드 속성 이벤트 등)를 위한 항목 

위의 두 테이블을 참조하여 파일의 메타 데이터 항목들을 살펴 봅니다.

ModuleDef
모듈의 이름 버전 ID (GUID의 형태로 생성됩니다.) 등이 기록되어 있는 것을 확인 할 수 있습니다.

TypeRef
4개의 타입 참조가 보입니다. 그 중 Console Type에 대한 정보를 살펴봅시다. 타입의 이름(Name)과 이 타입이 어디에 있는지(Namespace)에 대한 정보를 포함하고 있네요.

TypeDef
모듈 내에 정의된 각 타입을 위한 항목을 포함한다고 했습니다. 각 엔트리는 타입의 이름(Name), 상위 타입(Namespace), 플래그(TypeDef Flags)등을 갖고 있습니다. Extends에 TypeRef Table Index 1이라고 되어 있네요. TypeRef의 1번째 인덱스는 위의 화면에서 보면 알겠지만 Object입니다. Object 클래스로부터 상속되어 확장되었다는 걸 알 수 있겠네요.

Method
위의 테이블에선 없던 항목이지만 Method라는 항목도 보이네요. 보시면 알겠지만 hi.exe 내의 메서드 정보를 포함하고 있습니다.  .ctor은 뭔가요? 생성자입니다. .ctor이 호출되어야지 해당 객체가 메모리에서 생성된 위치를 가리키는 포인터 this라는 값을 갖게 됩니다.

MemberRef
모듈이 참조하는 각 멤버들의 참조 정보를 갖고 있네요. 3번째는 WriteLine입니다. Class정보를 보면 TypeRef Table Index 4 라고 되어 있네요. 위에서 확인해 보면 System.Console을 가리키는 것임을 알 수 있습니다. 다른 멤버들 역시 TypeRef의 다른 멤버들을 가리키고 있습니다.

그리고 밑에 보이는 CustomAttribute는 나중에 Attribute를 공부할 때 다시 한번 언급해 보기로 하구요. Assembly는 다음에 공부해야 할 Assembly에서 다시 한번 보면 될 것 같네요.

대략이나마 Metadata 정보를 확인해 보니까 정말 다양한 정보들이 체계적으로 기록되어 있다는 것을 확인해 볼 수 있었습니다.

생각보다 진도가 늦어지고 있네요. 그래도 이왕 공부하는 것 아주 완벽히는 아니더라도 이렇게 하나하나씩 살펴봐야지 공부하면 공부할수록 좀 더 깊이있는 이해가 필요한 부분에서 도움이 될 것이라고 생각합니다.

이 글을 보시는 분들 시간을 내서 직접 맨 위의 코드를 컴파일 해보시고 이런저런 메타데이터 정보를 한번 확인해 보세요~ CFF Explorer 라는 툴도 있지만 기본적로 지원하는 IL 역어셈블러 툴인 ILDasm.exe를 이용하셔도 위에서 언급한 메타데이터 정보들을 확인할 수 있습니다.



메타데이터 정보가 보이지요?


함수의 IL코드도 확인할 수 있습니다.

위에서 언급한 .ctor 코드도 볼 수 있습니다. System.Object의 생성자를 부르고 있네요. 이외에도 다양한 정보들을 확인해 볼 수 있으니까 꼭 한번씩 살펴보세요. :)


참고 자료
CLR via C# 2nd Ed.



'CLR' 카테고리의 다른 글

6. Assembly - GAC(Global Assembly Cache)  (2) 2010.02.02
5. Assembly - Strongly named assemblies  (0) 2010.01.26
4. Assembly  (2) 2010.01.15
2. CLR! CLR! CLR!  (3) 2009.12.30
1. Hello 世界  (0) 2009.12.23

SharePoint 2010 Overview

SharePoint 2010 2010. 1. 6. 08:30 Posted by 알 수 없는 사용자

현재 SharePoint 관련 제품은 MOSS 2007, WSS 3.0을 사용하고 있으며 SharePoint 2010 버전은 Beta(http://sharepoint2010.microsoft.com)를 다운로드 받을 수 있습니다.

 

SharePoint 개발에 대한 내용을 들어가기 전에 SharePoint 2010 에 대한 Overview를 살펴보도록 하겠습니다. SharePoint 2010을 한마디로 정의한 내용은 아래 그림으로써 비즈니스 협업 플랫폼이라고 할 수 있습니다.

 



SharePoint 2010 비즈니스 협업 플랫폼은 사람들이 어디에 있던 어떤 장치를 사용하던 상관없이 자원과 지식을 액세스할 수 있도록 해서 생산성을 향상시키며, SharePoint 2010으로 협업 솔루션이 일원화되어 교육비용, 유지비용, IT 비용 등의 절감이 가능하며, 인터넷, 엑스트라넷, 인트라넷 등을 위한 커스마이징된 솔루션을 빠르고 안전하게 배포가 가능하고 정보 액세스가 검색 기술의 강화로 손쉬워지며 데이터 기반 의사 결정이 가능해서 변화하는 비즈니스 요구사항에 빠르게 대처가 가능합니다.

 

위 그림의 왼쪽 차트에 대한 부분을 관련 요소를 나열해보도록 하겠습니다.

l  Sites

-       Ribbon UI, SharePoint Mobile, Office Client Office Web 통합, 사이트 템플릿

l  Communities

-       Tagging, Ratings, Social Bookmarking, BlogWiki, 내 사이트, Profiles, Feeds

l  Content

-       Enterprise 콘텐트 형식, Metadata Navigation, 문서 셋, Audio Video 콘텐트 형식, 강화된 리스트

l  Search

-       사회적 연관성, 탐색, FAST 통합

l  Insights

-       PerformancePoint 서비스, Excel 서비스, Visio 서비스, Chart 웹 파트, PowePivot

l  Composites

-       Business Connectivity Services, InfoPath Form Services, External Lists, Workflow, SharePoint Designer, REST/RSS/ATOM 지원

 

위의 요소들을 접근할 SharePoint 개발자를 위한 새로운 내용은 뭐가 있는지 나열해보겠습니다. 아래와 같이 여러 요소들이 있으며 몇몇을 제외하고 세부적으로 다루어보도록 하겠습니다.

 

l  Windows 7 또는 Windows Vista SP1 에 개발 환경 구성 가능

l  Visual Studio 2010에서의 여러 템플릿

l  SharePoint Designer 2010

l  Developer Dashboard

l  Business Connectivity Services

l  LINQ to SharePoint

l  Client OM, REST API

l  향상된 Workflow

l  Ribbon Custom Actions

l  Dialog Framework

l  Silverlight 3

l  SharePoint Service Applications

l  Sandboxed Solutions

l  Upgrade and Packaging

l  Team Foundation Server와 통합

 

 

아래 그림의 프로젝트 템플릿만 봐도 MOSS 2007에서의 개발과는 완전히 달라졌다고 볼 수 있습니다.

SharePoint 2010에 참고할 수 있는 링크는 아래와 같습니다.

 

SharePoint 2010 사이트

http://sharepoint2010.microsoft.com/Pages/default.aspx

SharePoint Team Blog

http://blogs.msdn.com/sharepoint/

SharePoint 2010 SDK

http://www.microsoft.com/downloads/details.aspx?FamilyID=F0C9DAF3-4C54-45ED-9BDE-7B4D83A8F26F&displayLang=en

SharePoint Developer Center

http://msdn.microsoft.com/en-us/sharepoint/ee513147.aspx

SharePoint Product Tech Center

http://technet.microsoft.com/ko-kr/sharepoint/ee518660(en-us).aspx



다음 블로그부터는 아래와 같은 내용을 다루어 보도록 하겠습니다.
  • SharePoint 2010 개발환경 구성
  • VS 2010에서의 SharePoint 2010 Developer Platform
  • Web Part 개발
  • Visual Web Part 개발
  • Ribbon Custom Action
  • Dialog Framework
  • Silverlight 콘텐트
  • VS 2010을 통한 Workflow Foundation
  • SharePoint에서 LINQ/REST 사용
  • SharePoint Masterpage 생성 및 구성
  • VS 2010을 통한 BCS
  • SharePoint에서 Client OM

SQL Azure 알아보기 (5)- SQL Azure 이점과 T-SQL 지원

Cloud 2010. 1. 1. 19:52 Posted by 알 수 없는 사용자


SQL Azure에 대해 어느 정도 살펴보았으며 간단하게 현재 운영하고 있는 SQL Server와 비교를 나열해보려고 합니다. 현재 CTP를 살펴본 내용으로 저와 생각이 상이할 수 있습니다.

그리고 실제 운영한다면 많이 차이점을 구체적으로 느낄 것 같습니다.


먼저 SQL Azure의 이점을 아래에서 살펴봅니다.

 

1.     관리적 요소와 확장성

패치 등등 많은 관리적 오버헤드 없이 손쉽게 엔터프라이즈의 데이터 서비스 응용프로그램 기능을 제공할 수 있습니다. 그리고 저장소 증가로 인한 비용은 현재 사용하고 있는 저장소에 대한 비용만을 지불하면 됩니다. 초기 비용에 대한 감소가 매력적으로도 보입니다. 데이터 센터인데 관리적으로 별 신경 안써도 된다는 것이라고 생각됩니다.

 

2.     고 가용성

SQL Azure 는 물리적으로 여러 복사본이 생성되어 비즈니스 연속성과 고 가용성을 제공해주고 있습니다. 하드웨어 고장시 자동 Failover를 제공합니다. 이 또한 관리적 요소와 초기 비용의 감소를 제공합니다.

 

3.     개발 및 관계형 데이터 모델

SQL Azure TDS를 통해 Client Server 사이 통신을 지원함으로 익숙한 개발 모델로 접근할 수 있습니다. Visual Studio 2010을 통해 ADO.NET으로 접근한다면 거의 동일한 코드를 사용하게 됩니다. 개발 모델에서는 별 차이를 느끼지 못합니다. 그리고 SSIS를 통해서도 SQL Azure를 접근할 수 있습니다.
SQL Azure
를 개체 탐색기에 연결하면 관리하고 있는 여러 인스턴스 중의 하나로 보입니다. 또한 로컬의 데이터베이스와 유사하게 테이블, , 저장 프로시저, 인덱스 등을 생성할 수 있습니다. 하지만 조금 차이점이 있으며 아래에서 T-SQL 의 지원 내용을 알아봅니다.

 

지원되는 T-SQL 기능

지원되지 않는 T-SQL 기능

  • Constants
  • Constraints
  • Cursors
  • Index management and rebuilding indexes
  • Local temporary tables
  • Reserved keywords
  • Stored procedures
  • Statistics management
  • Transactions
  • Triggers
  • Tables, joins, and table variables
  • Transact-SQL language elements such as
    • Create/drop databases
    • Create/alter/drop tables
    • Create/alter/drop users and logins
    • and so on.
  • User-defined functions
  • Views, including sys.synonyms view
  • Common Language Runtime (CLR)
  • Database file placement
  • Database mirroring
  • Distributed queries
  • Distributed transactions
  • Filegroup management
  • Global temporary tables
  • Spatial data and indexes
  • SQL Server configuration options
  • SQL Server Service Broker
  • System tables
  • Trace Flags







아래 주소에서 보다 더 구체적으로 T-SQL 지원 내용에 대해서 알아볼 수 있습니다.

http://msdn.microsoft.com/en-us/library/ee336281(lightweight).aspx



2. CLR! CLR! CLR!

CLR 2009. 12. 30. 09:00 Posted by 알 수 없는 사용자
CLR의 장점은 무엇일까요? 비교 대상은 CLR을 통해 생성되는 관리되는 코드(managed code)와 기존의 컴파일러로 실행 파일이 생성되는 관리되지 않는 코드(unmanaged code) 입니다.


CLR 이래서 좋다!

1. 성능 향상

CLR의 JIT 컴파일러를 통해 만들어진 코드는 unmanaged code에 비해 성능이 우수하다고 합니다. 처음 듣기에는 좀 의아한데 성능이 향상된다고 주장하는 근거는 다음과 같습니다.



a. 컴파일 시에 실행 환경에 대한 정보를 알 수 있고 이에 최적화된 지시어를 사용하여 코드를 생성합니다. (예 : 실행 환경이 펜티엄 4라고 한다면 펜티엄 4에 최적화된 지시어를 이용하여 코드를 생성하게 됩니다.)

b. 특정 상황의 테스트 값 또는 논리 연산의 결과를 실행 전에 이미 정확하게 예측할 수 있습니다.

if (numberOfCPUs > 1)
{
...
}

위와 같은 코드가 있을 경우 현재 JIT컴파일러를 통해 컴파일 될 시스템의 CPU가 하나라면 CLR의 컴파일러는 해당 if 블록이 항상 실행되지 않을 것을 알기 때문에 이 코드를 네이티브 코드로 변환하지 않습니다. 이 경우 이 실행코드는 호스팅 하는 운영체제에 최적화된 코드로 컴파일이 될 것이며 좀 더 작고 빠른 코드를 생성하게 됩니다.

c. CLR은 어플리케이션의 실행 패턴을 profile 할 수 있으며 이에 따라 실행 중에 IL코드를 네이티브 코드로 다시 컴파일 할 수 있습니다. 재 컴파일된 코드는 profile된 실행 패턴을 바탕으로 코드의 분기를 최적화하기 위해 재정렬 됩니다.

d. 일반적으로 unmanaged code는 최저사양에 맞춰 컴파일이 됩니다. 하지만 managed 코드는 실행 환경에 최적화된 코드를 생성할 수 있습니다.

저 근거들을 보면 정말 managed code가 성능면에서 봤을 때 우월하겠다는 생각이 들기도 합니다. 그런데 곰곰히 생각해보면 실제 Native Code로 컴파일하는 과정에 있어서 컴파일러가 얼마나 최적으로 컴파일을 해 내느냐가 관건일 텐데 CLR의 JIT컴파일러와 기존 비관리되는 코드를 생성해 내는 컴파일러들의 성능 비교를 해봐야 할 것입니다.

하지만 평균적으로 봤을 때 실제 실행되는 환경에 최적화된 코드를 즉시에서 뽑아내는 방식의 managed code가 좀 더 나은 코드를 만들어 낼 수 있을거라는 생각이 들기는 합니다.

2. 다른 언어로 개발된 구성 요소를 쉽게 사용할 수 있는 기능

managed code는 IL 코드와 함께 메타데이터 정보가 들어있습니다. CLR은 이 메타데이터 정보를 이용하여 클래스를 찾고 로드하며, 메모리에 인스턴스를 배치하고, 메서드 호출을 확인하고, 네이티브 코드를 생성하고, 보안을 강화하며, 런타임 컨텍스트 경계를 설정합니다. CLR을 지원하는 어떤 언어든지 컴파일을 하게 되면 동일한 IL을 생성하게 됩니다. 이러한 이유로 인해 다른 언어로 개발되었다 하더라도 구성 요소를 쉽게 사용할 수 있게 됩니다.

3. 클래스 라이브러리에서 제공하는 확장 가능한 형식

구성 요소 및 응용 프로그램에 속한 개체가 여러 언어를 통해 상호 작용하는 경우 이를 쉽게 디자인할 수 있습니다. 다른 언어로 작성된 개체들이 서로 통신할 수 있고 해당 동작들이 완벽하게 통합될 수 있습니다. 예를 들어, 클래스를 정의한 다음 다른 언어를 사용하여 원본 클래스에서 클래스를 파생시키거나 원본 클래스의 메서드를 호출할 수 있습니다. 또한 클래스의 인스턴스를 다른 언어로 작성된 클래스의 메서드로 전달할 수 있습니다. 런타임을 대상으로 하는 언어 컴파일러 및 도구에서 런타임에서 정의한 공용 형식 시스템을 사용하고, 형식의 생성, 사용, 유지 및 바인딩 뿐만 아니라 새 형식을 정의할 때도 런타임 규칙을 따르기 때문에 이러한 언어 간 통합이 가능합니다.

4. 상속, 인터페이스 및 개체 지향적인 프로그래밍을 위한 오버로딩 등과 같은 새로운 언어 기능. 확장 가능한 다중 스레드 응용 프로그램을 만들 수 있도록 해주는 명시적 자유 스레딩에 대한 지원. 구조적 예외 처리 및 사용자 지정 특성에 대한 지원.

이 부분은 이전의 unmanaged code와 비교한 장점이라기 보다는 .NET Framework 차원에서 지원하는 플랫폼 상의 새로운 기능에 대한 이야기로 보입니다. 말이 참 길고 어렵습니다. 이 부분에 대해서는 공부하면서 차차 알아가게 될 것으로 보입니다.

5. 횟수 계산이 필요 없도록 개체 수명을 관리하는 가비지 수집

기존 C/C++ 환경에서의 프로그래밍을 하던 분이시라면 가장 편리하게 생각할 것이라고 생각합니다. 예전 JAVA가 나왔을 때도 장점으로 내세웠던 부분 중 하나였지요. 이건 CLR의 장점이라기 보다는 .NET Framework 차원에서 지원하는 장점이라고 봐야 할 것 같네요. 가비지 수집기는 메타데이터를 통해 객체의 수명 상태를 조사해서 수집 대상을 확인할 수 있으며 런타임시에도 해당 객체가 포함하고 있는 멤버의 파악은 물론 이들 중 어떤 멤버가 다른 객체에 의해서 참조되고 있는지도 파악이 가능합니다.  이런 이유로 메모리 누수로 인한 문제점을 원천적으로 해결할 수 있기 때문에 프로그래밍 환경이 매우 깔끔하며 메모리 누수로 인해 시스템에 악영향을 미치지 않습니다.

7. IDL(인터페이스 정의 언어)의 필요성을 없앤 자체 설명 개체

CLR환경의 파일들은 실행파일 자체내에 모든 정의된 타입과 참조된 타입의 정보가 자세하게 기록되어 있습니다. MIDL의 경우에는 사용하기가 복잡하고 어려웠던 것이 사실이지요.

8. 한 번 컴파일하여 런타임을 지원하는 모든 CPU와 운영 체제에서 실행할 수 있는 기능

지금까지 거론된 장점들도 중요한 장점들이겠지만 이만큼 한눈에 확- 들어오는 장점이 있을까요. 한번 작성된 프로그램은 어디에서나 수정 없이 실행이 가능합니다. 다만 이 플랫폼 독립성이 윈도우 환경에만 국한된다는 점이 아쉽습니다.

9. 손쉬운 IL 컴파일러 제작 및 코드 검증

IL코드는 스택기반이며 레지스트리를 직접 제어하는 지시어를 포함하고 있지 않습니다. 그리고 IL의 모든 지시어들은 특별히 타입에 의존적이지 않습니다. (예 : IL의 ADD 지시어의 경우 32비트 또는 64비트의 경우의 ADD가 따로 존재하지 않습니다.) 그렇기 때문에 개발자는 레지스트리나 CPU에 대한 관리를 생각할 필요가 없이 비교적 손쉽게 IL코드를 생성하는 컴파일러를 만들 수 있습니다.

그리고 이 IL코드가 CPU종속적인 네이티브 코드로 전환 될 때 CLR은 검증 작업이라는 것을 수행하게 됩니다. 수행되는 메서드의 인자의 타입과 개수 체크부터 시작하여 메모리 관련 오류나 (잘못된 메모리를 읽고 쓰는 등의) 타 프로세스의 메모리에 불법적으로 접근하는 등의 문제도 검증할 수 있기 때문에 부적절한 코드의 실행을 원천적으로 차단할 수 있습니다.(이를 코드 기반 보안이라고 합니다.) CLR은 각각의 관리되는 어플리케이션을 AppDomain이라는 것으로 안전하게 관리하게 됩니다. 이로써 프로그램을 안전하고 견고하게 작성하는 것이 가능합니다.

10. 손쉬운 응용프로그램 배포

단순히 파일을 복사하는 것만으로도 설치가 가능합니다. 이전의 레지스트리에 의존하는 COM이나 DLL처럼 버전차이로 인한 문제도 없습니다.


 
CLR이 과연 좋기만 할까?

1. IL 코드 보안

IL코드는 역어셈블을 하게 되면 소스코드를 얻어내는 것이 매우 쉽습니다. 이 말은 소스코드 레벨의 보안이 어렵다는 이야기입니다. 물론 third-party 벤더에서 판매하는 암호화 처리 유틸리티등으로 좀 더 역어셈블을 어렵게 만들 수는 있습니다.

2. 다양한 언어를 지원한다는 것이 마냥 좋을 것일까?

다양한 언어를 지원하여 언어 독립성을 지켜준다는게 대규모 프로젝트 시 장점으로만 작용하는 것은 아닐거라고 생각합니다. 물론 한 프로젝트에서 3~4가지 이상의 언어가 동시에 사용되는 경우가 드물기는 하겠지만 만에 하나 사용된다고 하더라도 언어별 차이로 인한 골치 아픈 관리문제가 발생할 가능성도 큽니다. 전체 프로젝트를 관리하는 입장에서 해당 프로젝트를 후에 유지보수하게 되는 개발자가 있다면 각 언어에 대해 어느정도의 지식이 있어야 전체 프로젝트를 관리할 수 있을 것입니다. 그런데 이렇게 써놓고 보니까 좀 억지스럽기도 하네요. ㅎㅎ 프로젝트 개발 시작 시 이런 문제는 정책적으로 해결할 수 있을테니까요.

3. Native Code보다 빠릅니까?

성능 향상에 대한 근거를 앞에서 살펴보았습니다. 그런데 메모리 관리나 명령어 최적화는 납득이 가는데 정말 C/C++을 이용하여 생성된 Native Code보다 빠르게 작동할 수 있겠느냐. 라는 문제는 회의적인 입장을 가진 시각이 있습니다.

4. Framework가 깔려야 합니다.

CLR을 이용하기 위해서는 .NET Framework가 설치되어야 합니다. 요사이는 윈도우의 경우 기본적으로 .NET Framework가 설치되어 있기 때문에 크게 문제될 것은 없습니다. 하지만 계속해서 새로운 버전의 .NET Framework가 출시되고 있는터라 개발 시 그리고 배포 시 버전에 신경을 써야 합니다.



지금까지 CLR에 대해 알아보았습니다. CLR은 .NET Framework의 구성요소 중 하나입니다. 그렇다면 우리가 배워야 할 CLR을 포함하고 있는 .NET Framework에 대해서도 간략하게 살펴보아야 하겠네요.

.NET Framework는 크게 다음과 같은 요소로 구성되어 있습니다.

1)CLR(Common Language Runtime) 공통 언어 런타임

우리가 배울 놈이지요. 자바에서는 JVM이 있고 .NET에서는 CLR이 있습니다. .NET의 핵심 커널로써 .NET 프로그램 실행을 위한 모든 서비스를 제공하는 주체라고 할 수 있습니다.

2) CTS(Common Type System) 공통 타입 시스템

.NET 언어 간에 공통으로 사용되는 표준 데이터 타입입니다. 각 언어마다의 변수, 메서드, 클래스, 구조체, 인터페이스 등의 타입이 다를수 있는데, 이렇게 다른 타입을 .NET 기본 클래스에 정의한 타입으로 관리할 때 참조하는 명세서와 같습니다. 이는 어떤 언어로 프로그래밍을 하던 .NET 기본 클래스에 정의된 타입으로 매치가 가능하다는것을 나타내고 있습니다. 다시 말해, 서로 다른 언어로 작성되었다 하더라도 .Net에서 이해할 수 있는 데이터 형식인지 아닌지를 테스트하고 검증 관리하는 역할을 담당합니다. 그러므로 .Net 내에서 동작할 수 있는 데이터 형에 대한 관리를 해준다고 말할 수 있습니다.

CTS의 멤버에는 필드(Field), 메서드(Method), 속성(Property), 이벤트(Event) 가 있으며 각 타입들의 접근성에 대해서도 명시하고 있습니다. 접근성의 종류에는 Private, Family(C++이나 C#에서는 Protected로 표현됩니다.), Family & Assmebly(C#등이나 Visual Basic .NET등에서는 지원하고 있지 않습니다.), Assembly(보통 Internal이라는 키워드로 표현됩니다.), Public 이 있습니다.

3) CLS(Common Language Specification) 공통 언어 사양

.NET 용 프로그래밍 언어가 따라야 하는 공통된 최소한의 표준 규약으로, 적어도 .Net에서 동작하기 위해서는 반드시 지켜야하는 언어 스펙입니다. 모든 언어들이 다 중간언어로 변환이 가능한 것은 아닙니다. 언어마다 특성이 있어서(예를 들자면 어떤 언어는 대소문자를 구분하지 않거나, unsigned integer 같은 형식은 지원하지 않습니다. 또는 어떤 언어는 가변 인자를 지원하지만 어떤 언어는 그렇지 않습니다.), 변환이 가능한 프로그램을 작성하기 위해서는 지켜져야 할 최소한의 규칙이 있는데, 이 규칙을 모아 놓은 것이 공통 언어 사양(Common Language Specification: CLS) 입니다.



그림을 보면 CLS는 다양한 언어들 사이에서 최소한의 교집합을 가지고 있습니다. 그리고 CLR을 지원하는 언어들은 CLR/CTS환경에 속해 있는데 이를 보면 알 수 있듯이 C#이나 Visual Basic 그리고 기타 등등의 CLR을 지원하는 언어들은 100% CLR/CTS의 기능을 지원해 주지 않는 것을 알 수 있습니다. 100% 활용을 위해서는 개발자가 IL 어셈블러 언어로 코드를 작성해야 합니다.

4) BCL(Base Class Library) 기본 클래스 라이브러리
모든 언어에서 공통적으로 사용할 수 있는 방대한 클래스 라이브러리입니다. 객체 지향적이며 문서화도 잘 되어 있기 때문에 쓰기가 매우 편리합니다. 대략 다음과 같은 것들이 있습니다.

* 기본 타입 관련
* 배열, 연결 리스트, 큐 같은 컬렉션
* 그래픽 라이브러리 (GDI+)
* 스레드와 동기화 클래스
* 각종 컨트롤
* 파일 IO
* 네트워크 / 인터넷
* 데이터 베이스

FCL(Framework Class Library)라는 명칭도 있습니다. BCL(최소한의 기본적인 라이브러리 모음) + 추가 클래스 라이브러리 모음으로 BCL보다 훨씬 큰 집합입니다.


자. 지금까지 CLR의 특징부터 .NET Framework의 구조에 대해 대략 알아봤습니다. 이제 배경에 대해 어느정도 살펴 봤으니 다음부턴 본격적으로 CLR에 대해 들어가보려고 합니다. :)

현재 .NET Framework는 3.5까지 공개가 되어 있고 Visual Studio 2010에서는 .NET Framework 4.0이 포함이 되어 있습니다. 우리가 공부할 CLR의 버전도 .NET Framework의 버전을 따라 업그레이드 되고 있지요.

.NET Framework 4.0의 특징은 .NET Framework 섹션에서 아주 자세히 잘 설명이 되어 있습니다.(http://vsts2010.net/6) 꼭 읽어보세요!!!




'CLR' 카테고리의 다른 글

6. Assembly - GAC(Global Assembly Cache)  (2) 2010.02.02
5. Assembly - Strongly named assemblies  (0) 2010.01.26
4. Assembly  (2) 2010.01.15
3. MSCorLib & Metadata  (4) 2010.01.06
1. Hello 世界  (0) 2009.12.23

WCF란 무엇인가?

WCF 2009. 12. 29. 09:11 Posted by 알 수 없는 사용자

안녕하십니까? 이번에 새롭게 vs2010 team 에 합류하게 된 오태겸이라고 합니다. 
앞으로, WCF를 주제로 한 포스팅을 맡아서 활동을 하게 되었습니다. 
부족한 점이 많지만 열심히 활동 할테니 이쁘게(?) 봐주셨으면 합니다. ^^;;

이제, 첫 포스팅을 시작하도록 하겠습니다.

첫 포스팅의 주제는 “WCF란 무엇인가?” 입니다.

WCF는 “Windows Communication Foundation”의 약자로서, 이 이름만 보더라도 왠지 ‘여러 가지 Communication을 지원하기 위한 기술인 것 같다,,’ 라는 예상을 하게 됩니다.
네!! 맞습니다. WCF는 여러 가지 컴포넌트(응용프로그램, 서비스 등,,)와의 Communication을 쉽게 구현할 수 있도록 해주는, Microsoft에서 새롭게(이미 몇 년 지났지만,,^^;;) 개발한 기술입니다.

한마디로 정의하자면, WCF는 분산 어플리케이션 개발과 플랫폼에 상관없는 높은 상호 운용성을 지원하는 어플리케이션을 쉽게 개발할 수 있도록 해주는 기반 기술입니다.

분산 어플리케이션이란 단어는 이제 너무 친숙한 단어가 되었으며,  꽤 오랜 시간에 걸쳐 이러한 분산 어플리케이션을 쉽게 구현하기 위한 여러 가지 기술들이 개발되어왔습니다. 이러한 노력에 의해 CORBA(Common Object Request Broker Architecture), DCOM(Distributed Component Object Model), Web Service 등의 기술들이 개발되어 적용되어 왔으며, 특히, Web Service는 이 전의 기술에 비해 인터넷을 기반으로 높은 상호 운용성을 지원했기 때문에 많은 곳에서 활용되어 왔습니다.

Web Service가 많은 곳에서 환영(?)을 받고, 활용될 수 있었던 이유에는 아마도 XML이라는 인터넷 표준과 이를 기반으로 한 SOAP이라는 표준 프로토콜 사용에 있었다고 생각합니다. 앞에서도 언급했지만, 인터넷과 이러한 표준 기술들을 사용함으로써 좀 더 쉽게 높은 상호 운용성을 지원하는 분산 어플리케이션을 구현할 수 있었기 때문입니다.

저는 개인적으로, “Web Service를 대체할 만한 기술이 나오는 것은 당분간 어렵다-!” 라고 생각했었습니다. 하지만 Microsoft 에선 이런 저의 생각을 보기 좋게 뻥~! 차버렸습니다. 저의 생각이 너무 짧았던 거죠 (역시 난 아직 멀었어,, ㅡㅠ)

WCF와 처음 만났을 때(그리 오래되진 않았지만), WCF의 확장성과 상호 운용성에 조금 놀라기도 하고, 신기해 하기도 했었던 기억이 납니다.

이제 WCF의 장점에 대해 몇 가지 설명을 해보도록 하겠습니다.

우선, WCF의 클라이언트 및 서비스는 기본적으로 SOAP을 사용하여 통신하며, 서비스의 메타데이터를 전달하기 위한 방식으로 WSDL을 사용합니다. 이는 Web Service와 동일한 방식이며, 앞에서 언급한 Web Service가 널리 활용될 수 있었던 이유와 동일한 장점을 가지고 있습니다.

또한, 기존의 Microsoft의 분산 어플리케이션 개발 기술을 통합하여 사용할 수 있다는 장점도 가지고 있습니다.
예를 들어 WCF 와 기존의 .NET Web Service는 모두 SOAP을 사용하기 때문에 WCF 기반 응용 프로그램은 .NET Web Service에 구축된 응용 프로그램과 직접 상호 운용할 수 있습니다. 그리고, WCF 기반 응용 프로그램은 MSMQ(Microsoft Message Queue)를 이용하여 통신을 할 수 있기 때문에 기존의 MSMQ 인터페이스를 사용하여 구축된 응용 프로그램과도 직접 상호 운용할 수 있습니다.

이러한 장점 이외에 HTTP 통신 뿐만 아니라, TCP 통신을 사용할 수도 있다는 장점 등 WCF는 많은 장점을 가지고 있는 기술입니다.
앞으로, WCF에 대해 포스팅을 해 가면서 WCF의 많은 장점들을 보여드릴 예정이니 많은 관심과 격려 부탁 드리겠습니다 ^^*

음,, 글만 생각 나는대로 적다보니 조금 지루해지는 것 같습니다.
WCF의 아키텍처를 간단한 설명과 함께 그림으로 보여드리고 이번 첫 포스팅을 마칠까 합니다.

 

위 그림은 WCF의 아키텍처를 보여주고 있습니다.

WCF 를 처음 접하시는 분이라면, 이 그림을 보고 한번에 이해하기는 좀 어려울 것이라 생각합니다. 하지만, WCF에 대해 조금 알게 된다면 그렇게 이해하기 어려운 그림은 아닐 듯 합니다. (지금 이해하기 어렵다고 걱정할 필요는 없단 말이죠 ^^)

WCF의 아키텍처 중 계약 계층은 서비스에서 제공하는 실제 메서드를 정의하거나 서비스와 통신할 때 사용되는 메시지 또는 데이터를 정의하는 부분으로 서비스의 기본이 되는 계층입니다.

메시징 계층은 채널로 구성되며, 채널은 크게 전송 채널과 프로토콜 채널의 두 가지 유형으로 구분되어집니다.
전송채널은 메시지를 전송하기 위한 전송 프로토콜에 관한 채널을 정의하며, HTTP, TCP, 명명된 파이프 및 MSMQ가 있습니다.
프로토콜 채널은 메시지를 처리하기 위한 프로토콜을 구현합니다. WS-Security와 WS-Reliability 채널을 이용하여 메시지의 보안과 신뢰적인 전달을 위한 추가적인 기능을 정의할 수 있습니다.

활성화 및 호스팅 계층은 서비스가 호스팅될 수 있는 방식을 정의합니다. IIS 7의 WAS를 이용한 호스팅, 실행 파일로 호스팅 하는 자체 호스팅, Windows 서비스를 이용한 호스팅, 그리고 COM+ 구성 요소를 이용한 호스팅 등 여러 가지 방식으로 서비스를 호스팅할 수 있습니다.

WCF 아키텍처에 대해 짧게 설명을 했는데, 이 아키텍처만 보더라도 WCF의 기능에 어떤 것이 있는지 조금은 예상할 수 있을 듯합니다.
WCF는 Web Service와 마찬가지로 SOAP과 WSDL 같은 표준을 사용하여 플랫폼에 상관없는 분산 어플리케이션 개발을 쉽게 지원하지만, Web Service와는 다르게 전송 프로토콜이라던지, 호스팅을 하는 방식이라던지, 여러 가지 기능들을 제공하여 Web Service 보다 더 큰 확장성과 상호 운용성을 지원하는 기술이라 생각하면 될 것 같습니다.

아- 이것으로 첫 번째 포스팅을 마무리할까 합니다.
사실, WCF가 아직까진 국내에 많이 활용되고 있는 것 같진 않습니다. 자료도 그렇게 많지 않은 것 같구요. 제가 꾸준히 포스팅을 하고 제가 남겨놓은 자료가 단, 한 사람에게라도 좋은 자료가 될 수 있다면 기분 좋을 것 같습니다.
앞으로는 WCF의 기초에 대한 내용으로 포스팅을 하고, 그 이후에 WCF 4.0에 대한 내용, 그리고 WCF의 활용에 관한 내용으로 포스팅을 할 예정입니다. 많은 관심과 격려 부탁 드립니다 ^^

첫 포스팅이라 어떻게 진행을 해야 할지,, 감도 안잡히고, 어설퍼 보이는 부분이 한 둘이 아닐 듯 합니다. 아직 모르는 것도 많고, 부족한 것도 많기 때문에 지금 당장 전문가 다운 모습을 보이긴 어렵겠지만, 욕심 부리지 않고 꾸준하게 정진하는게 가장 바람직한 모습일 것 같습니다.

그럼, 다음 포스팅때 뵙겠습니다 ^^


[d3dm 기초] 1. wm6.x 개발환경 세팅

Direct3d Mobile 2009. 12. 26. 23:06 Posted by 알 수 없는 사용자

<<연재 일시 중단>>

vs 2010 beta2 가 스마트기기 개발환경을 지원하고 있지 않은 관계로 연재를 일시 중단 합니다. 

미리 확인 하지 않고 연제를 시작한 점 사과드립니다.

차후에 스마트기기 개발환경이 지원되는 대로 다시 하도록 하겠습니다.

1.     들어가며

 

안녕하세요.

저는 이번에 vsts2010에 참여하게 된 이석준 이라고 합니다.

앞으로 잘 부탁 드리겠습니다.

이런 공인된 장소를 글을 쓰는 것은 첨이다 보니 무척 부담이 많이 밀려오는 군요.

혹시 잘못된 부분이나 미흡한 부분이 있으면 바로 지적해 주시면 감사하겠습니다.

(제가 국어가 약해서 가끔 안드로메다틱한 문법이 나올 수도 있으니 이해 안 되는 문장은 반드시 지적을 해주시면 감사하겠습니다. .; )

 

VS상의 윈도우모바일(이하 wm) 개발환경은 리눅스나 기타 임베디드 개발환경에 비해 빠르고, 편리하고, 쉽습니다. 기존의 win32api, .Net 코드를 쓸 수 있음은 물론 WTL,MFC등과도 많은 부분의 코드가 호환이 됩니다. 모바일이나 임베디드 에서는 대부분 3D 랜더러로 opengl-es가 많이 사용되는 것으로 알려져 있습니다.  그러나 게임을 만들 때는 direct3d를 많이 사용합니다. Direct3d Mobile 이하 D3dm 을 사용하면 기존의 Direct3d코드를 그대로 활용할 수 있는 장점이 있습니다.  지금부터 약 10회로 나누어서 wm6상에서의 개발환경부터 오픈소스공개 랜더엔진인  irrlicht3dd3dm용 드라이버까지 제작을 해보도록 하겠습니다.

 

2.     준비물

 

wm6sdk , active sync 두 가지가 필요합니다.

여기서 wm6sdk 은 소프웨어 개발킷 이므로 애뮬레이터와 샘플소스코드는 물론 VS용 라이브러리와 클래스위져드관련 환경파일들이 모두 포함된 형태입니다.

요즘 나오는 옴니아2등의 폰에는 6.1버전이라고 되 있는데요 따로 6.1sdk는 존재하지 않습니다. 검색해보시면 DDK가 나와있는 것을 볼 수 있는데요.

DDK sdk가 다른 점은 DDKVS관련 라이브러리 파일제외하고 에뮬레이터와 샘플소스 각종 유틸리티 툴이 업그래이된 것이라고 보시면 됩니다.

요약하자면 wm6sdk 설치후 원하시는 타겟의 DDK나 에물레이터 image를 받아서 먼저 SDK설치하신 다음에 설치 하시면 됩니다.




만약 특정스마트기기의 특정한 기능을 이용하고 싶으시면 이 위에 다시 해당 기기용 sdk를 설치해서 사용하시면 됩니다.

그러면 특정 스마트기기용 추가 API Set 이 설치됩니다.

 

active sync는 스마트기기와 VS개발환경간의 통신수단을 해주는 역할을 하므로 Sdk를 설치 하기 이전에 이것부터 설치를 해주셔야 합니다.


wm6가 설치된 스마트기기는 기본적으로 이미 설치되 있으니 개발 pc에서 설치를 한번 해주시면 됩니다.

 

3.     Hello wm6!!

 

모든 설치가 순조롭게 끝나고 새프로잭트->스마트기기(Smart Device) 항목이 나온다면 설치가 성공한 것 입니다.

그럼 간단한 프로그램부터 만들어 보도록 하죠. 아래와 같이 Smart Device->Win32 Smart Device Project를 선택합니다


 


그 다음 platforms 탭에서 windows mobile6 sdk를 추가 시켜줍니다.



 

자동 생성된
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 의 WM_PAINT에 아래와 같이 DrawText 함수를 추가 해 줍니다.

프로잭트 위져드 덕택에 자동으로 기본프레임웍까지 코드가 작성되서 나오니 편리 하지 않습니까? ^^;

 기존 데스크탑용 어플처럼 빌드후 실행하면 에뮬레이터로 필요한 파일이 전송된후(Deployment 설정 참고) 크로스 컴파일된 어플리캐이션이 실행됩니다.


 

4.    Deployment

데스크톱 어플개발시와는 다르게 프로잭트 속성 페이지에 Deployment라는 항목이 있습니다.

Additional Files항목에서는 스마트기기에서 어플리캐이션실행시 필요한 파일들을 정의해줍니다. (물론 에뮬레이터도 똑같은 스마트 기기로 추상화 됩니다.)

항목을 만드는 양식은 다음과 같습니다.

원본파일이름|원본파일이 있는 경로|파일이 카피될 원격경로|0

Remote Directory 에는 스마트기기에서 실행파일이 실행될 경로를 정해줍니다. 그러나 주의 할점은 어플상에서 파일을 참조할경우 경로는 여기서 지정해준 원격경로가 아닌 저장장치단위의 최상위디랙토리인 My Device/ 기준으로 경로를 잡게됩니다.

참고로 %CSIDL_PROGRAM_FILES% 는 My Device/Program files를 가리킵니다.

실행파일은 Deployment ->Additional Files에서 추가 하지않고 디버깅->Remote Executable 에 정해진 파일이 원격실행 디랙토리에 자동으로 카피가 됩니다.

5.     to be continued…

      다음에는 샘플로 제공된 basicApp를 분석해 간단한 이미지 뷰어를 만들어 보도록 하겠습니다.

'Direct3d Mobile' 카테고리의 다른 글

.NET 기반에서 공개소스 게임엔진 포팅하기  (0) 2010.07.25
안녕하세요. 이번에 새롭게 팀원이된 박세식이라고 합니다. 많이 부족해서 컴터앞에 앉아 이렇게 자판을 두드리고 있는 시간에도 떨림이 멈추질 않네요-_-; 앞으로 잘 부탁드리겠습니다.(따스~한 피드백 아시죠^^;)  
자~ 그럼. ASP.NET MVC에 대해 알아보도록 하겠습니다.

첫번째 시간으로 ASP.NET MVC vs ASP.NET WEB FORM 에 대해 글을 써보도록 하겠습니다. 제 포스트는 ASP.NET MVC에 관한 글입니다.^^; 그래서 이 둘의 대결구도라기 보다는 웸폼의 문제점을 짚어보고 MVC에 좋은 점에 대해서 글을 써 나가려고 합니다.


ASP.NET WEB FORM의 문제점?

ASP.NET WEB FORM은 ASP.NET 개발의 전통적인 스타일이고, 큰 스케일의 웹사이트를 좀더 간단하게 만들게 해주는 기술입니다. 웹폼은 드래그 앤 드랍으로 컨트롤들을 ASP.NET 페이지에 추가하고 그것들에 맞는 코드를 작성합니다. 이러한 개발방식이 개발자들의 마음을 끄는거죠. 그!러!나! 웹폼은,

관계가 분리되어 있지 않습니다. UI와 코드가 섞여있죠--;
● 자동적으로 테스트하는 것이 쉽지 않습니다. 런타임 시작없이 테스트하기가 어렵죠. 이는 실행환경을 쭉~ 돌면서 테스트할 수 밖에 없다는 겁니다-_-;
● 상태정보를 저장하려면 각 서버페이지의 상태를 뷰스테이트라고 하는 히든 필드값으로 클라이언트 페이지에 저장합니다.

하지만, 웹폼 개발에서의 특징인 뷰스테이트와 포스트백은 축복이자 파멸의 원인이됩니다. 뷰스테이트는 클라이언트와 서버간의 오고가는 데이터들의 상태를 히든 필드로 구성하고 있는 메커니즘으로, 이것의 크기는 무지막지하게 커질 수 있습니다. 매번 호출시 이 거대한 데이터가송수신된다니 끔찍스럽죠-_-; 특히 페이지에 데이터그리드나 그리드뷰와 같은 서버컨트롤이 포함되어있다면 한페이지 한페이지 넘길때마다 응답지연의 원인이 되어 사용자들을 기다림에 지치게 만드는거죠 OTL;; 또한 포스트백은 매번 액션에 의한 트리거로서 발생이됩니다. 그 거대한 데이터(뷰스테이트)를 어떤 액션만 취하게 되면 다시 그리게 되는거죠. 이 뷰스테이트에 대해 좀더 알아보죠.


뷰스테이트(View State)란?

뷰스테이트는 포스트백시 웸폼의 상태의 변화를 유지시켜주는 기술입니다. 일반적으로 __VIEWSTATE라는 이름의 히든 필드로 웹페이지에 위치합니다. 이 히든값은 수십 킬로바이트씩 쉽게 커질 수 있습니다. 이 뷰스테이트는 사용자가 웹 페이지를 포스트백 할 때 천천히 불려지고(다운로드), 그 히든 값의 내용을 웹 요청시에 포스트해서 요청 시간을 길어지게 합니다. ASP.NET 웹 페이지의 요청이 올 때 정확하게 무슨 일이 일어나는지를 알려면 ASP.NET 페이지의 생명주기(Life Cycle)을 알아봐야 하는데요. 잠깐 간단하게만 알아보도록 하죠^^;(어째~ 이야기가 점점 옆으로 새네요.. 언제 제자리로 돌아올지는 생각하지 말아주세요-_-;)


Asp.Net Page Life Cycle

매번 ASP.NET 웹 페이지에 의해 서버에 요청이 오면 첫째로 웹 서버는 ASP.NET 엔진으로 요청을 넘깁니다. ASP.NET 엔진은 웹 페이지의 올바른 파일 접근을 확인하는 여러 단계로 구성된 파이프라인을 통해서 사용자의 세션 정보를 얻습니다. 파이프라인의 끝에서는 요청된 웹 페이지에 상응하는 클래스를 인스턴스화하고 ProcessRequest() 메쏘드를 호출합니다. ASP.NET 페이지의 생명주기는 ProcessRequest() 를 통해서 시작됩니다. 이 메쏘드는 페이지의 컨트롤 단계를 준비합니다. 그 다음으로, 페이지와 서버는 ASP.NET 웹 페이지에 필요한 여러 단계를 하나씩 단계별로 밟게 됩니다. 이 단계들에는 뷰스테이트를 관리하고, 포스트백 이벤트를 처리하고, HTML 페이지를 렌더링하는 것들이 포함되어 있습니다.


그림 1. 페이지 생명 주기의 이벤트들
출처 : http://msdn.microsoft.com/en-us/library/ms972976.aspx

다시 뷰스테이트로 돌아와서 정리하자면, 세상에 공짜는 없습니다.(비용이 든다는거죠) 여기 뷰스테이트도 예외일 수는 없습니다^^; ASP.NET 페이지가 요청될 때마다 뷰스테이트는 두가지 성능에 관련되는 일을 합니다. 첫째는, 모든 페이지를 방문할 때 뷰스테이트는 해당 컨트롤 계층의 모든 컨트롤의 뷰스테이트를 모아서 베이스 64 인코딩으로 시리얼라이즈합니다. 여기서 생성된 스트링이 __VIEWSTATE에 값인거죠^^

반대로, 포스트백시에는 뷰스테이트를 읽엇 저장된 뷰스테이트 데이터로 디시리얼라이즈하고 컨트롤 계층구조에 있는 적절한 컨트롤러로 업데이트합니다. 두번째로, 뷰스테이트는 클라이언트가 다운로드 받아야할 웹페이지의 크기를 증가시킵니다. 원래 보여질 페이지의 데이터와는 또다른 데이터인거죠. 뷰스테이트 크기가 큰 페이지는 이 뷰스테이트의 크기가 수십 킬로바이트가 됩니다.  이것을 다운받기 위해 또 수 초나 수 분의 시간을 할애해야합니다.(이게~ 뭔가요-_-;) 또, 포스트백시에도 뷰스테이트를 웹 서버로 보내야하고, 그것 때문에 포스트백 요청시간이 증가하는 거죠.


ASP.NET MVC 알아보기

ASP.NET MVC는 모델, 뷰 그리고 컨트롤러로의 3개의 파트로 분리되어 구현됩니다.


그림 2. MVC Framework
출처 : http://dotnetslackers.com/articles/aspnet/KiggBuildingADiggCloneWithASPNETMVC1.aspx

● 뷰(View) 는 애플리케이션의 UI를 담당하고, 이는 단지 컨트롤러에 의해 애플리케이션의 데이터로 채워질 HTML 템플릿에 지나지 않습니다.
● 모델(Model) 은 UI를 렌더링하는 뷰가 사용할 애플리케이션의 객체, 즉 애플리케이션의 데이터의 비즈니스 로직을 구현합니다.
● 컨트롤러(Controller) 는 사용자 입력과 상호작용하는 응답을 핸들링합니다. 웹 요청은 컨트롤러에 의해 핸들링되고, 요청된 URL의 표현될 뷰와 적절한 데이터(모델 객체)를 결정합니다.


ASP.NET MVC의 요청 흐름도

ASP.NET MVC 애플리케이션은 웹폼과 같이 주소창에 입력된 URL이 해당서버의 디스크에 있는 페이지(파일)을 찾는것이 아닌 컨트롤러를 통한 뷰를 호출하게 됩니다. URL은 컨트롤로와 매핑이 되고 컨트롤러는 뷰를 리턴해주는 식이죠. 다음의 그림을 보시면


그림 3. 요청 흐름도
출처 : http://dotnetslackers.com/articles/aspnet/KiggBuildingADiggCloneWithASPNETMVC1.aspx

처음 사용자 요청(URL)이 들어오면 Routing Rule 에 의해 컨트롤러를 매핑시킵니다. Routing Rule 은 ASP.NET MVC 프로젝트를 생성하면 Global.asax에 정의되어 있는데요. 제 블로그에 컨트롤러를 설명하면서 Global.asax에 대해 간략하게 설명한 부분이 있는데요 참고하시기 바랍니다. 여기서도 간단히 설명드리자면, 주소는 {controller}/{action}/{id} 이런식으로 들어오게됩니다. 특정 컨트롤러의 특정 액션메쏘드의 파라미터로 id를 넘겨준다는 룰이죠. (액션메쏘드는 컨트롤러 클래스에서 public으로 제공되는 메쏘드를 가리킵니다.)

다시, 컨트롤러는 뷰에 넘겨줄 데이터를 만들 모델을 선택합니다. 선택된 모델객체는 뷰에 넘겨줄 데이터(ViewData)를 만들고, 컨트롤러가 이를 뷰에 넘겨줍니다. 마지막으로 뷰는 HTML로 렌더링해서 사용자에게 보여줌으로 하나의 흐름이 흘러가는 거죠^^;

그래서 ASP.NET MVC의 장점은?

● 모델, 뷰, 컨트롤러로 명확하게 관계과 분리되어 있어 복잡한 애플리케이션 로직을 관리하기 쉽게 해줍니다. 이로 인해 각 개발자는 MVC 패턴의 분리된 컴포넌트를 각자 개발할 수 있습니다. 페이지 단위로 되어 있는 웸폼은 비하인드 코드에서 로직을 담당하게 되는데요. 다른 두개의 페이지에서 비슷한 작업을 하게 된다해도 하나의 작업으로 사용하기가 어렵다는 거죠^^; 특정 페이지의 이벤트가 그 페이지의 비하인드 코드를 호출하기 때문에 같은 작업을 해도 저처럼 잘 모르는 사람들은 저희에게 무한한 능력(?)을 심어주는 카피 앤 페이스트 작업을 거쳐야한다는 겁니다.

● 유닛테스팅을 쉽게해줍니다. 이 유닛테스트도 M,V,C 가 각각 깔끔하게 분리되어 있어주기 때문에 가능한거죠^^; 추후에 유닛테스트가 과연 얼마나 쉬운지 알아보는 시간을 갖도록 하겠습니다.

● MVC 모델은 뷰스테이트와 포스트백을 사용하지 않습니다. 그래서, MVC는 일반적으로 웹폼에 비해 페이지 사이즈가 작습니다. 폼의 히든 필드인 뷰스테이트 데이터와 같은 불필요한 데이터가 없기 때문이죠.

● 웸폼 모델에서의 URL이 서버의 존재하는 파일을 직접 요청하는 것 대신에 REST 방식의 URL을 사용하여 URL을 간단하게 해주고, 기억하기 쉽게 해주고, SEO의 도움을 줍니다.

SEO(Search Engine Optimization) 는 검색엔진의 결과로 보여질 랭크의 순위를 높이는 작업을 말합니다. 상위 랭크의 검색결과로 나타내어지면 사용자가 아무래도 계속 그것만 보게되니 좋겠죠^^; 그래서 URL 또한 사용자가 보기 쉬운 걸로 나타내면 좋다는거죠. 예를들어, /Product/Edit/4 이런 URL 이라면 4번째 상품을 수정하겠다는 거군. 이렇게 명시적으로 알수 있다는 겁니다. 예가 좀 부적합한가요^^;

● jQuery나 ExtJS와 같은 클라이언트단 자바스크립트 프레임워크와 쉽게 통합할 수 있습니다.


마무리요

사실, 웸폼과 MVC를 비교해서 꼭 이것이 더 좋으니까 이것만 사용해야지가 아닙니다. 각 프로젝트의 특성에 맞게 선택하는 거죠. (다시한번 말씀드리지만 이 포스트는 ASP.NET MVC에 관한 글입니다--;) 성능을 따지지 않고 빠른 개발을 원한다면 웹폼을 선택하는 것이 좋을 것 같고, 유닛테스팅과 성능에 중점을 두겠다 싶으면 MVC쪽을 선택해봄이 좋겠다는 거죠. 다음 포스트에는 예제를 통해서 ASP.NET MVC와 인사를 나눠보는 시간을 갖도록 하겠습니다^^


참고자료 :
http://msdn.microsoft.com/en-us/library/ms972976.aspx
http://dotnetslackers.com/articles/aspnet/KiggBuildingADiggCloneWithASPNETMVC1.aspx
http://msdn.microsoft.com/en-us/magazine/dd942833.aspx
http://www.techbubbles.com/aspnet/aspnet-mvc-and-web-forms/
http://www.taeyo.net/lecture/NET/AspNet35_pre02.asp
http://weblogs.asp.net/shijuvarghese/archive/2008/07/09/asp-net-mvc-vs-asp-net-web-form.aspx
http://weblogs.asp.net/scottgu/archive/2007/10/14/asp-net-mvc-framework.aspx

1. Hello 世界

CLR 2009. 12. 23. 09:00 Posted by 알 수 없는 사용자
다음의 소스코드로 시작해 봅시다.

.assembly PrintString {}

/*
    Console.WriteLine("Hello, 世界)"
*/

.method static public void main() il managed
{
    .entrypoint            // 프로그램의 진입점. 곧 Entrypoint입니다.
    .maxstack 8


    // *****************************************************
    // Console.WriteLine("Hello, 世界");
    // *****************************************************
    ldstr "Hello, 世界"        // 스택에 스트링을 PUSH 합니다.

    // System.Console.Writeline 함수 호출합니다.
    // 이 함수는 스택에 있는 스트링을 인자로 POP합니다.
    call   void [mscorlib]System.Console::WriteLine
                                 (class System.String)

    // *****************************************************
    ldstr "Press Enter to continue"
    call   void [mscorlib]System.Console::WriteLine
                                 (class System.String)

    // System.Console.Read 함수를 호출합니다.
    // 키입력을 기다리게 되겠네요.
    call int32 [mscorlib]System.Console::Read()

    // Read()함수 호출로 인한 키 입력이 스택에 PUSH되었을 테니까
    // 이 함수가 끝나기 전에 POP하여 스택을 비웁니다.
    pop
    // *****************************************************

    ret
}

어 이거 뭔가요. 뭔가 익숙한 것 같으면서도 이상한 코드입니다.

대충 보아하니 화면에 "Hello, 世界" 를 출력하는 프로그램 같은데 Console::WriteLine() 같은 걸 보자니 Visual C++ 에서 Managed Code 프로그래밍 하는 것 같기도 하고, call, pop 이런 것들을 보니까 어셈블리어 같기도 합니다. 야~~ 21세기에 컴퓨터 개론에서나 보던 스택 PUSH, POP 신경쓰면서 화면에 저런거 찍어야 겠나 싶기도 하네요.

그런데 또 다시 생각해보면 사람이 보긴 답답해도 속도만 빨라졌지 여전히 좀 멍청한 CPU가 알아먹기는 좀 쉬울 것 같다는 생각이 들기도 합니다. 

네 저 코드는 .NET하면 누구나 들어봤을만한 IL (Intermediate Language) 코드라고 하는 것이라고 하네요. .NET Framework 기반의 환경에서 프로그래밍을 하게 되면 어떤 언어로 프로그래밍을 하던 .NET을 지원하는 모든 컴파일러는 지금까지 많이 봐오던 기계어로 컴파일을 하는 것이 아니라 MSIL이라는 코드로 컴파일을 합니다.

자. 일단 코드를 만들어 봤으니 실행을 시켜봐야죠. IL코드는 뭘로 컴파일을 해야 하나요. MSDN을 디벼보니 ilasm.exe 라는 .NET Framework의 도구를 이용해 컴파일을 할 수 있다고 합니다.

그러면 Visual Studio 2010에서 제공하는 CMD를 열고 해당 소스를 컴파일 해봅니다. (시작 -> 프로그램 -> Microsoft Visual Studio 2010 -> Visual Studio Tools -> Visual Studio Command Prompt (2010) 을 이용하면 됩니다.)



컴파일 하면 exe 실행파일이 생성이 되고 그 실행파일을 실행하니까 Hello, 世界 찍힙니다! 코드대로 Press Enter to continue 나오고 거기서 아무 키나 누르면 프로그램 실행이 종료됩니다.

(당연한거지만) 유니코드 지원 잘 되는군요. 보통 Hello World를 찍는데 Hello 世界 라고 글로벌하게(?) 찍은 이유는 얼마전 구글에서 공개한 Go 언어의 소개 프로그램이 Hello 世界 였거든요. 그게 괜히 멋져보여서 따라해 봤습니다. ㅎㅎ


명색이 프로그래머인데 첫인사는 코드로 해야 하지 않겠나. 싶어서 이렇게 너저분하게 인사를 해봤네요. 앞으로 CLR에 대해서 공부하면서 공부한 내용을 나름대로 정리해서 이런식으로 공유를 해 볼 생각입니다. 같이 공부하는 입장이라 이래저래 시행착오도 많을테고 실수도 분명히 있을테지만 앞으로 잘 부탁드립니다. _(_ _)_

CLR은 Common Language Runtime의 약자로 우리말로 번역하니 [공용 언어 런타임] 이라고 번역이 되네요. [공용 언어]는 우리말인데 [런타임]은 왜 런타임인가. 도대체 런타임이 뭔가요?

IT용어사전을 찾아보니 런타임에 대한 내용이 다음과 같이 나와 있습니다.

런타임 【run-time】

읽기 : 런타임

어플리케이션 소프트를 실하는데에 필요한 소프트웨어 모듈(부품)을 말한다. Windows의 경우 DLL파일의 형태로 제공된다. 실시에 런타임이 필요한지는 어플리케이션 소프트의 개발에 쓰여진 개발 툴에 의존한다. 런타임은 어플리케이션 소프트에 같이 들어있는 경우도 있지만, Microsoft사의 Visual Basic으로 개발 된 어플리케이션 소프트를 실하기 위해서는 [MSVBVMxx.DLL](xx는 버전 번호)라는 파일이 필요하지만, Borland Software사의 C++ Builder로 개발된 어플리케이션 소프트는 런타임 없이 동작 시킬수 있다.


출처 : http://www.chinatotheworld.net/w/C3ABC29FC2B0C3ADC283C280C3ACC29EC284.html


아. 프로그램을 실행하는데 필요한 소프트웨어 모듈을 말한답니다. 그렇다면 CLR은 공용 언어를 실행하는데 필요한 소프트웨어 모듈. 정도가 되는건가요?

위키도 한번 뒤져봤습니다.

공통 언어 런타임

위키백과 ― 우리 모두의 백과사전.

공통 언어 런타임(Common Language Runtime, CLR)은 마이크로소프트 닷넷 이니셰이티브의 가상 머신 구성 요소이다. 프로그램 코드를 위한 실행 환경을 정의하는 마이크로소프트의 공통 언어 기반 (CLI) 표준의 기능이다. 공통 언어 런타임은 공통 중간 언어(CIL, 이전에는 MSIL로 알려져 있었음)라고 불리는 바이트코드의 형태를 실행한다.

공통 언어 런타임을 사용하는 개발자들은 C#이나 VB 닷넷과 같은 언어의 코드를 기록한다. 컴파일 시간에 닷넷 컴파일러는 이러한 코드를 공통 중간 언어의 코드로 변환한다. 런타임할 때 공통 언어 런타임의 JIT 컴파일러(JIT 컴파일러)는 공통 중간 언어 코드를 운영 체제의 네이티브 코드로 변환한다. 아니면 중간 언어 코드는 런타임 이전에 개별단계에서 네이티브 코드로 컴파일될 수도 있다. 이로써 공통 중간 언어를 네이티브 코드로 변환하는 컴파일이 더 이상 필요하지 않기때문에 나중에 실행되는 모든 소프트웨어가 빠르게 실행되도록 도와 준다.

공통 언어 기반의 몇 가지 다른 기능이 윈도가 아닌 운영 체제에서 실행되는 반면, 공통 언어 런타임은 마이크로소프트 윈도 운영 체제에서만 동작한다.

출처 : http://ko.wikipedia.org/wiki/%EA%B3%B5%ED%86%B5_%EC%96%B8%EC%96%B4_%EB%9F%B0%ED%83%80%EC%9E%84


아 맞네요. 우리가 오늘부터 공부하고자 하는 CLR이라는 놈은 바로 IL을 실행가능하게 해주는 놈입니다. .NET Framework 기반의 모든 언어들은 언어를 가리지 않고 각자의 컴파일러에 의해 IL이라는 언어로 컴파일이 되고 CLR에 의해 IL기반의 코드들이 실제로 실행이 되게 되는 것이네요.

대충 CLR이 어떤 일을 한다는 것을 알게 되었습니다. 그렇다면 왜 CLR이라는 걸 만들었는지 CLR의 주변엔 또 어떤 것들이 있는지 주욱- 한번 훑어봐야지 앞으로 진도 나가는데 어려움이 없겠지요.

후아-
오늘은 여기까지 하죠!

'CLR' 카테고리의 다른 글

6. Assembly - GAC(Global Assembly Cache)  (2) 2010.02.02
5. Assembly - Strongly named assemblies  (0) 2010.01.26
4. Assembly  (2) 2010.01.15
3. MSCorLib & Metadata  (4) 2010.01.06
2. CLR! CLR! CLR!  (3) 2009.12.30

VS 2010 기능 소개 03 - IDE의 변화

Visual Studio 2010 2009. 12. 23. 09:00 Posted by 알 수 없는 사용자
 

VS 2010 IDE 어제 설명했다면. 오늘은. ^^ 2번째 IDE 소개이지 변화 입니다. 이번에 이야기 내용은 IDE 적용한 기술과 기술을 이용한 활용 편이라고 생각하시면 될것 같습니다.(활용은 여러분 마음입니다.~ .)

 

다들 아실겁니다. 아시죠?/ WPF ~

Windows Presentation Foundation 약자이며, 이제 딱딱한 윈도우는 가라~ 새로운 이쁘장하게 또는 멋있게~ 또는 진짜 진짜~ 멋있게 다른 한마디로 이게 윈도우야? ~~ 하는 말이 나올 정도로 윈도우를 멋있게 만들 있는 하나의 기술(?) 이죠. 많은 전문가 분들도 있고 커뮤니티도 있습니다.( 처음에 이것을 김태영 MVP님이 하시는 세미나에서 봤습니다. ^^ 오래전이였죠  ㅎㅎ) WPF 꺼낸 이유가 당근 있습니다. 우리가 VS 2010 또는 VS   실행하게 되면 어떤 화면이 나오는지 아시는지요?

 

개발자 1 : 빈화면 ? 뜨는게 느려서….

개발자 2 : 마지막 프로젝트 ? 하던일 마저 해야지

………

등등 많이 있습니다.

 

일을 하기 위해선 우리는 TFS Source Safe 연결하여 Source 가져오고 어쪄고 하고 내가 오늘 해야할 일이 무엇인지 등등.. 여러 윈도우 또는 VS IDE 필요한 것을 표시하는 등등을 합니다. 저는 프로젝트를 하고 있다고 가정하고 많이 많이 주는 회사(희망사항입니다. 백수 입니다 ㅠㅠ 어디 찾아주는 회사도 엄고 .)에서 일하고 있으며, TFS 연결하여 내가 오늘 해야할 일을 확인하고, Outlook 열고 메일을 확인 TFS에서의 결과를 보든등.. 여러 창을 봐야하는.. . 일을 합니다.(절대 가정입니다.. 하나의 예입니다.. - 사실 요즘 VS 2008 에서 그러구 있습니다 .)

VS 2010에서는 이것을 한방에 해결 할수 있습니다. 어떻게?

 

VS 2010 화면이 어떠시나요?  바로 이런 화면 아닌가요?

 

 

화면이은 어떻게 만들어 졌을까요? 이게바로 WPF만든 화면입니다. 화면을 우리가 바꿀수 있다면?

앞에서 이야기 내용,

 

  1. Outlook 에서 TFS 메일 내용 확인 또는 RSS 보기
  1. Groupware 에서의 공지사항 보기
  1. TFS 작업 내용 보기

 

개발에 필요한 공지사항이나 회사 주요 공지사항을 한눈에 보고 메일중에서 TFS 개발에 필요한 메일을 읽을 있거나 RSS 화면에서 있다면 어떨까요? 이런 이야기는 사실 초에 건대에서 세미나에서 제가 잠시 데모와 함께 이야기를 했었습니다. 이런 화면을 변경할 필요한 기술은 별도로 원하지 않습니다. 바로 WPF 알고 있고 이미 WPF 한다면 이미 시작 화면을 여러분의 마음에 드시는 것을 변경할 있습니다.( 이리 거창한지 사실 이것은 정말 정말 .. 예입니다.^^)

옛날에도 VS IDE 변경하거나 하는 기술은 있었지만, WPF 화면을 이미 여러 분들이 알고 있는 기술로 변경할 있으므로 별도의 기술이나 교육을 받지 않아도 된다는 것입니다.

 

이미 Beta 1이나 CTP 버전에서 사이트의 엄준일 MVP님의 사이트에도 있으며 영문으로는

http://blogs.msdn.com/vsxteam/archive/2009/05/20/visual-studio-2010-beta-1-start-page-customization.aspx

곳에 가시면 옛날 버전으로 나와 있습니다. 이것을 이야기 하자고 하는것이 아니라 VS 2010 Beta 2에서도 되냐고 말씀하시면.. 되곘죵? ㅎㅎ 그런데 조금 다릅니다 어떻게? 위의 블로그 Beta1 경우이고 이제 Beta 2 에서는 조금 다릅니다.

 

 

 

위치는 특별하지 않습니다. 옛날 그대로 C:\Program Files(x86)\Microsoft Visual Studio 10.0\Common7\IDE\StartPages\en이라는 곳에 있습니다. X64 버전의 윈도우에 VS 2010 설치 하셨다 하여도 위치는 그대로 입니다. 엣날에는 제가 아마 이곳을 복사하여 VS 2010 폴더에 저장하는 등등 일을 했는데 이제는 하지 않습니다. 바로 VS 2010 보시면.. 메뉴에서

   Tools  -> Options -> Environment 에서 Startup 찾습니다.

 

다음 Customize Start Page :  항목을

 








VS 2010
설치하셨다면 " 문서" 에서 "Visual Studio 2010" 폴더에서 "StartPages" 보실 있습니다. 곳으로 가시면 VS 2010 시작화면을 담당하는 xaml 프로젝트 파일이 있습니다.

 

 

 

 

 

사실 이미 StartPages.xaml 파일을 이미 백업해 두고 있습니다. ^^ 엣날에는 이게 없어서 복사하고 어쪄구 했는데 이제는 복사고 뭐고 VS 2010 beta2 에서는 프로젝트 파일과 xaml 파일이 이미 들어 있습니다. 프로젝트 파일을 열어보면.. 다음과 같은 화면입니다.

 

 

바로 WPF 만든 시작페이지를 보실 있습니다. 이것을 변경하면 어떻게 될까요? 변경해 보겠습니다.

어떻게 마음대로 변경합니다. ㅎㅎ 그렇지만 몇가지 제한이 있습니다. 보시면 cs파일이 없습니다.( WPF 찰스 아찌 책이 생각납니다.. 서점에서 4시간 조금 넘게 쭈구리고 앉아서 정신 없이 봤던..  아찌 책은 텍스트야 .)

그래서 제한이 조금 있습니다. 어떤것? 보시면 "vs:" 으로 시작하는데 이곳에서 작업을 할때는 vs:으로 지원하는 녀석들을 써야 하는 것입니다.(그럼 다른 방법은???  . 정식 블로그 입니다.. 이해를..)

 

http://msdn.microsoft.com/en-us/library/aa991992(VS.100).aspx

 

이곳에 가보시면 어떻게 만들어야 하는지가 나오는데.. 부분은 추후 시간 되면 블로그에 " 맘대로 번역"이라는 주제로 번역과 함께 쏙쏙들이 알아볼까 합니다.(정말 할수 있을지는 .)

그래서 어찌 됐든. 이제 코딩합니다.

Vs: 하면 바로  다음과 같은 선택화면이 나옵니다.

 

이곳의 녀석을 이용해서 코딩하는데 일단 ImageButton으로 해보겠습니다. 왜나면? 일단 URL 가져보는 녀석으로 해보려구요 ^^ 물론 WPF 도구를 가져와도 되긴 합니다. 그래서 WPF 달력 컨트롤과 VS: 이용한 간단한 이미지 버튼을 만들어봤습니다.

 

이렇게 WPF 코딩을 하면..

 

 

결과는 이렇습니다. ^^ 그럼 저장하고 Build 하면.

 

시작화면이 변경이 됩니다. 다음 VS:ImageButton에서 Command 이용해서 VS2010.net 이로 이동하도록 했습니다. 날짜가 아닌 이미지 버튼을 클릭하면 ^^ VSTS2010.net으로이동합니다.

간단히 변경을 했지만 몇가지 주의 사항과 결론입니다. ( 사견 입니다. ^^ MSDN 영문 자료를 참고하시길^^)

 

 1. VS: 이용하여 코딩한다.

 2. WPF 이용할 있지만 Event 다르게 해야한다.

 3. VS 2010 IDE 환경을 변경하려면 MEF 하면 좋다

 4. 절대 StartPages.xaml 백업한다 (? 혹시 모르니까요 ^^)

 5. 만약 백업도 하지 않았다면  앞에서 설명한 VS설치 폴더의 StartPages 폴더의 StartPages.xaml 이용하여 복원할 있다.

 

 

위의 주의사항인 1번을 확인하시고 MSDN 사이트를 참고하여 여러분의 시작화면을 변경을 해보시는 것도 좋습니다.

사실 앞에서 이야기한 것을 하기 위하여는 조금 공부를 해야하므로.. 그것은 다른 기회에 해보구요. ^^

(정말 " 맘대로 번역" ^^ 생각중입니다. MSDN에서 제가 필요한 부분에 대하서만요 ㅎㅎㅎ  )

 

Beta1에서는 복사하고 어떻게 했지만 이제 Beta2 부터는 시작페이지 프로젝트를 바로 열기를 하여 수정하여 저장하면 된다는 것입니다. 이게 Beta1하고의 차이점 입니다.

 

그럼 오늘은 여기 가지 하고 다음은 ^^ 언어별 IDE 조금 알아보겠습니다.


VS 2010 기능 소개 02 - IDE의 기능 추가

Visual Studio 2010 2009. 12. 22. 09:30 Posted by 알 수 없는 사용자

 

기업 하십니까?? VS에 있는 우리의 Get/Set 를 자동으로 해주는.... 하나의 기능...

(모르시면.. ㅠ.ㅠ 넵.. 이런 기능이 있었습니다.) 그외 메서드 추출이란 것도 있었고, 매우 편리한 도구(?)들이 있었지만, 모르고 지나쳤던 것들이 있었습니다.

 

그럼 두번째로 IDE 대한 것을 설명할까 합니다. IDE 여러 번에 걸쳐서 설명을 할까 합니다.

우리가 프로젝트를 진행하면 많은 이해관계자(전문용어로 뭐라 하긴 합니다. 스뭐라고 ^^ 자세한 것은 PMP부분에 잇습니다.) 보면 개발자, 설계자, 테스터, 데이터베이스 개발자 관리자 등등 프로젝트에 필요한 많은 인력이 필요로 합니다. 많은 프로젝트 참가자 분들이 필요로 하는 프로그램은 어떤것들이 있을까요? 이런 프로그램들 중에 설계자, 개발자, DB관리자 개발자, 테스트 분들이 하나의 프로그램에서 같은 개발환경을 이용한다면? 각자 화면이 조금 다르지만 기본적으로 같은 환경을 이용한다면 어떨까요?

 

VS 2010에서의 IDE에는 추가 된것이 많은데 Architect 또는 Developer 따라 자기에게 필요한 환경을 선택해서 자기의 업무를 한번에 처리할 있도록 도와줍니다. 편리하죠 ~ ㅎㅎ

Visual Studio IDE 정의를 잠시 내려보자면 Visual Studio 이용하여 하나의 통합 개발 환경을 지원하는 것입니다. Visual Studio IDE 코드 작성과 수정 오류를 검색, 수정하는데 도움이 되는 여러가지 도구를 제공하고 언어, 또는 사용환경에 따려 변경할 있습니다.

 

IDE 지원하는 개발 도구 중에 Visual Studio 위치는 매우 높다고 있습니다. 당연히 언어나 해당하는 플랫폼을 개발하시는 분들이 사용하는 도구에 이미 익숙하면 다른 도구를 사용하지 않을 수도 있지만, VS 2010 도구는 그중에서 Visual C++ IDE 앞에서 설명한 Smart Intellisense 이용한다면 개발 속도 또는 전문용어를 조금 빌리자면 개발 속도의 향상은 다른 도구보다 뛰어나다 있습니다. 그럼 이제 IDE 대하여 하나 알아보는데 앞에서 Intellisense 했지만. VC++ 언어를 설명할 언어에 맞게 설명하도록 하겠습니다.( 블로그에 최홍배 MVP님의 설명도 있습니다.^^)

 

IDE 변화 첫번째는 듀얼 모니터 입니다. 이것은 이상 설명하지 않아도 될듯 한데 모니터가 두개일 경우 개발 소스를 작성하는 창을 분리하려 다른 모니터에 Full Screen 또는 여러분이 원하는 크기의 창으로 있다는 것입니다. - 이건 많이 아시거나 해보셨으므로 Pass 입니다. ^-^

 

두번째 TFS와의 창과 SharePoint 연결이 기본으로 있다는 것입니다.

( 왼쪽에 하나로 몰빵 스탈~ 입니다. ㅋㅋㅋ)

 

다음 SharePoint 연결 창입니다.

 

 

우리가 Server 개발중에 Exchange , OCS, SharePoint 중에서 SharePoint 기본적으로 연결 설정을 지원하고 해당 하는 사이트에 대한 기능과 템플릿등등 많은 것을 보실수 있습니다.

 

 

 

이렇게 SharePoint 개발시에 필요한 정보를 서버에 접속하여 해당하는 장보를 있습니다.

이제 SharePoint 개발 시에 VS 2008, 2005 에서는 추가로 설치 했던 것을 설치하지 않아도 됩니다.

아직 Beta라서 SharePoint 2007 없지만, 프로젝트 선택시에 2007 항목이 있으므로 추가가 예상됩니다. (RC버전에서는 나오지 않을까요? ^^)

 

IDE에서 기본적으로 이제는 Team Foundation Server 접속할 있는 Team Explorer SharePoint 개발시 서버에 연결정보와 함께 해당 사이트의 정보를 제공하는 Server Explorer 추가 기능등 입니다.

 

별도의 설치가 없어도 된다는 것으로 이제는 기본 ~ 비스~ 라는 거죵.. 별도의 설치를 하지 않아도 된다는 것은 VS 2010설치만 하면 지금까지 별도로 설치 했던 것이 자동 또는 선택하여 설치할 있습니다. 그럼 다음은.. ㅎㅎㅎ

 

다음 편에 ~~ Coming Soon~~ 입니다. ^^