
Kenny Kerr (영문)
목차
커널 트랜잭션 관리자
명령 링크
현대적인 UI: Aero 마법사
메시지 상자에서 작업 대화상자로
세련된 작업 대화상자
결론
커널 트랜잭션 관리자
개발자에게 제공되는 새로운 서비스 중에서 가장 신나는 것들 중 하나로 커널 트랜잭션 관리자(KTM) 을 꼽을 수 있습니다. 이는 로컬 트랜잭션 관리자의 역할을 하는 동시에 분산된 로컬 트랜잭션을 위한 자원 관리자 역할 도 합니다. KTM은 단일 컴퓨터에 작동 하는 다중의 트랜잭션 관리자라는 새로운 개념을 제공 합니다. 이는 복수의 트랜잭션과 이와 관련된 리소스 관리자를 함께 관리 하게 됩니다. KTM의 기능에 대해 좀더 자세히 들여다 보기 전에 트랜잭션과 리소스 관리자의 용도에 대해 간단히 복습 해보겠습니다.
리소스 관리자는 데이터베이스 엔진 또는 메시지 큐 서버와 같은 로컬 리소스를 관리 합니다. 이 리소스 관리자는 트랜잭션 관리자와 함께 작동 하여 한 트랜잭션 안에서 관리되는 리소스들의 변화를 추적합니다. 한 개의 트랜잭션 관리자에는 한 개 또는 그 이상의 리소스 관리자들이 함께 통합 되어 한 트랜잭션 내에서 작업을 할 수 있습니다. 실제 상황에서 트랜잭션이 단일 리소스에 국한이 되어 있는 경우 대부분의 리소스 관리자는 트랜잭션 관리자의 역할도 하게 됩니다. 데이터베이스 엔진 같은 경우가 이에 해당 하며 이를 로컬 트랜잭션이라 부릅니다.
한 트랜잭션에 여러 개의 리소스 관리자가 포함되어 있는 경우 이를 분산 트랜잭션 이라고 부르며 이 경우 독립된 트랜잭션 관리자가 추가 되어 여러 가지의 리소스 관리자들의 협업을 관리 하게 됩니다. 이렇게 여러 리소스 관리자들을 관리 해 줌으로써 각 리소스 관리자들이 자신들의 리소스들의 모든 변경 사항을 commit 하거나 roll back 하도록 해줍니다. 물론 이런 여러 관리자들을 포함 시키고 이 들을 관리 하는 것에 대한 Overhead 또한 존재 하며 따라서 가능하면 로컬 트랜잭션을 사용하는 것이 좋습니다.
리소스 관리자의 좋은 예로 Microsoft SQL Server™를 들을 수 있습니다. 단일 SQL Server 에서의 명시적 또는 암시적인 트랜잭션은 한 트랜잭션 내의 명령을 실행 하기 위해 SQL Server 자신의 트랜잭션 관리자를 사용합니다. Windows 에서 제공 하는 서비스인 Microsoft Distributed Transaction Coordinator(DTC)는 한 트랜잭션에 한 개 이상의 리소스 관리자가 관여 하게 되는 경우 사용 됩니다. DTC는 SQL Server와 다른 user-mode 리소스 관리자들과 트랜잭션을 조율 하는 역할을 합니다.
SQL Server가 로컬 데이터베이스 트랜잭션을 위한 리소스 관리자 역할을 하고 분산 데이터페이스 트랜잭션을 위해서는 트랜잭션 관리자 역할을 하는 것처럼 KTM은 로컬 파일 시스템과 레지스트리 작업에 대한 트랜잭션 관리자의 역할을 하며 파일 시스템과 레지스트리 작업과 관련된 분산 로컬 트랜잭션을 위한 리소스 관리자 역할 도 합니다.
KTM의 진가는 여러분이 파일과 레지스트리 키와 작업하는 기존의 방식 그대도 작업 할 수 있게 해준 다는 데에 있습니다. 여러분이 현재 파일이나 레지스트리 키를 작업을 위해 사용하는 API들이 궁극적으로 커널 객체를 다루기 위해 파일과 레지스트리 핸들을 통해 작업을 한다면 그 API는 미래에도 똑같이 작동 할 것입니다.
Windows SDK의 파일과 레지스트리 관리 함수를 사용하는 간단한 예제를 보도록 하겠습니다. 여러분이 프로그램을 만드는데 한 파일 시스템 폴더를 계속 추적해야 한다고 가정 합니다. 메신저의 대화 기록 저장 같은 기능을 위해서 말이죠. 그리고 해당 기록이 저장되는 폴더를 사용자 임의대로 변경 할 수 있도록 하려고 한다고 가정 합니다. 이는 그림 1의 간단한 함수로 구현 가능 하겠죠.
MoveHistoryFolder 함수는 기록 폴더를 옮기고 이의 위치를 저장하는 레지스트리를 변경 하도록 되어 있습니다. 그러나 이 구현은 너무나도 간단하여 몇몇의 시나리오에 대한 처리를 제대로 못하게 되어 있습니다.
MoveHistoryFolder 함수는 기록 폴더를 옮기는 것에서부터 시작을 합니다. 만약 옮기는 작업이 성공적이라면 레지스트리 변경을 시도합니다. 레지스트리 변경이 실패 하면 MoveHistoryFolder는 옮겼던 폴더를 다시 원 위치로 되돌리는 작업을 조심스레 시도 합니다. 함수가 실패 하더라도 아무런 부작용 없이 리턴 함을 보장 하기 위해서 입니다.
그렇다면 이 함수의 뭐가 잘 못 됐을까요? 이런 단순한 예제 에서도 프로그램의 상태가 손상될 수 있습니다. 예를 들어 전원이나 다른 하드웨어 오류로 인해 해당 레지스트리 변경 없이 기록 폴더만 옮겨질 수도 있습니다. 여기서 문제는 운영 체제가 여러 가지의 파일과 레지스트리 관리 함수의 호출을 독립적인 호출로 본다는 것입니다. (반면 여러분의 프로그램은 이들 함수 호출이 잠재적인 부작용이 없는 단일 논리 작업으로 간주 한다는 것이죠.)
이젠 KTM 덕분에 이런 문제의 해결이 아주 간단해 졌습니다. 이 예에서 사용된 모든 리소스들은 커널 객체로 제어 되는 로컬 리소스들(사용자들이 기록 폴더를 원격 컴퓨터로 옮기는 것을 허용하지 않는다는 가정 하에) 이므로 여러분들은 KTM을 로컬 트랜잭션을 위한 트랜잭션 관리자 그리고 리소스 관리자로도 활용 할 수 있게 됩니다.
CreateTransaction 함수는 KTM에 의해 제어 되는 새로운 트랜잭션 객체를 생성 합니다. 이벤트나 파일과 같은 운영체제의 구성 요소들이 커널 객체로 표현 되고 안전한 핸들로 접근 가능 한 것처럼 트랜잭션 객체도 일반적인 커널 객체 입니다. CreateTransaction는 트랜잭션 객체의 핸들을 반환 합니다. 한 컴퓨터 내에서의 트랜잭션을 구분 하기 위해 GUID가 사용됩니다(Default로 사용자가 제공하지 않으면 KTM이 GUID를 생성합니다.). 다른 커널 객체와 마찬 가지로 SECURITY_ATTRIBUTES 구조체를 지정하여 핸들의 보안 속성을 조정 할 수 있습니다. 추가로 CreateTransaction 함수에 사용자가 읽을 수 있는 설명이 담긴 문자열을 마지막 인자로 넘길 수도 있습니다. 관리 용도로 권하는 기능 입니다.
트랜잭션이 더 이상 필요 하지 않을 시엔 CloseHandle 함수로 트랜잭션 핸들을 닫습니다. Commit 이 안된 트랜잭션의 마지막 핸들을 닫는 경우엔 트랜잭션이 roll-back 됩니다. 트랜잭션을 commit 하시려면 CommitTransaction 함수를 사용합니다. Roll-back은 RoolbackTransaction 함수를 사용 합니다. C++을 활용하면 그림 2에서처럼 이 함수들을 좀더 간단히 사용할 수 있습니다.
코드를 보시면 KtmTransaction 클래스의 사용법을 보실 수 있습니다. 하지만 이 클래스를 실제로 사용하기 전에 파일이나 레지스트리 관리 함수들이 특정 트랜잭션과 관련되어 호출 된다는 것을 알게 금 해당 함수를 호출 하는 쓰레드와 트랜잭션을 bind 시켜 줘야 합니다. 이를 위해 사용되는 함수가 SetCurrentTransaction 입니다. 이 함수는 이를 호출 하는 쓰레드를 해당 트랜잭션과 bind 시켜 줍니다. 해당 쓰레드는 SetCurrentTransaction이 무효한 핸들로 다시 호출 되기 전까진 bind 된 상태로 유지 됩니다. 그림 3의 KtmTransactionBinding 클래스를 사용하면 간단히 호출 쓰레드와 트랜잭션을 bind 하실 수 있습니다.
이제 KtmTransaction과 KtmTransactionBinding을 사용하여 그림 4와 같이 예제 프로그램의 MoveHistoryFolder 함수를 한 트랜잭션 내에서 호출 할 수 있습니다. MoveHistoryFolder가 성공적인 HRESULT 값을 반환 하지 안는 한 트랜잭션 객체의 Commit 함수는 호출 되지 않으며 따라서 모든 파일이나 레지스트리 작업은 트랜잭션 객체가 삭제됨과 동시에 roll-back 됩니다.
파일과 레지스트리 작업에 있어서 트랜잭션이 주는 이점을 아무리 강조 해도 모자를 것 같습니다. 모든 roll-back 이 자동으로 실행 됨으로써 여러분은 roll-back을 위한 코드에 대한 고민 없이 모든 시나리오를 고려하여 필요한 작업만을 수행하는 코드 작성에만 신경 쓰면 되니까요. 한가지 예로 그림 1의 MoveHistoryFunction 함수는 MoveFile 함수가 성공하기 위해선 바로 상위 디렉토리가 존재해야 함에도 불구 하고 이런 조건에 대한 고려가 되어 있지 않습니다. 부모 디렉토리가 없는 경우 이를 생성 해주도록 하는 로직을 추가 하는 것이 어려운 작업은 아니지만 이에 따른 roll-back 로직은 상당히 까다로울 수 있습니다.
명령 링크명령 링크(Command Link)는 새로운 스타일의 버튼으로써 사용자의 주의를 “명령”에 초점을 두어 사용자 경험을 좀더 쉽고 간단하게 해줍니다. 주로 마법사에 사용하는 용도로 디자인 되었으나 예전 버튼에 특별한 속성값을 더한 것 보다 그 이상을 제공 하는 것이 명령 링크 입니다.
명령 링크를 만드는 가장 쉬운 방법은 Visual C++® 2005 리소스 편집기를 사용하는 것입니다. 대화 상자 편집기의 도구 상자를 열어 사용자 정의 컨트롤을 대화상자에 추가 합니다. (명령 링크는 단순한 버튼 컨트롤이지만 대화상자 편집기는 이런 사항을 모르며 따라서 명령 링크에 대한 버튼 속성을 제공 하지 않습니다.) 명령 링크는 보통의 버튼 보다는 상당히 크게 표시되도록 되어 있으므로 사용자 정의 컨트롤을 비교적 크게 만드시길 바랍니다. 이제 컨트롤의 클래스 속성을 BUTTON으로 하고 스타일 속성을 0x5001000e로 변경 하세요. 캡션 속성도 명령 링크에 보여주고자 하는 글로 바꾸시기 바랍니다. 이 들 값은 그림 5의 오른쪽에서 보실 수 있습니다. 이제 여러분은 프로젝트를 컴파일 하고 그림 5에서 보이는 것처럼 대화상자를 화면에 띄워 볼 수 있습니다.

