블로그 이미지
Every unexpected event is a path to learning for you. blueasa

카테고리

분류 전체보기 (2797)
Unity3D (853)
Programming (479)
Server (33)
Unreal (4)
Gamebryo (56)
Tip & Tech (185)
협업 (61)
3DS Max (3)
Game (12)
Utility (68)
Etc (98)
Link (32)
Portfolio (19)
Subject (90)
iOS,OSX (55)
Android (14)
Linux (5)
잉여 프로젝트 (2)
게임이야기 (3)
Memories (20)
Interest (38)
Thinking (38)
한글 (30)
PaperCraft (5)
Animation (408)
Wallpaper (2)
재테크 (18)
Exercise (3)
나만의 맛집 (3)
냥이 (10)
육아 (16)
Total
Today
Yesterday
반응형
Posted by blueasa
, |

Poser 스샷

Programming/Etc / 2010. 5. 27. 16:33

반응형
Posted by blueasa
, |

언리얼 에디터

Programming/Etc / 2010. 5. 27. 14:35
반응형
Posted by blueasa
, |


Dax Pandhi

Nukeation Studios

2006년 4월

요약: Dax Pandhi는 Windows 응용 프로그램을 위한 사용이 쉬운 사용자 인터페이스를 구현하는 방법과 사용자 환경 디자인 원칙에 대해 설명합니다.

목차

소개소개
적절한 UI를 만들기 위한 기본 원칙적절한 UI를 만들기 위한 기본 원칙
보다 효율적이고 편리한 사용자 환경 조성을 위한 20가지 팁보다 효율적이고 편리한 사용자 환경 조성을 위한 20가지 팁
결론결론
참조 및 자료참조 및 자료

소개

개발자들은 한 가지 시각만을 갖는 경우가 흔히 있습니다. 아마도 약간 무미건조할 수 있겠지만 코드에는 분명히 느낌이 있습니다. 그러나 그뿐입니다. 때로는 기술, 그 중에서도 특히 '새로운' 기술과 소프트웨어 기능에 자만하여 최종 사용자가 중요시하는 건 다를 수도 있다는 점을 간과할 수도 있습니다. 아마 지금도 개발자들은 "코드를 보여주세요. 설명은 필요 없습니다!"라고 말할 수도 있습니다. 개발자들은 사용자가 '기대하는 것처럼' 응용 프로그램이 작동하도록 최선을 다합니다. 그러나 사용자들은 단순히 작동하는 것 이상을 바라게 됩니다. 일반 판매용 소프트웨어를 개발하거나 비전문가들이 사용하는 제품을 개발할 경우에는 특히 그렇습니다. 처음에는 다소 불쾌하다고 느껴질 수도 있지만 사용자는 어디까지나 고객이므로 사용자 환경을 좀 더 개선할 수 있는 방법에 대해서 알아보도록 하겠습니다.

만약 사용자가 일주일에 수십 시간을 특정 소프트웨어 응용 프로그램을 보면서 작업하는 데 보낼 경우 최소한 이 소프트웨어가 눈에 편안하기를 바랄 것입니다. 또한 되도록 탐색과 사용이 편리하기도 바랄 것입니다. 문제는 소프트웨어가 대량으로 생산되는 상황에서 소프트웨어 응용 프로그램 중 40% 정도만이 최종 사용자들이 정말 마음에 들어 하고 즉시 편안하게 사용할 수 있는 매우 우수한 UI를 갖추고 있다는 것입니다.

수많은 기업 내부용 소프트웨어가 생산되고 있습니다. 그러나 자체적으로 개발하든 컨설턴트의 도움을 받아 개발하든 보다 나은 UI를 만들기 위한 시간, 노력 또는 비용은 거의 투자되지 않고 있는 실정입니다. 개발 과정에서 '디자이너'의 역할은 미미하며 특히 Windows 응용 프로그램의 경우에는 더욱 그렇습니다. 현재 개발 중인 UI가 형편 없다는 것이 아니며 개발자가 할 수 있는 일들이 아주 많다는 점을 말하고 싶습니다. 이젠 더 이상 "이 정도면 괜찮은 수준" 또는 "프로그램을 개발"하는 것만으로 충분하지 않습니다.

보다 외관이 멋지고 기능이 우수한 응용 프로그램용 UI를 만들려면 준수해야 하는 몇 가지 기본 규칙이 있습니다. 이 기본 규칙을 준수하는 데 있어 시간과 비용이 그다지 많이 드는 것은 아니나 투자수익(ROI)은 분명히 향상됩니다.

자세히 설명하기에 앞서 사용자 인터페이스와 사용자 환경을 구분해 보도록 하겠습니다. 사용자 인터페이스(UI)란 응용 프로그램의 시각적 측면과 컨트롤을 나타내는 반면, 사용자 환경(UX)은 UI 및 그 UI와 관련된 응용 프로그램의 동작뿐 아니라 이 응용 프로그램에서 사용자가 받게 되는 "느낌"까지 포괄합니다. 즉, 단순히 외관이 훌륭한 UI를 설계하는 것이 아니라 성능도 우수해야 한다는 것입니다.

여기서는 응용 프로그램 디자인 단계에서 쉽게 적용할 수 있는 UX 디자인을 위한 20가지 중요한 규칙에 대해서 설명하도록 하겠습니다. 그러면 보다 사용이 쉬운 기능, 즉 "휴먼 UX"를 갖춘 다양한 응용 프로그램을 개발할 수 있습니다. 모두 알다시피 Windows Vista용 응용 프로그램을 제작할 경우에는 다르게 보고 다르게 행동해야 합니다. 여기서 설명하는 내용이 현재 사용자에게는 미래의 프로그램을 미리 경험해 볼 수 있는 기회를 제공하면서 개발자에게는 미래의 응용 프로그램을 준비하는 데 도움이 되기를 바랍니다.

먼저 우수한 UI 디자인의 기본 사항에 대해서 간략하게 설명한 후에 이 주제에 대해서 자세히 살펴보도록 하겠습니다.

적절한 UI를 만들기 위한 기본 원칙

예전에 제 친구 중 하나가 자신이 수석 설계자로 참여했던 응용 프로그램을 자랑한 적이 있었습니다. 기능은 정말 우수하더군요. 그 개발 팀에서 소프트웨어의 핵심 부분을 개발하는 데만도 2년 정도가 걸렸지만 수천 달러의 가격으로 판매될 예정이었던 이 응용 프로그램의 UI는 테마별로 되어 있지 않은 일반 Windows 응용 프로그램보다도 더 단조로웠습니다. 저는 그 친구에게 왜 UI 개선에는 시간을 좀 더 들이지 않았는지 물었습니다. 그는 "Windows 응용 프로그램이기 때문이네. 웹 응용 프로그램이었다면 물론 시간을 더 들였겠지. 하지만 Windows XP라 하더라도 응용 프로그램의 외관을 치장하는 것 이외에 UI에 할 수 있는 일이 무엇이겠나"라고 대답했습니다.

그의 말은 일리는 있었으나 만약 당신이 Windows Vista에서 가능한 작업을 염두에 둔다면 그의 말이 전적으로 옳지만은 않다는 것을 알 수 있을 것입니다. 창의 모양을 개선하려고 굳이 사용자 지정 스킨을 만들 필요는 없습니다. 진정으로 전문적으로 보이는 UX를 만드는 것은 다음 네 가지 요소에 달려 있습니다.

  • 간격 조정 및 위치 지정

  • 크기

  • 그룹화

  • 사용 편이성

Visual Studio 8.0의 이전 버전에서는 간격 조정과 크기 조정이 매우 어려웠습니다. 4x4 또는 8x8 표 형태가 항상 맞지는 않았기 때문입니다. 하지만 SnapLines가 포함되면서 이 프로세스는 한층 간단해졌습니다. 이 점에 있어서는 이 기능이 매우 만족스러웠으나 레이블 하나를 텍스트 상자에 맞추는 작업이나, 설상가상으로 여러 레이블을 각각 해당 텍스트 상자에 맞추는 작업을 할 때는 종종 광부와 같은 육체 노동 직종으로 바꾸고 싶다는 생각이 들기도 했습니다. 그러나 이제 그런 어려움은 모두 해소되었습니다. 저는 이 SnapLines를 사용해 볼 것을 권장합니다.

이제 위에서 말한 네 가지 측면에 대해서 잠시 살펴보도록 하겠습니다.

간격 조정 및 위치 지정

두 컨트롤 사이의 간격은 중요합니다. 그림 1에는 간단한 사용자 정보 입력 폼이 나와 있습니다. 이 폼에서 위의 두 입력란은 너무 가깝게 붙어있고 그 아래 목록은 너무 멀리 떨어져 있어서 사용되지 않은 공간이 많습니다.

humanux_01.gif

그림 1. 잘못 설계된 

humanux_02.gif

그림 2. 올바르게 설계된 

그림 2의 경우 대화 상자의 간격이 적절히 조정되어 보다 전문적으로 보입니다. 이 폼은 그림 1의 폼과 동일하지만 SnapLines에서 추천하는 간격을 사용하도록 수정되었습니다. 항상 실제 하단 가장자리가 아닌 입력란의 텍스트 기준선이나 그 옆의 컨트롤과 레이블을 맞출 것을 권장합니다. 원하는 대로 정렬되면 대개 하단 가장자리에서 몇 픽셀 위의 SnapLines 색상이 바뀝니다.

간격 조정에 대한 정확한 규칙은 없으나 가장 좋은 것은 SnapLines를 따르는 것입니다. 적절한 간격을 유지하기 위한 다른 훌륭한 도구로는 컨테이너 도구 상자 그룹 아래의 레이아웃 컨트롤을 들 수 있습니다. TableLayoutPanel은 입력 폼 스타일 대화 상자 생성에 매우 유용합니다.

크기

크기에도 같은 방식이 적용됩니다. 도구 상자에서 폼으로 단추를 끌어올 때 높이와 너비는 완벽한 균형을 이룹니다. 모든 중요한 이유는 배제하고 권장되는 최대 너비는 원래 너비의 두 배입니다. 그렇�� 않으면 단추가 두드러져 나와서 팝업 광고와 같이 눈길을 끌게 될 것입니다. 그러면 안 되는데 말이죠!

시작 메뉴의 실행 창 또는 Windows 탐색기 개체의 속성 대화 상자를 살펴보면 단추 크기가 '꼭 맞음'을 알 수 있습니다. 최종 사용자에게 반드시 알리고 싶은 매우 중요한 기능이 있는 경우 큰 단추나 평범하지 않은 화려한 색상을 사용하지 않고도 여러 가지 방법을 사용할 수 있습니다. 이에 대해서는 나중에 설명합니다.

humanux_03.gif

그림 3. 단추 크기 비교

그림 3에는 세 가지 크기의 단추가 나와 있습니다. 첫 번째 단추는 가장 권장되는 크기로 도구 상자에서 끌거나 두 번 클릭하면 기본적으로 생성되는 크기입니다. 텍스트를 추가로 입력하려면 단추를 더 크게 만들어야 합니다. 두 번째 단추는 약간 더 크지만 사용할 수 있는 크기입니다. 다른 컨트롤의 배치를 방해할 정도로 크지는 않기 때문이죠. 그러나 세 번째 단추는 사용하기 어려운 크기입니다. 이 크기의 단추를 사용하면 Windows에서 테마가 적용된 컨트롤을 그릴 때 사용하는 테마 비트맵까지 흐트러진다는 것을 알 수 있습니다. 또한 이 단추 주변에 다른 컨트롤을 맞추기도 매우 어렵습니다.

위에 나온 그림 1의 경우 대화 상자의 크기와 오른쪽의 여백을 감안할 때 두 개의 입력란이 너무 작다는 것을 알 수 있으며 이에 비해 그림 2는 좀 더 적절히 조정된 크기입니다. SnapLines는 크기 조정에도 도움이 됩니다. SnapLines는 특정 상황에서 가장 구체적인 크기 또는 위치를 제안하므로 따르는 것이 좋습니다.

그룹화

거의 모든 응용 프로그램에는 수많은 컨트롤이 있습니다. 적절하고 알아보기 쉽게 그룹화해야만 이러한 컨트롤을 사용하기 쉽게 만들 수 있습니다. 기능에 따른 그룹화 또는 범주별 그룹화를 가장 잘 수행하려면 탭 컨트롤을 사용합니다. 예를 들어 일반적인 비즈니스 응용 프로그램에서는 '계정', '보고서', '직원' 및 '프로젝트'를 탭으로 사용하는 것이 가장 좋습니다. 동일한 최종 결과를 가져오도록 제어하는 형제 그룹화를 가장 훌륭히 수행하려면 그룹 컨트롤을 사용합니다. 이러한 그룹화에 테두리가 있는 패널은 사용하지 않는 것이 좋습니다. 그룹 컨트롤을 사용하면 추가적인 레이블 컨트롤을 사용하지 않아도 됩니다. 특히 하위 컨트롤이 그 자체만으로도 알아보기 쉬운 경우에는 더 그렇습니다.

그룹 컨트롤 내에 그룹 컨트롤을 배치하는 것은 하나의 큰 그룹 컨트롤 안에 2~3개의 컨트롤만 있는 경우가 아니면 권장되지 않습니다. 그룹 컨트롤 안의 다른 그룹 컨트롤 내에 그룹 컨트롤을 배치하는 것은 더더욱 권장되지 않습니다. 이렇게 쓰는 것조차 이상합니다.

사용 편이성

사용 편이성은 훌륭한 사용자 환경에 있어 실제로 중요한 측면입니다. 이해가 쉬운 UX인 경우 설명할 필요가 줄어듭니다. 사용자들이 컨트롤의 기능을 곧바로 알기 때문입니다.

