Search

'분류 전체보기'에 해당되는 글 671건

  1. 2010.09.30 SharePoint 2010 Developer Dashboard
  2. 2010.09.29 [STL] 6. <algorithm>에 추가된 새로운 함수들 all_of, any_of, none_of (2/5) 2
  3. 2010.09.27 ASP.NET 4 와 Visual Studio 2010 Web Development Beta 2 Overview - Web Forms(3)
  4. 2010.09.27 Concurrency Runtime – Task Scheduler 3. ( ScheduleGroup ) 1
  5. 2010.09.24 [Step. 15] static 생성자, initonly, literal 1
  6. 2010.09.20 [알콜코더의 미리 배워보는 DirectX11-입문편] 1.튜터리얼 01 : 다이렉트 3D 기초 #2
  7. 2010.09.18 Concurrency Runtime – Task Scheduler 2. ( SchedulerPolicy )
  8. 2010.09.17 KGC10에서의 VS2010 스터디 팀의 활약 모습
  9. 2010.09.10 [Step. 13] parameter array 1
  10. 2010.09.08 9월 13일에 개최하는 KGC에서 강연을 합니다.
  11. 2010.09.08 [알콜코더의 미리 배워보는 DirectX11-입문편] 1.튜터리얼 01 : 다이렉트 3D 기초 #1 11
  12. 2010.09.07 [세미나] Visual Studio Seminar #1 / 2010년 9월 28일 1
  13. 2010.09.06 Windows Azure Update: myAzureStorage
  14. 2010.09.06 WCF Security (2) - 전송 계층에서의 메세지 인증 (사용자 지정 인증)
  15. 2010.09.06 [세미나 발표 자료] Visual Studio Camp #1
  16. 2010.09.04 Hello Windows Azure / Twitter 스타일 방명록 만들기 #3
  17. 2010.09.03 [Step. 12] for each 1
  18. 2010.09.02 [ALM-Test] 6. Load Runner vs Visual Studio 2010 테스팅 비교 분석 - http://willstory.tistory.com/4 제공 1
  19. 2010.09.02 Concurrency Runtime – Task Scheduler 1. ( Scheduler )
  20. 2010.08.31 SharePoint 2010 프로젝트 디버깅

SharePoint 2010 Developer Dashboard

SharePoint 2010 2010. 9. 30. 22:18 Posted by 알 수 없는 사용자

ASP.NET Trace와 유사하게 SharePoint 2010의 웹 페이지를 Trace 할 수 있는 기능을 제공해주고 있는데 이를 Developer Dashboard 라고 합니다.

기본값은 Off 이며 필요할 경우 Power Shell이나 Stsadm을 이용하여 On, OnDemand 두 가지 방식으로 Developer Dashboard를 사용할 수 있습니다. C# 코드로도 On 시킬 수 있습니다.

개발자들이 만든 웹 파트의 성능 문제, 병목을 찾아낸다거나 할 경우 아주 유용하게 사용이 가능합니다.

아래는 C# 코드로 Developer Dashboard On 시키고 있습니다. 사용을 완료했으면 Off 시키면 됩니다. 또는 OnDemand 모드로 Update 할 수 도 있습니다.


Developer Dashboard
On 시켰을 경우 아래와 같은 결과를 웹 페이지에서 살펴볼 수 있습니다.

속도, 이벤트, SQL 쿼리 문까지 볼 수 있습니다.


아래는 Developer DashboardOnDemand 모드로 사용하는 경우입니다. SharePoint 사이트의 맨 위 오른쪽에 작업 관리자의 성능 그래프와 같은 이미지를 볼 수 있으며 클릭할 경우 Developer Dashboard 결과를 확인할 수 있습니다.

아래는 SharePoint 2010의 관리 셀을 이용해서 Power Shell을 통해 Developer Dashboard를 액세스하고 있습니다.


전체 구문은 아래와 같습니다.

$devdashboard =[Microsoft.SharePoint.Administration.SPWebService]::ContentService.DeveloperDashboardSettings

$devdashboard.DisplayLevel = 'OnDemand'; 

$devdashboard.Update()

성능 측정이나 병목 현상의 원인을 파악할 경우 Developer Dashboard를 이용할 수 있습니다.


'SharePoint 2010' 카테고리의 다른 글

SharePoint 2010에서의 대화상자(Dialog) (1)  (0) 2011.02.02
SharePoint 2010에서의 Ribbon  (0) 2011.01.26
SharePoint 2010 프로젝트 디버깅  (0) 2010.08.31
REST - jQuery  (0) 2010.08.30
REST – Silverlight  (0) 2010.07.30
안녕하세요. 방수철입니다.
다들 즐거운 한가위를 보내셨는지 궁금하세요.
저는 여러모로 바쁜일이 추석 직전까지 있어서 정신 없이 시간을 보내고 푹 쉬다가
다시 글을 쓰게 됬습니다. 이전 글과 비교해서 너무 오래동안 글이 없었네요.
혹여 기다리신 분들이 있다면 죄송합니다.

이번 글에서는 all_of, any_of, none_of 에 대해서 설명하겠습니다.
이 세가지 함수는 VS2010에서 새로이 <algorithm> 에 추가되었습니다.
이 함수들은 반복자로 탐색이 가능한 구조체에서 특정 조건을 만족하는 원소가 있는지 확인하는 기능을 합니다.

template <class InputIterator, class Predicate>
  bool none_of(InputIterator first, InputIterator last, Predicate pred);

template <class InputIterator, class Predicate>
  bool any_of(InputIterator first, InputIterator last, Predicate pred);

template <class InputIterator, class Predicate>
  bool all_of(InputIterator first, InputIterator last, Predicate pred);

위와 같이 정의된 함수들은 똑같이 세가지 인수를 입력으로 받습니다.

first : 조건을 만족하는지 시험할 범위의 시작 위치의 반복자
last : 조건을 만족하는지 시험할 범위의 마지막 위치의 반복자
pred : 조건을 만족하는지 시험할 때에 사용되는 function 객체. 반드시 한개의 인수만을 전달받아야 하며 true또는 false를 반환해야 한다.

이렇게 인수가 주어질때에 각각의 함수는 다음과 같이 반환하게 됩니다.

all_of : 주어진 범위에서 모든 원소들이 조건을 만족하면 true, 그렇지 않으면 false를 반환한다.
any_of :
주어진 범위에서 한개 이상의 원소들이 조건을 만족하면 true, 그렇지 않으면 false를 반환한다.
none_of :
주어진 범위에서 모든 소들이 조건을 만족하지 않으면 true, 그렇지 않으면 false를 반환한다.

다음의 코드는 numbers라는 배열의 값을 여러 조건식으로 all_of, any_of, none_of를 실행시켜본 것이다.

    array<int,5> numbers = {2, 3, 4, 6, 7};

    auto isPositive = [](int n) { return n > 0; };
    auto isNegative = [](int n) { return n < 0; };
    auto isZero     = [](int n) { return n == 0; };
    auto isEven     = [](int n) { return n % 2 == 0; };
    auto isOdd      = [](int n) { return n % 2 != 0; };

    array<function<bool(int)>, 5> func = {isPositive, isNegative, isZero, isEven, isOdd};
    array<std::string, 5> desc = {"isPositive",
                                  "isNegative", 
                                  "isZero    ", 
                                  "isEven    ", 
                                  "isOdd     " };

    cout<<"The list is { ";
    for_each(numbers.begin(), numbers.end(), [](int n){ cout<<n<<", ";});
    cout<<"}"<<endl;

    cout << "\t\tall_of\tany_of\tnone_of"<<endl;

    for(int i = 0 ; i<5 ; ++i )
    {
        cout << desc[i].c_str() << "\t";
        cout << all_of(numbers.begin(), numbers.end(), func[i]) << "\t";
        cout << any_of(numbers.begin(), numbers.end(), func[i]) << "\t";
        cout << none_of(numbers.begin(), numbers.end(), func[i]) << "\t";
        cout << endl;
    }


아래는 실행 결과입니다.


위의 코드에서 조건식을 변환해본다거나, 주어지는 숫자의 배열에 변화를 줘가면서 테스트를 해보면 더 쉽게 이해 될 것 입니다.

Routing in ASP.NET 4

ASP.NET 4 는 웹폼에서 라우팅하는 것을 사용하기 위한 지원이 추가로 내장되었습니다. 라우팅은 당신이 요청한  URL 들을 받아들이기위한 어플리케이션을 확인하게 합니다. 그 URL들은 물리적 파일경로를 보여주지 않습니다. 대신에, 당신은 사용자들에게 의미있고, 당신의 어플리케이션을 위한 검색엔진 옵티마이저에 도움을 줄 수 있는 URL로 정의하여 라우팅을 사용 할 수 있습니다. 예를들어,  존재하고 있는 어플리케이션안에서 제품 종류를 보여주는 페이지를 위한 URL은 다음의 예와 같이 보여 줄 수 있습니다.

http://website/products.aspx?categoryid=12

라우팅을 사용사면, 당신은 같은 정보를 랜더링하기 위하여 다음의 URL을 받아들이기 위하여 어플리케이션을 확인 할 수 있습니다.

http://website/products/software

라우팅은 ASP.NET 3.5 SP1 에서 사용이 가능했습니다. (ASP.NET 3.5 SP1 에서 라우팅을 사용하는 방법에 대한 예는, Phil Haack의 블로그의 Using Routing With WebForms 에 들어가 보세요) 그러나, ASP.NET 4은 라우팅을 사용하기 더 쉽게 만들어진 다음의 몇가지 특징이 있습니다.

  • PageRouteHandler  클래스는 당신이 경로를 정의할 때 사용하는 간단한 HTTP 핸들러입니다.
  • HttpRequest.RequestContext  과Page.RouteData(HttpRequest.RequestContext.RouteData 객체를 위한 대리의 것) 새로운 속성. 이 속성들은 경로로 부터 통과되었을 때의 정보에 접근을 더 쉽게 합니다.
  • System.Web.Compilation.RouteUrlExpressionBuilderSystem.Web.Compilation.RouteValueExpressionBuilder 안에 정의된 다음의 새로운 표현의 빌더들
    • RouteUrl 은 ASP.NET 서버 컨트롤에서 경로 URL 형식에 일치하는 URL을 창조하는 간단한 방법을 제공한다.
    • RouteValue RouteContext 객체로 부터 정보를 추출하여 간단한 방법으로 제공한다.
  • RouteParameter 클래스는 데이터 소스 컨트롤을 위한 쿼리에서 RouteContext 객체안에 포함된 데이터를 넘기기 쉽게 합니다.(FormParameter 에서 유사하다).

 

Routing for Web Forms Pages

다음의 예는 Route 클래스의 새로운 MapPageRoute  매소드를 사용하는 것에 의하여 웹폼 라우트를 정의하는 법을 보여줍니다:

public class Global : System.Web.HttpApplication
{
  void Application_Start(object sender, EventArgs e)
  {
    RouteTable.Routes.MapPageRoute("SearchRoute",
      "search/{searchterm}", "~/search.aspx");
    RouteTable.Routes.MapPageRoute("UserRoute",
      "users/{username}", "~/users.aspx");
  }
}

ASP.NET 4 는 MapPageRoute 매소드를 소개합니다. 다음의 예는 이전의 예에서 보여준 SearchRoute 정의와 같습니다. 그러나 PageRouteHandler 클래스를 사용합니다. 

RouteTable.Routes.Add("SearchRoute", new Route("search/{searchterm}",
  new PageRouteHandler("~/search.aspx")));

예시 코드는 물리적 페이지에서 경로는 보여줍니다(첫번째 라우트안에서, ~/search.aspx 로). 첫번째 라우트 정의는 또한 searchterm 이라고 이름지어진 파라미터는 URL로 부터 추출 되어지고, 페이지로 넘겨지게 되는 것을 명시합니다.

MapPageRoute 매소드는 다음의 매소드 오버로드를 지원합니다:

  • MapPageRoute(string routeName, string routeUrl, string physicalFile, bool checkPhysicalUrlAccess)
  • MapPageRoute(string routeName, string routeUrl, string physicalFile, bool checkPhysicalUrlAccess, RouteValueDictionary defaults)
  • MapPageRoute(string routeName, string routeUrl, string physicalFile, bool checkPhysicalUrlAccess, RouteValueDictionary defaults, RouteValueDictionary constraints)

checkPhysicalUrlAccess 파라미터는 다음을 명시합니다. 그것은 라우트된 물리적 페이지(이 때는 search.aspx)를 위한 보안 승인과 들어오는 URL(이 때는 search/{searchterm})의 승인을 체크해야 되는지입니다. checkPhysicalUrlAccess 의 값이 false 라면, 단지 들어오는 URL의 승인만 체크 될 것입니다. 이 승인은 다음과 같은 설정으로 Web.config 파일안에서 정의 됩니다.

<configuration>
  <location path="search.aspx">
    <system.web>
      <authorization>
        <allow roles="admin"/>
        <deny users="*"/>
      </authorization>
    </system.web>
  </location>
  <location path="search">
    <system.web>
      <authorization>
        <allow users="*"/>
      </authorization>
    </system.web>
  </location>
</configuration>
 

예시의환경설정에서, admin권한을 가진 사람들을 제외하고 모든 사용자들은 물리적 페이지 search.aspx 에 접근이
거부됩니다.
checkPhysicalUrlAccess 파라미터가 true (기본 값)로 설정 되었을 때, 단지 admin 사용자가 URL /search/{searchterm} 에 접근이 허용됩니다. 왜냐하면 물리적 페이지 search.aspx는 그 역할안에 있는 사용자들에게 제한이 됩니다. checkPhysicalUrlAccessfalse 로 설정되고 그 사이트가 이전 예에서 보여준것 처럼 환경설정이 되어 있다면, 모든 권한받은 사용자들이 URL /search/{searchterm}에 접근이 허용됩니다.

Reading Routing Information in a Web Forms Page

웹폼의 물리적 페이지상의 코드에서 당신은 두 가지 새로운 속성을 사용하는 것에 의하여 라우팅이 URL(혹은 다른 객체가 RouteData 객체에 추가한 다른 정보)로 부터 추출한 정보에 접근 할 수 있습니다: HttpRequest.RequestContextPage.RouteData. (Page.RouteData wraps HttpRequest.RequestContext.RouteData.) 다음의 예는 Page.RouteData 를 사용하는 법을 보여줍니다.

protected void Page_Load(object sender, EventArgs e)
{
  string searchterm = Page.RouteData.Values["searchterm"] as string;
  label1.Text = searchterm;
}

예시의 라우트는 더 쉽게 정의 됨으로써, 그 코드는 searchterm 파라미터를 위하여 넘겨진 값을 추출합니다. 다음의 요청 URL을 고려해 봅시다:

http://localhost/search/scott/

이 요청이 만들어 졌을 때 "scott"이라는 단어는 search.aspx 페이지안에 랜더링 될 것입니다.