그림 5a 명령 링크 생성

그림 5b
명령 링크에 텍스트를 추가하여 추가 설명을 표시 할 수 있게 해줍니다. 이를 하려면 버튼에 BCM_SETNOTE 메시지를 보내거나 이보다 간단한 Button_SetNote 매크로를 사용합니다. 명령링크를 좀더 눈에 띄게 하기 위해 화살표를 방패 표시로 변경 하실 수 있습니다. 이를 하려면 BCM_SETSHIELD 메시지를 보내거나 Button_SetElevationRequiredState 매크로를 사용하면 됩니다. 다음의 코드에서 Active Template Library(ATL) 대화 상자 클래스에서 앞의 메시지를 보내는 예제를 보실 수 있습니다.
CWindow button1 = GetDlgItem(IDC_BUTTON1);
Button_SetNote(button1,
L"You know you want to click it.");
Button_SetElevationRequiredState(button1,
TRUE);
현대적인 UI: Aero 마법사마법사가 생긴지 꽤 되었지만 Wizard 97 명세서는 외부 페이지나 헤더 같은 불필요하고 중복되는 정보들이 많았습니다. 나이 먹어 가는 Wizard 97 명세서를 대체할 Aero™ 마법사는 명료하고 간결하도록 설계 되었습니다. 이로 인해 복잡할 수 있는 작업을 사용자들에게 안내 하는데 보다 새로운 경험을 제공 할 수 있게 되었습니다.
명령 링크에서와 같이 Aero 마법사는 기존의 컨트롤에 속성을 추가한 형태로 제공 됩니다. Aero 마법사의 경우엔 속성 시트(Property Sheet)를 이용합니다. 그림 6이 Wizard 97 스타일 마법사의 최소 버전입니다. 이 마법사를 반짝이는 Aero 마법사로 변신 시키기 위해 무엇을 해야 하는지 보도록 하겠습니다. 이 과정을 최대한 명료하고 짧게 하기 위해 ATL과 Windows Template Library(WTL)을 사용해 보여드리도록 하겠습니다. 물론 여러분이 원하는 어떠한 Framework도 사용 가능 합니다.