알아보기 쉬운 디자인에서 가장 중요한 것은 색 구분입니다. 가장 좋은 예는 Windows XP 출시 전에 Microsoft에서 발표한 Windows XP Design Guidelines (영문)에 나와 있습니다. Windows XP에서는 테마별 응용 프로그램, 로그오프, 시스템 종료 대화 상자 등에서 탐색과 같은 기능을 위해 모서리가 둥근 새로운 단추를 제공했습니다.

이러한 컨트롤의 색은 해당 단추를 눌렀을 때 나타나는 결과의 심각도에 따라 결정됩니다. 탐색은 '보행' 신호등과 같이 녹색이고 작업 손실이 야기될 수 있는 시스템 종료는 경고 신호와 같이 빨간색이며 로그오프나 최대 절전 모드와 같은 심각도가 덜한 단추는 노란색입니다. 도움말과 같이 사용자의 작업 프로세스에 심각한 영향을 미치지 않는 중립적인 단추는 옅은 파랑색입니다. 스킨이 적용된 UI를 만들 때 이러한 색 구분을 염두에 두어야 합니다.

색으로 콘텐츠를 구분할 수 있는 가장 좋은 예는 Microsoft Office OneNote입니다. 이 응용 프로그램의 탭은 전체 Windows XP 스타일 디자인에 무난하게 어울리도록 하면서도 다양한 색으로 설정할 수 있습니다.

또 하나의 중요한 측면은 응용 프로그램의 텍스트입니다. 최근 소프트웨어에 작성된 명령에서는 표현이 단순화되었습니다. 소프트웨어 내의 텍스트에 대해서는 나중에 설명하도록 하겠지만 사소하면서도 중요한 한 가지 세부 사항에 주목해 주시기 바랍니다. 예를 들어 살펴보겠습니다.

MSN Messenger에는 옵션 대화 상자에 "웹캠 기능 공유"라는 확인란이 있었습니다. 물론 개발자나 해박한 기술 지식이 있는 사람들은 이 기능이 무엇을 의미하는지 압니다. 그러나 초보 사용자는 대화 상대방과 자신의 웹캠을 함께 사용할 수 있는 기능이라 생각할 수 있을 것입니다. 혼동을 주는 설명이었죠. 그래서 최신 버전에서는 "웹캠: 내 웹캠을 통해 다른 사람이 나를 볼 수 있도록 허용"이라는 옵션으로 변경되었습니다. 이 메뉴 옵션은 기술적 지식이 없고 단순한 표현에 익숙한 사람들도 완벽하게 이해할 수 있습니다.

단순한 표현은 이해하기 쉬울 뿐 아니라 나중에 살펴보게 되겠지만 또 다른 이점이 있습니다. 과학적 연구에 따르면 무언가 새로운 것을 이해하려고 할 때 단순한 표현은 의미 파악이 더 쉬운 것으로 나타났습니다. 흔히 인간의 두뇌는 '그것', '~에 대한', '저것'과 같은 단어와 기타 일반적인 단어는 매우 빠르고 쉽게 이해하지만 위의 예에서 볼 수 있듯이 '웹캠' 또는 '다른 사람'과 같은 단어를 이해하는 데는 더 많은 사고 영역을 할당합니다.

메시지 상자 제목, 그룹 상자 캡션 및 기타 비슷한 종류의 텍스트 블록을 사용하면 몇 단어만으로 최종 사용자에게 많은 컨트롤의 기능을 쉽게 전달할 수 있습니다.

사용 편이성은 친숙함에서도 나옵니다. 예를 들어 확인/취소 단추를 함께 배치하는 것은 매우 일반적이므로 우리들의 머리 속에 이 순서대로 각인되어 있어서 만약 어떤 대화 상자에서 확인 다음에 취소가 있지 않고 반대 순서로 취소 다음에 확인이 있는 경우 취소를 누르게 될 수 있습니다. Windows 기반 응용 프로그램과 같이 어떤 작업에 대해 특정 표준을 1년 이상 사용해 온 결과 습관으로 자리잡게 되었습니다. 문서화되어 있지는 않지만 이러한 산업 표준을 따르면 소프트웨어를 사용하기 쉽게 만들 수 있습니다.

다른 예를 살펴보도록 하겠습니다. 초기 Windows Vista 시험판 빌드 중 하나에서는 창의 최소화, 최대화닫기 단추의 순서가 달랐습니다. 이전 버전의 Windows에서는 특히 단일 모니터를 사용하는 경우 화면의 오른쪽 상단 모서리에 커서를 "어림짐작으로 가져가서" 무의식적으로 클릭하는 습관이 생기게 되었습니다. 이렇게 하면 항상 창이 닫히게 되었죠. 그러나 위에서 말한 Windows Vista 빌드에서는 닫기 단추와 창의 가장 오른쪽 가장자리 사이에 8픽셀 정도 되는 여백이 있었기 때문에 오랫동안 자리잡은 "어림짐작으로 하는 클릭"으로는 창이 닫히지 않았습니다. 여분의 공간이 있어 외관상으로 좋아 보이는 것은 물론이며 아마도 이 단추를 누르면 시작되는 화려한 애니메이션에 이러한 공간이 필요할 수도 있었겠지만 창이 닫히지는 않으니 짜증나는 일이었습니다. 습관을 바꾸는 것은 어려운 일이었으니까요. 다행히도 이후 빌드에서는 이 문제가 해결되었습니다. 아마도 저와 같이 어림짐작으로 클릭했던 많은 사람들이 Microsoft에 의견을 보내지 않았을까 싶습니다. 이제 창의 가장자리와 닫기 단추 사이에 공백이 있기는 하지만 그 공백을 클릭해도 창이 닫힙니다. 문제가 해결된 것이죠.

알아보기 쉬운 디자인에서 매우 중요한 점은 '생각해야 하는 영역'이 얼마나 되느냐입니다. 즉, 머리 속에서 무언가를 이해하는 데 걸리는 시간이 어느 정도냐 하는 것이죠. 이 '사고 영역'이 적으면 적을수록 훌륭한 UX라고 할 수 있습니다.

소프트웨어 응용 프로그램 사용 "환경"에 기여하는 사소한 항목들도 있기는 하겠으나 이론만으로도 충분합니다. 심지어 저 조차도 "실용적인" 정보를 원하니까요. 그러므로 이제 이론적인 얘기는 접어 두고 실제로 응용 가능한 팁과 트릭을 사용하여 응용 프로그램을 향상시키는 방법에 대해서 알아보도록 하겠습니다.

보다 효율적이고 편리한 사용자 환경 조성을 위한 20가지 팁

보다 나은 UX를 구축하는 목적은 외관이 훌륭하면서도 간단하고 알아보기 쉬우며 기능이 뛰어난 UI를 얻기 위함입니다. 이제 소프트웨어 응용 프로그램을 사용해 본 경험이 별로 없고 기술적 지식이 그다지 많지 않은 사용자들의 일상 업무에 초점을 두고 살펴보도록 하겠습니다. 아마도 이런 '유형'의 소비자들이 대부분 소프트웨어 응용 프로그램을 사용하겠죠. 아래에 나오는 팁은 보다 효과적인 UI를 만드는 데 도움이 됩니다.

1. 표준 준수

운영 체제 수준, 브랜드 수준 또는 응용 프로그램 수준 등 어떤 수준에서 수립된 것이든 소프트웨어 환경에서 수립된 기준은 매우 중요합니다. 브랜드와 더불어 이러한 표준은 사용자에게는 일종의 신뢰할 만한 방식으로 여겨집니다. 어떤 소프트웨어 응용 프로그램을 사용하여 오랜 시간을 작업할 경우 해당 사용자는 소프트웨어와 점점 친숙해지면서 생산성이 자동으로 향상될 것입니다. 이것은 마치 집 근처의 도로를 운전하는 것과 같습니다. 권유하지는 않지만 아마 이런 경우 눈을 감고도 운전할 수 있을 것입니다.

표준에 대해서 더 설명하기 전에 먼저 이러한 표준이 정확하게 무엇을 의미하는지 알아보도록 하겠습니다. 앞에서 말했듯이 확인/취소의 순서로 단추를 배치하는 것처럼 표준에는 대화 상자의 컨트롤을 특정 방식으로 배치하는 것에서부터 Windows XP 대화 상자의 사용자 인터페이스 창 상단의 둥그런 모서리, 아이콘 스타일, 기타 그래픽 스타일, 응용 프로그램의 대화식 동작 등 모든 것이 포함됩니다.

올바른 표준 집합을 선택하려면 응용 프로그램을 간단히 검사해야 합니다. 새 응용 프로그램을 위한 가장 좋은 표준은 현재 Windows 디자인 지침으로, 당장 사용할 수 있는 최신 표준으로는 Windows XP 디자인 지침을 들 수 있습니다. 응용 프로그램을 디자인하는 중에 곧 다른 운영 체제 버전이 출시될 상황인 경우 이전 버전과의 호환성만 유지된다면 다음 버전용 디자인 지침을 사용하는 것도 무방합니다. 그러면 적어도 최종 사용자에게는 "좀 더 앞서간다"는 느낌을 줄 수 있습니다.

만약 응용 프로그램이 일반적인 응용 프로그램이 아닌 경우 다른 표준 집합을 따르는 것이 좋습니다. 일례로 개발 중인 응용 프로그램이 Microsoft Office OneNote 2003용 응용 프로그램이나 추가 기능을 지원할 경우 Microsoft Office의 UI 스타일과 대화형 작업 표준 및 OneNote 자체의 표준을 따르는 것이 현명합니다. 즉, 시각적, 기능적 면에서 표준 도구 모음이 아닌 Office 스타일 명령 모음을 사용하고 대부분 Office 스타일을 따르는 것을 뜻합니다. 개발 중인 응용 프로그램이 Microsoft Visual Studio .NET 범주에 속할 경우 별도의 표준 집합을 준수해야 합니다. 사실 이러한 추가 기능이나 지원 응용 프로그램을 위해 Microsoft에서는 문서화된 지침을 배포하고 있습니다. 또한 그래픽과 디자인 개념은 종종 보호되는 지적 재산이므로 이러한 디자인을 만들 수 있는 라이선스가 있는지 항상 해당 설명서를 확인해야 합니다.

표준의 세 번째 예는 Tablet PC 환경입니다. 이러한 표준은 운영 체제 지침과 응용 프로그램 지침 사이의 경계를 넘나듭니다. Tablet PC SDK documentation(영문)에는 "응용 프로그램 계획"에 관한 주제와 관련하여 매우 유용한 몇 가지 정보가 수록되어 있습니다. Office 2003 또는 Visual Studio 지침과는 달리 이러한 디자인 권장 사항은 사용자들이 응용 프로그램을 어떻게 사용하는지, 이에 따라 응용 프로그램이 어떻게 작동해야 하는지에 직접적으로 영향을 미칩니다. 예를 들어 응용 프로그램에 고정 창이 있는 경우 설명서에서는 화면 방향이 변경될 경우 감지할 수 있는지 확인하고 필요에 따라 가로, 세로 방향으로 고정 창이 적절히 재구성되도록 하라고 권장합니다. Tablet PC용으로 응용 프로그램을 설계하지 않는다 해도 이러한 지침을 준수하라고 다시 한번 당부 드리고 싶습니다. 개발자인 여러분과 여러분이 개발하는 응용 프로그램은 이러한 지침을 준수함으로 인해 보다 향상될 수 있을 것입니다.

스마트 클라이언트의 출현으로 일반 PC, Tablet PC, 모바일 또는 초소형 모바일 장치, 미디어 센터 PC 등 서로 다른 하드웨어의 경계를 넘어 응용 프로그램이 사용되고 있습니다. 각각의 상황에 맞추어 서로 다른 또는 추가적인 표준 집합을 준수해야 합니다.

응용 프로그램에서 운영 체제 수준 또는 응용 프로그램 수준 표준을 공유할 경우 사용자들은 배우기 쉽고 사용이 편리한 소프트웨어를 통해 편안함을 느낄 수 있으며, 이는 생산성 향상에 직접적으로 이어집니다. 더욱이 사용자들은 프로그램의 사용 방법을 배우기보다는 프로그램을 바로 사용하길 원합니다.

2. 중요 단추에 주의 끌기

때로는 주변에 다른 단추가 4~5개 있는 경우 가장 중요한 단추에 사용자들의 관심을 집중시켜야 하는 경우가 있습니다. 크기, 색상 또는 글꼴 때문에 혼동스럽다면 표준을 위반해도 되기는 합니다. 그러나 물론 권장되지는 않습니다. 대신 간단한 몇 가지 트릭을 사용할 수 있습니다.

humanux_04.gif

그림 4. LinkLabel 쌍을 이루어 사용하면 단추에 주의가  집중됩니다.

첫 번째 트릭은 중요하지 않은 단추를 LinkLable로 변환하는 것입니다. 이렇게 하면 사용자는 이러한 링크가 작업을 수행하게 된다는 것을 알게 되므로 표준 디자인 지침을 위반하지 않고도 먼저 눈에 띄는 단추로 주의를 돌리게 됩니다.

humanux_05.gif

그림 5. 왼쪽에서 오른쪽으로 읽는 습관으로 인해  왼쪽의 단추가 가장 먼저 눈에 띕니다.

두 번째 트릭은 단추를 줄의 가장 처음에 배치하는 것입니다. 즉, 가로로 배치된 경우에는 맨 왼쪽에 세로로 배치된 경우에는 맨 위에 배치합니다. 대상 사용자의 습관에 따라 이러한 배치에 변화가 있을 수 있다는 점을 염두에 두시기 바랍니다. 오른쪽에서 왼쪽으로 읽는 언어로 된 응용 프로그램의 경우 해당 단추를 가장 오른쪽에 두는 것이 좋습니다.

가장 분명하고 권할 만한 옵션은 기본적으로 관심이 집중되도록 설정하라는 것입니다. 예를 들어 삭제 확인 대화 상자에서는 사용자가 실수로 삭제하는 것을 방지하기 위해 아니오 옵션이 강조 표시되어야 합니다.