Accessing Routing Information in Markup

이전의 섹션에서 설명된 매소드는 웹폼 페이지 상의 코드에서 라우트 데이터를 얻는 법을 보여주었습니다. 당신은 또한 마크업 안에 표현들을 사용할 수 있는데, 그 마크업은 당신이 같은 정보에 접근할 수 있게 합니다. Expression builders는 "ASP.NET의 숨겨진 보석"으로 설명되어 졌습니다. (Phil Haack의 블로그의 Express Yourself With Custom Expression Builders 에 들어가 보세요). 아주 불행하게도 그것들은 잘 알려지지 않았습니다. 왜냐하면 표현 빌더들은 명령형 코드와 함께 작업하기 강력하고 센련되었기 때문입니다.

ASP.NET 4는 웹폼 라우팅을 위한 두 가지의 새로운 표현 빌더들을 포함합니다. 다음의 예는 그것들을 사용하는 방법을 보여줍니다.

<asp:HyperLink ID="HyperLink1" runat="server"
  NavigateUrl="<%$RouteUrl:SearchTerm=scott%>">Search for Scott</asp:HyperLink>

예제에서, RouteUrl  표현은 라우트 파라미터에 기반한 URL을 정의하기 위하여 사용되었습니다. 이것은 마크업으로 완전한 URL을 하드코드 해야하는 것으로 부터 당신을 구해줍니다. 그리고 당신이 이 링크에서 변화를 요청하는 것 없이 후에 URL 구조를 바꿀 수 있게 합니다.

더 쉽게 라우트를 정의하게 되면서, 이 마크업은 다음의 URL을 발생합니다.

http://localhost/search/scott

ASP.NET은 자동적으로 인풋 파라미터에 기반해서 올바른 라우트(즉, 올바른 URL을 발생합니다)로 동작합니다. 당신은 또한 표현 안에 라우트 이름을 포함 할 수 있습니다. 그것은 사용할 라우트를 명시하게 합니다.

다음의 예는 RouteValue 표현을 사용하는 법을 보여줍니다. 

<asp:Label ID="Label1" runat="server" Text="<%$RouteValue:SearchTem%>" />

이 컨트롤을 포함한 페이지가 동작할 때, 레이블은 "scott"이라는 값을 표시합니다.

RouteValue 표현은 마크업 안의 라우트 데이터 사용을 아주 쉽게 만들고, 그것은 마크업안의 더 복잡한 Page.RouteData["x"] 문법과 함께 동작해야 하는 것을 피할 수 있습니다.

Using Route Data for Data Source Control Parameters

RouteParameter 클래스는 당신이 데이터 소스 컨트롤 안의 쿼리를 위한 파라미터 값으로 라우트 데이터를 상세화하게 합니다. 다음의 예에서 보여지듯이, 그것이 FormParameter 처럼 잘 작동합니다:

<asp:sqldatasource id="SqlDataSource1" runat="server"
    connectionstring="<%$ ConnectionStrings:MyNorthwind %>"
    selectcommand="SELECT CompanyName,ShipperID FROM Shippers where
      CompanyName=@companyname"
  <selectparameters>
    <asp:routeparameter name="companyname" RouteKey="searchterm" />
  </selectparameters>
</asp:sqldatasource> 


 이 경우에, 라우트 파라미터 searchterm의 값은 Select 구문의 안에 @companyname 파라미터를 위하여 사용 될 것입니다다.

Concurrency Runtime
– Task Scheduler 3. ( ScheduleGroup )

작성자: 임준환( mumbi at daum dot net )

 

시작하는 글

 Scheduler 는 항상 하나 이상의 스케줄 그룹을 가지고 있습니다. 스케줄 그룹이 무엇인지 알아보고 동시성 프로그래밍에 어떤 영향을 주는지 알아보도록 하겠습니다.

 

SchedulerGroup

 SchedulerGroup 이란 Scheduler 가 스케줄링 해야 할 작업들을 모아 놓은 스케줄 그룹을 대표하는 클래스입니다.

 

정책

 이전 글에서 본 스케줄러 정책들 중 SchedulingProtocol 정책은 스케줄링 순서를 변경하여 작업들의 처리 순서를 변경할 수 있습니다. ScheduleringProtocol 정책이 EnhanseScheduleGroupLocality 로 설정된 경우에는 스케줄링 중인 스케줄 그룹을 변경하지 않고, 현재 스케줄링 중인 스케줄 그룹을 다른 스케줄 그룹보다 먼저 처리합니다. 반면에 SchedulingProtocol 정책이 EnhanseForwardProgress 로 설정된 경우에는 다른 스케줄링 그룹의 작업을 처리합니다. 스케줄 그룹 간에 작업을 공평하게 처리하게 됩니다.

 

생성

 CurrentScheduler::CreateScheduleGroup() 또는 Scheduler::CreateScheduleGroup() 을 통해 ScheduleGroup 객체를 생성할 수 있습니다.

 Scheduler 가 참조 개수를 사용하여 수명을 관리하는 것처럼 ScheduleGroup 객체 또한 참조 개수를 사용합니다. 생성되는 순간 참조 개수는 1이 됩니다. SchedulerGroup::Reference() 는 참조 개수는 1이 증가하고, SchedulerGroup::Release() 는 참조 개수가 1이 감소하게 됩니다.

 

동작 및 사용

 Scheduler 객체에는 기본적으로 기본 ScheduleGroup 을 가지고 있습니다. 명시적으로 ScheduleGroup 을 생성하지 않는다면 스케줄링 해야 할 작업들은 기본 ScheduleGroup 에 추가됩니다.

 ScheduleGroup 은 Concurrency Runtime 중 Asynchronous Agents Library( 이하, AAL ) 에서 사용할 수 있습니다. agent 클래스나 message block 들의 생성자로 ScheduleGroup 을 전달하여 사용할 수 있습니다.

 

예제

 ScheduleGroup 을 어떻게 사용하는지 이해를 도울 예제를 살펴보겠습니다.

 

시나리오

 단순하게 어떤 스케줄 그룹의 작업들이 어떤 순서로 처리되는지 알아보는 예제입니다.

 

코드

#include <agents.h>
#include <vector>
#include <algorithm>
#include <iostream>
#include <sstream>

using namespace std;
using namespace Concurrency;

#pragma optimize( "", off )

void spin_loop()
{
	for( unsigned int i = 0; i < 500000000; ++i )
	{
	}
}

#pragma optimize( "", on )

class work_yield_agent
	: public agent
{
public:
	explicit work_yield_agent( unsigned int group_number, unsigned int task_number )
		: group_number( group_number )
		, task_number( task_number ) { }

	explicit work_yield_agent( ScheduleGroup& scheduleGroup, unsigned int group_number, unsigned int task_number )
		: agent( scheduleGroup )
		, group_number( group_number )
		, task_number( task_number ) { }

protected:
	void run()
	{
		wstringstream header, ss;

		header << L"agent no. " << this->group_number << L"-" << this->task_number << L": ";

		ss << header.str() << L"first loop..." << endl;
		wcout << ss.str();
		spin_loop();

		ss = wstringstream();
		ss << header.str() << L"waiting..." << endl;
		wcout << ss.str();
		Concurrency::wait( 0 );

		ss = wstringstream();
		ss<< header.str() << L"second loop..." << endl;
		wcout << ss.str();
		spin_loop();

		ss = wstringstream();
		ss << header.str() << L"finished..." << endl;
		wcout << ss.str();

		this->done();
	}

private:
	unsigned int	group_number;
	unsigned int	task_number;
};

void run_agents()
{
	const unsigned int group_count = 2;
	const unsigned int tasks_per_group = 2;

	vector< ScheduleGroup* > groups;
	vector< agent* > agents;

	for( unsigned int group_index = 0; group_index < group_count; ++group_index )
	{
		groups.push_back( CurrentScheduler::CreateScheduleGroup() );

		for( unsigned int task_index = 0; task_index < tasks_per_group; ++task_index )
		{
			agents.push_back( new work_yield_agent( *groups.back(), group_index, task_index ) );
		}
	}

	for_each( agents.begin(), agents.end(), []( agent* pAgent )
	{
		pAgent->start();
	} );

	agent::wait_for_all( agents.size(), &agents[0] );

	for_each( agents.begin(), agents.end(), []( agent* pAgent )
	{
		delete pAgent;
	} );

	for_each( groups.begin(), groups.end(), []( ScheduleGroup* pScheduleGroup )
	{
		pScheduleGroup->Release();
	} );
}

int main()
{
	wcout << L"Using EnhanceScheduleGroupLocality..." << endl;
	CurrentScheduler::Create( SchedulerPolicy( 3,
		MinConcurrency, 1,
		MaxConcurrency, 2,
		SchedulingProtocol, EnhanceScheduleGroupLocality ) );

	run_agents();
	CurrentScheduler::Detach();

	wcout << endl << endl;

	wcout << L"Using EnhanceForwardProgress..." << endl;
	CurrentScheduler::Create( SchedulerPolicy( 3,
		MinConcurrency, 1, 
		MaxConcurrency, 2,
		SchedulingProtocol, EnhanceForwardProgress ) );

	run_agents();
	CurrentScheduler::Detach();
}

[ 코드1. 처리되는 스케줄 그룹의 순서를 확인하는 예제 ]

 최대 동시성 리소스( computing core ) 의 개수를 2개로 하고, 한 번은 SchedulingProtocol 정책을 EnhanceScheduleGroupLocality 로 하고, 한 번은 EnhanceForwardProgress 으로 하여 작업의 순서를 알아보았습니다.

 2개의 스케줄 그룹을 생성하고, 하나의 그룹에 2개의 작업을 추가하여, 총 4개의 작업이 수행됩니다.

 예제의 spin_loop() 는 어떤 작업을 처리하는 것을 의미하고 wait() 는 양보를 뜻합니다. wait() 가 호출되면 다른 작업이 스케줄링 되는데 이 때 결정되는 작업이 어떤 작업인지는 앞서 설정한 SchedulingProtocol 정책에 따릅니다.

 EnhanceScheduleGroupLocality 로 설정된 경우에는 같은 스케줄 그룹 내의 작업이 처리되는 반면에, EnhanceForwardProgress 로 설정된 경우에는 다른 스케줄 그룹의 작업이 처리되게 됩니다.

 

[ 그림1. 처리되는 스케줄 그룹의 순서를 확인하는 예제 실행 결과 ]

[ 그림1. 처리되는 스케줄 그룹의 순서를 확인하는 예제 실행 결과 ]

 

마치는 글

 이렇게 스케줄링 정책과 스케줄 그룹을 통해서 스케줄링 순서를 결정하는데 관여할 수 있다는 것을 알아보았습니다.

다음 글에서는 스레드를 직접 생성하여 사용할 수 있는 ScheduleTask 라는 것에 대해서 알아보도록 하겠습니다.

[Step. 15] static 생성자, initonly, literal

C++/CLI 2010. 9. 24. 09:00 Posted by 알 수 없는 사용자

static 생성자

 

static 생성자는 클래스의 생성자에서 static 멤버를 초기화 하고 싶을 때 사용합니다.

ref class, value class, interface에서 사용할 수 있습니다.

 

#include "stdafx.h"

#include <iostream>

 

using namespace System;

 

ref class A {

public:

    static int a_;

    static A()

    {

        a_ += 10;

    }

};

ref class B {

public:

    static int b_;

    static B()

    {

//        a_ += 10; // error

        b_ += 10;

    }

};

ref class C {

public:

    static int c_ = 100;

    static C()

    {

        c_ = 10;

    }

};

 

int main()

{

    Console::WriteLine(A::a_);

    A::A();

    Console::WriteLine(A::a_);

 

    Console::WriteLine(B::b_);

 
    Console::WriteLine(C::c_);


     getchar();

    return 0;

}

 

< 결과 >


 

static 생성자는 런타임에서 호출하기 때문에 클래스 A의 멤버 a_는 이미 10으로 설정되어 있습니다. 그리고 이미 런타임에서 호출하였기 때문에 명시적으로 A::A()를 호출해도 실제로는 호출되지 않습니다.

 

클래스 B의 경우 static 생성자에서 비 static 멤버를 호출하면 에러가 발생합니다.

 

클래스 C의 경우 static 멤버 c_를 선언과 동시에 초기화 했지만 런타임에서 static 생성자를 호출하여 값이 10으로 설정되었습니다.

 

 

 

initonly

 

initonly로 선언된 멤버는 생성자에서만 값을 설정할 수 있습니다. 그리고 initonly static로 선언된 멤버는 static 생성자에서만 값을 설정할 수 있습니다.

 

 

ref class C
{
public:
    initonly static int x;
    initonly static int y;
    initonly int z;
    static C()
    {
        x = 1;
        y = 2;
        // z = 3; // Error
    }
    C()
    {
        // A = 2; // Error
        z = 3;
    }
    void sfunc()
    {
        // x = 5; // Error
        // z = 5; // Error
    }
};


int main()
{
    System::Console::WriteLine(C::x);
    System::Console::WriteLine(C::y);
    C c;
    System::Console::WriteLine(c.z);
    return 0;
}

 

 

 

literal

 

literal로 선언된 멤버는 선언과 동시에 값을 설정하고 이후 쓰기는 불가능합니다. 오직 읽기만 가능합니다.

using namespace System;
ref class C
{
public:
    literal String^ S = "Hello";
    literal int I = 100;
};

int main()
{
    Console::WriteLine(C::S);
    Console::WriteLine(C::I);
    return 0;
}



참고
http://cppcli.shacknet.nu/cli:static%E3%82%B3%E3%83%B3%E3%82%B9%E3%83%88%E3%83%A9%E3%82%AF%E3%82%BF
http://cppcli.shacknet.nu/cli:initonly
http://cppcli.shacknet.nu/cli:literal





'C++/CLI' 카테고리의 다른 글

[Step. 16] array 클래스에 non-CLI 오브젝트 사용  (0) 2010.10.27
[Step. 14] 인터페이스 ( interface )  (1) 2010.10.01
[Step. 13] parameter array  (1) 2010.09.10
[Step. 12] for each  (1) 2010.09.03
[Step. 11] 열거형( enum )  (2) 2010.08.27

 

 

 

 

안녕하세요. 알콜코더 민군입니다. ^^

DX11 튜터리얼 2번째 연재를 시작하겠습니다.

 

저번시간에는 3D 디바이스를 초기화하는 전체 과정에 대해서 살펴보았습니다. 3D 디바이스를 초기화 한다는 말은 곧 3D 화면을 생성하고 오브젝트를 렌더링하기 위한 준비단계를 의미합니다. 이 과정을 거쳐서야 비로서 애플리케이션의 윈도우에 3D 렌더링을 위한 화면이 준비되고, 거기에 오브젝트들을 렌더링하고 움직이면서 게임이나 3D 그래픽스 프로그래밍이 시작되는 것입니다.

 

