CLR의 JIT 컴파일러를 통해 만들어진 코드는 unmanaged code에 비해 성능이 우수하다고 합니다. 처음 듣기에는 좀 의아한데 성능이 향상된다고 주장하는 근거는 다음과 같습니다.
JIT 컴파일러?
JIT (Just In Time) 컴파일러
managed code의 소스코드는 각 언어의 컴파일러에 의해서 IL코드와 실행에 필요한 정보들을 갖고 있는 메타데이터로
이루어진 managed module로 생성됩니다. 이 모듈의 파일 포맷은 기존의 실행파일의 일반적인 형식인 PE32(64비트의
경우 PE32+)형태로 되어 있습니다.
이 모듈이 실행될 경우 JIT컴파일러에 의해 실행에 필요한 부분이 곧바로 Native code로 컴파일되어 실행됩니다. 당연히
매번 실행시마다 JIT컴파일러에 의해 컴파일되어 실행되는 것은 아니고 한번 컴파일 된 부분은 재 사용하는 등의 최적화 과정을
통해 CLR의 코드는 실행됩니다.
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 Via C# 2nd Ed. / Jeffrey Richter
.NET 프로그래밍 정복 / 김상형 저
안녕하십니까? 이번에 새롭게 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의 활용에 관한 내용으로 포스팅을 할 예정입니다. 많은 관심과 격려 부탁 드립니다 ^^
첫 포스팅이라 어떻게 진행을 해야 할지,, 감도 안잡히고, 어설퍼 보이는 부분이 한 둘이 아닐 듯 합니다. 아직 모르는 것도 많고, 부족한 것도 많기 때문에 지금 당장 전문가 다운 모습을 보이긴 어렵겠지만, 욕심 부리지 않고 꾸준하게 정진하는게 가장 바람직한 모습일 것 같습니다.
vs 2010 beta2 가 스마트기기 개발환경을 지원하고 있지 않은 관계로 연재를 일시 중단 합니다.
미리 확인 하지 않고 연제를 시작한 점 사과드립니다.
차후에 스마트기기 개발환경이 지원되는 대로 다시 하도록 하겠습니다.
1.들어가며…
안녕하세요.
저는 이번에 vsts2010에 참여하게 된 이석준 이라고 합니다.
앞으로 잘 부탁 드리겠습니다.
이런 공인된 장소를 글을 쓰는 것은 첨이다 보니 무척 부담이 많이 밀려오는 군요.
혹시 잘못된 부분이나 미흡한 부분이 있으면 바로 지적해 주시면 감사하겠습니다.
(제가 국어가 약해서 가끔 안드로메다틱한 문법이 나올 수도 있으니 이해 안 되는 문장은 반드시 지적을 해주시면 감사하겠습니다. ㅡ.ㅡ; )
VS상의 윈도우모바일(이하 wm) 개발환경은 리눅스나 기타 임베디드 개발환경에 비해 빠르고, 편리하고, 쉽습니다. 기존의 win32api, .Net 코드를 쓸 수 있음은 물론 WTL,MFC등과도 많은 부분의 코드가 호환이 됩니다. 모바일이나 임베디드 에서는 대부분 3D 랜더러로 opengl-es가 많이 사용되는 것으로 알려져 있습니다. 그러나 게임을 만들 때는 direct3d를 많이 사용합니다. Direct3d Mobile 이하 D3dm 을 사용하면 기존의 Direct3d코드를 그대로 활용할 수 있는 장점이 있습니다. 지금부터 약 10회로 나누어서 wm6상에서의 개발환경부터 오픈소스공개 랜더엔진인 irrlicht3d의 d3dm용 드라이버까지 제작을 해보도록 하겠습니다.
Visual Studio 2010 Beta 2 버전에서 Smart Device 개발이 가능한 것인가요? 아니면 Visual Studio 2008 버전 기준인가요? 혹시 Visual Studio 2010 Beta2버전이 설치되어 있는 이후에 wm6sdk를 설치해야 하나요?
안녕하세요. 이번에 새롭게 팀원이된 박세식이라고 합니다. 많이 부족해서 컴터앞에 앉아 이렇게 자판을 두드리고 있는 시간에도 떨림이 멈추질 않네요-_-; 앞으로 잘 부탁드리겠습니다.(따스~한 피드백 아시죠^^;) 자~ 그럼. 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 페이지를 렌더링하는 것들이 포함되어 있습니다.
다시 뷰스테이트로 돌아와서 정리하자면, 세상에 공짜는 없습니다.(비용이 든다는거죠) 여기 뷰스테이트도 예외일 수는 없습니다^^; ASP.NET 페이지가 요청될 때마다 뷰스테이트는 두가지 성능에 관련되는 일을 합니다. 첫째는, 모든 페이지를 방문할 때 뷰스테이트는 해당 컨트롤 계층의 모든 컨트롤의 뷰스테이트를 모아서 베이스 64 인코딩으로 시리얼라이즈합니다. 여기서 생성된 스트링이 __VIEWSTATE에 값인거죠^^
반대로, 포스트백시에는 뷰스테이트를 읽엇 저장된 뷰스테이트 데이터로 디시리얼라이즈하고 컨트롤 계층구조에 있는 적절한 컨트롤러로 업데이트합니다. 두번째로, 뷰스테이트는 클라이언트가 다운로드 받아야할 웹페이지의 크기를 증가시킵니다. 원래 보여질 페이지의 데이터와는 또다른 데이터인거죠. 뷰스테이트 크기가 큰 페이지는 이 뷰스테이트의 크기가 수십 킬로바이트가 됩니다. 이것을 다운받기 위해 또 수 초나 수 분의 시간을 할애해야합니다.(이게~ 뭔가요-_-;) 또, 포스트백시에도 뷰스테이트를 웹 서버로 보내야하고, 그것 때문에 포스트백 요청시간이 증가하는 거죠.
● 뷰(View) 는 애플리케이션의 UI를 담당하고, 이는 단지 컨트롤러에 의해 애플리케이션의 데이터로 채워질 HTML 템플릿에 지나지 않습니다. ● 모델(Model) 은 UI를 렌더링하는 뷰가 사용할 애플리케이션의 객체, 즉 애플리케이션의 데이터의 비즈니스 로직을 구현합니다. ● 컨트롤러(Controller) 는 사용자 입력과 상호작용하는 응답을 핸들링합니다. 웹 요청은 컨트롤러에 의해 핸들링되고, 요청된 URL의 표현될 뷰와 적절한 데이터(모델 객체)를 결정합니다.
ASP.NET MVC의 요청 흐름도
ASP.NET MVC 애플리케이션은 웹폼과 같이 주소창에 입력된 URL이 해당서버의 디스크에 있는 페이지(파일)을 찾는것이 아닌 컨트롤러를 통한 뷰를 호출하게 됩니다. URL은 컨트롤로와 매핑이 되고 컨트롤러는 뷰를 리턴해주는 식이죠. 다음의 그림을 보시면
처음 사용자 요청(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와 인사를 나눠보는 시간을 갖도록 하겠습니다^^
// 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로 개발된 어플리케이션 소프트는 런타임 없이 동작 시킬수 있다.
공통 언어 런타임(Common Language Runtime, CLR)은 마이크로소프트닷넷 이니셰이티브의 가상 머신 구성 요소이다. 프로그램 코드를 위한 실행 환경을 정의하는 마이크로소프트의 공통 언어 기반 (CLI) 표준의 기능이다. 공통 언어 런타임은 공통 중간 언어(CIL, 이전에는 MSIL로 알려져 있었음)라고 불리는 바이트코드의 형태를 실행한다.
공통 언어 런타임을 사용하는 개발자들은 C#이나 VB 닷넷과 같은 언어의 코드를 기록한다. 컴파일 시간에 닷넷 컴파일러는 이러한 코드를 공통 중간 언어의 코드로 변환한다. 런타임할 때 공통 언어 런타임의 JIT 컴파일러(JIT
컴파일러)는 공통 중간 언어 코드를 운영 체제의 네이티브 코드로 변환한다. 아니면 중간 언어 코드는 런타임 이전에 개별단계에서
네이티브 코드로 컴파일될 수도 있다. 이로써 공통 중간 언어를 네이티브 코드로 변환하는 컴파일이 더 이상 필요하지 않기때문에
나중에 실행되는 모든 소프트웨어가 빠르게 실행되도록 도와 준다.
공통 언어 기반의 몇 가지 다른 기능이 윈도가 아닌 운영 체제에서 실행되는 반면, 공통 언어 런타임은 마이크로소프트 윈도 운영 체제에서만 동작한다.
아 맞네요. 우리가 오늘부터 공부하고자 하는 CLR이라는 놈은 바로 IL을 실행가능하게 해주는 놈입니다. .NET
Framework 기반의 모든 언어들은 언어를 가리지 않고 각자의 컴파일러에 의해 IL이라는 언어로 컴파일이 되고 CLR에 의해
IL기반의 코드들이 실제로 실행이 되게 되는 것이네요.
대충 CLR이 어떤 일을 한다는 것을 알게 되었습니다. 그렇다면 왜 CLR이라는 걸 만들었는지 CLR의 주변엔 또 어떤 것들이 있는지 주욱- 한번 훑어봐야지 앞으로 진도 나가는데 어려움이 없겠지요.
VS 2010의 IDE를어제설명했다면. 오늘은. ^^ 네 2번째 IDE 소개이지변화입니다. 이번에이야기할내용은 IDE에적용한기술과그기술을이용한활용편이라고생각하시면될것같습니다.(활용은여러분마음입니다.~ ㅠ.ㅠ)
다들아실겁니다. 아시죠?/ WPF ~
Windows Presentation Foundation 의약자이며, 이제딱딱한윈도우는가라~ 새로운이쁘장하게또는멋있게~ 또는진짜진짜~ 짱멋있게다른한마디로이게윈도우야? 오~~ 하는말이나올정도로윈도우를멋있게만들수있는하나의기술(?) 이죠. 많은전문가분들도있고커뮤니티도있습니다.(전처음에이것을김태영 MVP님이하시는세미나에서봤습니다. ^^ 참오래전이였죠ㅎㅎ) 이 WPF를꺼낸이유가당근있습니다. 우리가 VS 2010 또는옛 VS 를실행하게되면어떤화면이나오는지아시는지요?
위치는특별하지않습니다. 옛날그대로 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 과프로젝트파일이있습니다.
SQL Azure에 데이터베이스와 데이터가 있으므로 응용 프로그램에서 액세스 해보도록 하겠습니다.
응용 프로그램이 Cloud 환경이 아닌 모습이라면 Far Application 이라고 말하며
SQL Azure 와 응용 프로그램이 같은 Cloud 환경이라면 Near Application 이라고 말합니다.
Visual Studio 2010으로 ASP.NET Web Role Application을 생성하여 Far, Near 응용 프로그램을 처리해보도록 하겠습니다.
먼저 등록된 SQL Azure의 데이터 쿼리 결과입니다.
위의 데이터를 Cloud Service의 ASP.NET Web Role 에서 액세스하고 Cloud로 게시해봅니다.
먼저 Visual Studio 2010에서 Cloud Service > Windows Cloud Azure Service 에서 ASP.NET Web Role 프로젝트를 생성합니다.
Web Role의 Default.aspx 에 대한 페이지는 많은 내용 없이 SQL Azure를 연결하여 Category 데이터와 SubCategory 데이터를 표시해주는 것으로 구성해보겠습니다.
Default.aspx의 화면 디자인은 DropDownList와 GridView 컨트롤을 배치합니다.
아래처럼 간단한 ADO.NET 프로그래밍을 통해 저장 프로시저를 호출하여 DropDownList1 과 GridView1에 데이터를 바인딩 합니다. 연결 문자열은 Web.Config에 connectionStrings 섹션에 위치시킵니다. 로컬 데이터베이스에서 테스트하고 SQL Azure 의 연결 문자열로 변경하도록 합니다.
로컬 데이터베이스에서 테스트하고 SQL Azure로 결과를 테스트하면 아래와 같은 결과를 볼 수 있으며 아래 형태가 Cloud와 코드가 멀리 있는 Far Application 형태가 됩니다. 웹뿐만 아니라 Cloud의 여러 서비스가 있다면 Windows Form에서도 액세스 가능하다는 것을 알 수 있습니다.
이제 Near Application으로 Windows Azure로 게시해봅니다. 솔루션 탐색기에서 게시를 선택해서 Windows Azure 사이트의 서비스에 cspkg 확장자 파일과 cscfg 확장자 파일을 업로드하고 게시합니다.
Production에도 게시를 하여 Azure URL로 접속하면 아래와 같은 결과를 얻을 수 있습니다.
물론 SQL Azure에 대한 방화벽 설정을 해주어야 합니다.~
요약하면 데이터베이스와 데이터가 게시된 SQL Azure를 이용하는 Cloud Application을 생성해보았습니다.
오늘도 하루가 밝았어요. 상쾌한 기분으로 기지개를 켜고, 커튼을 젖혔어요. 오~ 마이~갓. 바깥에 왠 검은 외투를 입은 사람들이 망원경 뒤집어쓰고 이쪽을 째려보고 있어요. 아침부터 기분이 좋지 않아요. 자고일어나니 스타가 된걸까요, 왜 이쪽을 째려보는 건지 도무지 모르겠어요. 집밖을 나섰어요. 대놓고 따라와요. 집밖을 나왔는데도 왜 망원경은 계속 뒤집어 쓰고 있는건지 모르겠어요. - [감시당하는 자]의 탐구생활
- 시작부터 탐구생활드립이냐.
그냥 한번 해보고 싶었을 뿐이니 노여워 마시길 바랍니다. 오늘은 감시하는 자와 감시당하는 자의 이야기를 해보려고 합니다. 즉, Observer패턴을 말하는 건데요. 뭔가 변화가 있을때 그 변화를 바로 알아차려서 어떤 동작을 수행해야 할때. 변화의 대상을 유심히 관찰하고 있어야 겠죠. 근데, 유심히 관찰하고 있는거 보다 변화가 일어났음을 알려주는 친구가 있다면 더 편리하겠죠. 이벤트 모델이 그중의 한 예 입니다. 이벤트가 일어났을때 통지를 받겠다고 등록을 해두면, 이벤트 발생시에 이벤트를 기다리는 모든 객체들에게 이벤트가 발생했음을 통지해줘서 적절한 조치를 취하도록 해주는 것 처럼 말이죠.
이런 건, 기존에는 직접 패턴을 통해 작성을 해야 했지만 닷넷 프레임워크 4.0에 이런 Observer패턴을 지원하기 위한 새로운 인터페이스가 추가 되었습니다. 거기에 대해서 설명을 드려볼까 합니다. 기존의 포스트와 마찬가지로 이번 포스트 역시 눈을 조심하시고 언제든지 OME를 외칠 준비를 하시길 바랍니다.
- 기존의 방식으로.
닷넷 프레임워크 4.0이전에는 어떻게 만들어야 했는지 한번 알아보겠습니다. 제 이해가 부족해서 적절치 못한 예제와 적절치 못한 수준일 수도 있으니, 마음의 준비 하시구요. 우선, UML 다이어그램을 한번 보시죠.
- 그림1. 예제의 UML 다이어그램.(인터페이스가 클래스모양을 하고 있는 것 같지만, 착시현상입니다. 이해를 위해서 부족한 실력이지만 그려봤습니다-_-)
네, 그림에서 느낌이 오듯이 라디오방송국과 청취자를 모델링해봤습니다. 제가 만드는거 중에 쓸모있는 건 별로 안나오죠-_-. 우선 RadioBroadcaster라는 인터페이스가 있구요, KBRRadioBroadcaster가 그걸 상속해서 방송국의 역할을 합니다. 그리고 각각의 Listener가 방송국에 주파수를 맞추고, 전달되는 전파를 수신하는 형태이구요.
그리고 이번엔 지켜보는 자, 청취자입니다. 라디오를 청취하고, 끊을 수 있으며, Listening을 통해서 매번 날아오는 전파를 수신합니다.
class Program { static void Main(string[] args) { Listener listener1 = new Listener("마논개"); Listener listener2 = new Listener("코턱용"); Listener listener3 = new Listener("송순신");
KBRRadioBroadcaster kbrRadioBroadcaster = new KBRRadioBroadcaster(); listener1.ListenToKBRRadio(kbrRadioBroadcaster);//마논개 라디오 청취시작. int count = 0; do { if (count == 0) { kbrRadioBroadcaster.StartBroadcast(); } if (count == 2) { listener2.ListenToKBRRadio(kbrRadioBroadcaster);//코턱용 라디오 청취시작 } if (count == 3) { listener1.QuitFromKBRRadio(kbrRadioBroadcaster);//마논개 라디오 끔 listener3.ListenToKBRRadio(kbrRadioBroadcaster);//송순신 라디오 청취시작 } kbrRadioBroadcaster.DoBroadcasting(); count++; Thread.Sleep(500); } while (kbrRadioBroadcaster.broadcastStatus != BroadcastStatus.End); } }
그리고 프로그램 코드지요. 마논개, 코턱용, 송순신 세명이 라디오를 청취하는데요. 처음에는 마논개 혼자 듣다가, 두번이후에 코턱용이 라디오를 듣기 시작합니다. 그리고 세번째가 되면, 마논개가 라디오가 지겨워서 끄구요, 송순신이 라디오를 듣기 시작합니다. 방송이 끝날때까지, 0.5초당 한번씩 전파를 타고 방송이 날아오구요. 아웃사이더쯤되야 가능한 속도겠네요. 실행화면을 보시면 아래와 같습니다.
-그림2. 실행한 모습!
넵, 의도했던대로 방송이 전파를 타고 나오면서 사람들이 방송을 들었다가 빠집니다. 대사가 다 나온후에 방송이 종료되구요. 제 내공의 문제로 정확한 Observer패턴의 형태나, 사용방법이라고 볼 수는 없겠지만 뭐 이해에는 문제가 없을 것 같습니다. 하하하-_-;;;
- 이제 새로운 걸 내놔봐.
넵. 이젠 닷넷 4.0에 추가됐다는 새로운 인터페이스 IObservable<T>와 IObserver<T>에 대해서 말씀드려보도록 하겠습니다. IObserable<T>는 지켜볼 대상이 되는 클래스가 구현을 할 인터페이스입니다. 위에서 보자면 방송국이 되겠죠. 그리고 IObserver<T>는 지켜보는 행위를 하는 클래스가 구현을 할 인터페이스입니다. 마찬가지로 청취자가 되겠죠. 즉 IObservable<T>를 구현하는 클래스는 말그대로 observable한(지켜볼 수 있는) 클래스를 말하는 거구요, IObserver<T>를 구현하는 클래스도 말 그대로 observer클래스(지켜보는)가 되는 거죠. 그럼, 위의 예제를 여기에 맞춰서 옮겨 볼까요~~~~! 그전에, 일단 다이어그램을 한번 보시져.
RadioBroadcaster가 IObservable<string>을 상속하고 있죠? 지켜볼 대상이 되기 때문이죠. 그리고 string은 지켜보는 observer가 전달받는 데이터를 말하는데요, 방송국에서 string타입의 전파를 뿌렸으므로 string이 됩니다.
class KBRRadioBroadcaster : RadioBroadcaster//정보의 공급자 { private List<IObserver<string>> listeners = new List<IObserver<string>>(); public BroadcastStatus broadcastStatus = BroadcastStatus.StandBy;
private List<string> scripts = new List<string> { "안녕하십니까. KBR방송국의 김병만 기자입니다.", "요즘 살림살이 초큼 어찌 나아지셨슴까?", "안 나아지셨다구요? 그럼 이 방송에서 취업 필살전략을 알려드립니다.", "요즘같이 취업이 어려운때 3개 국어가 가능하면 취업 직빵이겠죠.", "따라 해보시져, Handle いぱい 꺽어.(핸들 이빠이 꺽어).", "3개국어 정말 쉽져? 이것만 한다면 당신도 취업계의 슈퍼스타!" };
private int currentScriptIndex = 0;
public void DoBroadcasting() { if (scripts.Count.Equals(currentScriptIndex)) { Console.WriteLine("방송끗."); broadcastStatus = BroadcastStatus.End; } else { foreach (IObserver<string> listener in listeners) { listener.OnNext(scripts[currentScriptIndex]); // Assume that we've arrived at location of Latitude has changed by 4. if (broadcastStatus == BroadcastStatus.End) { listener.OnCompleted(); } } currentScriptIndex++; } }
public void StartBroadcast() { broadcastStatus = BroadcastStatus.OnAir; }
#region IObservable<Listener> Members
public IDisposable Subscribe(IObserver<string> listener) { listeners.Add(listener); // Announce current location to new observer. Console.WriteLine("{0} : 수신감도 조쿠나. ㅎㅎㅎㅎ", (listener as Listener).Name );
return listener as IDisposable; }
#endregion
public void UnSubscribe(IObserver<string> listener) { listeners.Remove(listener); Console.WriteLine("{0} : 아놔. 완전 재미없엉", (listener as Listener).Name); } }
변화가 있다면, IObservable의 메서드인 Subscribe를 구현했다는 것과 QuitFrom이 이름을 맞추기 위해서 UnSubscribe로 바뀐건데요. Subscribe는 ListenTo가 그랬듯이 변화가 생기면, 그걸 알려달라고 등록하는 통로가 됩니다.
class Listener : IObserver<string>//지켜보는 행위를 하는 주체 { private string name;
public string Name { get { return name; } }
public Listener(string name) { this.name = name; Console.WriteLine("나는야 {0}. 라디오를 가진 남자지.", this.name); }
그리고 요건 청취자죠. 지켜봐야 하기 때문에 IObserver<string>을 구현한게 보이시죠? 그리고 인터페이스의 메서드를 구현했는데요. 각각 완료시에 할 동작을 담을 OnCompleted와 에러발생시에 처리할 OnError, 그리고 기존의 Listening과 같이 변화를 전달받을때 할 동작을 담을 OnNext로 나눠집니다.
class Program { static void Main(string[] args) { Listener listener1 = new Listener("마논개"); Listener listener2 = new Listener("코턱용"); Listener listener3 = new Listener("송순신");
KBRRadioBroadcaster kbrRadioBroadcaster = new KBRRadioBroadcaster(); kbrRadioBroadcaster.Subscribe(listener1);//마논개 라디오 청취시작. int count = 0; do { if (count == 0)//방송시작 { kbrRadioBroadcaster.StartBroadcast(); } if (count == 2)//잠시후 코턱용 라디오 청취시작 { kbrRadioBroadcaster.Subscribe(listener2); } if (count == 3)//잠시후 { kbrRadioBroadcaster.UnSubscribe(listener1);//마논개 라디오 끔 kbrRadioBroadcaster.Subscribe(listener3); //송순신 라디오 청취시작 } kbrRadioBroadcaster.DoBroadcasting(); count++; Thread.Sleep(500); } while (kbrRadioBroadcaster.broadcastStatus != BroadcastStatus.End); } }
그리고 프로그램 코드죠. 동작은 위와 동일합니다. 결과를 보시죠.
-그림4. 동일한 결과
- 마무리.
의의를 찾자면, 프레임워크 레벨에서 Observer패턴을 지원하면서 좀 더 정돈된 형태로 구현을 할 수 있다는 것과 그렇게 구현을 했을때 나중에 프레임워크 레벨에서 성능 개선이 있던지 하면, 그런 혜택을 코드의 변경없이 누릴 수 있다는 점이 있겠구요. 또 한가지 점은 프레임워크나 다른 기술에서 내부적으로도 이 인터페이스를 활용하게 될거고, 그리고 새로운 형태의 프레임워크도 등장을 기대할 수 있다는 점일 것 같습니다.
실제로, 이 인터페이스를 통해서 Reactive Extensions for .NET(줄여서 Rx) 라는 프로젝트가 Devlab에 공개되었습니다. 스크린캐스트를 살짝 들여다보니, 흥미로운 응용이 가능하더군요. 가능하면 다음번에는 Rx를 가지고 이야기를 한번 해보고 싶네요. 그럼, 시력을 떨어뜨리는 글을 열심히 읽어주셔서 감사합니다. 날도 추운데 피드백은 따쓰하게... 아시져? ㅋㅋㅋㅋ 그리고! 소스는 첨부해드립니다.
concurrent_queue는 queue
자료구조와 같이 앞과 뒤에서 접근할 수 있습니다.
concurrent_queue는 스레드
세이프하게 enqueue와 dequeue(queue에 데이터를
넣고 빼는) 조작을 할 수 있습니다.
또 concurrent_queue는 반복자를 지원하지만 이것은 스레드
세이프 하지 않습니다.
concurrent_queue와 queue의 차이점
concurrent_queue와 queue는 서로 아주 비슷하지만 다음과 같은 다른 점이 있습니다.
( 정확하게는 concurrent_queue와 STL의 deque와의 차이점 이라고 할수 있습니다. )
- concurrent_queue는
enqueue와 dequeue 조작이 스레드 세이프 하다.
- concurrent_queue는 반복자를 지원하지만 이것은 스레드
세이프 하지 않다.
- concurrent_queue는
front와 pop 함수를 지원하지 않는다.
대신에 try_pop 함수를 대신해서 사용한다.
- concurrent_queue는
back 함수를 지원하지 않는다.
그러므로 마지막 요소를 참조하는 것은 불가능하다.
- concurrent_queue는
size 메소드 대신 unsafe_size 함수를 지원한다.
unsafe_size는 이름 그대로 스레드 세이프 하지 않다.
스레드 세이프한 concurrent_queue의 함수
concurrent_queue에
enqueue 또는 dequeue 하는 모든 조작에 대해서는 스레드 세이프합니다.
- empty
- push
- get_allocator
- try_pop
empty는 스레드 세이프하지만 empty
호출 후 반환되기 전에 다른 스레드에 의해서 queue가 작아지던가 커지는 경우 이 동작들이
끝난 후에 empty의 결과가 반환됩니다.
스레드 세이프 하지 않은 concurrent_queue의 함수
- clear
- unsafe_end
- unsafe_begin
- unsafe_size
반복자 지원
앞서 이야기 했듯이 concurrent_queue는 반복자를 지원하지만
이것은 스레드 세이프 하지 않습니다. 그래서 이것은 디버깅 할 때만 사용할 것을 추천합니다.
또 concurrent_queue의 반복자는 오직 앞으로만 순회할 수
있습니다.
concurrent_queue는 아래의 반복자를 지원합니다.
- operator++
- operator*
- operator->
concurrent_queue는 앞서 설명한 concurrent_vector와 같이 스레드 세이프한 컨테이너지만 STL의 vector와 deque에는 없는 제약 사항도 있습니다. 우리들이 Vector와 deque를
스레드 세이프하게 래핑하는 것보다는 Concurrency Runtime에서 제공하는 컨테이너가 성능적으로
더 좋지만 모든 동작이 스레드 세이프하지 않고 지원하지 않는 것도 있으니 조심해서 사용해야 합니다.
다음에는 일반적인 queue에는 없고 concurrent_queue에서만 새로 생긴 함수에 대해서 좀 더 자세하게 설명하겠습니다.
ps : 앞 주에 Intel의 TBB에 대한 책을 보았습니다. 전체적으로 Concurrency Runtime과 비슷한 부분이 많아서 책을 생각 외로 빨리 볼 수 있었습니다. 제 생각에 TBB나 Concurrency Runtime를 공부하면 다른 하나도 아주 빠르고 쉽게 습득할 수 있을 것 같습니다.
Microsoft Ajax 라이브러리는 오직 클라이언트 자바스크립트 라이브러리입니다. 그것은 인터넷 익스 플로러, 구글 크롬, 애플 사파리, 그리고 모질라 파이어폭스를 포함한 현대의 모든 브라우저에 호환성을 갖고 있습니다.
당신은 웹브라우저에서 완벽히 작동하는 높은 응답성과 쌍방향의 DB로 이루어진 웹 어플리케이션을 구축하는데 Microsoft Ajax 라이브러리가 도움을 줄 수 있습니다. Microsoft Ajax 라이브러리는 오직 클라이언트 자바스크립트 라이브러리이기 때문에, 당신은 ASP.NET 웹 폼과 ASP.NET MVC 어플리케이션과 함께 그 라이브러리를 사용할 수 있습니다. 당신은 또한 단지 HTML로 이루어진 Ajax 페이지들을 만들 수 있습니다. Microsoft Ajax 라이브러리는 오픈소스로서 ASP.NET 4과 독립적으로 배포되었으며, 완벽히 제품을 지원하게 됩니다. http://www.asp.net/ajax/ 당신은 다음의 웹사이트 주소로부터 Microsoft Ajax 라이브러리의 최신 버전을 다운로드 할 수 있습니다.
Note: ASP.NET 4는 이 섹션에서 설명된 특징을 지원한지 않는 Microsoft Ajax 초기 버전을 포함합니다. 반드시 ASP.NET 웹사이트로 부터 최신 버전을 다운로드 해주세요.
Sys.require 매소드는 그 다음에 스크립트 로더를 사용합니다. 당신은 Sys.require 매소드에 컴포넌트의 이름(혹은 컴포넌트의 배열)과 콜백 매소드를 제공합니다. 컴포넌트에 의하여 요구된 모든 스크립트들이 로드되었을 때, 콜백 매서드는 불러오게 됩니다. 예를 들어, 이전의 코드는 다음의 스크립트들을 로드합니다. 그것은 워터마크 칸트롤에 모두 필요합니다:
MicrosoftAjaxComponentModel.js
MicrosoftAjaxCore.js
MicrosoftAjaxGlobalization.js
ACTCommon.js
ACTExtenderBase.js
ACTWatermark.js
성능을 향상시키기 위하여, 스크립트 로더들은 이 스크립트들 모두 동시에 로드랍니다. 그리고 올바른 순서로 그 스크립트를 실행합니다. 그 스크립트 로더는 아주 영리해서 단지 한번 요청된 스크립트를 로드합니다. 당신은 페이지에 스크립트로더를 추가할 수 있는데, 그것은 Start.js파일을 참조하는 script 태그를 덧붙이는 것입니다. Start.js 파일은 당신의 로컬 서버에 있을수 있고, 혹은 당신은 다음의 스크립트 태그를 사용하여 Microsoft Ajax Content Delivery Network 상에서 Start.js 파일을 참조할 수 있습니다.
당신이 Start.js에서 참조한 후에, 당신은 Sys.requires를 사용하는 것에 의하여 다른 필요한 자바스크립트 파일을 로드할 수 있습니다. Microsoft Ajax Content Delivery Network에 대하여 더 많이 배우기 위해서, ASP.NET 웹사이트 상의 Microsoft Ajax CDN를 보세요.
Microsoft Ajax 라이브러리는 웹브라우저 상에서 완전히 동작하는 DB로 이루어진 웹 어플리케이션을 빌드 가능하게합니다. 클라이언트가 데이터에 접근 가능하게 하는 Microsoft Ajax의 3가지 특징이 있습니다.
Client data controls
Client templates
Client data context
클라이언트 DataView 컨트롤은 하나의 혹은 다수의 데이터베이스 레코드를 보여 줄 수 있게 합니다. 당신은 클라이언트 템플릿을 만드는 것으로 DataView 컨트롤을 통하여 데이터 베이스 레코드들을 보여 줍니니다. 예를 들어, 당신은 모든 데이터베이스를 보여주는 다음의 코드처럼 코드를 사용할 수있습니다. 그 데이터베이스 레코드들은 MovieService라고 이름 붙여진 WCF 서비스로부터 찾게 될 수 있습니다.
<!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>
<title>Movies</title>
<link href="Site.css" rel="stylesheet" type="text/css" />
예제 속의 자바스크립트 코드는 모든 스크립트를 로드하기 위하여 클라이언트-스크립트를 사용합니다. 그 스크립트들은 DataView 컨트롤과 MovieService WCF 서비스로 부터 데이터를 찾기 위한 DataView 컨트롤에 의하여 사용된 DataContext 컨트롤의해 필요했습니다. 다음 DataView 컨트롤은 생성되고, ID moviesView를 갖는 HTML UL요에 덧붙여졌습니다. 클라이언트 템플릿은 페이지의 바디안에 포함되고, 다음과 같습니다:
DataView 컨트롤은 클라이언트 템플릿과 함께 WCF 서비스로부터 찾아진 각 데이터베이스 레코드를 구성합니다. {{Title}} 플레이스홀더는 Movie 값을 보여줍니다. Title 속성과 {{Director}} 플레이스홀더는 Movie.Director 속성 값을 보여줍니다. 당신이 위 문서를 필요할 때, 다음의 페이지는 웹브라우저에서 렌더링 됩니다.
Microsoft Ajax 라이브러리는 클라이언트 DataContext 클래스를 포함하는데, 그것은 SQL DataContext 혹은 객체 프레임워크 ObjectContext 클래스에서 서버 쪽의 LINQ와 동등한 개념의 클라이언트 사이드입니다.
DataContext 클래스는 다음의 특징을 갖고 있습니다:
DB의 데이터에 접근하여 읽고, 쓰는 것을 지원합니다.
아이덴티티 관리와 변화 추적을 지원합니다.
복잡한 링크들을 관리하기 위한 지원과 다중의 객체 집단 혹은 테이블들로 부터 객체들 사이에 조합을 지원합니다.
Microsoft Ajax 라이브러리는 일반적인 DataContext 클래스를 포함합니다. 그리고 당신이 ASP.NET 혹은 WCF Web 서비스가 상호작용하기 윈할 때 사용할 수 있습니다. Microsoft Ajax 라이브러리는 또한 AdoNetDataContext 클래스를 포함하며 당신이 쉽게 ADO.NET Data Services 함께 상호작용 할 수 있도록 설계되었습니다. 당신은 DB의 데이터를 찾고 업데이트 할 대 모두 DataContext 혹은 AdoNetDataContext 클래스를 사용 할 수 있습니다.
jQuery 라이브러리는 아주 인기있는 오픈소스 자바스크립트 라이브러리 이며, ASP.NET 웹폼과 ASP.NET MVC 안에 모두 포함되어 있습니다. Microsoft Ajax 라이브러리는 jQuery 개발자들에게 마음에 들도록 설계되었습니다. 당신은 jQuery 플러그인과 Microsoft Ajax 클라이언트 컨트롤들을 같은 Ajax 어플리케이션에서 문제없이 함께 사용 할 수 있습니다.
예를 들어, 다음 페이지에서 Microsoft Ajax 워터파크 컨트롤은 당신이 jQuery 플러그인으로 만들려고 사용했을 때 처럼 같은 문법을 사용하면서 창조 되었습니다.
<!DOTYPE 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>
<title>jQuery Watermark</title>
<link href="Site.css" rel="stylesheet" type="text/css" />
jQuery $(".required") 섹터는 요구한 CSS 클래스를 가진 페이지로 부터 모든 요소를 찾기위하여 사용 되었습니다. 워터마크는 매칭하는 모든 요소에 덧붙여 졌습니다. Microsoft Ajax 라이브러리가 jQuery 체이닝을 지원하는 것을 알려줍니다. 워터마크가 jQuery 섹터에 의하여 반환된 요소들에 적용된 후에, 매치되는 모든 요소의 배경색과 두드러진색이 바뀌어졌습니다. jQuery 섹터에 의하여 반환된 같은 wrapped set에 반하여, 다중의 연산들이 수행 되었습니다.
지난 글에서 말씀 드렸듯이, 이번 글에서는 새롭게 추가된 Data Flow Rules에 대해서 소개 드리겠습니다.
새롭게 추가된 8개의 Data Flow 규칙들
일단, 새롭게 추가된 규칙 목록을 먼저 보도록 하겠습니다.
CA1062 ValidateArgumentsOfPublicMethods: 함수의 인자유효성 검사 여부 CA1303 DoNotPassLiteralsAsLocalizedParameters: 문자열 인자의 Globalization 처리 여부 CA2100 ReviewSqlQueriesForSecurityVulnerabilities: SQL Injection 취약점 파악 CA2202 DoNotDisposeObjectsMultipleTimes: Dispose 메서드를 여러 번 호출하는지 여부 CA2204 LiteralsShouldBeSpelledCorrectly: 스펠링 체크 CA2215 DisposeMethodsShouldCallBaseClassDispose: Base 클래스의 Dispose 메서드를 호출하는지 여부 CA2241 ProvideCorrectArgumentsToFormattingMethods: Format 함수 인자 검사 CA2000 DisposeObjectsBeforeLosingScope: Dispose 메서드를 호출하는지 여부
이 규칙들 중에서, CA2000을 제외하면 모두 Visual Studio Team System 2005에서 이미 지원했었던 규칙입니다. 그리고 사실 CA2000도 VSTS 2005에 없었다 뿐이지, FxCop 1.35버전에서는 있었구요. 하지만 이 규칙들은 FxCop 1.36과 Visual Studio Team System 2008에서는 빠져있습니다.
즉, FxCop 1.35와 VSTS 2005에 있었던 Analysis 엔진에 성능의 결함, 버그, 일관적이지 못한 분석 결과 등의 문제가 있어서, 그 엔진을 VSTS 2008과 FxCop 1.36에서는 완전히 없애 버린 것입니다.
하지만, 이번 Visual Studio 2010에서는 화려하게 복귀가 되었습니다.
Phoenix Framework의 탑재
그게 가능했던 이유는 새롭게 탑재된 Phoenix Framework 덕분입니다. 피닉스 프레임워크는 향후 마이크로소프트 컴파일러 기술을 위한 새로운 코드 최적화/분석 프레임워크입니다. C++/CLI 기반으로 만들어진 피닉스 프레임워크는 컴파일러, 코드 최적화, 자동 코드 생성 등 여러 분야에 사용될 수 있는 프레임워크인데요. 자세한 정보는 아래 URL에서 보실 수가 있습니다.
shink_to_fit는 메모리 사용량과 단편화를 최적화 시켜줍니다. 이것은 메모리 재할당을 하기 때문에 요소에 접근하는 모든 반복자가 무효화됩니다.
Intel TBB
CPU로 유명한 Intel에서는
멀티코어 CPU를 만들면서 병렬 프로그래밍을 좀 더 쉽고, 안전화고, 확장성 높은 프로그램을 만들 수 있도록 툴과 라이브러리를 만들었습니다.
라이브러리 중 TBB라는 병렬 프로그래밍 용 라이브러리가 있습니다. 아마 TBB를 아시는 분이라면
Concurrent Runtime의 PPL에 있는 것들이
TBB에 있는 것들과 비슷한 부분이 많다라는 것을 아실 것입니다.
VSTS 2010 Beta2가 나온지 얼마 되지 않아서 병렬 컨테이너에
대한 문서가 거의 없습니다. 그러나 TBB에 관한 문서는
검색을 해보면 적지 않게 찾을 수 있습니다. concurrent_vector에 대해서 좀 더 알고 싶은
분들은 Intel의 TBB에 대해서 알아보시면 좋을 것 같습니다.
Web.config 파일은 웹 어플리케이션을 위한 구성정보를 포함하고 있는데, AJAX, 라우팅, IIS 7과 함께 인티그레이션 같은 새로운 특징들이 추가되었기 때문에 닷넷 프레임워크의 과거 일부 릴리즈들 보다 꽤 늘어났습니다. 이것은 비쥬얼 스튜디오 같은 툴 없이 새로운 웹어플리케이션을 구성하거나 시작하는데 더 어렵게 만들었습니다. 닷넷 프레임워크 4에서 주요한 구성정보들은 machine.config 파일로 이동하게 되었고, 어플리케이션들은 지금 이 설정들을 상속합니다. 이것은 빈 공간으로 남겨 두던지 아니면 단지 어플리케이션이 목표로하는 프레임워크의 버전이 무엇인지를 비주얼 스튜디오를 위하여 명시하는 다음의 줄들을 ASP.NET 4 어플리케이션들 안의 Web.config에 남겨주기만 하면 됩니다.
ASP.NET 1.0이 배포 되었을때 부터, 아웃풋 캐싱은 개발자들이 발생된 출력 페이지, 컨트롤, HTTP 리스펀스를 메모리 안에 저장할 수 있게 하였습니다. 다음 웹의 요청에서 ASP.NET은 스크래치로 부터 출력을 다시 발생하는 것 대신에 메모리로부터 발생된 출력을 찾는 것에 의하여 훨씬 빠르게 내용을 처리합니다. 그러나, 이 접근은 제한이 있다. - 발생된 내용은 항상 메모리와 무거은 트래픽을 경험하고 있는 서버상에서 저장 되어져야 하고, 아웃풋 캐싱에 의하여 소비된 메모리는 다른 웹 어플리케이션으로 부터 메모리 수요를 경쟁 할 수 있습니다.
ASP.NET 4는 당신이 하나 또는 더 많은 커스텀 아웃풋 캐시 공급자들을 설정할 수 있게 아웃풋 캐싱에 확장성을 더했다. 아웃풋 캐쉬 공급자들은 HTML 지속하기 위한 저장 메커니즘을 사용 할 수 있습니다. 이것은 로컬 혹은 원격 디스크, 클라우드 스토리지, 그리고 분산 캐쉬 엔진을 포함 할 수 있는 다른 종류의 지속성있는 메커니즘을 위하여 커스텀 아웃풋 캐쉬 공급자들이 가능하도록 하였습니다.
당신은 새로운 System.Web.Caching.OutputCacheProvider 타입으로 부터 상속한 클래스로 custom output-cache provider를 만듭니다. 그리고 Web.config 파일 안에 outputCache 요소의 새로운 하부 공급자를 사용해서 그 생성자를 구성 할 수 있습니다. 다음의 예를 보세요.
ASP.NET 4에서 기본으로, 모든 HTTP 응답들, 랜더된 페이지들 그리고 컨틀롤들은 인메모리 아웃풋 캐쉬를 사용합니다. 앞의 예를 보면 defaultProvider 특성이 AspNetInternalProvider 으로 설정되어 있는 것을 볼 수 있습니다. 당신은 웹어플리케이션을 위해 사용된 default output-cache 공급자를 바꿀 수 있습니다. 그 방법은 defaultProvider 를 위한 다른 공급자이름을 구체화하는 것입됩니다.
덧붙여, 당신은 컨트롤당, 요청당 다른 다른 아웃풋 캐쉬 공급자들을 선택할 수 있습니다. 다른 웹 사용자 컨트롤들을 위해 다른 아웃풋캐쉬 공급자들을 선택하는 가장 쉬운 방법이 있습니다. 그것은 페이지 혹은 가리키는 컨트롤안에 새로운 providerName 특성을 선언적으로 사용하는 것입니다. 다음의 예를 보세요.
HTTP 요청들을 위한 다른 아웃풋캐쉬 공급자를 구체화하는 것은 약간 더 작업이 필요합니다. 선언적으로 그 공급자를 구체화하는것 대신에, 당신은 특별한 요청을 위해 사용할 공급자를 프로그래밍적으로 구체화하기 위한 Global.asax 파일 안에 새로운 GetOuputCacheProviderName 매소드를 오버라이드 하는 것으로 대신합니다. 다음의 예를 이것을 사용하는 법을 보여줍니다.
public override string GetOutputCacheProviderName(HttpContext context)
{
if (context.Request.Path.EndsWith("Advanced.aspx"))
return "DiskCache";
else
return base.GetOutputCacheProviderName(context);
}
ASP.NET 4에서 아웃풋캐쉬 공급자의 확장성으로, 당신은 지금 당신의 웹사이트들을 위한 더 적극적이고 더 영리한 아웃풋캐싱 전략을 추구할 수 있습니다. 예를들어, 그것은 디스크 상의 낮은 트래픽으로 얻은 페이지들을 캐싱하는동안 메모리 안에서 사이트의 Top 10 페이지를 캐쉬 할 수 있습니다.
어떤 웹 어플리케이션은 많은양의 데이타를 로드하고, 처음 요청을 처리하기 전에 값비싼 초기화 처리를 수행할 필요가 있습니다. ASP.NET의 초기버전에서 이러한 상황을 위하여, 당신은 ASP.NET 어플리케이션을 깨우기 위하여 커스텀 접근을 고안해야만 했습니다. 그런 다음에 Global.asax에서 Application_Load 매소드 동안 초기화 코드를 실행하였습니다.
이 시나리오는 직접적으로 지정하는 auto-start 라는 새로운 확장성있는 특징이 가능합니다. 단 ASP.NET이 Windows Server 2008 R2, IIS7.5 환경에서 작동할 때입니다. 그 auto-start 특징은 어플리케이션 풀을 시작하고, ASP.NET 어플리케이션을 초기화하고, HTTP 요청을 접수하는 동안 제어된 접근을 제공한다. auto-start 특징을 사용하기위하여, IIS 관리자는 applicationHost.config 파일에서 다음의 컨피그레이션을 사용하는것에 의하여 자동적으로 시작되기위하여 IIS7.5에서 어플리케이션 풀을 설정합니다.
IIS 7.5 서버가 콜드 스타트 되었거나 개별 어플리케이션 풀이 리사이클링 되었을 때, IIS7.5는 웹어플리케이션이 자동적으로 시작되는 것을 결정하기 위하여 applicationHost에서 그 정보를 사용합니다. 자동 시작을 위하여 기록된 각 어플리케이션을 위하여, IIS7.5는 ASP.NET에 요청을 보냅니다. 그것은 어플리케이션을 임시적으로 HTTP요청을 받아들이지 않는 동안의 상태에서 어플리케이션을 시작하기 위해서입니다. 그것이 이상태에 있을 때, ASP.NET은 preloadProvider 특성에 의하여 정의된 타입을 예를들어 보여주고(이전의 예에서 보여주었을 때), 그것의 public 엔트리 포인트를 부릅니다. 당신이 관리된 자동시작형을 필수적인 엔트리 포인트와 함께 아래 예처럼 IProcessHostPreloadClient interface 를 실행하는것에 의하여 창조합니다.
public class CustomInitialization : System.Web.Hosting.IProcessHostPreloadClient
{
public void Preload(string[] parameters)
{
// Perform initialization.
}
}
당신의 초기화 코드가 Preload 매소드에서 실행되고 메소드가 반환한 후에, ASP.NET 어플리케이션은 요청을 처리할 준비가 되어 있습니다. IIS5와 ASP.NET에서 자동시작 추가를 위해, 당신은 지금 처음 HTTP 요청을 처리하기 전에 값비싼 어플리케이션 초기화를 수행하는 것을 위해 잘 정의된 접근을 해야합니다. 예를 들어, 당신은 어플리케이션을 초기화하기 위한 새로운 자동시작 특징을 사용할 수 있고, 그런 다음에 어플리케이션이 초기화되고 HTTP 트래픽을 받을 준비하는 로드 밸런서에 신호를 보낼 수 있습니다.
검색 엔진에서 한물간 링크의 축적을 이끌 수 있는 시간이 지나 페이지나 다른 내용으로 이동하는 것은 웹어플리케이션에서의 공통적인 실행입니다. ASP.NET에서 개발자들은 전통적으로 새로운 URL로 요청을 포워딩하기 위하여 Response.Redirect 함수를 사용하여 오래된 URL 에서의 요청을 처리하였습니다. 그러나, Redirect 함수는 HTTP 302 Found(임시적 리다이렉트) 응답이라는 문제가 발생했습니다. 그 문제는 오래된 URL로 사용자들이 접근을 시도했을 때 여분의 HTTP 왕복에서 발생하였습니다.
ASP.NET 4는 다음의 예로 HTTP 301 Moved Permanently 응답 문제를 해결한 새로운 RedirectPermanent 도우미 함수를 추가했습니다:
RedirectPermanent("/newpath/foroldcontent.aspx");
영구적인 리다이렉트를 인정하는 검색 엔진과 다른 사용자 에이전트들은 그 내용을 포함하는 새로운 URL을 저장할 것이다. 그 내용은 임시 리다이렉트를 위한 브라우저에 의새러 불필요한 왕복을 제거한 것이다.
The Incredible Shrinking Session State (놀랍게 감소하는 세션상태)
ASP.NET은 웹 팜에서 세션 상태를 저장하기 위한 두 가지 기본 옵션을 제공합니다: 하나는 외부 프로세스의 세션 상태 서버를 요청하는 세션상태 제공자이고, 다른 하나는 MS-SQL 서버 데이터 베이스에서 데이터를 저장하는 세션상태 제공자입니다. 왜냐하면 두 옵션은 웹 어플리케이션의 작업자 프로세스 밖에서 상태 정보를 저장하는 것을 포함하는데, 세션 상태는 그것이 원거리 스토리지에 보내기 전에 연속 진행되어야 합니다. 개발자가 세션 상태에 꽤 많은 정보를 저장하는것에 의존하면서, 시리얼라이즈 된 데이터의 양이 아주 많이 성장할 수 있습니다.
ASP.NET 4는 두 종류의 외부프로세스 세션 상태 제공자를 위한 새로운 압축 옵션을 소개합니다. 다음의 예에서 보여진 CompressionEnabled 확인 옵션이 true로 설정 되었을 때, ASP.NET은 .NET Framework System.IO.Compression.GZipStream 클래스를 사용하는 것에 의하여 시리얼라이즈된 세션 상태를 압축할 것입니다.
ASP.NET 4은 어플리케이션의 URL의 길이를 확장하기 위한 새로운 옵션을 소개합니다. 이전 버전의 ASP.NET 은 URL경로 길이들이 (NTFS 파일 경로 제한에 기반한) 260 문자로 제한했습니다. ASP.NET 4에서 당신은 두가지 새로운 httpRuntime configuration 특성을 사용해서 당신의 어플리케이션을 위해 적절하게 이 제한을 증가 혹은 감소시키는 옵션을 사용할 수 있습니다.
(프로토콜, 서버이름, 쿼리스트링을 포함하지 않는 URL의 일부)경로를 더 길게 혹은 짧게 하기 위하여, maxRequestPathLength 특성을 수정합니다. 쿼리스트링을 더 길게 혹은 더 짧게 하기 위해서, maxQueryStringLength 특성의 값을 수정합니다.
ASP.NET 4 는 또한 URL문자 체크에 의하여 사용된 문자들을 당신이 확인 할 수 있게 합니다. ASP.NET 4 URL 경로 부분 안에서 잘못된 문자를 찾았을 때, 그것은 그 요청을 거절하고, HTTP 400 에러를 발생합니다. 이전 버전의 ASP.NET 4에서, URL문자 체크는 문자들의 고정된 셋의 문자들로 제한되어졌다. ASP.NET 4 에서 당신은 다음의 예를보면 httpRuntime configuration 요소의 새로운 requestPathInvalidChars 특성을 사용하여 유효한 문자 집단을 커스터마이즈 할 수 있습니다.
기본적으로 requestPathInvalidChars 특성은 올바르지 않은 것으로 7개의 문자들로 정의한다. ( 디폴트로 requestPathInvalidChars 에 정의된 문자열에서, '<','>','&' 문자들은 엔코딩 된다. 왜냐하면 Web.config 파일은 XML 파일이기 때문이다.)
당신은 필요에 따라 유효한 문자 집단을 커스터마이즈 할 수 있다.
Note: ASP.NET 4는 0x00에서 0x1F의 ASCII 영역에서의 문자들을 포함하는 URL경로를 거절합니다. 왜냐하면 그것들은 IETF의 RFC 2396 안에서 정의된 올바르지 않은 URL 문잘열들입니다. (http://www.ietf.org/rfc/rfc2396.txt). IIS 6을 운영하는 윈도우즈 서버 버전 혹은 그 이상에서, http.sys 프로토콜 디바이스 드라이버는 자동적으로 이 문자들과 함께 URL들을 거절합니다.
ASP.NET 요청 유효성은 XSS 공격에서 공통적으로 사용되는 문자열을 위하여 들어오는 HTTP 요청 데이터를 검색합니다. 만약 잠재적인 XSS 문자열이 발견된다면, 요청 유효성이 의심스러운 문자열을 알리고 에러를 반환한다. 내장 요청 유효성검사는 그것이 XSS 공격에서 사용된 가장 공통적인 문자열들을 찾았을 때, 단지 에러를 반환합니다. 더 공격적인 XSS 유효성 검사를 만들기 위한 이전의 시도는 매우 잘못된 상황을 야기시켰습니다. 그러나, 소비자들은 더 적극적인 요청 유효성 검사를 원하거나, 거꾸로 의도적으로 특별한 페이지 혹은 특별한 형태의 요청들을 위한 느슨한 XSS 검사를 원했습니다.
ASP.NET 4에서의 요청 유효성검사의 특징은 확장성이 있어서, 당신이 맞춤형 요청 유효성 검사 로직을 사용할 수 있습니다. 요청 유효성 검사를 확장하기 위하여, 당신은 새로운 System.Web.Util.RequestValidator 타입으로부터 상속 받는 클래스를 창조 할 수 있다. 그리고 당신은 맞춤형 타입을 사용하기 위하여 Web.config 파일의 httpRuntime 에서 어플리케이션을 설정합니다. 다음의 예는 커스텀 리퀘스트 유효성검사 클래스를 확인하는 법을 보여줍니다.
새로운 requestValidationType 의 특성은 스탠다드 닷넷 프레임워크 타입의 식별자 문자열을 요구한다. 그 식별자 문자열은 맞춤형 요청 유효성검사를 제공하는 클래스를 구체화하는 역할을 합니다. 각 요청을 위하여 ASP.NET은 들어오는 각각의 HTTP 요청 데이터를 처리하기위하여 맞춤형 타입을 요청합니다. 들어오는 URL, 모든 HTTP 헤더들(쿠키와 커스텀 헤더들) 그리고 엔티티 바디는 모두 맞춤형 요청 검사에 의한 정밀검사로 모두 가능하게 합니다. 다음 예를 보세요.
public class CustomRequestValidation : RequestValidator
{
protected override bool IsValidRequestString(
HttpContext context, string value,
RequestValidationSource requestValidationSource,
string collectionKey,
out int validationFailureIndex)
{
// ......
}
}
당신이 들어오는 HTTP 데이터를 검사하는 것을 원하지 않는 경우에는, 요청 유효성검사 클래스는 간단하게 base.IsValidRequestString.부르것에 의하여 ASP.NET의 디폴트 요청 유효성 검사가 작동하게 돌아 갈 수 있습니다.
첫 배포이후, ASP.NET은 강력한 인 메모리 객체 캐쉬(System.Web.Caching.Cache)를 포함했습니다. 그 캐쉬 실행은 매우 있기 있어서 웹어플리케이션이 아닌 곳에서도 사용되었습니다. 그러나 윈도우즈 폼 혹은 WPF 어플리케이션 ASP.NET의 객체 캐쉬를 사용 가능하게 한 System.Web.dll에서 참조하는 것은 어설펐습니다.
모든 어플리케이션들이 캐싱을 가능하게 하기위하여, 닷넷 프레임워크 4는 새로운 어셈블리, 새로운 네임스페이스, 베이스 타입, 실제적인 캐싱 실행을 소개합니다. 새로운 System.Runtime.Caching.dll 어셈블리는 새로운 System.Runtime.Caching 네임스페이스에서 새로운 캐싱 API를 포함합니다.
새로운 MemoryCache 클래스는 ASP.NET 캐쉬에 가깝게 만들어 졌고, 그것은 ASP.NET과 함께 많은 양의 내부 캐쉬 엔진 로직을 공유합니다. 비록 System.Runtime.Caching 안의 퍼블릭 캐싱 API들이 맞춤형 캐쉬들의 개발을 지원하기 위하여 업데이트 되었더라도, 당신이 ASP.NET 캐쉬 객체를 사용했다면, 당신은 새로운 API들에서 비슷한 개념을 찾을 것입니다. 새로운 MemoryCache 와 제공하는 기초 API들에 대한 면밀한 논의는 완벽한 문서를 요구할 것입니다. 그러나 다음의 예는 당신에게 새로운 캐쉬 API 어떻게 작동하는 지 알려줍니다. System.Web.dll 의존 없는 윈도우즈 폼을 위한 예입니다.
private void btnGet_Click(object sender, EventArgs e)
{
//Obtain a reference to the default MemoryCache instance.
//Note that you can create multiple MemoryCache(s) inside
//of a single application.
ObjectCache cache = MemoryCache.Default;
//In this example the cache is storing the contents of a file string
fileContents = cache["filecontents"] as string;
//If the file contents are not currently in the cache, then
//the contents are read from disk and placed in the cache.
if (fileContents == null)
{
//A CacheItemPolicy object holds all the pieces of cache
//dependency and cache expiration metadata related to a single
//cache entry.
CacheItemPolicy policy = new CacheItemPolicy();
//Build up the information necessary to create a file dependency.
//In this case we just need the file path of the file on disk.
List<string> filePaths = new List<string>();
filePaths.Add("c:\\data.txt");
//In the new cache API, dependencies are called "change monitors".
//For this example we want the cache entry to be automatically expired
//if the contents on disk change. A HostFileChangeMonitor provides
//this functionality.
policy.ChangeMonitors.Add(new HostFileChangeMonitor(filePaths));
//Fetch the file's contents
fileContents = File.ReadAllText("c:\\data.txt");
//And then store the file's contents in the cache
cache.Set("filecontents", fileContents, policy);
}
MessageBox.Show(fileContents);
}
Extensible HTML, URL, and HTTP Header Encoding
(확작성있는 HTML, URL 그리고 HTTP 헤더 엔코딩)
ASP.NET 4 에서 당신은 다음의 공통 텍스트-엔코딩 일을 위한 커스텀 엔코딩 루틴들을 창조 할 수 있습니다: HTML 엔코딩; URL 엔코딩; HTML 특성 엔코딩; 그리고 외부 HTTP 헤더들의 엔코딩. 당신은 새로운 System.Web.Util.HttpEncoder 타입으로 부터 상속받는 것과 Web.config 파일의 httpRuntime 섹션안에 커스텀 타입을 사용하기 위한 ASP.NET을 구성하는 것 에 의한 커스텀 엔코더를 창조 할 수 있습니다. 다음 예를 보세요.
커스텀 엔코더가 구성된 후에, ASP.NET은 자동적으로 public ASP.NET 엔코딩 함수인 System.Web.HttpUtility 혹은 System.Web.HttpServerUtility 클래스들이 불리어질 때마다 커스텀 엔코딩 실행을 호출합니다. 이것은 일부의 웹 개발팀이 적극적인 문자 엔코딩을 실행할 커스텀 엔코더를 창조할 수 있게 합니다. 그 동안 쉬는 웹 개발팀은 계속 ASP.NET 엔코딩 API들을 사용합니다. httpRuntime 요소안에 커스텀 엔코더를 중심으로 구성하는 것에 의하여, 당신은 모든 텍스트-엔코더가 public ASP.NET 엔코딩 함수들로부터의 호출들이 커스텀 엔코더를 통하여 라우트되는 것을 보장 받습니다.
하나의 서버상에 호스트 될 수 있는 웹사이트의 수를 증가시키기 위하여, 많은 호스터들은 하나의 작업자 프로세스 안에 다중의 ASP.NET 어플리케이션들을 운영하였습니다. 그러나 다중 어플리케이션들이 하나의 공유된 작업자 프로세스를 사용한다면, 서버 관리자들은 문제를 가지고 있는 개별 어플리케이션들을 확인하기가 어려울 것입니다.
ASP.NET 4는 CLR에 의해 소개된 새로운 자원 모니터링이 기능적으로 영향을 줍니다. 이 기능을 활성화 하기 위해서, 당신은 aspnet.config 구성정보 파일에 다음의 XML 구성정보 조각을 추가 할 수 있습니다.
Note: aspnet.config 파일은 .NET Framework가 인스톨 된 디렉토리 안에 있습니다. 그것은 Web.config 파일에 존재하지 않습니다.
appDomainResourceMonitoring 특징이 활성화 될었을 때, 두 개의 새로운 수행 카운터들이 "ASP.NET Applications" 수행 카테고리 안에서 가능합니다: % Managed Processor Time 와Managed Memory Used. 이 두 수행 카운터들은 새로운 CLR 어플리케이션-도메인 자원 관리 특성을 추정된 CPU 시간과 개별 ASP.NET 어플리케이션의 관리된 메모리 이용을 추적하기 위하여 사용합니다. 결과적으로 ASP.NET 4와 함께, 관리자들은 지금 하나의 작업자 프로세스 안에 동작하는 개별 어플리케이션의 자원 소비를 더 상세하게 볼 수 있습니다.
You can create an application that targets a specific version of the .NET Framework. In ASP.NET 4, a new attribute in the compilation element of the Web.config file lets you target the .NET Framework 4 and later. If you explicitly target the .NET Framework 4, and if you include optional elements in the Web.config file such as the entries for system.codedom, these elements must be correct for the .NET Framework 4. (If you do not explicitly target the .NET Framework 4, the target framework is inferred from the lack of an entry in the Web.config file.)
당신은 .NET Framework 특정 버전을 규정하는 어플리케이션을 창조할 수 있습니다. ASP.NET 4에서 Web.config 파일의 compilation 요소의 새로운 특성은 당신이 .NET Framework 4와 이전버전으로 규정하게 합니다. 당신이 명시적으로 .NET Framework 4를 설정하고, 당신이 system.codedom 위한 입력 같은 것을 Web.config 파일안에 선택적인 요소를 포함한다면, 이 요소들은 .NET Framework 4 위해 잘 작동할 것입니다.(만약 당신이 명시적으로 .NET Framework 4를 설정하지 않는다면, 목표 프레임워크는 Web.config 파일의 부족한 입력으로 추측을 합니다. )
다음의 예는 Web.config 파일의 compilation 요소안의 targetFramework 특성의 사용을 보여줍니다.
<compilation targetFramework="4.0"/>
Note the following about targeting a specific version of the .NET Framework:
.NET Framework의 특정버전을 지정하는 것에 대해 다음을 기억할 것:
만약 Web.config 파일이 targetFramework 특성을 포함하지 않거나 Web.config 파일을 분실했다면 .NET Framework 4 어플리케이션 풀안에서 ASP.NET 빌드 시스템은 목표로 .NET Framework 4를 취할 것입니다.
만약 당신이 targetFramework 특성을 포함하고, system.codeDom 요소가 Web.config 파일안에 적의 되어 있다면, 그 파일은 .NET Framework 4. 위한 올바른 입력을 포함해야합니다.
당신이 (빌드 환경같은)당신의 어플리케이션을 프리컴파일 하기위한 aspnet_compiler 명령어를 사용하고 있다면, 당신은 목표 프레임워크를 위한 aspnet_compiler 의 올바른 버전을 사용해야 합니다. 당신이 (빌드 환경같은)당신의 어플리케이션을 프리컴파일 하기위한 aspnet_compiler 명령어를 사용하고 있다면, 당신은 목표 프레임워크를 위한 aspnet_compiler 의 올바른 버전을 사용해야 합니다. .NET Framework 3.5와 이전 버전을 위해 컴파일하기 위해서 .NET Framework 2.0 (%WINDIR%\Microsoft.NET\Framework\v2.0.50727) 안에 위치한 컴파일러는 사용합니다. 그 프레임워크 혹은 최근 버전에서 창조된 어플리케이션을 컴파일하기 위해서는 .NET Framework 4 안에 위치한 컴파일러는 사용합니다.
At run time, the compiler uses the latest framework assemblies that are installed on the computer (and therefore in the GAC).
런타임에서, 컴파일러가 (GAC 안의 그결과와 )컴퓨터상에 인스톨된 최신 프레임워크 어셈블리들을 사용합니다. (예를 들어, 가상의 버전 4.1이 인스톨 된다면) 업데이트가 나중에 프레임워크에 만들어진다면, 비록 targetFramework 특성이 (4.0 같은) 낮은 버전을 가리키더라도 당신은 새로운 버전의 프레임워크에서 특징들을 사용할 수 있습니다. (그러나 Visual Studio 2010의 설계 시간에 혹은 당신이 당신이 aspnet_compiler 명령어를 사용할 때, 프레임워크의 새로운 특징을 사용하는 것은 컴파일러 에러를 일이킬 것입니다.
- 비동기적으로 자유스러운 리소스 로딩과 관리.
( 이들은 렌더링과 동시에 수행될 수 있어야 한다. )
- 멀티스레드 형식으로 렌더링 커맨드의 생성.
( 여러 스레드로 나누어서 렌더링 작업을 할 수 있어야 한다. )
- 디스플레이 리스트( Display lists )의 지원.
첫번째 리소스와 관련한 것을 지난 시간에 알아보았습니다.
이제는 실제 렌더링 작업에 대해 알아보아야 합니다.
그 실제 렌더링 작업을 위해서 우리는 새롭게 등장한 Deferred Context 라는 것을 살펴볼 것입니다.
이 Deferred Context 가 멀티스레드 기반의 렌더링에서 가장 중요한 키워드입니다.
< Device 의 분리 >
지난 세대의 DirectX는 모든 GPU 관련 내용의 처리는 Device 인터페이스를 통해서 수행했습니다.
즉 지난 회들에서 꾸준히 언급했던 것처럼,
Device 인터페이스를 통해서만 커맨드( Command ) 를 생성할 수 있었습니다.
오직 싱글코어 기반으로 설계된 지난 세대의 DirectX 였기 때문에,
위의 그림과 같은 상황이 연출되었습니다.
이들에 대한 내용은 지난 시간을 통해서 꾸준히 언급되었기 때문에, 더 자세한 언급은 하지 않겠습니다.
Device 인터페이스에 모든 작업이 집중되어 있었기 때문에,
이를 분리할 방법이 필요했습니다.
그 기준은 앞서 언급했듯이,
그래픽카드에 보내는 작업이 Free threaded 한지였습니다.
결론적으로 얘기 드리면 DirectX11 에서는 기존의 Device 가 분리에 분리를 거듭했습니다.
그래서 아래와 같은 구조로 되었습니다.
DirectX11 에서 이제 개발자가 다루어야하는 커맨드 생성 인터페이스는 총 3가지입니다. Device 는 Free threaded 한 API 만 사용하는 인터페이스입니다.
주로 리소스들이 포함됩니다.( 버퍼나 텍스쳐, 쉐이더 등 )
Device Context 는 실제로 렌더링과 관련된 인터페이스입니다.
렌더스테이트의 교체나 Draw 명령을 내리기 위해서는
반드시 Device Context 를 통해서 커맨드를 생성해야 합니다.
더 자세한 사항은 http://vsts2010.net/115 여기를 보시기 바랍니다.^^
Device Context 는 다시 두개로 분리될 수 있습니다.
Immediate Context 와 Deferred Context 가 바로 그것들입니다.
만약 멀티스레드 기반으로 렌더링 하고 싶지 않다면,
Deferred Context 는 사용하지 않으셔도 됩니다.
이 Deferred Context 의 유무가 바로 멀티스레드 기반의 렌더링이냐,
아니면 일반적인 렌더링이냐를 결정합니다.
반면에 Immediate Context 는 반드시 한개만 존재해야 합니다.
이 인터페이스는 실제로 렌더링과 관련된 커맨드를 생성하기도 하지만,
생성된 커맨드를 그래픽 카드로 보내는 일도 합니다.
< Deferred Context >
Deferred Context는 애플리케이션에서 여러개 생성될 수 있습니다. 하나의 스레드에 하나씩 Deferred Context 가 사용될 수 있으며, 이들은 Thread unsafe 합니다.
이렇게 하나의 스레드에 할당되어진 Deferred Context는 Display List 를 생성합니다.
이들은 GPU 가 바로 처리 가능한 커맨드들을 모아둔 버퍼라고 할 수 있습니다.
이렇게 Display List 를 미리 만들어둠으로써 성능을 크게 개선 시킬 수 있습니다.
일반적으로, CPU 가 커맨드를 생성시키는 시간이 꽤 오래 걸리기 때문입니다.
( 생성될 커맨드가 변화가 없다면, 이렇게 미리 만들어 두면 크게 도움이 되겠죠? ^^ )
사실 위의 그림은 개념적인 것입니다.
실제 소스레벨에서 Deferred Context 를 가리키는 인터페이스는 별도로 존재하지 않습니다.
Immediate Context 를 가리키는 인터페이스는 ID3D11DeviceContext 입니다.
Deferred Context 를 가리키는 인터페이스도 ID3D11DeviceContext 입니다.
즉, 둘 다 동일한 인터페이스를 통해서 처리되고 있는 것입니다.
실제 멤버 변수 선언들을 조금 나열해 보면 다음과 같습니다.
동일한 인터페이스 선언을 확인하셨습니까?
하지만 인터페이스가 동일하다고 해서, 이를 동일하게 생각해서는 안됩니다.
동일한 인터페이스를 사용하는 이유는 Deferred Context 는 Immediate Context 의 모든 기능을 지원한다는 의미로 받아들여야 합니다.
결과적으로 Device Context 는 아래의 그림과 같은 구조로 확장될 수 있습니다.
멀티스레드 기반으로 렌더링을 한다는 것은 엄밀히 말해서는 지원하지 않습니다.
정확히 말하자면, 멀티스레드 기반으로 커맨드를 생성해서
이들을 순차적으로 그래픽 카드로 보냅니다.
위의 그림이 이를 잘 표현하고 있습니다.
Deferred Context 는 각각의 스레드에 의해서 DisplayList 를 생성하고,
이들을 그래픽 카드에 보내기 위해 버퍼에 저장합니다.
그리고 실제로 그래픽카드에 커맨드를 보내기 위해서는
반드시 Immediate Context 를 통해야 합니다.
이때 Immediate Context 를 통해서 직접적으로 커맨드를 생성시킬 수 있습니다.
아무래도 렌더링이라는 작업은 순간순간의 렌더링 상태들에 의해서
결과가 변하기 때문에, 최종적으로 전송하는 작업만큼은 순차적으로 설계한 듯 합니다.
이로써 우리는 Deferred Context 를 사용할 준비가 되었습니다.^^
댓글을 달아 주세요
글 잘 쓰시는데요^^ 잘 읽었습니당.
네이티브(unmanaged)코드 와의 성능 비교에 대해서 좋은글이 있어서 참고로 달겠습니다. 관심있으신 분들은 참고하세영~.
http://www.grimes.demon.co.uk/dotnet/man_unman.htm
http://www.codinghorror.com/blog/archives/000234.html
여러모로 서투르고 부족한데 칭찬해주시니까 부끄럽네요. ㅎㅎ 감사합니다.
비밀댓글 입니다