3. 알아보기 쉽도록 아이콘 제공

"백문이 불여일견"이라는 말이 있습니다. 아이콘, 그 중에서도 특히 XP 및 Office 2003 아이콘과 도구 모음 비트맵은 UI를 파악하고 사용자가 수행해야 하는 작업을 빨리 알아볼 수 있게 해 줍니다.

예를 들어 메시지 상자에서 흔히 볼 수 있는 느낌표 아이콘이 나타나면 이 아이콘 옆의 컨트롤과 관련된 위험 수준을 즉각 알아차릴 수 있습니다. 마찬가지로 응용 프로그램에 컨트롤이 많으면 비록 적절히 배열되어 있다고는 해도 원하는 컨트롤 집합을 찾는 것이 매우 힘들 수 있습니다.

Windows XP 서비스 팩 2에서는 업데이트된 탭이 "자동 업데이트"라는 시스템 속성 제어판 애플릿에 추가되었습니다. 자동으로 업데이트를 다운로드하는 옵션, 업데이트를 다운로드하기는 하지만 사용자가 설치 시기를 결정할 수 있도록 하는 옵션, 업데이트가 있는 경우 사용자에게 알리기는 하지만 다운로드를 시작하지는 않는 옵션 그리고 자동 업데이트를 완벽하게 비활성화하는 옵션 등 4가지 옵션이 있습니다.

초보 PC 사용자인 경우 이러한 업데이트가 무엇을 의미하는지 모르는 것은 물론이며 어떤 옵션을 선택해야 하는지도 모를 수 있습니다. 그렇기 때문에 Microsoft에서는 "안전한" 옵션을 나타내는 가장 권장되는 옵션 옆에는 커다란 확인 표시가 있는 녹색 방패 아이콘을 표시하고 사용자에게 위험을 초래할 수 있는 옵션 옆에는 커다랗게 "x" 표시를 한 빨간색 방패 아이콘을 표시하였습니다. 급박한 상황 특히, 사용자가 너무 많은 설명을 읽을 시간이 없는 경우에 이 아이콘은 매우 유용합니다.

해당 시스템 속성 애플릿의 각 탭에는 서로 다른 작업에 대한 다양한 컨트롤이 있는 그룹 상자가 여러 개 있습니다. 컨트롤 그룹의 작업을 쉽게 나타낼 수 있도록 각 그룹의 옆에는 관련이 있는 그래픽이 표시됩니다. 이 그래픽 코드 유형은 실제 파일이나 주차장의 색 구분선과 유사합니다. 잡지 기사에 독자의 관심을 끌 수 있도록 최소한의 그래픽을 넣는 것과 같은 원칙이 적용됩니다.

올바른 아이콘을 선택하는 것도 중요합니다. Microsoft는 Visual Studio 2005에서 많은 표준 그래픽을 기본으로 제공하므로 이 그래픽을 선택하는 것이 가장 좋습니다. 사용자 지정 아이콘을 만들 경우 위의 표준 준수 섹션에 나와 있는 그래픽에 대한 운영 체제 수준 또는 응용 프로그램 수준의 표준을 준수하는 것이 좋습니다.

Windows XP Design Guidelines (영문)에는 Windows XP 스타일 32비트 아이콘을 만드는 방법에 대한 유용한 지침이 나와 있습니다. Windows Vista 스타일 아이콘에 대한 새로운 지침은 곧 배포될 예정입니다. 자세한 내용은 이 기사 끝 부분에 있는 링크를 참조하십시오.

4. 알아보기 쉽도록 머리글 작성

머리글은 한 문장(필요에 따라 그래픽도 함께 사용할 수 있음)으로 전체 대화 상자를 설명하는 완벽한 방법입니다. 때로는 머리글 내에 탐색 및 명령을 포함할 수도 있습니다. 머리글은 대화 상자가 팝업될 때 가장 먼저 눈에 띄기 때문에 일반적인 설명 레이블보다 더욱 효과적입니다.

Windows Installer 마법사는 아마도 가장 인기 있는 머리글일 것입니다. 맨 오른쪽에 간단한 아이콘이 있고 대화 상자를 설명하는 제목 레이블(예: 설치 폴더 선택) 다음에 대화 상자의 목적을 설명하는 하위 머리글(예: 소프트웨어 파일을 설치할 폴더 선택)로 구성됩니다. 그러나 이러한 원칙은 마법사 이외의 항목에도 적용됩니다.

계정 섹션이 있는 일반적인 업무용 응용 프로그램이 있다고 가정해 봅시다. Windows Vista에서 많이 사용되는 디자인 방식을 따라(그림 6 참조) 머리글 자체(상황에 따라 바닥글)에 필수적인 업무 정보와 관련 명령을 제공할 수 있습니다. 사용자가 "Big Company"에 대한 계정 파일을 열면 그림 7과 같은 머리글이 나타날 것입니다.

humanux_06.gif

그림 6. 상세한 바닥글이 있는 Windows Vista 탐색기

humanux_07.gif

그림 7. Windows Forms 응용 프로그램의 종합적인 머리글

마찬가지로 몇 가지 명령만 있으면 세로 공간이 많이 낭비되는 Windows XP 스타일 작업창을 추가하지 않아도 되며, 이러한 명령을 머리글로 옮기면 번거로움이 많이 사라집니다.

머리글을 설계할 때는 다음과 같은 사항을 염두에 두어야 합니다.

  • 대화 상자의 배경색과 다르도록 배경색을 설정하십시오. 흔히 흰색 머리글을 기본 Windows 내부 컨트롤 표면 색 위에 놓으면 됩니다. 그러나 특수 테마나 사용자 지정 색상으로 인해 머리글이 흐려지지 않도록 하려면 ControlLightControlDark라는 색이 있는 Color.FromKnownColor를 사용하여 LinearGradient를 그리십시오.

  • 가능하면 머리글의 높이를 150픽셀 미만으로 유지하시기 바랍니다. 일반적으로 100 또는 120픽셀이 적당하며, 전체 폼 높이의 1/4을 넘지 않도록 하십시오.

  • 위에 나온 그림 7의 Customer Name과 같은 머리글 정보를 즉석에서 수정할 수 있도록 하려면 동적으로 LinkLabel을 입력란으로 바꾸고 수정이 완료되면 이를 다시 한 번 교체하면 됩니다.

  • 글꼴 크기가 10pt가 넘는 제목 레이블이 있는 경우 Arial이나 Franklin Gothic Medium을 사용하십시오. MS Sans Serif는 너무 들쭉날쭉해서 전문적이지 않게 보입니다. Franklin Gothic Medium은 Windows XP 디자인 지침 설명서에서 권장되는 글꼴입니다. Windows Vista에서 사용되는 응용 프로그램에는 시스템 기본 글꼴인 Segoe UI 글꼴을 사용하십시오.

5. 사용자 지정 메시지 상자 사용

기본 Windows 메시지 상자에서 사용 가능한 옵션은 매우 제한되어 있습니다. 단순한 /아니오 또는 확인/취소로 답할 수 없는 질문을 해야 할 경우 문제가 복잡해 집니다. 결국 "~하려면 예를 클릭하십시오 또는 ~하려면 아니오를 클릭하십시오"와 같이 설명해야 할 것입니다.

Windows 응용 프로그램은 비전문적인 사용자들이 많이 사용함에 따라 점차 사용이 단순해지고 있습니다. 때로는 작업을 쉽게 수행할 수 있도록 하기 위해 친숙한 설명이 있는 단추나 심지어는 LinkLabel과 같은 추가 컨트롤을 제공하는 것이 보다 간단할 수 있습니다.

.NET Framework에서는 사용자 지정 대화 상자를 쉽게 구현할 수 있습니다. 사용자 지정 대화 상자 폼에 몇 가지 속성만 할당하거나 코드 한 줄만 할당하면 폼이 기본 메시지 상자와 동일하게 작동합니다. 단추를 클릭할 경우 대화 상자의 DialogResult 속성을 DialogResult.Ok 또는 DialogResult.Cancel로 설정하십시오. 상위 폼에서 ShowDialog([OwnerForm]) 메서드를 사용합니다. 그러면 ShowDialog 메서드가 DialogResult 값을 반환합니다.

모든 DialogResult 멤버를 사용할 수 있습니다. 이 동일한 옵션이 기본 MessageBox.Show 메서드에 사용됩니다.

또는 대화 상자의 AcceptButton 속성을 btnOK로 설정하고 CancelButton 속성을 btnCancel로 설정할 수도 있습니다. 그러면 EnterEsc 키가 btnOK 및 btnCancel 단추의 각 Click 이벤트에 자동으로 매핑됩니다.

다음은 사용자 지정 대화 상자를 꾸미는 데 필요한 몇 가지 팁입니다.

  • 복잡한 주제의 경우 적절한 텍스트 레이블 아래 "자세한 정보"라는 LinkLable을 사용하여 로컬 또는 온라인 도움말에 대한 링크를 제공합니다.

  • /아니오/취소 단추 대신 단추를 클릭할 경우의 결과를 분명히 나타내는 "파일 저장 후 종료", "저장하지 않고 종료" 및 "종료하지 않음"과 같은 텍스트를 사용합니다. 그러나 가능하면 표준인 /아니오, 확인/취소 및 기타 표준 단추를 사용하도록 하십시오. 친숙한 단추일수록 작업 효율성이 높아집니다.

  • 왼쪽 또는 대상 문자 환경에 따라 오른쪽에 50픽셀 정도의 여백을 남겨두고 대화 상자를 사용하는 경우를 나타내는 아이콘을 추가합니다. 정보 대화 상자인 경우 표준 메시지 상자에서 사용되는 "i" 아이콘을 사용하고, 보안 대화 상자인 경우 자물쇠 아이콘이나 열쇠 아이콘을 사용할 수 있습니다. Visual Studio 2005에는 몇 가지 우수한 고품질 그래픽이 기본 제공됩니다.

  • 항상 단추 사이를 키보드에서 편리하게 이동할 수 있도록 하십시오. 사용자들은 메시지 상자에서 키보드 단축키를 많이 사용합니다(예: 확인(Ok)은 O, 예(Yes)는 Y, 취소(Cancel)는 C). 사용자 지정 대화 상자에서 단축키를 사용할 수 없으면 사용자들이 불편을 느낄 것입니다.

6. 대체 명령 포함

의욕 저하와 게으름이라는 두 가지 중요 요인으로 인해 대체 입력 방법이 필요하게 되었습니다. 의욕 저하는 컴퓨터 사용자들에게 자주 나타나는 일입니다. 의욕 저하에 빠졌을 때는 작업을 빨리 끝내고 싶어합니다. 스트레스를 받고 있는 사람의 경우 추가로 클릭해야 한다거나 몇 초 간 더 기다려야 한다면 정말로 화가 나겠죠. 어떤 기분인지 아실 겁니다. 우리는 모두 이런 일을 항상 겪고 있으니까요. 게으름으로 인해 사람들은 그 시점에 사용 중인 것이 키보드나 마우스 중 어느 것이든 사용하던 수단으로 작업을 끝내고 싶어합니다. 그러나 이 두 가지 요인 이외에도 대체 입력 방법이 있으면 사용자들은 보다 쉽게 작업을 수행할 수 있게 됩니다.

예를 들어 "추가" 및 "제거"라는 두 개의 단추가 있는 목록 상자의 경우 어느 쪽이든 이러한 단추와 유사한 메뉴 명령이 있는 상황에 맞는 메뉴를 그 목록 상자에 추가해야 합니다. 그러면 사용자에게는 자신들이 가장 적합하다고 생각하는 방식을 선택할 수 있는 기회가 제공됩니다. Windows Vista User Experience Guidelines (영문)에 나와 있듯이 초보 사용자는 상황에 맞는 메뉴를 많이 사용하고 마우스 오른쪽 단추로 클릭하면 항상 이러한 메뉴가 나타날 것이라 예상합니다.

이와 비슷하게 텍스트나 숫자 입력에 시각적 컨트롤이 사용됩니다. 대표적인 예로 슬라이더는 정수 지정에 사용되고 Calendar 컨트롤은 날짜 입력에 사용되는 것을 들 수 있습니다. 때로는 키보드를 사용하여 입력하는 것이 가장 편안합니다. 슬라이더에 연결된 숫자 Up-Down 컨트롤을 추가하거나 Calendar 컨트롤 대신 DateTimePicker를 사용할 경우 사용자는 그 차이를 느낄 수 있습니다.

7. 중요 작업을 처리하는 방법

사용자들은 항상 혼란스러워 합니다. 그렇기 때문에 기술 지원 엔지니어들이 생계를 유지할 수 있습니다. 이 친절한 사람들의 수입을 갉아먹지 않으면서도 개발자들은 몇 가지 방법을 통해 사용자들의 혼란을 덜어주거나 최소한 치명적 오류가 발생했을 때 스스로 복구할 수 있도록 도움을 줄 수 있습니다.

치명적인 복구 불가능한 기능을 수행할 때는 일반적으로 해당 작업을 정말로 수행할 것인지 확인하는 메시지 상자 팝업을 표시하는 것이 좋습니다. 이에 대해서 좀 더 자세히 살펴보도록 하겠습니다. 그림 8에 있는 사용자 지정 메시지 상자는 어디서나 볼 수 있는 것이지만 진행률 표시줄이 있는 타이머가 있다는 추가적인 이점이 있습니다.

humanux_08.gif

그림 8. 기본적으로 가장 안전한 옵션이 선택되어 있는 중요 작업 대화 상자

몇 가지 경우에 따라 변형 메시지 상자를 사용해 볼 수 있습니다. 원자력 발전소의 과부하에서 파일의 영구 삭제에 이르기까지 수행할 작업이 매우 중요한 경우 타이머가 만료된 후의 기본 작업은 취소로 지정합니다. 대화 상자는 사라지면 안 되며 텍스트 레이블에 작업이 취소되었음이 표시됩니다. 사용자는 명령이나 취소를 확인하도록 선택할 수 있습니다.