이번 시간에는 지난 시간에 알아본 내용들을 실제로 코드로 어떻게 구현하는지에 대해서 이야기 해보겠습니다. 전체 예제 코드는 DirectX SDK에 포함되어있는 Tutorial을 보시면 됩니다. ^^

 

우선은 튜터리얼의 코드를 수정하지 않고 있는 그대로 설명을 하겠습니다. 튜터리얼은 간단히 내용만 구현하기 위해서 코드가 지저분한 부분도 있고, 필요없는 부분도 있습니다 수정을 해서 좀더 깔끔하게 만들 수도 있습니다만 우선은 기본 이해를 위해서 튜터리얼 1번 예제 코드를 수정없이 그대로 분석하면서 연재를 진행하겠습니다. (제가 수정해서 헷갈릴수도 있으니까요.. 예제 코드와 다르잖아!! 이런걸 방지하기 위해 ㅡ.ㅡ;)

 

그리고 이해를 돕기위해 튜터리얼 코드에 한글 주석을 달아서 첨부파일로 첨부하였습니다. 참조하시기 바랍니다.

 

 

DirectX3D 디바이스와 SwapChain 생성하기

 

DX11에서 3D디바이스와 SwapChain은 동시에 생성됩니다. "D3D11CreateDeviceAndSwapChain" 함수를 이용해서 두개의 디바이스 객체를 한번에 생성하게 됩니다. 생성하는 방법은 DX의 객체의 생성법이 다 그렇듯이, 생성을 위한 인자들과 생성 정보를 담고 있는 구조체를 인자로 넘겨주면 생성이 됩니다.

이제는 예제 코드의 순서에 따라서 생성하기 위한 정보들이 어떤것들이 있고, 어떻게 설정하는지 Step by Step으로 설명하겠습니다. (다시 말씀드리지만 이 연재는 초보자용으로 쓰고 있는 입문 연재입니다.^^)

  1. 변수 선언


디바이스를 생성하고, 생성된 디바이스 객체 정보를 담을 변수들을 선언합니다.

 

위 객체들이 어떤 역할을 하는지는 타입명만 보면 대충 감이 잡히실겁니다. 초기화의 목적은 아래 세개의 객체 디바이스, 디바이스컨텍스트, SwapChin을 생성하고 초기화하는 것입니다. 생성 방법은 아래 내용에서 알아보겠습니다.

 

2. CreateDeviceFlag의 설정
생성할 DX 디바이스의 플래그를 설정해줍니다.



위와 같이 UINT값으로 플래그를 설정합니다. 디버그 버전에서는 위처럼 디버그용 플래그를 설정하고 릴리즈의 경우에서는 0을 설정하면 됩니다.

 

3. 3D 드라이버 타입의 설정
생성할 3D 드라이버 타입 배열을 설정합니다.



원래는 바로 하드웨어 지원으로 설정해도 되지만, 아직 DX11을 지원하지않는 그래픽카드가 많기 때문에, DX11을 지원하지 않는 그래픽 카드에서는 REF 모드로 생성하기 위해서 가능할만한 드라이버 타입들을 배열로 생성해서 나중에 디바이스를 생성할 때 for 문을 돌면서 하나씩 직접 생성해 볼것입니다. 그래서 처음으로 생성에 성공하는 드라이버 타입을 사용할 겁니다.
즉, 하드웨어 모드나 WARP 모드로 디바이스가 생성되지 않는다면, DX11을 지원하지 않는 하드웨어이기 때문에 마지막 레퍼런스 모드로 생성이 됩니다.
레퍼런스 모드는 하드웨어가 지원하지 않을 때 소프트웨어적으로 지원을 해서 디바이스를 생성하여 줍니다. 물론 하드웨어 가속을 사용하지 못하기 때문에 성능이 상당히 처절하긴 하지만, 이로 인해서 DX11을 지원하지 않는 하드웨어서도 DX11 디바이스를 생성하고 사용할 수 있습니다. 아직 기초 예제에서는 성능에 부하가 큰 내용이 없기 때문에 DX11을 지원하지 않는 그래픽 카드에서도 이 예제를 실행해 보는데는 무리가 없습니다.

4. Feature Level의 설정
피처레벨은 DX의 어느 버전의 기능을 지원할지를 설정하는 것입니다.



피처레벨에 대해서는 '조진현'님이 상세한 설명을 해주셨기 때문에 그 연재 내용을 참고하시면 됩니다.

 

5. DXGI_SWAP_CHAIN_DESC 구조체 설정
스왑체인을 생성하기 위한 정보들을 구조체에 세팅하여 줍니다.



가장 설정하게 많은 스왑체인 생성 구조체입니다. 우선 하나하나 설명을 하겠습니다.

BufferCount는 생성할 백버퍼의 카운트입니다. 현재는 하나만 생성합니다. Width와 Height는 생성할 백버퍼의 해상도입니다. 생성한 윈도우와 같은 크기의 백버퍼를 생성하기 때문에, 윈도우의 크기와 같게 설정하여 줍니다. (윈도우 크기를 구하는 코드는 예제코드 위쪽에 있습니다) Formatr은 역시 백퍼러를 생성할 포맷을 설정합니다. 지금은 기본 포맷이기 때문에 R8G8B8A8, 즉 각각의 RGBA 컬러에 8비트씩을 할당하는 32비트 컬러포맷으로 백버퍼를 생성합니다.

RefreshRate는 화면 주사율을 의미합니다. 일반적으로 60으로 설정합니다. Denominator 역시 1로 설정합니다.

BufferUsage는 생성한 버퍼의 사용 용도를 의미합니다. 백버퍼에 사용할 렌더타겟으로 버퍼를 생성하고 있기 때문에 위와 같이 설정하여 줍니다.

OutputWindow는 이 버퍼를 출력할 윈도우 핸들을 지정합니다. 어플리케이션을 생성할 때 저장한 현재 윈도우의 핸들을 지정해 줍니다.

SampleDesc는 멀티샘플링을 사용할지에 대한 설정입니다. 멀티샘플링은 다른 말로 하면 안티얼라이싱과 같은 의미입니다. 화면의 계단 현상을 줄이기 위한 기술로 독자 여러분도 많이들 들어보셨을 겁니다. 이 설정을 Count = 1, Quality = 0으로 설정하면 이 기능을 사용하지 않는 다는 의미입니다. 이 예제는 멀티샘플링을 사용하지 않기 때문에 위와 같이 설정합니다.

Windowed는 풀스크린으로 출력할지, 윈도우 창으로 출력할지에 대한 설정입니다. 예제에서는 윈도우 모드로 생성하기 때문에 TRUE를 설정하였습니다.

 

6. 3D 디바이스와 스왑체인의 생성
이제 위와 같은 설정들이 모두 끝나면 실제로 디바이스와 스왑체인을 생성할 수 있습니다. 지금까지 위의 과정은 이 과정을 위한 준비단계였습니다. 실제로 Create함수를 호출하여 디바이스를 생성하겠습니다.



지금껏 준비과정에서 생성된 정보들을 가지고 함수를 호출해서 필요한 객체들을 생성합니다.
실제 예제 코드에서는 DX11을 지원하지 않는 하드웨어를 위해서 for문 내에서 드라이버 타입을 바꿔가면서 위 함수를 호출하고 있습니다. 그러다가 디바이스가 성공적으로 생성되면 그 디바이스를 사용하게 되어있습니다. 따라서 이 예제는 DX11이 지원되지 않는 그래픽카드에서도 레퍼런스 모드로도 돌아가게 되어있습니다. 나중에 DX11이 기본적으로 지원되는 세상이 된다면 이런 작업을 해주지 않고 바로 하드웨어 지원으로 설정해도 되겠죠. (사실 이런 코드 때문에 코드가 좀더 복잡해 보입니다.. =ㅅ=)

 

 

다음 내용으로 이어집니다. ^^;;

이 연재에는 예제 코드가 첨부 파일로 포함되어 있습니다.

 

 

 

 

언젠가 우즈벡에 미소녀 게임 회사를 차리고 싶은 개발자

3D게임 클라이언트 프로그래머, 살짝 오타쿠

드래곤볼 온라인 개발, 현재는 네오위즈 서식중

'신입게임 개발자의 서울상경기' '초중급 게임개발자 스터디' 운영중

 

 

Concurrency Runtime
– Task Scheduler 2. ( SchedulerPolicy )

작성자: 임준환( mumbi at daum dot net )

 

시작하는 글

 지난 글에서 Scheduler 를 통해서 스케줄링 방법을 설정할 수 있다고 설명 드렸습니다. 스케줄링 방법을 제어하기 위한 기반 정보를 스케줄러 정책이라고 표현하고, 우리는 이 스케줄링 정책을 사용해서 스케줄링을 제어할 수 있습니다.

스케줄러 정책을 대표하는 클래스가 바로 오늘 설명드릴 SchedulerPolicy 입니다.

 

SchedulerPolicy

 스케줄러에게 스케줄링에 필요한 기반 정보를 제공하는 클래스입니다. Scheduler 객체를 생성할 때, 이 SchedulerPolicy 를 지정할 수 있습니다. Scheduler 객체가 생성된 후에는 SchedulerPolicy 를 변경할 수 없습니다.

 

정책 생성과 설정

 스케줄러 정책을 설정하기 위해서는 SchedulerPolicy 객체를 생성할 때, 설정할 정책들을 생성자의 매개변수로 설정해야 합니다.

_CRTIMP SchedulerPolicy();
_CRTIMP SchedulerPolicy(size_t _PolicyKeyCount, ...);
_CRTIMP SchedulerPolicy(const SchedulerPolicy& _SrcPolicy);

[ 코드1. SchedulerPolicy 의 생성자 ]

 기본 생성자와 복사 생성자를 제공하고, 정책을 설정할 수 있는 생성자를 제공하고 있습니다.

 기본 생성자로 생성할 경우, 기본 설정으로 정책을 생성합니다.

 정책을 설정할 수 있는 생성자는 첫 번째 인수로 설정할 정책의 수를 입력하고, 그 뒤에 입력한 정책의 수 만큼 정책의 키( key ) 와 값( value ) 을 입력해야 합니다.

SchedulerPolicy policy(3,       
   MinConcurrency, 2,
   MaxConcurrency, 4,
   ContextPriority, THREAD_PRIORITY_HIGHEST
);

[ 코드2. SchedulerPolicy 객체의 생성 ]

 위와 같이 생성한 SchedulerPolicy 객체는 3개의 정책을 설정하는데, 사용할 최소 동시성 자원( computing core ) 의 개수는 2개, 사용할 최대 동시성 자원의 개수는 4개, 현재 컨텍스트의 스레드 우선순위를 최고 순위로 설정하게 됩니다.

 위 코드에서 보여드린 정책들 뿐만 아니라 여러 가지 정책들을 설정할 수 있습니다.

 

설정할 수 있는 정책들

 PolicyElementKey 열거형으로 설정할 수 있는 정책들을 정의하고 있습니다. 그 내용은 다음과 같습니다.

 정책 키  설명  기본 값
 SchedulerKind  작업들을 수행할 때, 일반 스레드를 사용할지, UMS 스레드를 사용할지 설정  ThreadScheduler
 MaxConcurrency  스케줄러에서 사용할 최대 동시성 자원 수  MaxExecutionResources
 MinConcurrency  스케줄러에서 사용할 최소 동시성 자원 수  1
 TargetOversubscriptionFactor  작업을 수행 시, 자원에 할당할 스레드의 수  1
 LocalContextCacheSize  캐시할 수 있는 컨텍스트 수  8
 ContextStackSize  각 컨텍스트에서 사용할 스택 크기( KB )  0( 기본 스택 크기 사용 )
 ContextPriority  각 컨텍스트의 스레드 우선 순위  THREAD_PRIORITY_NORMAL
 SchedulingProtocal  스케줄 그룹의 작업 예약 알고리즘  EnhanceScheduleGroupLocality
 DynamicProgressFeedback  자원 통계 정책, 사용 금지.  ProgressFeedbackEnabled

[ 표1. PolicyElementKey 열거형에 정의된 설정할 수 있는 정책들 ]

기본 정책 설정

 Asynchronous Agents Library( 이하, AAL ) 에는 우리가 생성한 정책을 지정한 Scheduler 객체를 사용할 수 있지만, Parallel Patterns Library ( 이하, PPL ) 에는 우리가 생성한 Scheduler 객체를 사용할 수 없고, 내부적으로 생성되는 기본 스케줄러를 사용하게 됩니다. 기본 스케줄러는 기본 정책을 사용하게 되는데, 이 기본 정책을 미리 설정해 둘 수 있습니다.

_CRTIMP static void __cdecl SetDefaultSchedulerPolicy(
   const SchedulerPolicy& _Policy
);

[ 코드3. SetDefaultSchedulerPolicy() 의 선언 ]

 SetDefaultSchedulerPolicy() 의 인자로 SchedulerPolicy 를 생성하여 설정하면, 직접 Scheduler 를 생성하여 사용하지 않더라도, 내부에서 생성되는 기본 스케줄러에도 정책을 설정할 수 있습니다.

 

스케줄러 정책 획득

 이미 생성된 Scheduler 객체로부터 설정된 정책을 가져올 수 있습니다.

_CRTIMP static SchedulerPolicy __cdecl GetPolicy();	// CurrentScheduler::GetPolicy() static function
virtual SchedulerPolicy GetPolicy(); 			// Scheduler::GetPolicy() member function

[ 코드4. GetPolicy() 들의 선언 ]

 Scheduler 객체로부터 얻어온 정책은 설정할 때의 정책과 다를 수 있습니다. 정책을 설정하더라도, 해당 시스템에서 설정 가능한 정책만 적용되고, 그렇지 않은 경우에는 기본 정책 값이나 Resource Manager 에 의해 적당한 값으로 적용됩니다.

예를 들어 UMS 를 사용할 수 없는 시스템에서 UMS 를 사용하라고 설정하더라도, ThreadScheduler로 설정됩니다.

 

예제

 Scheduler 를 사용하는 방법과 SchedulerPolicy 인해 어떤 영향을 받는지 알아보는 예제를 보도록 하겠습니다.

 

시나리오

 문자열 순열을 구하는 프로그램입니다. 문자열 순열이란 문자열을 이루는 알파벳들로 만들 수 있는 모든 경우의 수를 말합니다.

문자열 순열을 구하는 작업은 오랜 시간이 걸리므로 agent 를 이용해 비 동기 처리를 합니다. 그리고  문자열 순열을 구하는 작업을 하는 agent 와 통신을 하며 진행 상황을 출력해주는 agent 가 비 동기로 처리됩니다.

 이 때, Concurrency Runtime 은 협조적 스케줄링을 하기 때문에 바쁜 스케줄러에 더 많은 자원을 할당합니다. 반대로 바쁘지 않은 스케줄러에는 적은 자원이 할당됩니다. 이로 인해 진행 상황을 출력하는 agent 가 제대로 스케줄링되지 않는 현상이 발생하게 됩니다.

 이의 해결책으로 진행 상황을 출력하는 agent 의 스레드 우선 순위를 높게 설정합니다.

 