그림 6 나이 먹어 가는 Wizard 97 변환
그림 6의 창은 Wizard 클래스에 의해 생성 되었습니다. CPropertySheetImpl base 클래스가 속성 시트 구현에 필요한 모든 함수, 메시지 그리고 구조체들을 wrapping 하고 있습니다. 마법사는 결국에는 속성 시트에 외관과 작동 방식 변경을 위한 Flag가 추가 된 것뿐이죠. 속성 시트의 거의 모든 면을 제어 하기 위해 PROPSHEETHEADER 구조체가 사용 됩니다. CPropertySheetImpl 클래스는 여러분 대신 이 구조체의 내용을 자동으로 채워 줍니다. 작동 방식을 변경 하시려면 m_psh 상속 멤버 변수를 통해PROPSHEETHEADER 구조체의 내용을 자유롭게 변경 하시면 됩니다. 그림 6에서 보이는 마법사를 위해서 저도 바로 이 방법을 이용 했습니다.
이 마법사를 Aero 스타일 마법사로 변경 하는 것은 PSH_WIZARD97 flag를 PSH_AEROWIZARD로 바꾸어 주시기만 하면 됩니다. 그러나 결과를 보시면 아시겠지만(그림 7 참조) 약간의 작업이 더 필요 합니다.

그림 7 Aero 마법사 변환
가장 눈에 띄는 변화는 창의 크기 입니다. Wizard 97 명세서에는 마법사 페이지들의 최소 크기를 명시되어 있습니다. 이 예제에 사용된 대화상자 템플릿은 이 최소 크기 보다 작습니다. PSH_WIZARD97 flag가 사용되는 경우 최소 크기를 지키기 위해 창이 조정 되지만 Aero 마법사는 이런 제한이 없이 실행 됩니다.
여러분이 주목 하실 만한 다른 점은 창 하단의 “뒤로” 버튼이 웹 브라우저 스타일의 “뒤로” 버튼으로 대체 되었다는 것 입니다. 외관이 변경 된 것 외에 버튼은 이전과 동일 하게 프로그램적으로 제어 됩니다.
Aero 마법사는 명령 링크를 염두 해 두고 설계되어 오늘 날 마법사의 하단 부분을 어지럽히는 버튼들을 최소화 할 수 있게 해줍니다. 제일 먼저 없어진 버튼이 “뒤로” 버튼 입니다. “다음” 버튼 또한 경우에 따라 제거 할 수 있습니다. 과거에는 PSM_SETWIZBUTTONS 메시지를 사용하면 “다음” 버튼을 비활성화 시킬 수 있었습니다. 그러나 Windows Vista 이전에는 “다음”과 “끝내기” 버튼을 숨길 수는 없었습니다. Windows Vista에서는 이 것이 가능하며 이를 여러 개의 명령 링크로 대체 할 수도 있습니다.
Aero 마법사는 마법사 버튼들의 보이는 정도를 제어 할 수 있도록 새로운 메시지들을 제공 합니다. 바로 여기에서 명령 링크의 진가를 보실 수 있습니다. Wizard 97 스타일에서 몇 개의 라디오 버튼이 들어 있는 마법사 페이지를 만들 수 있습니다. 이 마법사에서 사용자는 선택을 하고 “다음” 버튼을 누릅니다. Aero 마법사에서는 이 라디오 버튼을 아예 숨기고 대신 명령 링크를 넣고 “다음” 버튼을 아예 숨길 수 있습니다. 이젠 사용자는 단 한번의 클릭으로 원하는 선택을 할 수 있게 금 된 거죠.
“다음” 버튼을 숨기려면 속성 시트에 PSM_SHOWWIZBUTTONS 메시지를 보내거나 PropSheet_ShowWizButtons 매크로를 사용합니다:
SetWizardButtons(0);
PropSheet_ShowWizButtons(m_hWnd, PSWIZB_CANCEL,
PSWIZB_CANCEL | PSWIZB_NEXT);
SetWizardButtons 함수는 CPropertySheetWindow 클래스에서 제공 되는 함수로 속성 시트에 PSM_SETWIZBUTTONS 메시지를 보냅니다. 0을 인자로 넣으면 “뒤로” 와 ”다음” 버튼 모두 비활성화 됩니다. “뒤로” 버튼을 활성화 된 상태로 두어야 한다면 PSWIZB_BACK flag를 지정하시면 됩니다. PropSheet_ShowWizButtons 매크로를 사용해 마법사 버튼을 보여줄지 안 보여줄지를 지정 하실 수 있습니다.
두 번째와 세 번째 인자에 동시에 나오는 Flag들은 해당 버튼이 보인다는 것을 뜻합니다. 세 번째 인자에만 나오는 Flag는 해당 버튼이 숨겨진다는 것을 의미 합니다. 마지막으로 그림 8에서처럼 명령 링크를 포함 시켜 어떻게 진행 할 것인지를 사용자가 결정 할 수 있게 합니다.