중요 작업을 수행하는 단추는 항상 분명히 표시하도록 하고 해당 작업을 정확하게 설명하는 분명한 텍스트를 사용해야 합니다. 예를 들어 파일을 삭제하는 작업의 경우 "리포지토리에서 파일 제거"라고 쓰지 말고 "리포지토리에서 파일 삭제"라고 써야 합니다. 파일 목록을 사용하여 작업할 때 삭제 메뉴 명령이 파일 목록에서만 파일을 제거하는 것이 아니라 하드 디스크 자체에서 선택된 파일을 삭제할 경우 이 작업이 심각한 결과를 초래할 수 있다는 점을 적절히 강조하고 이 작업을 수행할 경우 영구적으로 파일이 삭제된다는 점을 분명히 알려야 합니다.

누군가가 "당신은 당신의 최악의 작품만큼의 값어치 밖에 없습니다"라고 말했다고 가정해 봅시다. 이 내용은 소프트웨어 응용 프로그램에도 적용됩니다. 여러분이 개발한 응용 프로그램 사용 시 경험한 단 한 번의 좋지 않은 기억이 그 사용자에게는 상당히 부정적인 인상을 줄 수 있습니다. 이러한 일이 발생하지 않도록 여러분이 취할 수 있는 조치는 응용 프로그램에 오류가 발생할 경우 점차적으로 여파를 줄이는 것입니다. 데이터 복구를 추가하거나 사용자가 해당 데이터의 사본을 저장할 수 있도록 하면 더 유리한 요인이 됩니다. 응용 프로그램에 오류가 발생할 경우 사용자에게 적절히 알려야 합니다. JIT-디버거 또는 중대한 오류 대화 상자는 그다지 좋은 방법이 아닙니다. 오류를 해결하는 방법에 대해 설명하는 것은 이 기사에서 다루는 범위를 벗어나기는 하지만 사용자에게 사과하고 상황에 대해 정확히 알리는 대화 상자를 표시하거나 자세한 정보를 볼 수 있는 링크 또는 이 오류를 복구할 수 있는 방법이 수록된 링크를 제공하면 사용자에게는 매우 큰 도움이 될 것입니다.

이보다 한 발 더 나아가려면 제가 가장 좋아하는 그래픽 디자인 응용 프로그램 중 하나에서 제공하는 기능을 제공하면 됩니다. 이 응용 프로그램은 오류가 발생할 경우 작업 중인 파일의 사본을 저장할 수 있도록 해 주는 복구 대화 상자를 표시한 다음, 물론 선택적 개인 정보이지만 오류에 대한 정보를 입력하여 개발자에게 보낼 수 있도록 해 주는 피드백 대화 상자도 표시합니다.

8. 라디오 단추 또는 콤보 상자

언뜻 보면 많은 항목 중 하나를 선택하도록 하는 방법은 그다지 어렵거나 중요해 보이지 않으나 시간에 민감한 작업에 사용되는 응용 프로그램인 경우에는 중요할 수 있습니다.

실제 예를 하나 살펴보도록 하겠습니다. Microsoft는 최근 그래픽 응용 프로그램인 Expression Graphics Designer(예전 코드명은 "Acrylic")의 시험판 버전을 출시했습니다. 저는 이 응용 프로그램에서 그래픽 개체 약 20개에 특정 속성을 각각 할당해야 했습니다. 정말로 지루한 과정이었죠. 이 작업을 위해서는 개체를 선택하고 설정 창을 표시하는 단추를 클릭한 다음, 옵션을 설정해야 했습니다. 그림 9에 나와 있듯이 한 옵션에서는 콤보 상자에서 두 가지 선택 항목 중 하나를 선택해야 합니다.

humanux_09.gif

그림 9. Microsoft Expression Graphics Designer, Edge Glow

콤보 상자 목록을 드롭다운해서 단지 두 개만 있는 선택 항목 중 두 번째 항목을 선택해야 할 경우 정말 번거로울 수 있습니다. 우리가 일반적으로 인식하지 못하는 것은 드롭다운 목록이 나타나는 데 걸리는 시간입니다. 이는 시간 낭비이며 답답한 상황일 수 있습니다. 두 개의 라디오 단추가 있는 그룹 상자를 배치하면 이 문제를 간단히 해결할 수 있습니다. 특히 가용 공간이 많은 경우에 유용합니다. CorelDRAW, Microsoft Access 등의 응용 프로그램에서도 이와 비슷한 문제에 봉착했습니다.

드롭다운 애니메이션 때문에 시간이 낭비될 뿐 아니라 "생각해야 하는 영역"도 허비됩니다. "항상 보이는" 라디오 단추가 있으면 커서로 클릭할 위치를 잠재 의식적으로 알게 됩니다. 콤보 상자가 있는 경우에는 목록이 표시된 '이후'에만 처리됩니다. 이것은 별로 중요한 내용이 아닌 것처럼 보일 수도 있으나 사실상 매우 중요한 문제입니다.

때로는 선택 항목이 4개 이하인 경우에는 라디오 단추를 사용하는 것이 더 좋을 수 있습니다.

9. 사용자를 방해하지 마십시오

머리에 총구를 겨누는 것까지는 아니지만 이는 개발자가 사용자에게 행할 수 있는 가장 파괴적인 일입니다. 여러분의 응용 프로그램이 다른 응용 프로그램을 사용하고 있을 때 메시지 상자를 띄우거나 작업 표시줄을 깜빡이게 해서 불필요하게 방해가 될 경우 그 사용자로부터는 감점을 받게 됩니다.

물론 작업 표시줄의 깜빡임은 유용할 수 있으나 응용 프로그램의 프로세스를 원활하게 계속하기 위해서는 사용자의 입력이 필요한 경우나 사용자에게 전달할 중요한 내용이 있는 경우에만 사용해야 합니다. 사용자가 작업 표시줄을 자동 숨기기로 유지할 경우 작업 표시줄 단추가 깜박이면 작업 표시줄이 가장 위에 나타나서 사용자가 다시 깜빡이는 단추를 클릭할 때까지 숨겨지지 않으므로 상태 표시줄이나 다른 하단에 고정된 컨트롤에 액세스하는 데 방해가 될 수 있습니다.

humanux_10.gif

그림 10. 그래픽과 컨트롤이 여러  있는 사용자 지정 팝업 알림 