코드

#include <Windows.h>
#include <ppl.h>
#include <agents.h>
#include <iostream>
#include <sstream>

using namespace std;
using namespace Concurrency;

// 문자열 순열을 구하는 agent
class permutor
	: public agent
{
public:
	explicit permutor( ISource< wstring >& source, ITarget< unsigned int >& progress )
		: source( source )
		, progress( progress ) { }

	explicit permutor( ISource< wstring >& source, ITarget< unsigned int >& progress, Scheduler& scheduler )
		: agent( scheduler )
		, source( source )
		, progress( progress ) { }	

protected:
	void run()
	{
		wstring s = receive( this->source );

		this->permute( s );

		this->done();
	}

	unsigned int factorial( unsigned int n )
	{
		if( 0 == n )
			return 0;

		if( 1 == n )
			return 1;

		return n * this->factorial( n - 1 );
	}

	wstring permutation( int n, const wstring& s )
	{
		wstring t( s );

		size_t len = t.length();

		for( unsigned int i = 2; i <  len; ++i )
		{
			swap( t[ n % i ], t[i] );
			n = n / i;
		}

		return t;
	}

	void permute( const wstring& s )
	{
		unsigned int permutation_count = this->factorial( s.length() );

		long count = 0;

		unsigned int previous_percent = 0u;

		send( this->progress, previous_percent );

		parallel_for( 0u, permutation_count, [&]( unsigned int i )
		{
			this->permutation( i, s );

			unsigned int percent = 100 * InterlockedIncrement( &count ) / permutation_count;
			if( percent > previous_percent )
			{
				send( this->progress, percent );
				previous_percent = percent;
			}
		} );

		send( this->progress, 100u );
	}

private:
	ISource< wstring >&			source;
	ITarget< unsigned int >&	progress;
};

// 진행 상황을 출력하는 agent
class printer
	: public agent
{
public:
	explicit printer( ISource< wstring >& source, ISource< unsigned int >& progress )
		: source( source )
		, progress( progress ) { }

	explicit printer( ISource< wstring >& source, ISource< unsigned int >& progress, Scheduler& scheduler )
		: agent( scheduler )
		, source( source )
		, progress( progress ) { }

protected:
	void run()
	{
		wstringstream ss;
		ss << L"Computing all permutations of '" << receive( this->source ) << L"'..." << endl;
		wcout << ss.str();

		unsigned int previous_percent = 0u;

		while( true )
		{
			unsigned int percent = receive( this->progress );

			if( percent > previous_percent || percent == 0u )
			{
				wstringstream ss;
				ss << L'\r' << percent << L"% complete...";
				wcout << ss.str();
				previous_percent = percent;
			}

			if( 100 == percent )
				break;
		}

		wcout << endl;

		this->done();
	}

private:
	ISource< wstring >&			source;
	ISource< unsigned int >&	progress;
};

// agent 의 작업을 관리하는 함수
void permute_string( const wstring& source, Scheduler& permutor_scheduler, Scheduler& printer_scheduler )
{
	single_assignment< wstring > source_string;
	unbounded_buffer< unsigned int > progress;

	permutor agent1( source_string, progress, permutor_scheduler );
	printer agent2( source_string, progress, printer_scheduler );

	agent1.start();
	agent2.start();

	send( source_string, source );

	agent::wait( &agent1 );
	agent::wait( &agent2 );
}

int main()
{
	const wstring source( L"Grapefruit" );

	// 기본 정책으로 작업을 수행
	Scheduler* pDefault_scheduler = CurrentScheduler::Get();

	wcout << L"With default scheduler: " << endl;
	permute_string( source, *pDefault_scheduler, *pDefault_scheduler );
	wcout << endl;

	// 진행 상황을 출력하는 agent 에 필요한 스레드 우선 순위를 높게 하는 정책을 설정하여 적용
	SchedulerPolicy printer_policy( 1, ContextPriority, THREAD_PRIORITY_HIGHEST );
	Scheduler* pPrinter_scheduler = Scheduler::Create( printer_policy );

	HANDLE hShutdownEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
	pPrinter_scheduler->RegisterShutdownEvent( hShutdownEvent );

	wcout << L"With higher context priority: " << endl;
	permute_string( source, *pDefault_scheduler, *pPrinter_scheduler );
	wcout << endl;

	pPrinter_scheduler->Release();

	WaitForSingleObject( hShutdownEvent, INFINITE );
	CloseHandle( hShutdownEvent );
}

[ 코드5. Scheduler 객체에 스레드 우선 순위를 높인 SchedulerPolicy 객체를 적용한 예제 ]

 기본 정책으로 수행했을 때에는 작업 진행 상황이 제대로 출력되지 않는 반면에, 스레드 우선 순위를 높게 설정한 경우에는 제대로 출력되는 것을 보실 수 있습니다.

[ 그림1. SchedulerPolicy 로 스레드 우선 순위를 변경한 예제 실행 결과 ]

[ 그림1. SchedulerPolicy 로 스레드 우선 순위를 변경한 예제 실행 결과 ]

 

마치는 글

 이번 글에서는 Scheduler 의 기본적인 기능 중 하나인 SchedulerPolicy 를 설정하는 방법을 알아보았습니다. SchedulerPolicy 를 이용하여 기본 정책으로 해결되지 않는 다양한 문제점들을 해결 하실 수 있을 것입니다.

KGC10에서의 VS2010 스터디 팀의 활약 모습

VSTS 2010 팀 블로그 2010. 9. 17. 10:00 Posted by 알 수 없는 사용자

어제로 13~15일까지 코엑스에서 열렸던 KGC10이 끝났습니다. KGC는 게임 개발자를 위한 컨퍼런스로 국내뿐만이 아닌 해외의 유명 인사들이 와서 강연을 합니다.

올해는 작년보다 강연의 질도 높아졌고, 참석자의 수도 더 늘어 난 것 같았습니다.

왠만한 강연은 앞 강연이 끝난 후 바로 들어가지 않으면 자리가 없어서 강연을 서서 보기가 일수였습니다.