그림 8 명령 링크
작업 대화상자(task dialogs)는 작은 양의 코드로 사용자에게 무언가 전달 하는 새롭고 강력한 도구 입니다. 사용자들에게 무언가를 알리거나 작업에 대한 확인을 받거나 예 또는 아니오 결정을 할 때 지난 수년간은 MessageBox 함수가 사용 했으나 때론 사용자 경험이 저하 되곤 했습니다. MessageBox 함수는 상당히 부족하였고 개발자들이 사용자 경험을 개선 하기 위해서는 메시지 상자 기능을 직접 구현 해야만 하는 경우가 많았죠.
메시지 상자가 드디어 작업 대화상자로 대체 되게 되었습니다. 이는 기존 메시지 상자의 단순함을 간직 하면서 사용자 경험 개선을 위한 커스터마이징을 위해 상당히 많은 옵션을 제공 합니다. 작업 대화상자는 두 함수 중 하나를 이용함으로써 제공 됩니다. 이 절은 좀더 간단한 TaskDialog 함수에 대해 다루고 다음 절에서 보다 강력한 TaskDialogIndirect 함수에 대해 다룹니다.
TaskDialog 함수는 MessageBox 함수와 매우 비슷하여 대부분의 경우 이 둘을 교체만 해주고 인자만 변경 해주시면 됩니다. 다음의 MessageBox 호출의 경우:
int result = ::MessageBox(0, // no owner window
L"Do you want to save changes?",
L"Application",
MB_YESNOCANCEL | MB_ICONINFORMATION);
이 코드는 TaskDialog 함수를 사용하여 대체 할 수 있습니다. 코드와 결과 대화상자는 그림 9에서 보실 수 있습니다.
극적인 변화는 없지만 TaskDialog 함수는 몇 가지 유용한 기능을 제공 합니다. 아마도 가장 좋은 새 기능으로 두 번째 인자로 module 핸들을 넣을 수 있다는 것입니다. 이는 LoadString 함수를 위한 많은 껍데기 코드(Boilerplate code)를 없애 줍니다. Module 핸들을 직접 지정 하는 것은 또한 대화 상자의 아이콘을 여러분이 원하는 것으로 할 수 있도록 해줍니다. 여기에 작업 대화상자는 작은 폰트로 별도의 추가 내용을 담을 수 있게 해줍니다. 마지막으로 그림 10에서처럼 각 버튼에 대한 Flag가 따로 존재 하여 표시 하고자 하는 버튼의 조합을 마음대로 변경 할 수 가 있습니다.
세련된 작업 대화상자단순한 TaskDialog의 문제 중 하나가 버튼에 나오는 텍스트의 내용을 바꿀 수 없다는 것입니다. 그림 10을 보면 버튼이 “저장”, “저장 안 함”, 그리고 “취소”와 같은 단어를 표시 하고 있었다면 그 위의 장황한 설명이 필요 없었을 것입니다. TaskDialogIndirect를 이용하면 이런 문제를 해결 할 수 있습니다. 그러나 TaskDialogIndirect는 이보다 더 많은 것을 제공 합니다. 보다 적은 코드로 사용자에게 보다 많은 정보를 화려하고 쌍방향 UI를 제공 할 수 있습니다.
TaskDialogIndirect는 다음과 같이 정의 되어 있습니다:
HRESULT WINAPI TaskDialogIndirect(
const TASKDIALOGCONFIG* config, int* button,
int* radioButton, BOOL* verificationChecked);
짐작 하셨 듯이 이 함수 사용을 위한 대부분의 작업이 config 인자를 구성하는 데에 있습니다. 호출자가 제공하는 TASKDIALOGCONFIG 구조체는 작업 대화상자의 UI나 작동 방식에 대한 모든 면을 제어 합니다. “Do you want to save changes?” 대화상자를 다시 만들어 좀더 자세한 설명이 들어간 버튼을 올려 보겠습니다. 그림 11에서 결과물을 보실 수 있습니다.
TASKDIALOG_BUTTON 구조체의 배열을 선언합니다. 각 구조체에 각 버튼의 ID값과 버튼 텍스트를 입력 합니다. 그리고 TASKDIALOGCONFIG 구조체를 채웁니다. 커스터마이징을 위해 더 많은 필드를 제공합니다. TaskDialogIndirect 함수는 대화상자의 외관 제어를 위해 굉장한 양의 제어 권을 제공 합니다. 너무 많아 이 글에 모두 설명 못할 정도로 말입니다. TaskDialogIndirect 함수의 옵션을 좀더 쉽게 알아 보기 위해 그림 12 에 보이는 것처럼 TaskDialog 디자이너를 만들었습니다.