MSN Messenger와 같은 인스턴트 메시지 클라이언트에 의해 유명해진 "팝업 알림" 창(그림 10 참조)은 성가시거나 사용자의 작업 흐름을 방해하지 않고도 사용자에게 무언가를 알릴 때 훌륭한 솔루션입니다. 팝업 알림 창을 만드는 방법에 대해 Bill Wagner가 기고한 훌륭한 기사!href(http://msdn.microsoft.com/msdnmag/issues/05/09/WindowsForms/default.aspx)를 읽어보시기 바랍니다. 다른 응용 프로그램의 팝업 알림을 방해하지 않는 것이 좋으며 이것이 매너이기도 합니다. 이러한 창이 나타나서 가로막으면 성가실 뿐 아니라 효율성도 떨어집니다. 한 가지 해결책은 팝업 알림 충돌을 피할 수 있도록 운영 체제에서 제공하는 ToastSemaphore Mutex!href(/library/en-us/WinMessenger/winmessenger/overview/toast.asp)를 사용하는 것입니다.

때로는 팝업 알림별로 여러 항목을 표시해야 할 수 있습니다. 3개 이상의 팝업 알림을 사용하는 것은 권장되지 않습니다. 대신 한 팝업 알림이 사라진 다음에 다른 팝업 알림을 띄우는 것을 반복하는 것이 좋습니다. Microsoft Outlook에서 사용자에게 수신 전자 메일을 알릴 때 이와 비슷한 방법을 사용합니다.

10. 진행 상태 알리기

종종 사용자가 기다려야 하는 작업이 있습니다. 물론 이렇게 기다리는 것은 사용자들이 싫어하는 일 중에 하나입니다. 그러나 최악의 상황은 진행 상태를 모르는 상태에서 기다려야 할 경우입니다. 때로는 응용 프로그램을 웹 서비스나 원격 컴퓨터에 연결해야 할 수도 있고 어떤 이유에서건 대규모의 데이터 처리가 필요한 경우도 있습니다. 이때 사용자는 응용 프로그램에서 어떤 일이 일어나고 있는지를 알아야 합니다. 막연하게라도 말이죠. 상황에 따라 이렇게 사용자에게 작업 상황을 알리는 방식은 여러 가지가 있습니다.

웹 서비스와 같이 멀리 떨어진 개체나 네트워크 또는 인터넷 서버에 있는 항목에 연결해야 할 경우 간단한 진행률 대화 상자(그림 11 참조) 또는 상태 표시줄에서 움직이는 진행률 표시줄을 보여주는 것이 좋습니다. 이때 표시되는 레이블은 현재 진행 상태를 설명해야 합니다. 예를 들어 웹 서비스에 연결하여 어떤 데이터를 처리할 경우 "웹 서비스에 연결하고 있습니다... " 또는 "잠시만 기다려 주십시오. 처리 중입니다... "와 같은 메시지를 표시해야 합니다. 이 프로세스가 동기식으로 이루어질 경우 프로세스가 완료될 때까지 사용자들이 액세스할 수 있는 모든 컨트롤을 비활성화하거나 진행률을 모달 대화 상자에 표시하는 것이 좋습니다.

humanux_11.gif

그림 11.  서비스 연결 상태를 보여 주는 간단한 진행률 대화 상자

진행률 표시줄을 사용 중이고 처리 시간을 알 수 없거나 최대값이 없는 경우 진행률 표시줄 스타일을 움직이는 텍스트 모드로 설정하는 것이 좋습니다.

점점 많이 사용되고 있는 다른 방법으로는 진행률을 표시하는 고정 '팝업 알림' 창을 들 수 있습니다. Microsoft AntiSpyware 다운로더/업데이터 또는 Norton AntiVirus 전자 메일 검색 팝업 알림은 이러한 좋은 예라고 할 수 있습니다. 물론 팝업 알림은 비동기 프로세스에만 사용해야 합니다. 그렇지 않으면 사용자가 당황할 수 있습니다. 이러한 창은 업데이트를 다운로드하거나 예약된 작업을 수행하는 등 백그라운드 처리에 사용하는 것이 가장 좋으며 "항상 위"로 설정하면 안 됩니다.

11. 마법사로 복잡한 단계를 간단히 수행

한 폼에 컨트롤이 너무 많은 경우 일반적인 사용자는 매우 당황할 것이라고 가정해야 합니다. 중요한 컨트롤이 많이 있는 경우에는 그룹화, 크기 조정 또는 간격 지정이 도움이 되지 않을 수도 있습니다.

이러한 경우에 마법사는 가장 좋은 해결책입니다. 가능한 경우 컨트롤을 작업 또는 범주별로 나누고 이를 별도의 단계로 구분할 수 있습니다. 그러면 사용자의 주의를 흐트러트리지 않고 작업을 정상적으로 진행할 수 있습니다. 도움말 단추로 해당 단계별 또는 작업별 도움말을 제공할 수 있습니다. MSDN Library에서 마법사 만들기 지침을 볼 수 있습니다.

마법사는 응용 프로그램의 초기 구성을 설정하는 데 도움이 되는 좋은 방법이기도 합니다. 많은 응용 프로그램은 이러한 마법사를 사용하여 설치가 완료된 후 또는 처음 사용 시에 개별화된 구성을 설정합니다. 이러한 초기 마법사는 가능한 한 옵션으로 제공해야 합니다. 사용자가 언제든 마법사를 취소할 경우 지정되지 않은 설정은 기본값으로 지정됩니다. 마법사에 그래픽적 요소를 첨가할 수 있다면(멋진 그래픽 사용 섹션 참조) 구성 작업이 훨씬 더 쉬워질 것입니다.

12. 텍스트의 어조를 정확히 전달

최근 발표된 Microsoft Windows Vista User Experience Guidelines (영문)에서는 "텍스트 어조"에 대해서 매우 중요한 점을 시사했습니다. 텍스트 어조란 응용 프로그램에서 텍스트가 주는 인상 및 느낌을 말하며, 간단한 도구 설명에서 지침 레이블 컨트롤에 이르기까지 모든 내용이 여기에 해당됩니다.

앞 부분에서 MSN Messenger의 웹캠 옵션의 텍스트를 변경하는 예에 대해서 설명했습니다. 이를 적절한 텍스트 어조라고 합니다. 비전문가 또는 초보 사용자를 대상으로 할 때는 메시지를 전달하는 것이 다른 양상으로 흐를 수 있습니다.

자동 압축 풀기 응용 프로그램에서 입력란 위에 "대상 경로"라고 쓰면 기술적 지식이 있는 사용자는 "C:\Temp\MyPath"와 같은 경로를 입력해야 한다는 것을 알겠지만 초보 사용자는 당황해서 설명서를 참조하거나 기술 지원팀에 문의하거나 최악의 경우에는 아마 여기서 포기하고 말 것입니다. 이런 경우 훌륭한 대안은 "이러한 파일을 저장할 폴더를 선택하십시오."와 같이 사용자가 취하길 원하는 작업을 지정하는 것입니다. 또는 이 입력란 옆의 "찾아보기... " 단추의 이름을 "폴더 선택..."으로 변경할 수도 있습니다.

사용자가 무엇을 하길 원하는지 명확하게 설명하면 도움말 파일을 제공할 필요성도 줄어듭니다. 최소한 도움말 파일에 포함시켜야 하는 세부 정보는 줄일 수 있을 것입니다.

Windows Vista User Experience Guidelines에서 제공하는 매우 훌륭한 제안은 모든 소프트웨어에 적용됩니다. 이 제안에 따르면 개발자는 텍스트를 대화식으로 유지해야 합니다. 이 지침에서는 이를 "직접 대면해서 말하지 못할 내용은 피하라"는 것으로 정의합니다.

다음은 텍스트 작성에 대한 몇 가지 팁입니다.

  • 사용자를 지칭할 때 3인칭을 사용하지 않도록 합니다. "사용자" 대신 "여러분"을 사용해야 합니다.

  • 가능한 한 "이름:" 또는 "전자 메일:" 대신 "내 이름:" 또는 "내 전자 메일 주소:"를 분별해서 사용합니다.

  • 옵션을 여러 개 제공할 때는 사용자의 관점에서 텍스트를 작성합니다. 예를 들어 "이 네트워크에서 [Username]에게 허용할 사용 권한 선택"이라는 레이블 아래에 "허용" 및 "거부"라는 라디오 단추가 있는 경우 이 라디오 단추의 텍스트를 "[Username] 허용" 및 "[Username] 허용 안 함"으로 바꾸어야 합니다.

  • 링크로 사용될 경우에만 텍스트에 밑줄을 긋습니다. 밑줄이 있는 텍스트가 링크가 아니면 사용자에게 혼동을 줄 수 있습니다.

  • 굵은 글씨로 된 레이블로 중요 정보에 주의를 집중시킵니다. 그러나 굵은 글씨는 주의해서 사용해야 합니다. 굵은 글씨로 된 텍스트가 너무 많으면 혼란스럽고 전체적인 폼의 효과가 감소됩니다.

  • 확인란의 텍스트를 작성할 때는 확인란을 선택하거나 선택하지 않았을 때 또는 선택을 취소했을 때 어떻게 되는지 알기 쉽도록 작성해야 합니다. 확인란을 선택할 경우의 叿䉍/᠀젇㠁㠀︂.�პɀĀ＀�ÿ阀䁉需 "귀사의 협력업체로부터 유용한 정보를 수신하지 않음" 대신에 "귀사의 협력업체로부터 유용한 정보 수신"이라고 확인란을 작성하십시오. 많은 마케팅 업계 종사자들은 이 예가 적절치 않다고 목소리를 높일 것이라 생각되지만 여러분은 제가 무엇을 의미하고자 하는지 아실 것입니다.

  • 활성화/비활성화를 제어하는 단추 모양의 컨트롤이 있는 경우(대개 명령 단추가 표시되는 라디오 단추) 레이블을 적절하��� 표시해야 합니다. 프로세스가 활성화되어 있으면 "활성화", "비활성화"라 하지 말고 "활성화됨"으로 표시합니다. 활성화됨이라고 작성하면 현재 상태를 나타냅니다. 단추가 클릭된 상태인 경우(활성화됨)에 "활성화"라고 표시되면 혼동할 수 있으며 이로 인해 문제가 될 수 있습니다. "활성화"라고 되어 있으면 사용자가 해당 프로세스가 활성 상태가 아닌 것으로 생각하고 클릭할 수 있기 때문입니다.

13. 때로는 ListView가 더 효율적

우리는 종종 선택 작업을 위해 데이터 표나 목록 상자 또는 콤보 상자를 사용하지만 Windows XP 및 이후 버전의 Windows에서는 ListView를 사용하면 보다 다양한 옵션을 제공할 수 있습니다.

ListView 컨트롤의 장점:

  • 아이콘과 비트맵으로 항목을 빠르게 인식할 수 있습니다.

  • 자세히 또는 바둑판식 보기로 추가 정보를 표시합니다.

  • Visual Studio 2005에는 추가 분류를 위한 그룹도 제공됩니다. 그룹은 모든 보기에 걸쳐 있으며 유연합니다. 그룹은 TreeView와 같이 부모 노드보다 자식 노드가 많은 계층 보기를 평면화하는 데도 사용할 수 있습니다. 이러한 좋은 예는 Windows XP의 네트워크 연결 대화 상자를 "그룹별로 표시"하여 나타내고 보기를 자세히로 설정한 상태입니다.

  • ListView 컨트롤을 사용자 지정하려면 OwnerDraw 속성을 설정하고 DrawItemDrawSubItem 이벤트를 사용하여 수동으로 구성합니다.

  • ListView 항목의 빠른 내부 수정을 지원합니다.

  • 수동 재배열을 손쉽게 지원합니다.

  • 사용자들이 가장 편안한 보기(큰 아이콘, 작은 아이콘, 목록 등)를 선택할 수 있도록 합니다.

14. 이동 경로(Breadcrumb) 컨트롤과 세로 막대로 간단한 탐색 지원

"하위 탐색"은 복잡한 UI에 있어 가장 중요합니다. 때때로 복잡한 UI를 사용해야만 하는 경우도 있습니다. 이런 상황에서 가장 좋은 방법은 가능한 사용자가 쉽게 사용할 수 있도록 지원하는 것입니다. 링크 레이블로 구성된 세로 막대나 계층별 탐색을 위한 TreeView에서는 현재 대화 상자의 작업과 동일한 수준의 탐색이 가능합니다. 이러한 보기에서는 사용자가 자신의 위치를 알면서 프로세스의 단계 간에 쉽게 이동할 수 있습니다.

TreeView에서 계층별 탐색을 하거나 다른 복잡한 탐색을 수행할 경우 이동 경로 컨트롤을 사용하는 것이 유용합니다. Visual Studio에는 아직까지 기본 제공 컨트롤이 없으나 사용자 지정 컨트롤을 만드는 방법에 대해 MSDN에 Duncan MacKenzie가 기고한 훌륭한 기사 (영문)가 있으므로 참조하시기 바랍니다. 이동 경로 컨트롤은 계층과 대비하여 현재 위치를 쉽게 파악할 수 있도록 해 줍니다.

이동 경로 탐색은 폼에 머리글이 있는 경우 이 머리글에 쉽게 병합될 수 있습니다. 앞에서 설명한 머리글에 관한 섹션을 참조하십시오. 그림 7은 머리글의 이동 경로 탐색 모음을 보여 줍니다.

15. 멋진 그래픽 사용

누구나 그래픽이 훌륭한 응용 프로그램을 좋아합니다. 아니 모두는 아니라도 대다수의 사용자가 그렇습니다. 당연히 모든 응용 프로그램의 UI 그래픽을 훌륭하게 만들어야 하는 것은 아니지만 그래픽이 우수하면 좋은 인상을 주고 즐겁게 작업할 수 있습니다. 물론 그래픽이 효율성을 저해해서는 안 되지만 적절히 사용할 경우 효율성이 향상됩니다.

그래픽이 많을 필요는 없으며 반드시 번거로운 작업이 필요한 것은 아닙니다. 전문적으로 설계된 화려한 시작 화면이나 앞에서 말한 것과 같은 머리글은 트릭에 불과합니다. 예산이 허용되는 한도 내에서 도구 모음, 마법사 등에 훌륭한 디자인의 그래픽을 사용할 수 있습니다. 그래픽을 넣으면 응용 프로그램이 외관상 훌륭해 보이며 보다 전문적으로 보입니다. 미묘한 효과이기는 하나 전문적인 외관을 갖추면 자신감과 안정감이 묻어납니다. 일반 판매용 응용 프로그램을 제작하는 상대적으로 규모가 작은 회사인 경우에는 이 점을 중요하게 고려해 봐야 합니다.

항상 전문적으로 설계된 그래픽을 사용하도록 합니다. 로열티가 없는 그래픽은 쉽게 사용할 수 있을 뿐만 아니라 가격도 저렴합니다. 디자이너를 고용할 수도 있습니다. 그러나 그래픽에 소질이 없다면 자체적으로 시도하지 마십시오. 전문적으로 설계된 그래픽을 얻거나 사용할 수 없는 경우 아예 사용하지 않는 편이 낫습니다.

작은 그래픽의 경우 언제나 Visual Studio 2005에서 기본 제공되는 아이콘과 비트맵을 사용할 수 있습니다. 이전 버전에서 기본 제공되는 그래픽은 권장되지 않습니다.

16. 가급적 크기 조정이 가능한 폼 제공

크기 조정이 가능한 창은 해상도와 상관없는 창과 어느 정도 비슷합니다. 해상도와 상관없는 창은 96DPI 화면을 사용하든 300DPI 화면을 사용하든 똑같아 보입니다. 응용 프로그램 UI의 해상도 여부와는 관계없이 크기를 조정할 수 있으면 좋습니다. 물론 많은 경우에 해당되는 내용은 아니지만 일반적으로 적용되는 좋은 규칙입니다.

창에 어떤 종류든 목록이 있는 경우 그 중에서도 특히 ListView는 더욱 중요합니다. 크기 조정을 통해 사용자는 동시에 더 많은 데이터를 볼 수 있습니다.

예를 들어 크기가 큰 컬렉션에서 이미지를 선택해야 하는 응용 프로그램이 있다고 가정해 봅시다. 이 열린 대화 상자에서는 미리 보기를 선택할 수 있으나 대화 상자의 크기가 고정되어 있으면 미리 보기 목록에 미리 보기가 한 번에 4개만 표시됩니다. 컬렉션에 이미지가 100개 있는 경우 이미지를 스크롤하는 반복되는 작업은 매우 지루하고 효율성을 떨어트릴 수 있습니다. 대화 상자의 크기가 조정 가능할 경우 사용자는 가능한 보기 편할 만큼, 아니면 화면에서 허용되는 만큼만이라도 대화 상자를 크게 키우고 작업을 빠르게 마칠 수 있습니다. 자세한 ListView나 DataGrid와 같이 목록에 가로 스크롤이 있는 경우 더욱 지루한 작업이 됩니다. 이러한 상황에서 창의 크기를 조정할 수 있는 기능은 매우 유용합니다.

17. 세로 막대/작업창으로 보다 다양한 기능 제공

앞에서 설명한 머리글과 마찬가지로 세로 막대와 작업창은 추가 기능과 유틸리티 명령을 제공할 수 있는 훌륭한 방법입니다. 예를 들어 Microsoft Office Word 2003의 작업창은 매우 편리하고 액세스가 용이하며 다른 작업에 방해가 되지 않습니다. 온라인 리소스에 연결하면 비동기식으로 작동하므로 사용자는 멀티 태스킹을 수행할 수도 있습니다.

맨 위에 제목 표시줄이 될 그래픽을 정면으로 넣는 옵션을 사용하면 고정 패널을 만드는 것만큼 쉽게 작업창이나 세로 막대를 만들 수 있습니다. 색상이 있는 레이블 컨트롤을 사용할 수도 있습니다. 작업창은 다양하게 활용할 수 있습니다.

추가 기능이 있고 방해하지 않는 방법으로 사용자에게 제공하려는 경우 작업창만큼 좋은 장소는 없습니다. 작업창을 "자동 숨기기"로 설정하거나 Visual Studio 도구 창과 같이 축소할 수도 있습니다. 간단하면서도 종합적인 작업창의 예는 Windows XP와 함께 제공되는 Microsoft Windows Movie Maker의 작업 세로 막대입니다.

18. 알림 옵션 제공

앞에서 사용자 지정 메시지 상자를 만드는 방법을 살펴봤습니다. 응용 프로그램의 메시지 상자가 사용자에게 종종 표시될 경우 앞으로 이 대화 상자가 표시되지 않도록 즉, 비활성화하도록 선택할 수 있는 확인란을 추가하면 세심한 배려가 될 수 있습니다. 이러한 옵션은 특히 보다 분명한 메시지에 유용합니다.

이에 대한 친숙한 예로는 Visual Studio의 찾기 대화 상자를 들 수 있습니다. 텍스트를 검색하거나 바꿀 때 Visual Studio에는 결과를 보여 주는 메시지가 나타납니다. 그러나 이 메시지 상자를 비활성화할 수 있는 옵션도 제공됩니다. 검색할 때마다 Enter 키를 누르거나 확인을 클릭해야 한다면 매우 번거로울 수 있습니다.

Visual Studio의 또 다른 훌륭한 점은 대화 상자를 비활성화하더라도 상태 표시줄에 작업 결과가 표시된다는 점입니다.

19. 도구 설명 제공

때로는 도구 설명이 있으면 많은 시간을 절약할 수 있습니다. 단추, 확인란 및 기타 컨트롤만으로는 확실하지 않아서 사용자가 어떻게 해야 할지 모르는 경우가 있습니다. 도구 설명은 상황에 맞는 도움말을 한 줄로 제공할 수 있는 가장 좋은 형태입니다. 도구 설명이 제공되면 사용자는 도움말 파일에서 항목을 검색하거나 다른 창을 열지 않고도 무엇을 해야 할지 빠르게 결정할 수 있습니다.

개발자들은 종종 응용 프로그램에서 도구 설명을 생략하기도 합니다. 모든 모호한 컨트롤 또는 가능한 경우 모든 컨트롤에 도구 설명을 추가하도록 하십시오. 옆에 나타나는 레이블의 텍스트나 컨트롤 자체에 표시된 텍스트를 반복해서 넣지 말고 해당 컨트롤에 대한 추가 정보를 제공하도록 합니다. 이 텍스트는 몇 단어만으로 컨트롤의 기능을 설명할 수 있어야 합니다.

20. 사소한 부분까지 배려

사소한 부분까지 신경을 쓰는 것이 다소 힘들게 느껴질 수 있으나 이렇게 사소한 부분을 무시하면 여러분에 대한 인상에 영향을 미칠 수 있습니다 저는 예전에 소프트웨어 업계의 저명한 개발자가 만든 응용 프로그램을 사용한 적이 있었습니다. 폼의 테두리 스타일은 조정 가능하도록 설정되어 있었으나 폼 오른쪽의 컨트롤은 고정되어 있지 않았습니다. 이 때문에 업계에서 명성이 있는 개발자가 만든 응용 프로그램이었음에도 그다지 전문적인 프로그램이라는 느낌을 받지 못했습니다.

이러한 "사소한 부분"은 전체적인 인상을 결정하는 중요한 요소입니다. 응용 프로그램의 UI와 UX는 사용자들이 여러분의 응용 프로그램을 판단하는 기준이 됩니다. 최소한 처음에는 말이죠. UI에서 명백한 버그를 발견할 경우 여러분의 응용 프로그램의 기능이나 효율성이 떨어진다고 생각할 수 있습니다. "표지로 책을 판단하지 말라"는 오래된 명언은 소프트웨어 응용 프로그램에는 해당되지 않습니다. 이 경우에는 책에도 해당되지 않습니다.

결론

지금까지 휴먼 사용자 환경을 만들기 위한 팁을 살펴봤습니다. 사용자 환경이 점차 단순하고 효과적이며 재미있고 보다 사용이 편리하게 되면서 사용자 환경을 구축하는 것도 점차 복잡해지고 있습니다. 그러나 어느 정도의 통찰력과 훌륭한 계획이 뒷받침된다면 훌륭한 사용자 환경을 만들 수 있을 것입니다.

완벽한 사용자 환경을 만들기 위한 가장 좋은 방법은 특수 테스트 그룹을 활용하든 자체적으로 하든 UI를 대상으로 유용성 테스트를 실행하는 것입니다. 응용 프로그램을 출시하기 전에 사용자 환경을 테스트하는 데 더 많은 시간을 들이면 들일수록 좋습니다. 이러한 테스트를 통해 추후 발생할 수 있는 많은 문제를 사전에 해결할 수 있습니다.

참조 및 자료

훌륭한 사용자 환경 설계를 위한 기타 다양한 측면에 대해서 알아보려면 아래 나온 자료를 읽어 보는 것이 좋습니다.

  • The Human Factor (영문) 약간 오래되기는 했으나 Scott Berkun이 MSDN에 기고한 이 컬럼은 소프트웨어 및 웹 디자인에 대해 매우 통찰력 있게 접근합니다.

  • Windows Vista User Experience Guidelines (영문) 준비 단계에 있는 경우라도 이 지침을 참조하면 Windows Vista는 물론 일반적인 응용 프로그램을 훌륭하게 설계하는 데 도움이 됩니다.

  • Windows XP Design Guidelines (영문) Windows Vista가 출시될 때까지는 일반적으로 이 지침을 따르는 것이 가장 좋습니다.

  • Tablet PC Documentation (영문) 이 문서 집합에는 훌륭한 Tablet PC 호환 문서를 계획하는 데 필요한 모든 내용이 수록되어 있습니다.

또한 사용자 인터페이스 디자인 및 사용자 환경 디자인에 대한 MSDN Library의 기사도 계속해서 확인하시기 바랍니다.

Dax Pandhi는 소프트웨어 및 기술 그래픽을 전문적으로 취급하며 수상 경력이 있는 기술 스튜디오인 Nukeation Studios (영문)의 주요 개발 책임자입니다. Pandhi는 시각적 기능이 강화된 Windows 및 웹 응용 프로그램뿐 아니라 Windows 프레젠테이션 파운데이션에 기반한 응용 프로그램을 개발하는 데 주력하고 있습니다. Pandhi에게 문의 사항이 있는 경우 그의 블로그 (영문)를 통해 연락할 수 있습니다.

반응형
Posted by blueasa
, |
System::String 관련

 

 

 

예제 소스 (Mngstr2Umngstr.h)

  1.  
  2. #include <string>
  3. using namespace System;
  4. String^ CppCliStrConv(const std::string& native_str)
  5. { return Runtime::InteropServices::Marshal::PtrToStringAnsi(IntPtr::IntPtr((void*)native_str.c_str())); }

 

반응형

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

C#에서 Native C++ 프로젝트 사용하기  (0) 2010.05.31
마샬링(Marshaling)  (0) 2010.05.27
혼합 모드에서 디버깅  (0) 2010.05.26
다양한 문자열 형식 간 변환  (0) 2010.05.26
C++/CLI & WCF Programming  (1) 2010.05.26
Posted by blueasa
, |
반응형

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

마샬링(Marshaling)  (0) 2010.05.27
System::String 관련  (0) 2010.05.26
다양한 문자열 형식 간 변환  (0) 2010.05.26
C++/CLI & WCF Programming  (1) 2010.05.26
Native C++ & C++ / CLI & C# 환경에서의 디버깅  (0) 2010.05.26
Posted by blueasa
, |
반응형

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

System::String 관련  (0) 2010.05.26
혼합 모드에서 디버깅  (0) 2010.05.26
C++/CLI & WCF Programming  (1) 2010.05.26
Native C++ & C++ / CLI & C# 환경에서의 디버깅  (0) 2010.05.26
System::String -> char* OR wchar_t*  (0) 2010.05.26
Posted by blueasa
, |

1. 알아두어야 할 이야기

 

C++/CLI를 사용하기 위해서는 Visual Studio 2005 이상의 버전이 설치되어 있어야 컴파일러가 C++/CLI 문법을 인식한다. C++/CLI를 이용하면 C# 의 장점과 C++의 장점을 동시에 취할 수 있다. Managed C++가 발전된 형태이다.

 

1.1. .Net Framework

C 언어가 널리 쓰였다는 점은 어떻게 보면 놀라운 일이다. C는 어려운 언어이기 때문이다. 강력한 반면 수 많은 메모리 관련 버그를 만들 수 있기 때문에 완벽하게 구사하기 어렵다. C++도 마찬가지로 좀 더 인간의 사고와 가까운 객체 지향의 패러다임을 도입하여 생각을 더 잘 표현해 낼 수는 있게 되고 클래스 재사용 등을 통해 생산성을 높였지만, 같은 문제를 지니고는 있었다. 아직까지도 탑을 차지하고 있는 프로그래밍 언어의 왕좌에 자극을 준 것은 자바이다. 자바는 가상머신 위에서 돌아가는 프로그램을 생산해내면서 플랫폼 사이의 호환 문제를 해결했을 뿐만 아니라, 더욱 높은 생산성을 가질 수 있게 되었다. 결과적으로 보면 자바를 따라 했다고 할 수 있겠는데, MS .Net Framework라는, 쉽게 말하면 라이브러리 셋을 만들어 내었다. (자바라는 언어가 없었다면 .Net Framework가 탄생할 수 있었을까?) .Net Framework을 통해 얻을 수 있었던 이점은 동일 프레임워크 상에서는 무조건 똑같이 수행될 바탕을 마련했다는 점과, 여러 유용하고 생산성을 증대시킬 수 있는 기능들을 미리 프레임워크 내에 구비시킴으로써 개발의 용이성을 증대시켰다는 점 등을 들 수 있겠다. 이를 위해 C#이라는 언어를 MS에서 등장시켜버렸다. 약간은 거부감까지도 가질 수 있도록 한 새로운 언어는 아마도 MS의 기대만큼은 인기를 얻지 못했다고 생각한다.

 

1.2. CLI (Common Language Infrastructure)

CLI(공통 언어 기반)MS.Net Framework, Mono, Potable .Net 과 같은 수많은 런타임의 중심부를 형성하는 실행 코드와 런타임 환경을 설명하기 위해 마이크로소프트사가 개발한 오픈 규격이다. 이 규격은 여러 개의 높은 수준의 언어가 다른 컴퓨터 플랫폼에서 특정한 구조를 위해 별도의 수정 과정 없이 사용될 수 있게 만들어 준다.

호환되는 모든 언어는 플랫폼 하드웨어에서 떨어져 나온 중간 언어인 공통 중간 언어(CIL)와 컴파일이 가능하다. 코드가 실행될 때, 플랫폼에 의지하는 VES는 공통 중간 언어를 호환 하드웨어에 맞추어 기계어로 컴파일하게 된다.

CLI 라이브러리는 웹서비스부터 3D 그래픽 프로그래밍까지 많은 부분의 기능을 제공하는데, 혹자는 MFC를 대체할 수 있을 정도라고까지 말한다. CLR(Common Language Runtime) CLI MS 버전으로 Windows에 맞도록 된 것이다.

 

1.3. Managed C++

MS는 개발자들을 감싸안기 시작했는데, .Net Framework 상에서 이루어지는 프로그래밍 언어의 특징을 Managed 라는 하나의 단어로 수렴시켜 그 특징들을 C++에 부여했다. 정확한 명칭은 Managed Extensions for C++이다. Visual Studio 내의 CLR(Common Language Runtime)을 이용하며 .NET 버전에서는 Managed라는 단어가 붙은 프로젝트들이 있었으며, 2005 이상에서는 공통 언어 런타임 지원(Common Language Runtime support) 옵션 중에 /clr:oldSyntax을 택해야 빌드 가능하다. 그냥 /clr C++/CLI를 위해 존재한다. 이미 Managed C++ Visual Studio 2008의 등장으로 막을 내렸다.

 

1.4. C++/CLI

Managed C++은 장점을 가려버릴 수 있는 단점들도 가지고 있었는데, 포인터를 나타내는 *과 같은 표현은 Managed C++에서의 참조 타입과 혼동을 일으킬 수 있었고, 이미 존재하는 키워드 들을 피하기 위해 __와 같은 표현을 사용하였는데, 개발자들이 매우 싫어하였다. C++/CLI는 이러한 점들을 고려하여 디자인 되었다그리고 Managed C++ MS 혼자 개발하였다면, C++/CLI CLI 라이브러리를 적극적으로 사용하여 여러 플랫폼에서도 공통적으로 사용할 수 있도록 되었다. C++/CLI C# CLI와 마찬가지로 유럽 전자계산기 공업회(ECMA)의 아래에서 표준화를 진행되고 있어 궁극적으로는 ISO의 아래에서도 표준화 되게 될 것이다.

 

 

2. 시작하기

 

2.1. 프로젝트 생성

2.1.1. CLR 프로젝트 생성

기본적으로 CLR을 사용하는 C++ 프로젝트로 C++/CLI를 지원함

2.1.2. 일반 C++ 언어를 사용하는 프로젝트 :

/clr 옵션 설정하고 빌드 (프로젝트 속성에서 공통 언어 런타임(Common Language Runtime)에서 선택) /clr 옵션을 사용할 때 설정해 주어야 하는 옵션 들에 대해 자세히 살펴본다.

2.1.2.1. /clr 옵션

전체 프로젝트에 적용하기 보다는 .cpp 파일에 따로 설정한다. /clr 옵션은 ‘/Yu:미리 컴파일된 헤더 사용’, ‘/Gy:함수 수준 링크 사용등의 몇몇 컴파일 옵션과 호환되지 않으므로 이전보다 빌드 속도가 떨어지기 때문이다.

 

위 그림과 같이 프로젝트 전체가 아니라 파일의 속성을 변경하도록 한다.

 

 

위 그림과 같이 Compile with Common Language Runtime Support 항목에서 /clr을 선택한다.

 

2.1.2.2. /Yu, /Gy 옵션

두 옵션은 /clr 옵션과 호환되지 않는다. 따라서 설정되어 있다면 옵션을 제거하도록 한다.

 

Enable Function-Level Linking : Yes(/Gy) -> No

Create/Use Precompiled Header : Use Precompiled Header (/Yu) -> Not Using Precompiled Headers

 

 

위와 같이 설정하여 준다.

 

2.1.2.3. /ZI, /EHsc, /RTC 옵션

3가지 옵션들은 경험상 디버그로 빌드시 /clr 옵션과 충돌나는 것들을 모아놓은 것이다. 각각 다음과 같이 바꾸어 주어야 한다.

 

Enable C++ Exceptions : /EHSc -> /EHa

Basic Runtime Checks : Both (/RTC1, equiv. to /RTCsu) -> default

 

각각의 위치는 다음과 같다.

 

 

 

 

 

2.1.3. MFC와 함께 사용하기

MFC와 함께 사용하기 위해서는 추가적으로 더 작업이 필요하다.

 

Use of MFC : Use MFC in a Static DLL -> Use MFC in a Shared DLL

Debug Information Format : ZI -> Zi

Runtime Library : Any -> Multi-threaded DLL (/MD) or Multi-threaded Debug DLL (/MDd)

 

그런데 중요한 사실은 MFC Static DLL로 사용할 수 없고, Shared DLL로만 사용 가능하다는 사실이다 .따라서 MFC와 함께 사용할 때는 따로 DLL로 만들어서 호출을 하는 것이 좋겠다.

각각의 위치는 다음과 같다.

 

 

 

 

 

 

2.2. 기본적으로 추가해야 할 파일

.Net 프로그래밍을 위해 추가되어야 할 파일

C#과 마찬가지이다.

 

#using <mscorlib.dll>

 

2.3. C++의 헤더 파일

Native C++처럼 그대로 사용 가능하다.

 

#include <stdio.h>

 

2.4. C#의 기본 클래스

C#처럼 사용하지 못하고, 상위 클래스와 하위 클래스 사이에 .대신 ::를 넣어서 사용한다.

 

using namespace System;
using namespace System::Runtime::InteropService;
// using namespace System.Runtime.InteropService; in C#
 
System::Console::WriteLine(“Hello”);
// System.Console.WriteLine(“Hello”); in C#

 

2.5. C++/CLI 처리 라이브러리

다음과 같이 필요한 dll들을 참조한다.

 

#using <mscorlib.dll>
#using <system.dll>
#using <system.drawing.dll>

 

2.6. 문법

기존의 C++ 코드를 그대로 사용 가능하고, C++/CLI에서 제공하는 기능을 이용하고 싶을 때에는 문서의 아래에서 설명하게 될 C++/CLI 문법을 사용한다.

명시적으로 나누어줄 수도 있는데, 다음과 같이 #pragma managed, #pragma unmanaged 를 사용해서 명시해 줄 수 있다.

 

#using <mscorlib.dll> // Console::WriteLine 사용하기 위해

 

#include <stdio.h> // printf() 사용하기 위해

using namespace System;

 

// 여기서부터는 unmanaged 코드

#pragma unmanaged

void print(char *msg)

{

  printf("%s\n", msg);

}

 

// 다시 managed 코드로

#pragma managed

int main()

{

  // managed 코드에서 콘솔에 출력

  Console::WriteLine("Hello world from managed method");

 

  // stdio 이용하여 콘솔에 출력

  print("hello world from unmanaged method");

return 0;

}

 

 

3. 객체(클래스)

 

3.1. 핸들과 포인터

포인터를 Native C++에서 흔히 쓰던 메모리의 주소값을 지니는 변수라고 하면, 핸들은 객체를 참조하는 변수라고 할 수 있으며 “safe pointer”라고 불리기도 한다. 가장 큰 차이는 핸들로 참조된 객체는 managed heap에 할당되고 Garbage Collector에 의해 관리되어 메모리 누수 등이 발생하지 않는다.

 

3.2. ^연산자

핸들을 나타낸다. “gcnew” 키워드를 이용해 할당한다.

 

System::Object ^x = gcnew System::Object();
 
N* pn = new N; // native heap 할당
N& rn = *pn; // ordinary reference native object 바인딩
R^ hr = gcnew R; // CLI heap 할당
R% rr = *hr; // tracking reference gc-lvalue 바인딩

 

3.3. CLI 타입

3.3.1. value type

stack에 할당 (할당과 제어의 효율성))