KGC10에 가지 못하신 분들은 PD님이 정리하신 글(http://parkpd.egloos.com/3441356)을 참고하시면 좋을 것 같습니다.

그리고 웹하드(http://webhard.co.kr)에서 내일부터 PT 문서가 다운로드 가능하면 이때 아이디(KGC10TH) 비밀번호(kgc2010)를 사용하면 됩니다.

 

KGC10에서 저희 스터디 팀에서는 강성재님, 김병진님, 남정현님, 조진현님, 저 이렇게 5명이 강연을 하였고 3일 동안 행사장에서 부스를 운영하였습니다. 부스에서는 비주얼 스튜디오에 대한 설문을 해 주시면 KGC10 부스에서만 받을 수 있는 비주얼 스튜디오 스티커와 C++0x 백서, 비주얼 스튜디오 평가판을 드렸으며 매일 6시 키보드와 마우스를 경품으로 추첨도 진행했습니다.

바쁜 와중에 시간을 쪼개어 강연 준비를 하느라 다들 수고 많았지만 그 중에 특히 3일 동안 부스를 지켜주신 강보람님 정말 수고 많으셨습니다.

 

아래는 KGC10에서 제가 찍은 사진입니다.


부스 첫 개시 전의 남정현님과 강보람님입니다.


DirectX11을 강연하신 조진현님입니다. KGC 강연은 이번이 두 번째인데 작년과 다르게 여유롭게 강연을 하시더군요^^


Azure 시연을 하고 계시는 남정현님입니다.


TFS 강연을 준비중이신 김병진님


VS를 사용한 애자일 강연을 하신 강성재님


사실 부스 시작 전에는 사람들이 많이 오지 않을까 걱정도 했는데 생각 외로 많은 분들이 오셨습니다.


6시 추첨을 위해서 부스 앞에 많은 분들이 모였습니다.^^




마우스에 당첨 !!!


키보드에 당첨 !!!

[Step. 13] parameter array

C++/CLI 2010. 9. 10. 09:00 Posted by 알 수 없는 사용자

비관리코드에서 로그 기능을 구현할 때 주로 가변 길이 인수를 사용합니다.

void LOG( char* szText, ... )

{

}

 


위와 같은 가변 길이 인수를 C++/CLI에서는 parameter array라는 것으로 구현합니다.

void LOG( … array<Object^>^ Values )

{

for each( Object^ value in Values )

{

   ….

}

}

 

int main()

{

LOG( 23 );

LOG( 2, 1, “error” );

 

return 0;

}

 


parameter array를 사용하면 이전 보다 안전하고, 하나의 형이 아닌 다양한 형을 인자로 받아 들일 수 있어서 유연성이 높습니다.

 

그러나 하나의 함수에서 parameter array는 하나 밖에 사용하지 못합니다. 하지만 parameter array가 아닌 형이라면 여러 개 사용할 수 있습니다. 다만 이 때는 parameter array는 가장 마지막 인수가 되어야 합니다.

 

void LOG( int nLogLevel, … array<Object^>^ Values )

{

}

 

 


참고

http://cppcli.shacknet.nu/cli:parameter_array

 

'C++/CLI' 카테고리의 다른 글

[Step. 14] 인터페이스 ( interface )  (1) 2010.10.01
[Step. 15] static 생성자, initonly, literal  (1) 2010.09.24
[Step. 12] for each  (1) 2010.09.03
[Step. 11] 열거형( enum )  (2) 2010.08.27
[Step. 10] 이벤트 ( event )  (0) 2010.08.20

9월 13일에 개최하는 KGC에서 강연을 합니다.

VSTS 2010 팀 블로그 2010. 9. 8. 09:00 Posted by 알 수 없는 사용자

913일부터 15일까지 3일간 코엑스 컨벤션 센터에서 KGC(Korea Games Conference)가 개최됩니다(http://www.kgconf.com). KGC는 미래의 게임 개발자가 될 학생이나 현업의 게임 개발자와 게임업계 관계자를 위한 컨퍼런스로 한국만이 아닌 외국의 개발자나 업계 관계자들이 강연자나 청중으로 참가합니다.

 

아마 게임 업계와 관계 없는 분들은 KGC에 대해서 잘 모르시겠지만 KGC는 올해로 10년째를 맞이하였고,

3일 동안 각각 오전 920분부터 시작하여 오후 6시에 끝날 때까지 7개의 트랙으로 나누어서 할 정도로 다양한 세션이 진행되고 5000명 이상의 청중들이 참가하는 등 국내의 다른 컨퍼런스와 비교할 수 없을 정도의 대형 규모의 컨퍼런스입니다.

 

작년 KGC에는 저와 조진현님, 강성재 차장님이 강연자로 참가했고, 올해는 두 분이 더 늘어서 총 5명이 강연자로 참가합니다.

KGC에서 어떤 것을 주제로 강연을 하는지 간단하게 소개하겠습니다.

 

 

 

Visual C++10과 디버깅

이름 : 최흥배

소속 : 마이에트 엔터테인먼트

 

강연목차

개발과 디버깅

Visual C++을 사용한 디버깅

디버깅을 도와주는 유틸리티와 라이브러리 소개

 

강연 내용 요약

프로그램을 만들 때 개발과 견줄 수 있을 정도로 많은 시간이 소요되는 것이 디버깅입니다.

이 세션은 이번에 새로 나온 Visual C++10을 사용하여 디버깅의 기초와 심화, 그리고 새로 추가된 디버깅 기능을 소개합니다(단 네이티브 지원되는 것만 소개합니다).

그리고 안전판 프로그램을 만들기 위해 도움이 되는 유틸리티를 소개합니다.

(참고로 제목만 보면 꼭 VC++ 10 사용자를 위해서인 것 같지만 실제 내용은 그렇지 않습니다. 내용의 80% 정도는 기존의 VC++ 사용자들도 들을 수 있는 내용입니다)

 

기존에 디버깅할 때 F5, F9, F10, F11만을 사용하고 있었다면 이 강연을 통해서 VC++이 지원하는 다양한 디버깅 기능과 디버깅에 큰 도움을 주는 유용한 유틸리티나 라이브러리를 배워보시기 바랍니다.

 

 

 

DirectX11 소개

이름 :  조진현

소속 : G.O.G.N.

 

 

강연목차

1.Tessellation

2.DirectCompute

3.Multi-threaded rendering

 

강연 내용 요약

조금씩 공개되고 있는 DirectX11 API적인 변화에 대해서 살펴보고, 그 트렌드에 대해서 소개한다. 그리고 그 변화의 핵심인 Tessellation, DirectCompute, Multi-threaded rendering 의 기본 개념과 내용을 소개한다.

 

 

 

소셜 게임과 Windows Azure Platform

이름 :  남정현

소속 : ㈜코아뱅크

 

강연목차

FarmVille의 사례 짚어보기

Windows Azure Platform의 주요 기술 소개

상호운용 기술에 대한 소개

수요에 따라 동적으로 관리되는 시스템 스케일

Social API를 사용한 Mashup 사례

Contents Delivery Network의 활용

 

강연 내용 요약

소셜 게임에 관하여 가장 많이 언급되는 대표적인 사례 중 하나인 FarmVille Xen Server 기반의 Linux Private Cloud Facebook과의 Social Mashup을 바탕으로 성공적으로 소셜 게임을 런칭한 것으로 유명합니다. 이와 같은 서비스를 지탱하고 있는 기술을 분석해보고, 개발자들의 입장에서 가장 손쉽게 사용할 수 있는 Cloud Computing Platform 중 하나인 Windows Azure Platform을 활용하여 소셜 게임을 성공적으로 작성할 수 있는 방안을 같이 모색해보는 시간이 될 것입니다.

 

(혹시 웹게임이나 소셜 게임 개발을 하거나 할 예정인 분들에게 강력하게 추천하는 세션입니다. 클라우드에 대한 개념 소개만으로 끝나는 것이 아닌 실제 클라우드를 사용할 수 있도록 MS Azure로 어떻게 클라우드를 사용하는지 알려주는 실용적인 강연입니다)

 

 

 

Visual Studio 2010을 통한 애자일 개발 방법

이름 :  강성재

소속 : 한국마이크로소프

 

강연목차

1. 애자일에 대한 작은 생각

2. 애자일 개발

3. 한국적 애자일 개발 모델

4. 소프트웨어 테스팅

 

강연 내용 요약

소프트웨어 개발에 있어 가장 중요한 요소 3가지를 이야기 하라고 한다면, Budget, Time, Feature를 들 수 있다.

최근 여기에 4대 요소로 Quality를 필수로 생각하고 있다.

최근 소프트웨어 개발 방법론의 가장 큰 흐름인 Agile 개발 또한 Process Quality를 소프트웨어 개발에서 가장 중요한 요소로 보고 발전하고 있다.

마이크로소프트 개발 툴인 Visual Studio 2005년부터 ALM이라는 이름으로 소프트웨어의 전체 생명 주기를 관리하는 도구로서 자리매김 하면서 이번 버전에서는 Agile개발을 보다 중요하게 생각하고 관련 기능 또한 많이 들어가게 되었다.

본 세션에서는 애자일 개발에 대해 논의하고, 한국적 모델은 어떤 것일지에 대해 이야기 하는 시간이 되었으면 한다.

 

 

 

SCRUM 사용을 위한 VS TFS 2010

이름 :  김병진

소속 : 아이티플로우

 

강연목차

1.New Visual Studio TFS 2010

2.Agile Scrum 방법론

3.Scrum 을 적용한 VS TFS 2010 개발 방법

4.VS TFS 2010에서 실제 Scrum 활용

5.TFS Power Tools Scrum 활용

 

강연 내용 요약

Visual Studio Team System에서 VS TFS 2010은 변화된 모습으로 새롭게 태어났습니다.

변화된 VS TFS 2010과 프로젝트 템플릿을 먼저 알아보고, Agile에서 사용되는 Scrum 방법론을

VS TFS 2010에서 실제 사용했던 경험을 기반으로 팀 프로젝트의 개발 방법을 소개합니다.

마지막으로 Power Tools을 활용하여 실제 업무에 맞도록 Scrum 방법론 수정하고 활용하는 것을

알아보겠습니다.

 

 

 

 


안녕하세요. 알콜코더 민군입니다. ^^

이제부터 본격적으로 연재를 시작하게 되었습니다. 많은 응원 부탁드립니다.

 

전에 예고했던 DX 11 튜터리얼을 하나씩 예제로 공부하면서 기초 단계부터 하나하나씩 밟고 올라가겠습니다. 이미 튜터리얼쯤이야 건너뛰신 분에게는 별로 도움이 안될지도…(쿨럭;;)

 

자 그럼 대망의 첫번째 튜터리얼을 공부해 보죠

 

 

 

이번 예제의 목표

 

l  DirectX 11을 이용하여 간단한 기본 어플리케이션을 만들어 본다

l  DirectX 11을 사용하기 위한 기본 디바이스 및 오브젝트들을 셋업한다

 

위가 이번 튜터리얼 01의 목표입니다. 우선은 3D 렌더링 화면을 가진 윈도우를 뛰우는것부터 시작해보죠. 3D 화면에 맵을 뛰우고 캐릭터가 뛰어다니는 게임을 만들어 보고 싶으시겠지만천리길도 한걸음 부터입니다. 우선 차근 차근 하나씩 시작해 보죠. ^^

 

 

참고 소스

 

l  DirectX 11 Sample – Tutorial 01 : Direct3D Basics

 

Direct X SDK에 포함되어 있는 샘플입니다. 이 샘플을 기반으로 설명하겠습니다.

직접 SDK에서 설치해서 공부하셔도 되고, 제가 첨부한 파일을 받아서 보셔도 됩니다.

 

 

사전에 준비해야 할 것

 

우선 기본적으로 튜터리얼 역시 윈도우 프로그래밍이기 때문에, 기본적인 윈도우는 뛰우고, DirectX를 설정해야 겠죠? ^^

윈도우를 뛰우는건 기본적인 내용이고 이 연재의 진행을 위해서도 과감하게 생략하겠습니다. (__)

하지만 공부하는 데 도움이 되시라고, 간단히 기본 윈도우를 뛰우는 프로그램을 첨부파일로 첨부합니다. (DX10의 튜터리얼 0번 샘플)

 

직접 코딩을 하면서 공부를 해보기 위해서는 샘플 파일을 받아서 기본적인 윈도우 프로그래밍 기반을 세팅한 후에 아래 내용을 따라서 DX11을 직접 작성해 보면 큰 도움이 될 겁니다.

 

첨부파일 – DirectX 10 Tutorial 00 : Win32 Basics

DirectX 를 아직 세팅하지 않고, 빈윈도우만 뛰우는 기본적인 프로그램입니다.

 

 

Direct3D 디바이스 오브젝트를 셋업하자

 

3D 디바이스 셋업은 3D 프로그래밍의 시작이자, 가장 필수적인 과정입니다.

3D 디바이스, 즉 그래픽카드를 셋업해야 그래픽카드를 통해서 3D 맵을 그리던가, 캐릭터를 렌더링하거나 할 수 있죠. 이 부분이 여타 일반 프로그래밍과 3D 프로그래밍이 시작부터 다른 점입니다. 일반 윈도우 프로그래밍은 그래픽 카드에 접근할 일이 없기 때문에 이런 과정이 당연히 없습니다. ^^

(나름 3D 프로그래머만의 특권일지아니면 지옥의 시작일지…)

 

DX11에서는 우선 아래 세가지 오브젝트를 만들어야 합니다

 

l  Device

l  Immediate Context

l  Swap Chain

 

Device

3D 그래픽 카드와 연결되는 기본 디바이스 객체

 

DX9의 디바이스와 같은 계열이지만, DX 11에서부터는 멀티스레드를 최적화하기 위하여 직접 디바이스를 사용하지 않고, Context를 이용하여 디바이스에 명령을 내립니다. 따라서 별로 사용할 일이 많지는 않을겁니다.

Immediate Context

DX11에 새로 추가된 오브젝트

 

DX11에서는 디바이스 객체에 직접 접근하지 않고, 이 객체를 이용해서 디바이스에 명령을 내린다고 생각하시면 됩니다.

 

DX11에서는 멀티코어/멀티스레드를 최적화 하기 위해서 Device의 하위에 Context를 분리하여 사용합니다. 현재는 이 Context로 디바이스에 명령을 내린다고만 알고 넘어가면 됩니다.

Swap Chain

화면에 렌더링할 백버퍼를 관리하고, 실제로 화면에 렌더링 하는 역할을 담당하는 오브젝트


이 오브젝트를 이용하여 백버퍼의 렌더 타겟을 얻어내 3D  오브젝트를 렌더 타겟에 렌더링하고, 프론트 버퍼와 백버퍼를 스왑(플립(Flip)이라고도 합니다)하여 실제 모니터에 게임 화면을 렌더링하는 역할을 합니다.

 

 

 

기본적인 셋업 및 오브젝트 생성 순서

 

기본적인 DX11의 셋업 순서는 아래와 같습니다.

 

1.   ID3D11Device SwapChain을 생성한다

2.   SwapChain에서 백버퍼를 가져온다(2D Texture)

3.   백버페 실제 렌더링할 렌더 타겟 뷰를 생성하여 바인딩 시킨다

4.   뷰포트를 생성한다

5.   매 프레임마다 위에서 생성한 렌더 타겟 뷰에 게임 화면을 렌더링한다.

6.   SwapChain을 이용하여 디바이스에 화면을 그린다

 

위 순서에서 가장 큰 목적은 바로 렌더 타겟 뷰(Render Target View)’를 생성하는 것입니다. 바로 이 렌더 타겟 뷰가 실제로 우리가 3D 게임 화면을 렌더링할 타겟이 됩니다. (그러니까 렌더타겟이라고 부르는 거겠죠.. ==)

 

이 랜더타겟뷰는 리소스뷰의 일종으로 디바이스의 백버퍼에 바운딩되면서 생성됩니다. 그래서 렌더타겟뷰에 게임 화면을 렌더링한다는 것은 백버퍼에 렌더링하는것과 같습니다. 그리고 백버퍼에 모든 화면을 렌더링하고 난 다음에는 SwapChain을 이용해서 백버퍼를 화면에 그리면 되는겁니다. 정확히는 백퍼버를 프론트버퍼와 바꾸는 스와핑 (또는 플립(Flip))이 일어나는 것이죠.

 

간단히 이야기면, SwapChain을 생성하고, SwapChain안에서 백버퍼를 꺼내오고, 꺼내온 백버퍼를 가지고 렌더타겟뷰라는 오브젝트에 바운딩합니다.

 

그리고 실제 내부에서는 SwapChain이 백버퍼라는 리소스를 가지고 있고, 개발자는 그 백버퍼를 렌더 타겟 뷰에 바인딩하여 사용하는 것입니다.

 

 

 

 

다음 내용으로 이어집니다. ^^;; 

 

 

언젠가 우즈벡에 미소녀 게임 회사를 차리고 싶은 개발자

3D게임 클라이언트 프로그래머, 살짝 오타쿠

드래곤볼 온라인 개발, 현재는 네오위즈 서식중

신입게임 개발자의 서울상경기’초중급 게임개발자 스터디’ 운영중

 

 

   

  • 주최 : 한국 Visual Studio 공식 팀
  • 일시 : 2010년 9월 28일 오후 7시 ~ 10시
  • 장소 : 한국 마이크로소프트 - 포스코 센터 5층
  • 참가비 : 무료
  • 최근 쏟아지는 기술의 홍수 속에서 '아차~' 하고 눈 깜빡할 순간 신기술에 낙오되기 쉽습니다. 한 번은 괜찮지만, 두 번은 기술 트랜드를 따라잡기가 더 힘들어 집니다. 저희 팀에서 기술을 먼저 접해보고, 먼저 고민해본 살아있는 경험을 여러분들에게 전수해 드립니다.

   

세미나 아젠다

시간

세션 내용

19:00 ~ 19:30

등록

19:30 ~ 20:10

현실적인 클라우드 컴퓨팅 이야기

남정현 C# MVP

20:20 ~ 21:00

Expression Blend 와 함께하는 윈도우 폰 7 개발 입문

조진현

21:10 ~ 21:50

Razor 로 열어가는 새로운 ASP.NET

김시원 ASP.NET MVP

   

   

발표 내용 소개

현실적인 클라우드 컴퓨팅 이야기 / 남정현 C# MVP

클라우드 컴퓨팅, 말로만 들어봤지 실제로 어디에 어떻게 사용이 될 수 있는지 알려주는 사람이 없어 답답할 때가 많습니다. 이번 세션에서는 클라우드 컴퓨팅에 관한 실질적인 이야기, 그 중에서도 특별히 마이크로소프트의 윈도 애저 플랫폼에 대한 이야기를 나누면서, 클라우드 컴퓨팅의 현실적인 사례를 간단히 들어보기로 하겠습니다.

  

Expression Blend 와 함께하는 윈도우 폰 7 개발 입문 / 조진현

윈도우 폰7 개발에 대한 간단한 소개와 방법에 대해서 살펴본다. 그리고 더 쉽고 편한 개발을 위한 고민을 해보며, 이를 위해서 Expression Blend 의 활용에 대해서 고민해 본다.

  

Razor 로 열어가는 새로운 ASP.NET - 김시원 ASP.NET MVP

Razor 는 차세대 ASP.NET 의 새로운 View Engine 으로써 , 이것 때문에 요즈음 ASP.NET 이 한창 주목 받고 있습니다. 이번 시간에는 Razor 의 등장배경과 함께 Razor 로 인해 개발 환경이 어떻게 변화하였는지 살펴보고 , 기본적인 Razor 의 사용법을 익혀보도록 하겠습니다.

   

발표자 소개

남정현 C# MVP

(주)코아뱅크에 재직 중이며, Microsoft Visual C# MVP로 활동 중입니다. DEVPIA C# Forum SYSOP, Windows Azure Cafe SYSOP을 맡고 있습니다. 여러 커뮤니티와 개인 블로그, 트위터 (@rkttu)를 통하여 윈도 애저 플랫폼에 대한 다양한 이야기를 전파하고 있습니다.

조진현

현재 게임 개발자로 재직 중이며  Visual Studio 2010 공식 팀 블로그 (http://vsts2010.net) 에서 DirectX 관련 분야에서 활동 중이다. 최근에는 '김탁구'와 '나는 전설이다' 라는 드라마에 빠져서 살고 있다.

  

김시원 ASP.NET MVP
ASP/ASP.NET MVP를 2009년 부터 계속 유지해오고 있으며 다양한 형태의 웹 어플리케이션 개발 경험과 세미나 경험을 가지고 있다. 현재 Hugeflow 웹 솔루션 개발팀에서 개발의욕을 불사르고 있다. 세상을 풍요롭게 하고 사람들에게 강한 종속성을 부여하는 프로그램을 개발하는 것이 목표이다.

   

오시는 길

한국 마이크로소프트 - 포스코 센터 5층

   

   

Windows Azure Update: myAzureStorage

Cloud 2010. 9. 6. 20:30 Posted by 알 수 없는 사용자

지난번 글 (2010/08/23 - [Cloud] - Windows Azure Update: CloudStorageAccount 클래스 사용 시 주의 사항)에 이어서 오늘은 myAzureStorage.com에 대한 내용을 소개합니다.

사이트 바로 가기: http://www.myazurestorage.com/

Windows Azure Platform의 핵심 기능들 중에서, Hosting Service (Compute) 영역 만큼 많은 비중을 차지하고 핵심적인 기능을 담당하는 것이 Storage Service (Storage) 영역입니다. 하지만 Storage Service를 단지 http://windows.azure.com/ 에서 제공하는 웹 프론트엔드로만 관리하는데에는 모자르는 점이 많은데요, 이를 효과적으로 보완하고 좀 더 쉽게 관리할 수 있는 웹 사이트를 소개합니다. 바로 myAzureStorage.com (http://www.myazurestorage.com) 이라는 사이트입니다.

myAzureStorage는 SQL Azure Labs에서 공개한 Codename: Houston과는 별도로 독립적으로 런칭된 웹 서비스로, Windows Azure의 REST Management API를 기반으로 작성된 웹 기반 관리도구이며, 별도의 사용 요금이 없으므로 편리하게 활용할 수 있습니다.

myAzureStorage.com에 접속하면 아래와 같은 로그인 화면이 나타납니다. Windows Azure Platform이 노출하는 REST Service API와의 연결을 위하여 Windows Azure Storage의 계정 ID와 Primary Access Key를 묻는 것이며 이는 http://windows.azure.com/ 에서 Storage Service 항목에 나와있는 값을 대입하면 됩니다.

사이트에 로그인하고 나서는 아래 그림과 같이 Table, Queue, BLOB Storage에 대한 접근을 할 수 있게 되어있습니다. Table Storage의 경우 테이블 스키마를 정의하고 웹 상에서 직접 데이터를 검색할 수 있습니다.

테이블 관리 기능 외에도, 큐에 쌓여있는 메시지를 조회하거나, BLOB 컨테이너 내의 파일을 편집하거나 다운로드하거나, 외부 공개 권한 설정 등을 관리할 수도 있게 되어있습니다. 이 서비스는 Windows Azure REST API를 이용하여 관리하므로 실제 트랜잭션을 일으키는 것 이외에 단순 조회 및 관리는 Windows Azure Platform의 요금 정책에 관계없이 편리하게 이용할 수 있습니다.


Visual Studio Camp #1 세미나를 무사히 마친 지 일주일이 지났습니다. 그 날 날씨가 많이 안좋았음에도 불구하고 많은 분들이 오셔서 너무 고마웠습니다. 나름 준비도 좀 많이 하고, 더 많은 걸 보여드리고 싶었는데, 정해진 시간의 압박으로 그렇게 하지 못해서 아쉬웠습니다. 더구나, 마지막엔 제대로 된 결과도 못 보여드리고,, ㅡㅠ
어찌됐든, 앞으로도 많은 정보를 알려 드릴 수 있도록 열심히 해보겠습니다. 많은 응원 부탁드려요~ ^^

지난 아티클에 이어서, 이번에는 전송 계층에서의 메세지 인증을 할 수 있는 서비스를 만들어 보려 합니다.

ASP.NET 웹 사이트에서 인증을 하는 방법에는 폼 인증과 윈도우즈 인증이 있습니다. 하지만, 보통 웹 어플리케이션을 구축할 때 윈도우즈 인증 보다는 폼 인증을 많이 쓰죠~ (개인적으로, 아직 경험이 미천하여, 윈도우 인증은 적용을 해본 적이 거의 없습니다. ^^;;) 사용자에 대한 정보를 데이터베이스에 따로 저장하고, 그 값을 가져와 인증을 해주는 그러한 방법,,
 
그래서, 이번 아티클에서도 데이터베이스에 사용자 정보를 두고, 이를 이용하여 인증을 할 수 있는 서비스를 만들어보겠습니다.

지난 아티클에서 만들었던 솔루션을 그대로 이용해서, SSL을 이용한 보안을 그대로 사용하려 합니다. 그리고, 여기에 사용자 이름과 패스워드를 이용한 인증을 처리하는 부분을 추가해보도록 하겠습니다. 그래서, 먼저 지난 아티클에서 만들었던 솔루션을 불러오고, 서비스를 다음과 같이 정의합니다.

[ServiceContract]

public interface IService

{

    [OperationContract]

    List<Product> GetAllProducts();

}

 

[DataContract]

public class Product

{

    [DataMember]

    public int Id { get; set; }

 

    [DataMember]

    public string Name { get; set; }

 

    [DataMember]

    public double Price { get; set; }

}


public class Service : IService

{

    public List<Product> GetAllProducts()

    {

        List<Product> products = null;

           

        // (SecurityException)

        if (OperationContext.Current.ServiceSecurityContext.PrimaryIdentity.IsAuthenticated == false)

        {
            // SecurityException 클래스는 System.Security 네임스페이스에 정의 되어 있다.

            throw new SecurityException();

        }

        else

        {

            products = new List<Product>()

            {

                new Product { Id = 1, Name = "Visual Studio 2010", Price = 223.00 },

                new Product { Id = 2, Name = "Expression Blend 4", Price = 133.00 },

                new Product { Id = 3, Name = "Team Foundation Server 2010", Price = 253.00 }

            };

 

            return products;

        }

    }

}


GetAllProducts 메서드에서 인증이 되지 않았을 경우 예외를 발생하는 부분이 있는데, 이 부분만 조금 주의해서 봐주시면 될 것 같습니다. 다른 부분은 지금까지 해온 여타 서비스와 다를게 없죠,,

이제 인증을 처리하는 코드를 작성하려 합니다. 그 전에 인증에 필요한 사용자 정보를 담아둘 데이터베이스가 필요하니깐, 이를 만들어둡니다. 저는 다음과 같은 간단한 Member 테이블을 만들어 보았습니다.


그리고, AuthenticationHelper 라는 이름으로 새로운 클래스를 하나 추가하고, 다음과 같은 코드를 작성합니다.


public class AuthenticationHelper : UserNamePasswordValidator

{

    SqlConnection conn;

    SqlCommand cmd;

    SqlDataReader reader;

 

    public override void Validate(string userName, string password)

    {

        if (userName == null || password == null)

        {

            throw new Exception("User Name or Password cannot be null");

        }

 

        if (!this.CheckIfUserNameExist(userName))

        {

            throw new Exception("Sorry! This User is Not Present");

        }

 

        if (!this.AuthenticateUser(userName, password))

        {

            throw new Exception("Invalid User Name or Password");

        }

    }

 

    private bool CheckIfUserNameExist(string userName)

    {

        bool exists = false;

        this.conn = new SqlConnection
                         ("Server=.\\SQLEXPRESS;Database=Temp;User Id=sa;Password=1111");

        this.cmd = new SqlCommand();

        this.cmd.CommandText = "SELECT UserName FROM Member WHERE UserName=@UserName";

        this.cmd.Connection = this.conn;

        this.cmd.Parameters.AddWithValue("@UserName", userName);

 

        try

        {

            this.conn.Open();

            this.reader = this.cmd.ExecuteReader();

            DataTable dtUser = new DataTable();

            dtUser.Load(this.reader);

 

            int count = dtUser.Rows.Count;

            if (count != 0)

                exists = true;

        }

        catch (SqlException ex)

        {

            throw ex;

        }

        finally

        {

            this.conn.Close();

        }

 

        return exists;

    }

 

    private bool AuthenticateUser(string userName, string password)

    {

        bool valid = false;

 

        this.conn = this.conn = new SqlConnection
                         ("Server=.\\SQLEXPRESS;Database=Temp;User Id=sa;Password=1111");

        this.cmd = new SqlCommand();

        this.cmd.CommandText = "SELECT Password FROM Member WHERE UserName=@UserName";

        this.cmd.Connection = this.conn;

        this.cmd.Parameters.AddWithValue("@UserName", userName.Trim());

 

        try

        {

            this.conn.Open();

            this.reader = this.cmd.ExecuteReader();

               

            reader.Read();

            if (reader["Password"].ToString() == password.Trim())

                valid = true;

        }

        catch (SqlException ex)

        {

            throw ex;

        }

        finally

        {

            this.conn.Close();

        }

 

        return valid;

    }

}

이번 코드는 조금 길군요 ^^;;
하지만, 코드를 조금 살펴보시면 알겠지만 그렇게 어려운 코드는 아닙니다. 코드가 길다고 어려워 할 필요 없다구요~ ㅎ

주목해야 할 점은 AuthenticationHelper 클래스가 UserNamePasswordValidator 클래스를 상속하고 있다는 것인데, UserNamePasswordValidator 클래스는 WCF 서비스에서 사용자 지정 사용자 이름 및 암호 유효성 검사기를 만들기 위한 클래스입니다. (사용자 지정 사용자 이름 및 암호 유효성 검사기 사용 참고)
한마디로, 윈도우즈 인증이 아닌 사용자가 정의한 인증 방법을 WCF 서비스에 적용하기 위한 유효성 검사기를 만들기 위한 클래스라고 이해하시면 될 것 같습니다.

유효성 검사기를 만드는 방법은 아주 간단한데, UserNamePasswordValidator 클래스에 정의 된 Validate 메서드를 재 정의(overriding) 해주면 됩니다.

이제, 거의 서비스를 다 만든 것 같습니다. 마지막으로 web.config를 수정하여, 사용자 지정 인증 방법을 쓸 수 있도록 해주는 일이 남았습니다. 그리고, 지난번 아티클에서 만들었던 인증서를 사용하도록 해주는 태그도 필요합니다.

web.config 파일을 다음과 같이 수정해 보도록 하겠습니다.

<system.serviceModel>

  <services>

    <service name="SSLService.Service" behaviorConfiguration="MyBehavior">

      <endpoint address="" binding="basicHttpBinding" bindingConfiguration="MyBind"

        contract="SSLService.IService">

        <identity>

          <dns value="localhost"/>

        </identity>

      </endpoint>

      <endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange" />

      <host>

        <baseAddresses>

          <add baseAddress="http://localhost:4949/Service1.svc" />

          <add baseAddress="https://localhost:4948/Service1.svc" />

        </baseAddresses>

      </host>

    </service>

  </services>

 

  <bindings>

    <basicHttpBinding>

      <binding name="MyBind">
        <!-- 메세지 자격증명을 위한 설정 -->

        <security mode="TransportWithMessageCredential">

          <message clientCredentialType="UserName"/>

        </security>

      </binding>

    </basicHttpBinding>

  </bindings>

  <behaviors>

    <serviceBehaviors>

      <behavior name="MyBehavior">

        <serviceCredentials>
          <!-- 메시지 보안 모드를 사용하는 클라이언트에 대한 서비스를
                인증하는 데 사용할 X.509 인증서를 지정합니다-->

          <serviceCertificate storeName="My" storeLocation="LocalMachine"
                                      x509FindType=
"FindBySubjectName"

                                      findValue="Dreamer"/>
          <!-- 사용자 인증을 할 때 사용할 component를 정의합니다. -->

          <userNameAuthentication

            userNamePasswordValidationMode="Custom"

            customUserNamePasswordValidatorType="SSLService.AuthenticationHelper,SSLService"/>

        </serviceCredentials>

        <serviceMetadata httpGetEnabled="true" />

        <serviceDebug includeExceptionDetailInFaults="false" />

      </behavior>

    </serviceBehaviors>

  </behaviors>

  <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />

</system.serviceModel>


web.config 파일도 뭔가 내용이 많습니다. 역시 보안 설정은 어려워요,, ^^;;

하지만, 자세히 보면 익숙하지 않은 태그는 그리 많지 않습니다. 이 태그들에는 대충의 주석을 달아놨으니 이해하기는 어렵지 않을 것 같구요~

전체적으로 설명을 붙이자면, 서비스에 적용할 Behavior와 Binding에 대한 설정이 필요하여 각각 "MyBehavior", "MyBind" 라는 이름으로 태그를 추가하였고, 그 안에 필요한 태그들을 추가하였습니다.

"serviceCertificate" 태그는 인증 시 사용할 인증서를 지정하는데 지난 아티클에서 만든 인증서를 사용하면 됩니다. 이때, "findValue" 속성에 들어갈 값은 인증서의 발급자에 들어있는 값을 입력하여야 합니다.
그리고, "userNameAuthentication" 태그는 사용자 인증 시 사용할 component를 정의하는데 "customUserNamePasswordValidatorType" 속성에는 UserNamePassowrdValidator 클래스를 상속받아 구현 된 클래스 명을 입력해주면 됩니다.

서비스 구현은 모두 끝났습니다. 이제 콘솔 어플리케이션을 이용해 이 서비스를 사용해보도록 하겠습니다.
클라이언트 구현은 이 전에 구현했던 다른 클라이언트들과 다를바가 없습니다. 단지, 서비스 인증을 위해 사용자 이름과 패스워드를 입력해줘야 하는 부분만 추가해주면 됩니다.

콘솔 어플리케이션 프로젝트를 추가한 후에 서비스를 추가하고(이때, https 로 시작되는 url을 이용하여 서비스를 추가합니다.), 다음과 같이 Main 메소드를 구현합니다.

static void Main(string[] args)

{

    ServiceClient proxy = new ServiceClient();

    // 패스 .

    proxy.ClientCredentials.UserName.UserName = "ruaa";

    proxy.ClientCredentials.UserName.Password = "P@ssw0rd";

 

    Product[] products = proxy.GetAllProducts();

 

    foreach (Product p in products)

    {

        Console.WriteLine("ID : {0}", p.Id);

        Console.WriteLine("Name : {0}", p.Name);

        Console.WriteLine("Price : {0:f}\n", p.Price);

    }

}


보이시죠? 어떻게 인증을 위한 사용자 이름과 패스워드를 입력하는지,, ㅎ

당연히 여기에 입력되는 사용자에 대한 데이터는 앞에서 만들었던 Member 테이블에 존재해야 합니다.

이렇게 하면, 다음과 같은 결과화면을 확인할 수 있습니다. ^^


네~ 이것으로 이번 포스팅도 끝이 났습니다.
긴 글 읽으시느라 모두들 수고하셨고, 다음 포스팅때 뵙겠습니다. 감사합니다~ ^^

안녕하세요. 지난 2010년 8월 28일, '한국 Visual Studio 공식 팀(Visual Studio Korea)' 에서 주최한 Visual Studio Camp #1 세미나의 발표 자료를 공개해 드립니다. (세미나의 후기는 [세미나 후기] Visual Studio Camp #1 를 참고하세요)    

※ 세미나 발표 자료의 저작권과 권리는 발표를 진행한 스피커와 Visual Studio Korea(한국 Visual Studio 공식 팀) 에 있으므로, 영리/비영리/변경하실 수 없습니다.

PDF 문서 다운로드

   

XPS 문서 다운로드

 

세미나 아젠다

  

Native 트랙

.NET 트랙

Enterprise 트랙

14:00 ~ 14:50

Visual Studio 2010 : C++0x와 Windows 7
최성기

그것이 알고싶다 - C# 4.0의 변화, 그 진실은 무엇인가. 희망인가? 또 다른 혼란인가?
강보람 C# MVP

VS Team Foundation Server 2010 의 새로운 변화
김병진 ALM MVP

15:00 ~ 15:50

비주얼 스튜디오 2010 의 Concurrency Runtime 을 이용한 멀티 코어 제대로 활용하기
임준환

좋은 프레임워크 있으면 소개시켜줘 - ASP.NET MVC
박세식

소프트웨어 품질 향상을 위한 다양한 테스트 기법
엄준일 ALM MVP

16:00 ~ 16:50

DirectX11 을 기다리며..
조진현

Beginnig WCF
오태겸

SharePoint 2010 Enterprise 솔루션 개발
정홍주 SQL Server MVP

   

발표 내용 소개 및 세미나 PPT 자료

Native 트랙

Visual Studio 2010 : C++0x와 Windows 7
그 동안 .NET 영역으로 적잖이 편중되었던 Visual Studio의 버전업에 비해 이번 2010 버전에서는 Native Code 개발환경에서도 많은 변화가 찾아왔다. C++0x 표준 반영에 의한 문법의 변화, 새로운 라이브러리 제공(Concurrency Runtime Library), Windows 7의 최신 기능들을 제어하기 위한 SDK의 업데이트 등이 그것이다. 본 세션을 통해 C++의 문법적인 변화와 Windows 7 기능 구현을 위한 SDK의 업데이트 사항들을 정리해본다.

 

비주얼 스튜디오 2010 의 Concurrency Runtime 을 이용한 멀티 코어 제대로 활용하기
요즘 가정의 PC 에 멀티 코어 프로세서가 많이 보급되어 있습니다. 하지만 실제로 PC 에 설치된 코어들을 모두 사용하는 애플리케이션들은 많지 않습니다. 이렇게 낭비되는 자원을 C++ 개발자가 쉽게 사용할 수 있도록 도와주는 Concurrency Runtime 을 비주얼 스튜디오 2010에서 제공합니다. 이 Concurrency Runtime 을 어떻게 시작해야 할지 알아보겠습니다.

 

DirectX11 을 기다리며...
조금씩 정보가 공개되면서 많은 변화를 예고하고 있는 DirectX11 에 대해서 살펴 볼 것입니다. 특히나 Tessellation, DirectCompute, Multi-threading 을 위한 기본 개념과 작업들에 대해서 체크해 볼 것입니다.

조진현님 PPT 는 현재 비공개이며, 추후 공개하도록 하겠습니다.

.NET 트랙

그것이 알고싶다 - C# 4.0의 변화, 그 진실은 무엇인가. 희망인가? 또 다른 혼란인가?
PDC 2008에 울려 퍼진 C# 4.0의 소식. 그 소식을 듣고 많은 사람들은 기대와 혼란을 가지게 되었다. C#은 분명히 정적 언어인데, 동적 언어에나 있을 법한 기능을 추가한다니? 이제 와서 뒷북일 수도 있는 C# 4.0의 변화에 대한 진실, 그 마지막 시리즈가 이제 시작된다. :)

   

좋은 프레임워크 있으면 소개시켜줘 - ASP.NET MVC
그 동안 아주 미묘하게 아쉬웠던 ASP.NET. 가려운 곳을 긁어줄 대안의 프레임워크가 나타났다. 웹 개발자들 한테 참~ 좋은데, 웹 개발자들 한테 정말 좋은데, 이걸 말로 그냥 할 수 없어서, 이번 기회에 소개한다.

   

Beginnig WCF
WCF는 서비스 지향 프로그래밍을 위해 마이크로소프트에서 개발 및 지원하는 기반 기술이며, 기존의 .NET 웹 서비스에 비해 유연성과 확장성이 뛰어나 최근 많은 관심을 받고 있습니다. 본 세션에서는 WCF가 무엇인지? 어떤 장점이 있는지? 그리고, WCF 를 이용하기 위해선 무엇이 필요한지? 에 대해 함께 알아보고, 마지막으로, WCF의 활용 예를 알아보도록 하겠습니다.

Enterprise 트랙

VS Team Foundation Server 2010 의 새로운 변화
V
isual Studio Team Foundation Server 2010의 혁신적인 변화와 개선 부분, 프로젝트 및 형상관리와 Agile의 Scrum 을 이용한 방법론을 알아보고, 단지 소스 체크인/아웃만 하는 Visual Source Safe에서 업그레이드 하는 방법에 대하여 알아봅니다.

   

소프트웨어 품질 향상을 위한 다양한 테스트 기법
소프트웨어는 개발 및 릴리즈 과정까지 수 많은 과정을 겪는데, 소프트웨어가 점진적으로 진화함에 따라 결함의 발생률이 증가합니다. 이를 개선하기 위한 테스트 기법 중 단위 테스트, WhiteBox 테스트, 화면 테스트, 성능 테스트, 부하 테스트 등 다양한 테스트 기법을 알아봅니다.

   

SharePoint 2010 Enterprise 솔루션 개발
SharePoint 2010은 기업 협업 플랫폼으로 개발자들은 VS 2010을 이용하여 더 생산성 있고 효과적인 SharePoint 2010 개발을 진행할 수 있습니다. 본 세션에서는 SharePoint 2010 개발에 대한 가장 필요한 내용을 구체적으로 알아보며 이를 통해 가장 많은 요구사항에 대한 실무 솔루션을 구성하는 방법에 대한 내용을 알아보겠습니다.

   

   

Hello Windows Azure / Twitter 스타일 방명록 만들기 #3

Cloud 2010. 9. 4. 00:27 Posted by 알 수 없는 사용자

시작하기 전에

지난번 글 (2010/08/10 - [Cloud] - Hello Windows Azure / Twitter 스타일 방명록 만들기 #2)에 이어서 이번 강좌에서는 Web Role과 Worker Role의 시작 원리, 방명록 서비스에 사진을 첨부하는 것과, 업로드한 사진을 비동기적으로 편집하고 처리하는 것을 설명하도록 하겠습니다.

Web Role의 시작점에 대한 이해와 학습

Windows Azure Platform에서 실행되는 Web Role은 ASP.NET 환경을 지원하지만, 좀 더 정확히 표현하면 Web Role은 ASP.NET 사이트를 논리적으로 표현한 모델이면서 동시에 하나의 Application Project이기도 합니다. Web Role 안에서 구동되는 Windows Server 2008 R2 운영 체제는 전적으로 개발자가 업로드한 Web Role 코드에 의하여 역할이 고정되고 주어진 작업만을 수행해 나가게 되어있습니다.

어떤 유형의 응용프로그램이라할지라도 만국 공통적인 요소가 하나 있는데, 바로 "진입점" (Entry Point)의 존재 여부입니다. 이것은 Windows Azure Platform 위에서 실행되는 Cloud Application에도 예외없이 적용됩니다. 지금 설명하려는 WebRole 클래스가 이러한 진입점에 속합니다. 아래는 WebRole.cs 파일의 소스 코드이며 중요한 부분에 설명을 기술하였습니다.

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.Diagnostics;
using Microsoft.WindowsAzure.ServiceRuntime;

namespace TwistBook.WebRole
{
    public class WebRole : RoleEntryPoint
    {
        public override bool OnStart()
        {
            DiagnosticMonitor.Start("DiagnosticsConnectionString");

            // 구성 변경 내용을 처리하는 방법은
            // MSDN 항목(http://go.microsoft.com/fwlink/?LinkId=166357)을 참조하십시오.
            RoleEnvironment.Changing += RoleEnvironmentChanging;

            return base.OnStart();
        }

        private void RoleEnvironmentChanging(object sender, RoleEnvironmentChangingEventArgs e)
        {
            // 구성 설정을 변경 중인 경우
            if (e.Changes.Any(change => change is RoleEnvironmentConfigurationSettingChange))
            {
                // e.Cancel을 true로 설정하여 이 역할 인스턴스를 다시 시작하십시오.
                e.Cancel = true;
            }
        }
    }
}

Worker Role의 시작점에 대한 이해와 학습

 

BLOB Storage에 파일을 첨부하고, 이미지를 꺼내오기

 

ImageProcessorRole에 작업을 통지하기

 

ImageProcessorRole에서 작업을 받아 처리하기

 

클라우드에 배포하기 - #1: Visual Studio - 또는 - Visual Web Developer를 통해 배포하기

 

클라우드에 배포하기 - #2: 웹 제어판을 통해 배포하기

 

클라우드에 배포하기 - #3: Visual Studio 2010 Ultimate 만의 특권 - IntelliTrace

 

결론

 

[Step. 12] for each

C++/CLI 2010. 9. 3. 09:00 Posted by 알 수 없는 사용자

데이터셋에 있는 요소를 열거할 때 비관리코드에서는 보통 for문이나 while문을 자주 사용합니다.

그러나 C++/CLI에서는 for each을 사용하여 데이터셋에 있는 요소들을 열거할 수 있습니다.

for each에서 사용할 수 있는 것은 배열 이외에도 아래의 형으로 구현한 것들을 사용할 수 있습니다.

 

1. IEnumerable 인터페이스를 구현한 클래스

2. STL의 이터레이터와 같은 것을 가지고 있는 클래스

 


참고로 VC++ 8(VS 2005)에서는 비관리코드에서도 for each 문을 지원하고 있습니다.

for each를 사용할 때 주의해야 할 점은 열거하는 요소를 변경할 수는 없다는 것입니다.

 

#include "stdafx.h"

#include <iostream>

#include <vector>

#include <map>

 

using namespace std;

using namespace System;

using namespace System::Collections;

 

 

int main(array<System::String ^> ^args)

{

     // 배열

     array< int >^ Nums = { 0, 1, 2, 3, 4, 5 };

     for each(int value in Nums)

     {

          value = 2;

          Console::WriteLine( value );

     }

    // 위에서 for each 내부에서 요소의 값을 바꾸었지만 아래의 출력 값을 보면

    // 바뀌지 않은 것을 알 수 있습니다.

    for each(int value in Nums)

    {

          Console::WriteLine( value );

    }

 

   

    // 리스트

    ArrayList^ NumList = gcnew ArrayList();

    NumList->Add(1);

    NumList->Add(2);

    NumList->Add(3);

 

    for each(int value in NumList)

    {

        Console::WriteLine(value);

    }

 

 

    // vector

    vector<int> vi;

    vi.push_back(3);

    vi.push_back(4);

   

    for each(int i in vi)

    {

        Console::WriteLine(i);

    }

 

 

    // map

    map<const char*, int> num;

    num["ten"] = 10;

    num["hundred"] = 100;

 

    for each( pair<const char*, int> c in num )

    {

        Console::WriteLine(gcnew String(c.first) + c.second.ToString());

    }

 

 

    // 해쉬 테이블

    Hashtable^ ht = gcnew Hashtable();

    ht["aaa"] = "111";

    ht["bbb"] = "222";

    for each(DictionaryEntry^ dic in ht)

    {

        Console::WriteLine(dic->Key->ToString() + dic->Value->ToString());

    }

    

 

    getchar();

    return 0;

}

'C++/CLI' 카테고리의 다른 글

[Step. 15] static 생성자, initonly, literal  (1) 2010.09.24
[Step. 13] parameter array  (1) 2010.09.10
[Step. 11] 열거형( enum )  (2) 2010.08.27
[Step. 10] 이벤트 ( event )  (0) 2010.08.20
[Step. 09] 델리게이트 (delegate)  (2) 2010.08.12

2010년 8월 28일, Visual Studio Camp #1 에서 발표한 "Enterprise Track : [2] 소프트웨어 품질 향상을 위한 다양한 테스트 기법 - 엄준일 ALM MVP" 세션을 들어주신 분 중에 어느 테스트 전문가를 만나 뵙게 되었습니다. 최근 테스트 공학과 테스트 프로세스에 푹 빠져있는 저에게 매우 단비와도 같은 분이시고, 특히 테스트 전문 도구인 Load Runner 제품을 실제로 사용하고 계신 분이셨습니다.

(http://willstory.tistory.com/4)

제 세션의 내용과 현재 사용하고 계신 Load Runner 제품에 대해 경험적으로 비교를 해 주신 후기를 작성해 주셔서, 여러분들에게 도움이 될까 싶어 @will_story 님의 동의를 얻어 저희 팀 블로그에 게시하게 되었습니다.

가격에서 상당히 차이가 나는 Load Runner 와 Visual Studio 2010 Ultimate(테스팅 기능에 한하여) 비교해 주셨는데, 역시 비싸다고 좋은 도구는 아닌가 봅니다.^^ 이 두 도구에 대해 냉철하게 비교해 주신 @will_story 님께 감사 드리며, @will_story 님의 글을 보기 쉽게 편집하여 전문을 공개해 드립니다.

참고로, Visual Studio 2010 은 매우 광범위한 테스트 영역을 지원하고 있습니다. 테스트 공학에서 접근하는 대부분의 테스트 기능이 Visual Studio 2010 하나의 통합 도구에서 제공하는 것입니다.

[그림1] 테스트 기법 정리(Visual Studio Camp #1 의 세션 내용 중)

   

아래의 글은 http://willstory.tistory.com/4 의 글쓴이의 동의 하에 제공되어, 약간의 편집하였으나, 원문의 의미상 변형이 전혀 없음을 알려드립니다. 좋은 글을 제공해 주셔서 감사의 마음을 전해 드립니다. ^^

비주얼 스튜디오 2010 팀 블로그에서 Visual Studio Camp를 진행하였다. 여러가지 세션이 있었지만 나의 관심사항만 세미나를 경청하고 퇴장하였다. 유익한 정보였고 너무나도 소중한 시간이었다. 혹시 세미나 후기에 대한 내용에 대하여 자세한 정보를 알고 싶다면 아래의 링크를 따라갔으면 좋겠다.

Load Runner 의 버전은 8.1이다. 나에게는 아직 Windows 7이 없어 XP에서 잘 돌아가는 8.1 버전으로 작성하였다. Windows 7 에서 Load Runner 10.1을 해보고 싶었지만 OS가 없기에 아쉽게도 XP기준으로 작성한다.

[세미나 후기] Visual Studio Camp #1

Enterprise Track : [2] 소프트웨어 품질 향상을 위한 다양한 테스트 기법 - 엄준일 ALM MVP – 땡쵸[엄준일]

소프트웨어 개발의 이전의 사례를 바탕으로 테스팅의 중요성과 그 기법과 방법을 공부하면서 경험한 내용을 전달하였습니다. 소프트웨어 개발 프로세스 중 테스팅의 매력에 푹 빠져 있답니다.

소프트웨어는 개발 및 릴리즈 과정까지 수 많은 과정을 겪는데, 소프트웨어가 점진적으로 진화함에 따라 결함의 발생률이 증가합니다. 이를 개선하기 위한 테스트 기법 중 단위 테스트, WhiteBox 테스트, 화면 테스트, 성능 테스트, 부하 테스트 등 다양한 테스트 기법을 알아봅니다.

사실 PPT 자료만 올라오면 이미지를 Load Runner 와 비교하고 싶었지만 아쉽게도 자료를 받지 못한 것이 아쉽다. 먼저 Load Runner 이미지로 비교 분석을 하고자 한다. 나중에 추후 VS2010 팀에서 자료를 받으면 추후 업그레이드를 하도록 하겠다.

자아.. 이제 내 Tistory의 첫 포스팅이자 첫 블로그 운영이 내가 관심이 있는 분야라서 매우 즐겁다. 이제 이야기를 보따리를 풀어보자.

Visual Studio Camp #1은 예전부터 신청하였다. 전에도 SW Testing Bar Camp 때 주최하였던 곳에서 그리 멀지 않은 곳이기 때문에 가기까지는 무리 없이 도착하였다. 이전에 Sten에서 Razar라는 제품[베타 테스트로 참석하여 경품을 받게 되었다.]으로 테스트한 경험을 공유한다고 하여 10시에 일정이 있었는데, 필요인원 부족으로 무산이 되어 집에서 피파온라인으로 열심히 게임을 하다가 세미나 시간에 맞추어 참석하였다.

도착하였을 때 깔끔한 신청 절차 간편한 입장이 인상적이다. 누가 발표자인지 누가 경청자인지 알 수 있는 이름표는 좋았다는 생각이 들었다. 하지만 이름표에 자신의 맡고 있는 MVP 분야를 적어 두었다면 경청자가 추후 질문을 하는데 있어 생각하는 수고를 덜어줄 수 있지 않았을까? 라는 생각을 하게 된다. 1시간 정도의 짧은 만남 물론 얼굴과 이름은 질문자가 당연히 갖추어야 할 기본 예의지만 … 그냥.. 뭐 아쉽다는거다.

난 엔터프라이즈 Enterprise Track : [2] 소프트웨어 품질 향상을 위한 다양한 테스트 기법 - 엄준일 ALM MVP 님의 세미나를 들었다. 들으면서 Load Runner 와 흡사하기 보다는 오히려 'Load Runner 를 뛰어 넘을 수도 있겠다'라는 생각과 전율이 마음 깊숙히 전해져 왔다. 이미지가 있다면 전달이 쉽겠지만 아쉽다.. 아쉬워….

   

첫 번째, 비교[다양한 옵션 VS 심플함]

  • Load Runner 의 강점! 다양한 옵션

    다양한 옵션을 포함하고 있어 스크립트 작성 시 웹 페이지에 맞도록 작성이 용이하다.
    이외에 다양한 옵션이 존재한다. 좀…. 복잡하다. 잘못 설정했다가 원하는 결과를 얻기 어렵다.

  • Visual Studio 2010 강점
    Simple 하다. 너무도 쉽게 심지어 Load Runner 보다 쉽다. Load Runner 의 사용자 매뉴얼은 너무도 이론적이며 복잡하다.
    하지만 Visual Studio 안내 설명은 매우 쉽게 설명하여, 특히 Visual Studio 2010 공식 팀 블로그에서도 자세하게 설명을 해주고 있다. 직접 경험을 기반으로 작성을 해주니 이보다 친절하고 절실하게 와닿은 설명이 어디 있겠는가!(소통과 공유가 존재하는 것)

    일반 사용자가 특히 개발자가 바로 바로 성능 테스트를 수행 할 수 있도록 되어있다.

   

두 번째, 비교[성능 테스트 시나리오]

  • 스케줄이 편리한 강점
    원하는 대로 인원도 증가 시킬 수 있다. 예약시간도 존재한다. 성능을 위하여 새벽2시에 기다려 테스트하지 않고 예약시간을 설정하면 알아서 돌아 간다. 랜덤으로 oo명에서 0명까지 물결 치듯 설정도 가능
  • 편리한 스케줄 일정
    Load Runner 와 마찬가지로 스케줄이 변경이 동일하다. 랜덤으로 oo명에서 0명까지 물결 치듯 설정도 가능한지는 짧은 세미나 내용으로 언급되지 못한 것이 아쉬운 점이다. 하지만 예상으로는 될 것으로 보인다.

   

세 번째, 비교[성능 모니터링]

  • Load Runner 의 모니터링
    Load Runner 는 Web/HTML만 반영하는 것이 아니며 DB/Oracle도 성능 테스트가 가능하기 때문에 매우 다양한 모니터링 지원이 가능하다[물론 돈이 많은 기업이라면 유로로 라이선스를 사야 한다.]
  • Visiual Studio 2010의 모니터링
    가장 아쉬운 부분 중에 하나이다. Load Runner 처럼 다양한 모니터링을 제공할 수 있을까[?] 라는 의문이 든다.
    하지만 강점도 있다. Load Runner 모니터링보다 심플하고 깔끔하며 원하는 정보만 보여준다. 로드러너 처럼 4개 정도의 모니터링 그래프를 제공하는 형식은 비슷하지만 디자인 면에서나 컴퓨터를 오래 사용하는 사용자의 입장에서 생각하는 UI는 Microsoft 의 Windows 7 로고처럼 심플하면서도 편안한 이미지로 되어있다.
    Load Runner 는 보고서를 출력하면 중복되는 내용이 많은데 Visual Studio 2010은 깔끔함과 심플함 원하는 정보와 불필요한 중복을 피하는 듯한 느낌을 받았다.

   

네 번째, 비교[리포트 및 보고서 출력]

  • Load Runner 의 모니터링
    Load Runner 는 2가지 방식으로 보고서를 출력할 수 있다. HTML, *.doc(docx) 방식이다. 알아서 목차도 만들어주고 내용도 작성해 준다. 물론 아쉽지만 영어로만 제공된다. 나는 그래서 주로 그래프만 이용한다.
     
        
  • Visiual Studio 2010의 모니터링
    내가 보았을 경우에는 *.execl 형식으로 출력을 하는 것을 보았다. 조금은 아쉬운 점이다. 보고서를 다른 발주처에 보내었을 때 엑셀보다는 워드파일로 만약 공공기관이라면 *.hwp 파일로 보내야 하지만 *.execl은 조금은 뽀대[?]가 부족하다. 작성한 문서를 워드로 다시 편집 해야하는 수고를 덜어야 한다.
    물론 99% 성능 전문가들과 각 회사마다 프로젝트 성능 담당자들은 회사에서 쓰는 양식을 이용하여 템플릿에 맞게 보고서를 작성할 것이다. 나 또한 회사 템플릿으로 작성한다. 하지만 보고서로 출력하여 바로 줄 수 있을 정도의 수준이라면 이제는 로드러너는 내 손을 떠나 보내고 Visual Studio 2010 을 사용하지 않을까 생각한다.

   

Visual Studio 2010 Camp #1 짧은 후기

세션을 들으면서 엄준일[땡초]님과 10정도의 대화를 나누었다. 테스트에 재미를 붙이신 듯 호기심 어린 모습과 열정에 박수를 보내주고 싶다. [테스트의 세계로 오신 것을 환영합니다. 쿠쿠쿠쿠.ㅋ]

Visual Studio 2010 Camp #1 를 진행하셨던 어느 기술전도사님이 예전에 나도 스탭으로 다른 몇몇 분들과 함께 진행한 SW Testing Camp 와 함께 진행하였으면 좋겠다고 제안하였을 때 당장 "그럽시다" 라고 대답하고 싶었지만 아쉽게도 나 혼자만의 결정할 사안이 아니기에 대답을 회피했다. 아쉽 아쉽… Windows 7 운영체제에 Visiual Studio 2010 을 설치한 제품과 Load Runner 를 비교하면 나의 객관적인 입장에서는 Load Runner 에게 8.5점을 Visual Studio 2010 에게는 9.0점을 주고 싶다.

1시간만 들었던 세미나였지만 너무나 강렬한 인상이 아직도 기억 속에 남는다. 엄준일님이 함께하자는 말과.. 기술전도사님이 Visual Studio 2010 팀에서 함께 하자는 말 들이..

"기술전도사님 사실 저는 Windows 7이 없어요.. Visual Studio 2010도 없어요. ㅠㅠ;;; 빌려주시면.. 해보고는 싶어요.ㅠㅠ". 흑흑 2010년도는 일만 벌린다.. 담 주는 대학원 개강이구나

Windows 7에 Visiual Studio 2010 설치해주는 회사로 이직 옵션의 하나로 정해야겠다.. 좋은 회사 있음 소개시켜줘~ *_*/

많은 정보를 공유하고 싶지만 방화벽으로 text로만 해야 하는 회사에 아쉬움을 던지며 이만 작성 끝~~~

필자는 Load Runner 를 써보지 않고, 오직 Visual Studio 만으로 테스팅 공학과 분야에 흥미를 갖고 공부를 하고 있습니다. 이번 Visual Studio Camp #1 을 통해서 오히려 저에게 좋은 정보를 제공해 주시고, 의견을 공유할 수 있어서 너무 뜻 깊은 자리였습니다.

좋은 글을 저희 팀 블로그에 기고에 동의해 주신 http://willstory.tistory.com/4 님께 감사합니다.

Concurrency Runtime – Task Scheduler 1. ( Scheduler )

VC++ 10 Concurrency Runtime 2010. 9. 2. 08:30 Posted by 알 수 없는 사용자

Concurrency Runtime
– Task Scheduler 1. ( Scheduler )

작성자: 임준환( mumbi at daum dot net )

 

시작하는 글

 이번 글은 Parallel Patterns Library( 이하 PPL ) 과 Asynchronous Agents Library( 이하 AAL ) 내부에서 스케줄링을 하는 Scheduler 에 대해서 알아보도록 하겠습니다.

 

Scheduler class

 Scheduler 클래스는 Concurrency Runtime 에서 실제로 스케줄링을 하는 객체입니다. 우리는 Scheduler 객체를 사용해서 스케줄링의 방법을 설정할 수 있습니다.

 Scheduler 는 내부적으로 작업들을 그룹화한 ScheduleGroup 을 관리합니다. 또한 요청된 작업을 수행하는 Context 객체에 접근할 수 있도록 하여, 좀 더 구체적인 스케줄링을 할 수 있도록 도와줍니다.

 

Scheduler 생성

 우리가 직접 Scheduler 를 생성하지 않아도, Concurrency Runtime 내부에서 기본 Scheduler 가 생성되어 스케줄링을 하게 됩니다. 이 경우에는 스케줄링 정책을 바꿀 수는 있으나, 세밀하게 제어할 수 없습니다.

 기본 Scheduler 외에 직접 우리가 Scheduler 를 생성하는 방법은 2 가지가 있습니다.

  • CurrentScheduler::Create() 는 현재 컨텍스트와 연결하는 Scheduler 를 만듭니다.
  • Scheduler::Create() 는 현재 컨텍스트와 연결되지 않는 Scheduler 를 만듭니다.

 Scheduler 는 내부적으로 참조 개수( reference counting ) 을 사용하여, 수명을 관리합니다. 그래서 참조 개수가 0이 되면 Scheduler 가 소멸됩니다.

 

Scheduler::Create()

 현재 컨텍스트와 연결되지 않은 Scheduler 를 생성합니다. 참조 개수가 1로 설정됩니다.

 

Scheduler::Attach()

 현재 컨텍스트와 Scheduler 를 연결합니다. 참조 개수가 증가합니다.

 

Scheduler::Reference()

 참조 개수가 증가합니다.

 

Scheduler::Release()

 참조 개수가 감소합니다. 참조 개수가 0이 되면 소멸됩니다.

 

CurrentScheduler::Create()

 현재 컨텍스트와 연결된 Scheduler 를 생성합니다. 참조 개수가 1로 설정됩니다.

 

CurrentScheduler::Detach()

 현재 컨텍스트를 분리합니다. 참조 개수가 감소합니다. 참조 개수가 0이 되면 소멸됩니다.

 

생성과 소멸, 연결과 분리

 위와 같은 함수들을 제공하지만, 생성과 소멸, 연결과 분리가 짝을 이루어야 합니다.

 CurrentScheduler::Create() 로 생성하였다면, CurrentScheduler::Detach() 로 소멸시키는 것이 좋습니다.

 Scheduler::Create() 로 생성하고, Scheduler::Attach() 로 연결하였다면, Scheduler::Detach() 로 해제하고, Scheduler::Release() 로 소멸해야 합니다.

 만약 Scheduler::Reference() 를 통해 참조 개수를 증가시켰다면, Scheduler::Release() 를 사용하여 참조 개수를 감소시켜주어야 합니다.

 

소멸 시점 알림

 모든 작업이 끝나기 전에는 Scheduler 를 소멸시키지 않습니다. 언제 Scheduler 가 소멸되는지 알기 위해서는 RegisterShutdownEvent() 를 사용하여 Windows API 의 EVENT 객체를 지정해 주고, WaitForSingleObject() 를 사용하여 소멸될 때까지 대기할 수 있습니다.

 

그 외의 멤버 함수

 위에서 설명한 멤버 함수 이외에 제공하는 멤버 함수들을 알아보도록 하겠습니다.

 

CurrentScheduler

  • Get() – 현재 컨텍스트에 연결된 Scheduler 의 포인터를 반환합니다. 참조 개수가 증가하지 않습니다.
  • CreateScheduleGroup() -  ScheduleGroup 을 생성합니다.
  • ScheduleTask() – Scheduler 의 일정 큐에 간단한 작업을 추가합니다.
  • GetPolicy() – 연결된 정책의 복사본을 반환합니다.

 

Scheduler

  • CreateScheduleGroup() – ScheduleGroup 을 생성합니다.
  • ScheduleTask() – Scheduler 의 일정 큐에 간단한 작업을 추가합니다.
  • GetPolicy() – 연결된 정책의 복사본을 반환합니다.
  • SetDefaultSchedulePolicy() – 기본 Scheduler 에 적용될 정책을 설정합니다.
  • ResetDefaultSchedulePolicy() – 기본 Scheduler 의 정책을 SetDefaultSchedulerPolicy() 를 사용하기 전의 정책으로 설정합니다.

 

마치는 글

 이번 글에서는 Concurrency Runtime 의 Scheduler 에 대해서 알아보았습니다. 위의 설명만으로는 어떻게 사용해야 하는지, 어떤 기능을 하는지 알기 어렵습니다.

다음 글에서 위에서 소개해드린 멤버 함수들의 사용 방법과 활용 예제들에 대해서 알아보도록 하겠습니다.

SharePoint 2010 프로젝트 디버깅

SharePoint 2010 2010. 8. 31. 23:41 Posted by 알 수 없는 사용자

이번 내용은 Visaul Studio 2010에서 SharePoint 2010 프로젝트로 개발할 경우 디버깅을 하는 방법에 대한 것입니다.

너무 간단하지만 몰라서 디버깅을 잘 못하는 분들이 있더라구요.

디버깅을 하는 방법은 그냥 F5 를 누르시면 됩니다. Feature를 Dactivate 하고 다시 배포하고 디버깅 메뉴에서 프로세스를 연결하고 등등은 다 옛날 얘기입니다. Visual Stduio 2010 에서의 SharePoint 2010 프로젝트는 그냥 F5 입니다. 물론 중단점 찍구요.

아래는 Visual Web Part 를 디버깅하기 위해 중단점을 찍은 화면입니다.



자 그럼 F5 를 누르면 어떤 일이 벌어지는지 한번 보도록 하겠습니다.

1. 새 버전 .wsp 파일 빌드
2. Feature 비활성화/삭제
3. old .wsp 파일 삭제
4. new .wsp 파일 추가/배포
5. Feature 활성화

디버깅을 해서 출력 창을 캡쳐해보도록 하겠습니다.



SharePoint 2010 웹 사이트의 웹 페이지가 뜨게 되고 웹파트를 추가하고 액션을 발생하면 디버깅으로 들어오게 됩니다. 무조건 알아서 오지는 않습니다. 여기는 드롭다운을 변경했을때 디버깅으로 들어오게 됩니다.
이제 디버깅으로 들어온 화면입니다. .NET 디버깅이므로 별로 드릴 말씀이 없습니다.



타임아웃이 있기 때문에 시간이 지나면 디버깅이 중지되게 됩니다.

이 디버깅으로 인하여 개발하기가 편해진 감이 있기는 합니다.

다음 내용은 Developer Dashboard에 대한 내용을 알아보도록 하겠습니다.

'SharePoint 2010' 카테고리의 다른 글

SharePoint 2010에서의 Ribbon  (0) 2011.01.26
SharePoint 2010 Developer Dashboard  (0) 2010.09.30
REST - jQuery  (0) 2010.08.30
REST – Silverlight  (0) 2010.07.30
REST -.NET  (0) 2010.07.28