그림 12 나이 먹어 가는 Wizard 97 변환
TaskDialog 디자이너는 C#으로 만든 작은 Windows Forms 프로그램으로써 여러분이 여러 옵션을 시험 해볼 수 있도록 몇 개의 속성 시트에 TaskDialog의 거의 모든 옵션을 제공 합니다. TaskDialog 디자이너는 TaskDialogIndirect 함수에 대한 관리 인터페이스를 제공하는 C++/CLI로 작성된 .NET 어셈블리를 사용합니다. 이전의 네이티브 C++ 코드를 다음의 C# 코드로 이전과 같은 작업 대화상자를 만들 수 있습니다:
using (TaskDialog dialog = new TaskDialog())
{
dialog.Title = "Application";
dialog.MainInstruction = "Do you want to save changes?";
dialog.Content = "Click Cancel to return to the application.";
dialog.Buttons = TaskDialogButtons.Cancel;
dialog.CustomButtons.Add(new TaskDialogButton("&Save", 6));
dialog.CustomButtons.Add(new TaskDialogButton("&Don’t Save", 7));
dialog.MainIcon = TaskDialogIcon.Information;
int button = dialog.ShowDialog();
}
작업 대화상자의 수 많은 용도 중 하나로 에러 보고 대화상자를 꼽을 수 있습니다. 작업 대화상자의 확장가능 영역을 사용하면 좀더 겸손한 대화 상자로 사용자에게 에러를 알릴 수 있죠. 사용자가 원하면 좀더 자세한 정보를 보게 할 수도 있고요.
그림 13을 보시면 TaskDialog는 Exception 객체의 정보를 전달 받습니다. 초기에는 에러메시지만 보이지만 사용자가 이를 보고자 할 때엔 예외 정보의 전체 내용이 표시 되겠죠.
결론Windows Vista는 기존 Windows 운영 제체에서 아주 큰 업그레이드 이며 이에 따라Windows SDK도 상당히 많이 업그레이드 됩니다. 많은 새 기능 중에서 커널 트랜잭션 관지라, Aero 마법사 그리고 작업 대화상자 같은 몇몇은 좀더 자세히 들여 볼만한 주제라고 생각 됩니다. KTM은 여러분들이 작업 하는 로직에 좀더 중점을 두어 개발 할 수 있게 하고 복잡한 roll-back 같은 기능을 운영체제가 담당 합니다. Aero 마법사는 명령 링크와 함께 사용자와 상호 작용 할 수 있는 새롭고 간단한 인터페이스를 제공 합니다. 그리고 작업 대화상자는 간단한 커뮤니케이션을 위한 강력한 API 이며 오래된 메시지 상자를 대체 할 만할 대안을 제공 합니다.