“value” 키워드 사용. = 오퍼레이터 사용하여 값을 넣는다.

 

public value struct MyPoint
{
  int x, y, z, time;
  MyPoint(int x, int y, int z, int t)
  {
    this->x = x;
    this->y = y;
    this->z = z;
    this->time = t;
}
}

 

3.3.2. reference type

managed heap에 할당 (객체 지향 프로그래밍에서의 클래스의 특징)

reference 타입의 객체는 기본적으로 헤더가 있는데, 이 헤더는 가상 메소드를 위한 클래스 계층도 등의 객체 지향 프로그래밍의 기본 서비스가 가능토록 하고, 모든 종류의 용도에 붙게될 메타데이터를 제공토록 한다.

 

public ref class MyClass
{
private:
public:
  MyClass()
  {
 
}
}

 

3.4. 메모리 관리

GC(Garbage Collector)에 의한 메모리 관리. 객체를 따로 delete 하지 않아도 된다.

어플리케이션이 더 이상 그 메모리를 참조하지 않아 GC가 결정내릴 때에 수거된다.

메모리 할당 성능이 더 좋고 참조의 격리성이 보장되는 이점도 있다.

 

3.5. 리소스 관리

(unmanaged 리소스 해제를 위한 지저분하기 짝이 없는, 그러나 반드시 알아야 하는내용이다. 좀 길지만 잘 숙지해야 한다.)

객체가 할당되었을 때, 사용 가능 메모리가 대부분 없어지면 GC가 수거하여 이를 관리한다. 이를 GC의 다이내믹 메모리 관리라고 한다. GC가 메모리를 해제할 때는 Finalize라는 메소드를 찾아보고 있으면 호출한다. 그러나 객체 내의 리소스, 즉 어떠한 종류의 락 또는 Native heap 메모리, 등의 기간 자원이 차지하고 있을 때, 다이내믹 메모리 관리는 효력을 발휘할 수 없다. 이때 리소스 자원은 필요없게 될 때 그 자원을 곧바로 해제하는 방법이 제일 유리하다. 현재 CLI에서 지원하는 해결책은 IDisposable 인터페이스의 Dispose 메소드를 구현하는 것이다. 문제는 이 경우, Dispose 메소드를 명시적으로 호출해야 한다는 점이다.

결론은 이렇다. C++/CLI에서는 Dispose 메소드를 소멸자로 매핑시킨다. 이로써 프로그래머는 좀 더 자연스러움을 느낄 수 있다. 여기에는 가비지 콜렉터가 그 객체에 해당하는 Finalize 메소드 호출을 막는 일도 포함된다. Finalize 메소드는 모든 자원을 해제하는 역할을 하는 실질적인 메소드라고 할 수 있다. 따라서 C++/CLI 설계시 소멸자 안에서 Finalize 메소드를 호출하는 것이 기본이다.

이제 소멸자가 자동으로 호출되게 하는 것이 필요한데, 이것을 지원하는 특별한 스택 기반 표기법이 있다. 그것은 객체의 lifetime이 그것의 선언의 유효 범위로 한정되게 한다. 내부적으로 컴파일러는 managed heap에 객체가 할당되도록 한 후, 유효 범위의 끝에 소멸자로 작성된 Dispose 메소드를 삽입하여 자동으로 호출되게 한다.

Finalize 메소드는 !가 클래스 이름에 붙은 형태로 선언되는데, 컴파일러가 역시 Finalize 메소드와 매핑시켜 준다.

이렇게 리소스를 사용하는 객체는 두 가지 메소드를 모두 선언해 놓아야 리소스 해제를 보장받을 수 있다. 항상 모든 케이스를 생각해야 하는 C++보다는 쉬워진 면이 있으나 소멸자와 Finalize를 반드시 구현해야 하는 점은 마찬가지인 것 같다. 아래의 코드를 보면 훨씬 이해가 쉬워질 것이다.

 

ref class Wrapper {
  Native *pn;
public:
  // pn Native heap 할당된 메모리
  Wrapper( int val ) { pn = new Native( val ); } 
 
  // Native heap 메모리에 대한 Dispose 함수
  ~Wrapper(){ this->!Wrapper(); }
 
  void mfunc();
protected:
 
  // 메모리 해제의 실패에 대비한 명시적인 Finalize 함수
  !Wrapper() { delete pn; }
};
 
void f1() 
{
  // 일반적인 참조 타입
  Wrapper^ w1 = gcnew Wrapper( 1024 );
 
  // lifetime 매핑된 참조 타입
  Wrapper w2( 2048 ); // ^(cap) 없다.
 
  w1->mfunc(); 
  w2.mfunc();
 
  // w2 아마도 여기서 Dispose 되어 메모리가 해제될 것이다.
  // finalize 호출되지는 않는다.
}
 
// 
// ... 후에, w1 여기서 finalize 호출되어 메모리가 해제될 것이다.

 

다음은 이와 관련된 추가적인 지식이다.

·       C++/CLI에서의 소멸자는 virtual 키워드가 없더라도 무조건 가상 함수이다.

·       finalizer의 가시성 범위는 accessor가 있건 없건 private이다.

·       destructor finalizer IDisposable::Dispose Finalize()를 완전 대체하지는 않는다. 컴파일러는 IL 코드 내에 Dispose() Finalize()를 따로 삽입하며, 각기 내부에서 destructor finalizer를 적절히 호출한다.

·       destructor가 호출되면 finalizer는 호출되지 않는다. 이는 IL 코드 내 Dispose() 구현에서 GC.SupressFinalizer()를 호출하기 때문이다.

·       위 코드를 기반으로 한 컴파일된 IL 코드는 C# 버전과 거의 흡사하다(Dispose(bool)을 통한 파생 클래스에서의 리소스 정리 등).

·       위와 같은 내용을 기반으로, 파생 클래스에서 역시 위 패턴과 동일하게 작성하면 된다(destructor 또는 Finalizer 등에서 base 클래스의 destructor/finalizer 명시적 호출 등 부가적 행동 불필요).

 

4. 프로그래밍 요소

 

4.1. Property

Property는 말 그대로 객체의 속성을 나타내는 지역변수라고 할 수 있다. 이는 C++만 다루었던 프로그래머에겐 생소하지만 다른 언어들이 많이 가지고 있는 property를 지원하기 위함인 듯싶다. CLI에서의 property get/set 멤버 함수를 통해 값을 얻고, 값을 설정하는 가상 데이터 멤버라고 볼 수 있다. 다음과 같은 syntax를 가지고 있으며 사용 방법도 볼 수 있다.

 

ref class R { 
 
public: 
property int Size { 
  int get() { return size_; } 
  void set( int val ) { size_ = val; } 
}   
 
private: 
int size_; 
};
 
void f1() 
{
  Size = 1; // Size.set 호출
int S = Size; // Size.get 호출
}

 

4.2. Boxing

value 타입을 reference 타입으로 바꾸는 것이 Boxing이다. 예를 들어 정수 값을 가지는 값 타입이 있을 때, 그것을 문자로 표현하고 싶다면 물론 문자열을 만들어서 format 변환을 한다던지 할 수 있지만, 정수 값을 가지는 reference 타입의 객체라면 간단히 ToString() 메소드를 써서 사용할 수 있다.

 

int C = 10; //value 타입
int^ refC = C; //boxing 통해 reference 타입으로 거듭나다.
String msg = “C  : “ + refC.ToString(); //이런 식으로 사용이 가능하다.
int D = *refC;
refC = nullptr; //핸들을 0으로 초기화 한다.

 

좀 더 자세히 알아보면 boxing이란 값과 객체간의 빈틈을 연결짓는 메카니즘이다. 비록 CLR은 모든 타입이, 간접적이건 직접적이건 간에, Object에 서 파생될 것을 요구하지만, 사실 값에 대해서는 그렇지가 않다. 스택에 존재할 정수와 같은 단순 값은 단지 컴파일러가 특정 연산을 가능케 하는 하나의 메모리 블록일 뿐이다. 만약 값을 객체처럼 다루고 싶다면, 그 값은 반드시 객체가 되어야 한다. 그 값은 Object에서 파생된 메소드를 제공할 수 있어야 하기 때문이다. boxing이란 개념은 바로 이를 가능케 하기 위해 CLR이 제공하는 메카니즘이다.

 

4.3. Delegate

Delegate C++의 함수 포인터와 같은 역할을 수행해서 콜백함수와 같은 구현을 할 때 쓸 수 있다. Delegate는 객체 내의 하나 또는 그 이상의 메소드와 바인딩 될 수 있다. Delegate는 두 개의 파라미터를 가지는데, 하나는 객체이고, 나머지 하나는 그 객체 내의 함수이다.

 

delegate void Function();
 
ref struct ReferenceType
{
    void InstanceMethod() {}
    static void StaticMethod() {}
};
 
// 객체와 객체 내의 함수를 바인딩 시켜 delegate 생성한다.
Function^ f = gcnew Function(gcnew ReferenceType,
                             &ReferenceType::InstanceMethod);
 
// static 멤버 gatneh delegate 추가한다.
f += gcnew Function(ReferenceType::StaticMethod);
 
//  함수를 한꺼번에 호출한다.
f();
 
//다음과 같이 IEnumerator 사용하여 하나씩 호출  수도 있다.
array<System::Delegate^, 1>^ d = f->GetInvocationList();
 
IEnumerator^ e = d->GetEnumerator();
int idx = 1;
while (e->MoveNext())
{
   Function ^delegateI = 
            dynamic_cast<Function ^>(e->Current);
   delegateI->Invoke();
   idx++;
}

 

4.4. Enum

다음과 같이 enum을 사용 가능하다.

 

public enum class SomeColors { Red, Yellow, Blue};

 

또한 타입을 정해주는 것도 가능하다.

 

public enum class SomeColors: char { Red, Yellow, Blue};

 

4.5. Arrays

다음과 같은 syntax들이 가능하다.

 

cli::array<int> ^a = gcnew cli::array<int> {1, 2, 3};
array<int> ^a = gcnew array<int>(100) {1, 2, 3};
//for each 구문 사용하기
for each (int v in a)
{
  Console::WriteLine("value={0}", v);
}

 

또한 다음과 같은 복잡하거나 특별한 Array도 사용 가능하다.

 

//multi dimension Array
array<int, 3> ^threed = gcnew array<int, 3>(4,5,2);
Console::WriteLine(threed[0,0,0]);
 
//클래스의 Array
<String ^> ^strs = gcnew array<String ^> {"Hello", "World"}

 

 

4.6. C#으로부터 인자값 받기

int, short 같은 경우는 그냥 받으면 된다.

 

void func(int a, short b){ }

 

string 형식 받기

 

void func(String^ _name_){ }

 

구조체 받기

 

void func(testStruct^% _name_){ }
_name_->member = 10;

 

C#에서는 func(ref teststruct); 이렇게 호출해야 한다

 

구조체 배열 받기

 

void func(array<testStruct^>^% _name_){ }

 

이때 C#에서는 func(ref teststructArray); 이렇게 호출해야 한다.

 

4.7. C++ 포인터로 옮기기

4.7.1. 배열

 

array<int>^ arr =  gcnew array<int>(SIZE);

pin_ptr<int> p = &arr[0];   // arr 첫번째 요소를 pin pointer 대입
int* np = p;   // arr
첫번째 요소를 포인터에 대입

native_function(np);   // native 함수에 포인터를 넘김

 

4.7.2. 문자열

 

String^ str = gcnew String("abcde"); //Managed String 생성
 
TCHAR* pstr =  static_cast<TCHAR*>(System::Runtime::InteropServices::Marshal::StringToHGlobalUni(str).ToPointer()); //Inerop 서비스를 이용한 문자열 변환

 

4.7.3. 구조체

 

//Managed class 생성
ref class TestClass
{
public:
     String^ A;
     UInt32 B;
     cli::array<byte>^ C;
 
public:
     TestClass(String^ _A, UInt32 _B, cli::array<byte>^ _C)
     {
             A = _A;
             B = _B;
             C = _C;
     }
};
//Umanaged 코드로 변경
#pragma unmanaged 
 
//C++ 구조체
struct TestStruct
{
     TCHAR *A;
     UINT B;
     BYTE *C;
};
 
//다시 Managed 코드로 변경
#pragma managed
 
TestStruct* copystruct()
{
     cli::array<byte>^ _bytes = gcnew cli::array<byte>(128);
 
     TestClass^ TT = gcnew TestClass("test", 1, _bytes);
 
     struct TestStruct* gg = (struct TestStruct*)malloc(sizeof(struct TestStruct));
 
     //각각 형식에 맞게 하나하나 대입
     gg->A = static_cast<TCHAR*>(System::Runtime::InteropServices::Marshal::StringToHGlobalUni(TT->A).ToPointer());
     gg->B = TT->B;
     pin_ptr<byte> pC= &TT->C[0];
     gg->C = pC;
     return gg;
}

 

4.7.4. System::Runtime::InteropServices::Marchal

마샬링 : 마샬링은 하나 이상의 프로그램 또는 연속되어 있지 않은 저장 공간으로부터 데이터를 모은 다음, 데이터들을 메시지 버퍼에 집어넣고, 특정 수신기나 프로그래밍 인터페이스에 맞도록 그 데이터를 조직화하거나, 미리 정해진 다른 형식으로 변환하는 과정을 말한다. 마샬링은 대체로, 어떤 한 언어로 작성된 프로그램의 출력 매개변수들을, 다른 언어로 작성된 프로그램의 입력으로 전달해야 하는 경우에 필요하다.

 

C++, C++/CLI간 데이터 변환에 관해서 Mashal 클래스를 주로 이용하도록 한다.

 

 

1 C++, C# 비교 요약

설명

C++/CLI

C#

참조 타입 할당

ReferenceType^ h
  = gcnew ReferenceType;

ReferenceType h
   = new ReferenceType();

값 타입 할당

ValueType v(3, 4);

ValueType v
   = new ValueType(3, 4);

참조 타입의 스택 의미론

ReferenceType h;

N/A

Dispose 메서드 호출

ReferenceType^ h
  = gcnew ReferenceType;

delete h;

ReferenceType h
   = new ReferenceType();

((IDisposable)h).Dispose();

Dispose 메서드 구현

~TypeName {}

void IDisposable.Dispose()

Finalize 메서드 구현

!TypeName {}

~TypeName {}

박싱

int^ h = 123;

object h = 123;

언박싱

int^ h = 123;
int c = *h;

object h = 123;
int i = (int)h;

참조 타입 정의

ref class ReferenceType {};
ref struct ReferenceType {};

class ReferenceType {}

값 타입 정의

value class ValueType {};
value struct ValueType {};

struct ValueType {}

속성 사용하기

h.Prop = 123;
int v = h.Prop;

h.Prop = 123;
int v = h.Prop;

속성 정의하기

property String^ Name
{
    String^ get()
    {
        return m_value;
    }
    void set(String^ value)
    {
        m_value = value;
    }
}

string Name
{
    get
    {
        return m_value;
    }
    void set
    {
        m_value = value;
    }
}

 

 

5. WCF C++/CLI

 

5.1. C++에서 WCF 사용하기

C++ WCF가 연동되어야 하는 이유는 굳이 이야기 하지 않아도 될 것 같다. 기존의 시스템과 연동되게 하기 위해서이다. 몇 가지 방법이 있는데 방법들에 대한 장단점만 나열해 보겠다.

 

방법

장점

단점

SProxy.exe

클라이언트만 구현 가능

Windows 플랫폼만 가능

Basic HTTP만 지원

WWSAPI

API 레벨 지원

클라이언트/서버 모두 구현 가능

Windows 플랫폼만 가능

Basic HTTP/wsHTTP 지원

gSOAP

클라이언트/서버 모두 구현 가능

플랫폼 독립성

Basic HTTP만 지원

COM Moniker

순수 Unmanaged 코드 사용
(/clr 옵션 적용 필요 없음)

Windows 플랫폼만 가능

.NET 3.0 이상 필요

COM Interop 사용

C++/CLI

WCF의 모든 기능 지원

클라이언트/서버 모두 구현 가능

Windows 플랫폼만 가능

.NET 3.0 이상 필요

/clr 옵션을 적용해야 함

 

앞으로 등장할 WWSAPI는 윈도우 플랫폼에서의 최상의 선택이 될 것 같지만, 일단 현재로써는 C++/CLI가 가장 좋은 선택일 것 같다.

 

5.2. 실제로 연동하기

WCF를 이용하려면 먼저 .NET Framework System.ServiceModel.dll을 이용해야 한다. C++/CLI코드를 이용하여 .NET의 컴포넌트들을 이용해야 하는데, 사용자가 직접 코딩을 할 필요는 없다. 서비스를 설명하는 WSDL 문서를 얻을 수만 있다면, WSDL로부터 프록시 코드를 얻을 수 있는데, 이 프록시 코드를 프로젝트에 포함시키고 클래스를 사용하기만 하면 된다. 단계별로 살펴보도록 하겠다.

 

5.2.1. 서비스 만들기

다음은 DB에서 고객 리스트를 검색하여 반환해주는 서비스를 제공하는 WCF 서비스 코드로 C#으로 작성되었다. 서비스 코드에 대한 설명은 생략하도록 하겠다.

 

//계약
[ServiceContract]
public interface ICustomer
{
     [OperationContract]
     void getUserList(ref List<USER_INFO> userList);
}
 
public class CustomerService : ICustomer
{
     //DB 연결하여 검색하는 라이브러리
     [DllImport("DBCon.dll")]
     private static extern uint getUserCount();
     [DllImport("DBCon.dll")]
     private static extern void getData(uint idx, ref USER_INFO aUser);
 
     public void getUserList(ref List<USER_INFO> userList)
     {
              List<USER_INFO> m_userList = new List<USER_INFO>();
 
              uint DataSize = getUserCount();
 
              for (uint i = 0; i < DataSize; i++)
              {
                      USER_INFO aUser = new USER_INFO();
                      getData(i, ref aUser);
                      m_userList.Add(aUser);
              }
              userList = m_userList;
     }
}

 

5.2.2. 서비스 호스팅

서비스는 그야말로 실제로 요청 받은 작업을 수행하는 모듈로 서비스는 적당한 네트워킹 서비스에 의해 호스팅 되어야 한다. 네트워킹 서비스는 사용자가 어플리케이션으로 작성할 수도 있고, IIS의 도움을 받을 수도 있고, 윈도우 서비스로 받을 수도 있다. 중요한 것은 서비스를 제공하는 방법을 binding endpoint로 정의한 내용인데, 호스팅을 하는 모듈의 코드에 직접 하드코딩 할 수도 있고, Configuraton 파일을 사용할 수도 있다. 다음은 윈도우 서비스로 호스팅을 하고 있는 서비스의 내용을 설명하고 있는 Configuration 파일이다.

 

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <services>
      <service name="Company.CustomerService"
           behaviorConfiguration="httpGetbehavior">
        <host>
          <baseAddresses>
            <add baseAddress="http://192.168.3.65/CustomerService"/>
          </baseAddresses>
        </host>
        <endpoint
          contract="Company.ICustomer"
          address=""
          binding="basicHttpBinding"
        />
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="httpGetbehavior">
          <serviceMetadata httpGetEnabled="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
</configuration>

 

여러가지 사항은 제외하고 serviceBehaviors httpGetbehavior의 이름을 가지고 있는 속성을 서비스에 behaviorConfiguration으로 등록해 주어야 WSDL 파일을 http 프로토콜의 Get 방식으로 얻을 수 있다. 이렇게 얻은 WSDL 코드는 다음과 같다.

 

<?xml version="1.0" encoding="utf-8" ?> 
<wsdl:definitions name="CustomerService" targetNamespace="http://tempuri.org/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:tns="http://tempuri.org/" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsap="http://schemas.xmlsoap.org/ws/2004/08/addressing/policy" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msc="http://schemas.microsoft.com/ws/2005/12/wsdl/contract" xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:wsa10="http://www.w3.org/2005/08/addressing" xmlns:wsx="http://schemas.xmlsoap.org/ws/2004/09/mex">
  <wsdl:types>
    <xsd:schema targetNamespace="http://tempuri.org/Imports">
      <xsd:import schemaLocation="http://192.168.3.65/CustomerService?xsd=xsd0" namespace="http://tempuri.org/" /> 
      <xsd:import schemaLocation="http://192.168.3.65/CustomerService?xsd=xsd1" namespace="http://schemas.microsoft.com/2003/10/Serialization/" /> 
      <xsd:import schemaLocation="http://192.168.3.65/CustomerService?xsd=xsd2" namespace="http://schemas.datacontract.org/2004/07/Company" /> 
  </xsd:schema>
  </wsdl:types>
  <wsdl:message name="ICustomer_getUserList_InputMessage">
    <wsdl:part name="parameters" element="tns:getUserList" /> 
  </wsdl:message>
  <wsdl:message name="ICustomer_getUserList_OutputMessage">
    <wsdl:part name="parameters" element="tns:getUserListResponse" /> 
  </wsdl:message>
  <wsdl:portType name="ICustomer">
    <wsdl:operation name="getUserList">
      <wsdl:input wsaw:Action="http://tempuri.org/ICustomer/getUserList" message="tns:ICustomer_getUSerList_InputMessage" /> 
      <wsdl:output wsaw:Action="http://tempuri.org/ICustomer/getUserListResponse" message="tns:ICustomer_getUserList_OutputMessage" /> 
    </wsdl:operation>
  </wsdl:portType>
  <wsdl:binding name="BasicHttpBinding_ICustomer" type="tns:ICustomer">
    <soap:binding transport="http://schemas.xmlsoap.org/soap/http" /> 
    <wsdl:operation name="getUserList">
      <soap:operation soapAction="http://tempuri.org/ICustomer/getUserList" style="document" /> 
      <wsdl:input>
        <soap:body use="literal" /> 
      </wsdl:input>
      <wsdl:output>
        <soap:body use="literal" /> 
      </wsdl:output>
    </wsdl:operation>
  </wsdl:binding>
  <wsdl:service name="CustomerService">
    <wsdl:port name="BasicHttpBinding_ICustomer" binding="tns:BasicHttpBinding_ICustomer">
      <soap:address location="http://192.168.3.65/CustomerService" /> 
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>

 

5.2.3. 프록시 코드 생성하기

프록시 코드는 svcutil.exe 라는 .NET 프레임워크에서 제공하는 유틸을 사용한다. svcutil.exe를 사용하면 WSDL 파일을 읽어서 선택한 언어로 된 프록시 코드를 생성해 준다. 다음과 같이 쓴다.

 

cmd> svcutil.exe http://192.168.3.65/CustomerService /language:C++ /out:proxy

 

이렇게 하면 해당 웹서비스를 이용할 수 있는 클래스가 정의된 프록시 코드가 proxy.h라는 이름으로 생성되고, 함께 사용 가능한 output.config 파일이 생성된다. Proxy.h 코드를 보면 알겠지만 C#에서의 List<USER_INFO>와 같은 경우 Array<USER_INFO>^ 와 같이 나름대로 해석해서 정의되어 있는 것을 볼 수 있다. 프록시 코드는 너무 길어서 첨부 생략한다.

 

5.2.4. 프록시 코드 사용하기

C++/CLI로 생성된 프로젝트(혹은 C++로 생성된 프로젝트에 /clr 옵션을 준 경우) proxy.h를 추가해서 빌드해 본다. 빌드 오류가 나지 않는다면 다음과 같이 코딩 할 수 있다.

 

int _tmain(int argc, _TCHAR* argv[])
{
     //proxy.h 내의 binding 이름을 가지고 클라이언트를 생성한다.
     CustomerClient^ Client = gcnew CustomerClient(_T("BasicHttpBinding_ICustomer"));
 
     //리스트의 개수는 128개라고 가정
     array<USER_INFO>^ userList = gcnew array<userList>(128);
 
     //메소드를 호출한다.
     Client->getUserList(userList);
}

 

 

6. References

 

A Design Rationale for C++/CLI

http://www.gotw.ca/publications/C++CLIRationale.pdf

C++: The Most Powerful Language for .NET Framework Programming

http://msdn.microsoft.com/en-us/library/ms379617.aspx

Quick C++/CLI - Learn C++/CLI in less than 10 minutes

http://www.codeproject.com/KB/mcpp/cpptomancpp.aspx

FunctionX C++/CLI Tutorial

http://www.functionx.com/cppcli/index.htm

Pure C++ Hello, C++/CLI

http://msdn.microsoft.com/en-us/magazine/cc163681.aspx

C++/CLI Quick reference

http://jundols.springnote.com/pages/1721142

How to: Compile MFC and ATL Code with /clr

http://msdn.microsoft.com/en-us/library/ms235211(VS.80).aspx




반응형
Posted by blueasa
, |

Native C++ LIB 프로젝트를 만들고 ( LIB 생성 )

C++ / CLI 프로젝트에서 LIB 프로젝트를 참조하여 Wraping 한다음 ( DLL 생성 )

C# 프로젝트에서 툴 UI를 작성 하게 되는데

그냥하면 LIB 프로젝트로 브래이크 포인트가 들어 오지 않는다. 디버깅을 할 수 없다.

 

Native C++ 프로젝트 속성-> 디버깅->디버거 형식 을 혼합으로 설정하고 ( 여기까진 했었다 )

C# 프로젝트 속성-> 디버그->디버거 사용 목록에서 '비관리 코드 디버깅 사용'에 체크 ( 이걸 안했었다 )

 

C#은 Maneged(관리) 코드 이고 Native C++은 None Managed(비관리 코드)다.

 

영어가 아니라 한글이라 헷갈리는 구나~ 보고도 바로 못 알아 봤다 ㄱㅡ

 

손발아~ 미안해~ 고생 시켜서.... ;ㅅ;


출처 : http://blog.daum.net/_blog/BlogTypeView.do?blogid=0PYd8&articleno=79#ajax_history_home

반응형
Posted by blueasa
, |

JIT

Programming/C# / 2010. 5. 26. 21:16

JIT는 일반적으로 영어에서 'Just-in-time'의 약어로 '즉시'라는 뜻이다.
  • JIT 생산 시스템은 고객의 주문이 들어오면 바로 생산되는 시스템이다.
  • JIT 컴파일은 Java, C#등에서 제공하는 실시간 컴파일 방식이다.


 

출처 : http://ko.wikipedia.org/wiki/Jit

반응형
Posted by blueasa
, |