'솔트' 안젤리나 졸리 먹튀 방한인 이유 ( http://www.jstarclub.com/956 )

라는 글을 쭉 읽었다.

한국 영화 팬이라면, 대부분 모든 형태의 영화를 영화관가서 몇번이고 보고, 혹은 놓치더라도, DVD나 Bluelay 디스크등을 구입하여 영화의 소장 가치를 나름대로 갖추고 있을 것이다.
하지만 이런 팬들의 정성에도 불구하고, 해외 영화 관계자 혹은 배우들은 대개 무성의한 방한 준비를 하고 들어오거나 실망스러운 발표회가 다반사이다. 가까운 일본만 보더라도, 영화 관련 배우나 스탭들의 방문 일정이나 계획, 진행의 규모를 보면 어지간한 미국내 발표회 못지 않게 진행되곤 한다.

우리나라가 최소한 일본에 비해 유럽, 미국 등에 제대로 이름이 알려지기 시작한 것은 그리 오래되진 않았을 것이다. 아시아에 대해 관심 많았던 사람을 제외하고는 한국이라는 나라는 동남아의 어느 변방정도로 인식하는 경우가 많았다. (우리가 아프리카의 나라 이름을 들었을 때의 느낌 정도 일까?) 그건 사실 별 의미는 없다. 2000년이 넘어가면서 대기업을 중심으로한 한국 브랜드 가치 상승과, 월드컵, 축구, 골프 등등의 스포츠 활동 등을 통해 나름 브랜드를 알렸다. 일단, 국가 브랜드 가치는 일단 뒤로 하자. 일본 만큼은 아니더라도, 이젠 어느정도 알려졌으니, 사실 방한을 제대로 안하는 것과는 별개라고 본다. 그러므로 이 부분에 대한 언급은 여기서 멈추어 보자.

그렇다면? 왜 그런 차별을 할까?

내가 바라보는 관점에서, 그것도 비지니스 관점에서 바라 볼때, 한국 시장에 비해 일본 시장이 훨씬 좋다는 생각이다.
일본이라는 국가와 한국이라는 국가의 비지니스 관점에서 볼때의 차이가 발생하는 이유는 무엇일까?

먼저 영화의 노출도.
단순 비교로 인구만 두고 보면 거의 2배 차이. 1억 2천정도 되는 일본과 5천만의 한국. 고령화 사회로 인한 상대적 생산이나 소비 인력이 감소하는 추세라고는 하지만, 대략적인 영화 감상 인원을 비율로 보든 절대적 수치로 보든 결국 몇천만 레벨로 차이가 날 수 밖에 없다. 우리나라가 5천만 중 2천만이 본다고 한다면, 일본은 1억2천만 중, 5천만이 본다는 것이다. 숫자적인 차이로 보아도 확실히 앞서가지 않는가? 즉 재미없는 영화라 할지라도, 전체 개봉작 중에 5% 차지한다고 볼때 어느쪽의 수익이 더 높을까? 당연히 일본쪽의 손을 들어 줄 수 밖에는 없다. 
당연한 것 아닐까?

다음의 중요한 요소인! 컨텐츠 소비 성향.
앞서 영화의 노출도를 이야기 하면서, 소비인구의 절대적인 가치로 볼 때, 일본이 앞선다고 했다. 그렇다면, 규모의 경제의 극을 보여주는 중국의 경우는?  수치적 비교를 할 때, 중국은 한국/일본 쌍방을 모두 합친 수의 그 몇배는 될만한 숫자가 될 것이다. 아직은 소비인구가 증가 추세이기에 당장의 규모가 절대적으로 큰 수치는 아니지만, 회소한 엄청난 숫자가 된다. 하지만, 컨텐츠 소비 성향을 바라볼때는 역시 일본이 앞서갈 수 밖에 없다.
일본은 컨텐츠를 진짜 소비한다. 컨텐츠에 매겨진 가격을 명확히 하여, 정확히 지불하여 소비한다. 물론 인기 없으면 당연히 가격은 내려가겠지만, 그 역시 사용에 따른 구매 방법을 통해 나름의 가치를 전달한다. (물론 일본이라고 불법 컨텐츠 없을리 있겠는가? 하지만, 우리나라나 중국에 비교하면 절대적 수치는 둘째 치고라도, 비율마저도 일본이 훨씬 낮다.)
그에 반해 우리나라와 중국의 경우에는 제 값을 내고 컨텐츠를 소비하는 인구가 얼마나 될까?
물론 2~30대의 왕성한 생산 인구들의 문화 소비량은 의외 대단하다. 하지만, 그들도 대부분 컨텐츠를 제 돈내고 소비하기보다는 그 속에서 이상한 합리적 소비문화를 강조한다. 즉 재미없을것 같으면 다운로드 해서 보거나 불법 복제된 DVD 등을 통해 본다는 것이다. 컨텐츠의 가격을 매기기 보다, 컨텐츠를 몰래 훔쳐온 자들에게 작은 댓가를 주고 컨텐츠를 가져다 쓰고 버린다. 즉 영화를 보는 인구 10% 란 말은 10%의 극장 및 정품 구매자와 25%의 불법 사용자라는 의미. 중국은 이보다 더 심했으면 심했지 덜하지도 않다.
주변을 보면 극장에서 영화를 보기 보다 되려 불법 다운로드 사이트를 통해 다운을 받으려 할 뿐이다. 또 받은 것을 주위에 나누어 줌으로써 컨텐츠의 제 값은 커녕, 더 이상의 상업적 가치를 상실하게 만들어 버린다.
이러니, 한 영화를 한국과 일본이 동시 상영하여 한국에서는 전체인구 20%가 관람하고, 일본에서는 전체 인구 5%가 본다고 할때, 어느쪽에 손을 들어주고 싶을까? 절대적인 숫자를 떠나, 컨텐츠의 가치로운은 어느쪽이 더 잘 쳐주는 걸까? 즉 한국은 20%라고 했지만, 불법까지 포함하면 50%가 넘을듯. 그에 반해 일본은 10%이니 대략 11~12% 가 보게 된다. 즉 불법의 정도의 차이가 틀리니, 한국의 경우 30%는 그냥 다운로드와 불법을 통해서 보고, 일본은 1~2% 정도?가치 환원을 볼때, 한국에 홍보해서 40~50%로 올릴 바엔, 일본에 더욱 홍보하여 20%로 늘리면 못해도 18%는 되돌려 받지 않을까?

올바른 문화 활용 경험이 제대로 없는 우리나라의 경우 위와 같이 외국 배우들이나 스탭들의 무성의한 방한에 대해서 나무랄 필요는 없어 보인다. 난 되려 부끄럽기만 할 뿐이다. 그나마 찾아와주는 구나.. 그래도 몇억 정도는 돌려 주니..

영화문제로 시작은 했지만, 이 모든 것은 컨텐츠 산업과 결부된다. 책도 되고, 만화책도 되고, 애니메이션도 된다. 심지어 게임, 소프트웨어 모든 것들. 우리는 무형의 가치를 가치로 제대로 인지 못하는 경우가 은연중 많다.
그 가치를 가치로써 대해주고, 스스로 지원해 줄 수 있다면, 조금은 더 당당히 외국 배우들에게 한소리를 하고 살 것이다.

아쉬울 따름이다.

아쉽다.

728x90

국내에는 2000년대를 기점으로 폭발적으로 늘어난 인터넷 인구 덕에, 수많은 서비스들이 만들어졌다. 대박이라고 불리는 싸이월드나, 추억의 만남의 상징인 아이러브 스쿨, 오덕들의 성지인 DC Inside. 국내 SNS의 대표주자인 미투데이 등등. 더욱이 Naver와 Daum이라는 걸출한 포탈은 인터넷 이용에 있어 훌륭한 역할을 수행했다고 본다.

그런데, 왜 Twitter와 FaceBook 일까?

그냥 외국거라서 좋은걸까?

복합적인 원인들이 있을 수 있다. 일단 Twitter를 보더라도, 다양한 앱들로 손쉽게 스마트 폰이나, 윈도우 클라이언트를 통해 올리고 내릴 수 있다. 직접 IE를 띄우지 않아도 말이다. 그에 반해 미투데이나, 기타 포털들은 독자적인 어플이 자체적으로 만든것 정도 밖에는 없고, 그 마저도 왠지 식상하다. 뭐 일단 그 부분이 개인적인 취향이 강하므로, 요인중에 하나라고 본다.

나는 이렇게 생각한다.
아마도 알게 모르게 조사들어가고 탄압되는 모습에 질린 사람들이 택한 길이지 않을까라는 ..
사실 네이버, 다음, 미투데이, 싸이월드... 어디든, 정치적인 부분이나, 개인적인 의견(아마도 타인을 비판하는) 등등을 잘못 올리면 즉시 조사 들어간다. 애석하게도 위에 열거된 서버들은 모두 국내에 있고, 국내 사업자들이기 때문에, 검찰에서 영장 들고 가면 얄짤 없이 털린다. 굳이 영장이 아니더라도, 좀 힘(권력?, 인맥?)좀 쓰면 그 안의 내용은 그리 어렵지 않게 가져오고, 그 결과는 손쉽게 예측할 수 있다.
(예를 들자면 이런 뉴스? http://news.khan.co.kr/kh_news/khan_art_view.html?artid=201007230240245&code=940202 )

그렇다면 정치쪽이든, 독설가든 간에 오피니언 리더들이 택할만한 방법은 무엇일까?

간단하지 않을까? 트위터나, 페이스북이면 딱이지 않을까 싶다.
설사 검찰에서 그 내용을 읽고 그사람이 기록한 내용을 전부 얻고 싶어도,
페이스북이든, 트위터든 그 서버는 미국이나, 기타 국가에 있다.
외교 능력 - 에 처박혀도 모자른 능력인데, 그런 나라의 내용을 가져올 수 있을까?
당연 못가져온다. 방법은? 글쎄다.

결국 화면에 보이는 내용을 근간으로 어떻게든 처리해야 하는데, 그게 그 사람의 전반적인
증거가 될 수 없고(단편적이니까) 그저 한번 흘러가버릴 내용정도에 불과한 것이다.

흐르는 물을 손으로 막으면 사이로 흐르거나 옆으로 흐르게 되어 있고,
새는 연기를 손으로 막으면 사이로 새거나, 막히지 않은 다른 곳으로 새게 되어 있다.

광장 틀어막고, 인터넷 뉴스 패널 틀어막고, 댓글 틀어막아도,
결국 하나씩 하나씩 열릴 수 밖에 없다고 본다.

좀 의견을 자유롭게 게재해도 나은 세상이 어서 왔으면 좋겠다.

728x90

출처 : 이선우 과장님.

.NET 응용 프로그램에 app.config 라는 설정을 넣는 부분이 있다.(ASP.NET의 web.config과 유사). 응용 프로그램이 최초 실행될때 기본적으로 설정할 때 사용되는 값들인데, 이 부분을 직접 Text로 열어 편집하곤 했다.

appsettings_view
이 부분을 직접 편집하는 것도 방법이겠지만, Resource 편집하듯 설정하는 방법이 있다.
솔루션 목록에서 윈도우 응용 프로그램 프로젝트 위에서 속성을 클릭하면 응용 프로그램 속성창이 뜨는데,
그 중 Settings 탭에 위치한 항목이 바로 그것이다.

property_settings

그런데 저 Type을 보면 알겠지만, .NET에서 제공되는 형만 존재한다.
만일 enum 형태로 사용자가 만든 별도의 형이 있다면? 그것을 사용하는 방법이 있다면?

바로 그것이다.예를 들어보자.만일 다음과 같은 enum이 존재한다면..

enums_example

TestType 이라는 형태로 저 Settings에 표현하려면??

물론 위와 같은 TestType을 먼저 선언한다.
그리고 난 뒤, 아까 Settings 에 들어가도록 한다. 그리고 Type 부분의 콤보 박스를 클릭한다.

settings_types

클릭하게 되면 여기서 사용가능한 Type들이 나열된다. 그러나 우리가 원하는 Type은 없다.
이제 맨 아래쪽에 있는 Browse... 를 선택하도록 한다.
이제 Select a Type 이라는 항목을 볼 수 있다. 여기서 아까 선언했던 enum을 찾도록 한다.
selectappsettingtype
찾았으면 선택한 뒤 OK를 클릭한다.

그리고 원하는 값을 선택한 뒤, 저장한다.
selectsettingsvalues

 

자! 그런데 여기서 문제 그 하나.

먼저 위에서 처럼 enum을 선언했는데, browse를 해도 그 enum을 찾을 수 없는 경우.
이 부분 때문에 이선우 과장님이 이리저리 헤매다가 그 차이점을 밝혔다.
즉 저 enum 선언은 반드시 app.config에 걸리는 응용 프로그램 외에 설정해야 된다는 것이다.
다시 말해 만일 app.config가 TestApp 라는 응용 프로그램에 존재한다면, Class Library 프로젝트를 별도로 만들어
그 안에서 선언해야 된다는 것이다.

correcteddefine

지금 필자가 구현한 코드 부분을 예로 든다면, 실제 실행되는 응용 프로그램이 TwainGui. 즉 app.config는 저 안에 있다. 하지만, enum은 별도의 Class Library 프로젝트인 TwainLib 라는 위치에 있다. 그것을 선언한 것.

저렇게 만들어 컴파일이 정상적으로 된다면, TwainGui에서 참조를 걸어 놓으면 위의 예제처럼 Browse 할 때 저 enum을 볼 수 있다.

 

이걸로 땡일까? 부부~ 이제 그 문제 2.

사용자 정의된 이 특수한 Type에 대한 안의 값을 선택하는 콤보 부분을 주목하자.
correcteddefine2 
아주 자연스럽게 나타나는데, 실제로 그럴까?

10이면 10, 100이면 100 대부분 아래와 같이 Type 목록으로 나오지 않고, 달랑 한개의 값만 표시된다.

correcteddefine3

실제로 그 안의 값을 열어보면, 마치 빈 TextBox 마냥 직접 사람이 입력하게 만든다.
말이 쉽지 실제로 그 값들이 기묘한 문자열이라면 찾기 무리.
처리 방법은 매우 간단하다. 일단 위의 값을 그대로 저장한 상태로 컴파일을 완료한다.
그리고 Visual Studio을 껏다가 다시켠다. 그리고 프로젝트 Reload.

즉 프로젝트를 Reload 함으로써 Reset이 되어야 올바른 값 목록이 나온다는 것이다.

일단 여기까지!

728x90

.NET Application에서 외부 이벤트를 끌어들이는 방법을 설명하고자 한다.

사실 Windows Event에서는 Managed 환경에서 제공되는 한정된 이벤트 처리를 의외로 간단하다. 하지만, Win32 기반의 외부 응용 프로그램에서 제공되는 커스텀 이벤트 처리에 대해서는 어찌되어야 할지 명확히 알지 못하는 경우가 많다. 이 부분을 언급하려고 한다.

먼저 .NET의 응용 프로그램은 Application 이라는 개체를 자체적으로 가지고 있게 된다. Static 기반으로 되어 있어, From을 띄우거나, 메시지를 가져오고 메시지를 보내는 등 어떻게 보면 OS 처럼 최하위단을 제어하고 움직이는 중요한 부분이다. 바로 이 부분을 활용하여 외부의 이벤트를 끌어오는 것이다.

이 작업을 수행하려면, 외부 이벤트를 수신하는 Windows 개체에 IMessageFilter 라는 인터페이스가 필요하다.
이 인터페이스는 System.Windows.Forms 라는 네임스페이스 상에 존재한다.

제일 먼저 이 인터페이스를 상속 받게 한다.
imessagefilter_init

그 다음은 해당 Windows 소스 내에 IMessageFilter 에 대한 구현을 구성한다.

imessagefilter_createmethod

즉 저 PerFilterMessage 라는 부분에서 실제적인 처리를 시도하게 된다.

Message 객체는 다음과 같이 구성되어 있다.

  • HWnd : 윈도우 Handle 주소값.
  • Msg : Windows 기반 메시지 ID
  • WParam : Windows 메시지와 같이 나온 값 - Word (unsigned int) 단위의 값
  • LParam : Windows 메시지와 같이 나온 값 - Long (unsinged Long) 단위의 값

Windows API 프로그래밍을 해본적이 있다면 바로 직감이 오겠지만...
바로 저 PerFilterMessage가 PumpMessage를 의미하는 것이고,
Message 객체는 Windows 메시지로 처리할 때 쓰는 모든 값이다.

이제 필요한 메시지를 직접적으로 처리해 주면 되는 것이다.

728x90

.NET을 이용해서 C++/C 로 만든 Windows DLL들을 호출하는 방법이 있다.

그 방법은 DllImport 라고 하는 System.Runtime.InteropServices 네임스페이스의 프로퍼티 클래스를 사용하면된다.

간단한 사용예는 아래와 같다.

[DllImport("twainDSM.dll")]
private static extern TwRC DSMSetParent( [In, Out] TwIdentity origin, IntPtr zeroptr, TwDG dg, TwDAT dat, TwMSG msg, ref IntPtr refptr );

DllImport 에 원하는 DLL을 선언하고, static extern 메소드에 걸어주면 된다.
만일 입출력이 겸해지는 파라미터 인 경우 [In,Out] 을 사용하면 되고, 입력이면 그대로 [in]을 쓰면 된다.

그런데, 하나의 DLL 함수에 여러가지 형태로 정의하고 싶은 경우가 있다.
입력값이 미묘하게 틀린경우 그에 맞추기만 하면 되는 경우다.

예를 들면 TWAIN에서 제공하는 DLL 함수 중 DSM_Entry 라는 함수가 있다.

TW_UINT16 FAR PASCAL DSM_Entry( pTW_IDENTITY pOrigin,
                                  pTW_IDENTITY pDest,
                                  uint    DG,
                                  uint    DAT,
                                  uint    MSG,
                                 (void**)    pData);

그 형태는 위와 같다. 즉 첫번째 두번째 파라미터는 규격화 된 것이지만, 맨 마지막 같은 경우에는 특정한 형태가 없는 값이다. 또, 두번째 파라미터가 null 인 경우도 있을 것이다. 호출하는 방법에 따라 그 방법이 다양한데, 이것을 C#에서는 아래와 같이 표현 할 수 있다.

[DllImport("twainDSM.dll", EntryPoint="#1")]
private static extern TwRC DSM_Entry1( [In, Out] TwIdentity origin, IntPtr zeroptr, TwDG dg, TwDAT dat, TwMSG msg, ref IntPtr refptr );

[DllImport("twainDSM.dll", EntryPoint="#1")]
private static extern TwRC DSM_Entry2( [In, Out] TwIdentity origin, IntPtr zeroptr, TwDG dg, TwDAT dat, TwMSG msg, [In, Out] TwIdentity idds );

[DllImport("twainDSM.dll", EntryPoint="#1")]
private static extern TwRC DSM_Entry3( [In, Out] TwIdentity origin, IntPtr zeroptr, TwDG dg, TwDAT dat, TwMSG msg, [In, Out] TwStatus dsmstat );

위의 첫번째 예에서 달라진 것은 EntryPoint를 명시한 것이다. 즉 DLL에서 제공하는 첫번째 메소드를 쓴다는 것이다. 함수 이름이야 뭐가 되든간에, 무조건 DLL에서 제공하는 첫번째 함수를 쓴다는 것이다. 파라미터도 최대한 DSM_Entry의 함수를 그대로 따르되, 두번째 파라미터가 Null 이라면 zeroptr에 IntPtr.Zero를 넣는 것이다. 그리고 맨 마지막 파라미터 같이 다양한 형태로 때려 박는 스타일일때는 그에 필요한 형을 그대로 집어넣는다. 그러면 .NET에서 DLL 함수와 연결할때, 알아서 해당 부분을 (void **)로써 제공할 뿐이라는 것이다. 다른 것들도 마찬가지로, 각 변수들의 크기만 잘 맞출 수 있다면 ( int 면 4바이트, short 이면 2바이트 등등) 그게 무슨 값이든 상관 없이 적용할 수 있다는 것이다.

Unmanaged .NET은 하면 할 수록 나름 매력이 솔솔 풍기는 기분이다.

728x90

지금 Scanner 의 동작을 위해 해당 기능을 탑재한 응용 프로그램들을 테스트 처럼 돌려보는데,
매번 오류가 발생했다. 뭘 설치하면, 뭐가 등록이 안된다는 둥, 무슨 기능이 동작하지 않는 다는 둥, 말도 많고 탈도 많았다. 이런 저런 오류를 찾아는 보지는 찾지 못했다.
그러다가 옆자리 분께 문의하니 간단하게 해결되었다.

Windows 2008을 처음에 쓰다 보면, 이상하게 일반 App 레벨의 프로그램들이 제대로 동작하지 않음을 쉽게 느낄 수 있다. 뭔가 많이 막힌듯 하면서도, 기묘하게 동작이 안되는….
Windows XP 이나 Vista 혹은 7에서 심지어는 Windows 2003에서도 제대로 돌던게,
이상하게 Windows 2008에서는 안도는 문제.

이 문제의 모든 핵은 Windows의 기능 중 하나인 Desktop Experience(데스크톱 경험) 이라는 기능 부재로 발생되는 현상이다. 예전에 바탕화면 꾸미는 작업이나, 간단하게 폴더의 Thumbnail 기능 등등, 이 모든 기능들이 바로 여기에 포함되어 있다. 즉 이 Desktop Experience 기능만 활성화 시켜준다면,
최소한 Windows 2008 에서도 일반 데스크톱처럼 대충이나마 사용이 가능하다.

728x90

.NET 2.0 부터 제공되는 Generic 형 Class. System.Collection.Generic 이라는 네임스페이스에 존재하는 내용이다. Collection에서는 모든 값들을 Object를 사용하기 때문에 매번 Casting 을 해야 했고, 그에 따른 성능상 문제로 인해 대안점 처럼 꺼내든 것이다. 뭐 Generic의 역사나 기타 방향성문제는 다른 문서들을 참고하시고..

여기서는 generic에 있는 각 형태에서 제공하는 find라는 함수를 이용하는 방법을 언급하려 한다. 물론 foreach와 같은 순환문을 이용해서 직접 find 함수를 구현할 수 있지만, 최소한 내부에 구현된 find 함수의 성능이 그나마 내가 직접 짠 것 보다는 좋을 것이라는 생각에 최대한 애용하는 편이다.

이 find 함수의 기본 형은 아래와 같다.

public T Find (
	Predicate<t> match
)

 

위의 형태에 대한 정의 내용을 보면 Predicate<T> 라는 게 있는데, 바로 이 부분에 대리자 역할을 하는 함수가 필요로 한다. match 라는 의미는 자신이 찾는 값의 형태인 경우에는 true 혹은 false를 돌려달라는 의미다.

여기서 개인적으로 가진 의문은 왜 find를 저렇게 구현했을까 했던 점이다. 만일 List<int> aaa 라는 개체를 만들었다면, aaa.find(1111) 식으로 aaa.find(<T>) 형태로 제공되었으면 그냥 썼을텐데, 저런식으로 만드니 원 접근이 될 터인가.. 했다. 하지만, 정작 <T> 안의 값의 형태가 복합형이고, 그 안에 찾는 조건이 복잡한 경우라면 오히려 위의 방법은 좋은 대안 식이라고나 할까?

 

일단 MSDN에서 제공되는 예제를 먼저 보자.

using System;
using System.Collections.Generic;

public class Example
{
    public static void Main()
    {
        List<string> dinosaurs = new List<string>();

        dinosaurs.Add("Compsognathus");
        dinosaurs.Add("Amargasaurus");
        dinosaurs.Add("Oviraptor");
        dinosaurs.Add("Velociraptor");
        dinosaurs.Add("Deinonychus");
        dinosaurs.Add("Dilophosaurus");
        dinosaurs.Add("Gallimimus");
        dinosaurs.Add("Triceratops");

        Console.WriteLine("\nFind(EndsWithSaurus): {0}", 
            dinosaurs.Find(EndsWithSaurus));
    }

    // Search predicate returns true if a string ends in "saurus".
    private static bool EndsWithSaurus(String s)
    {
        if ((s.Length > 5) && 
            (s.Substring(s.Length - 6).ToLower() == "saurus"))
        {
            return true;
        }
        else
        {
            return false;
        }
    }
}

 

끝의 글자가 saurus 로 끝나는 명칭을 찾는 로직. 저기서 보면 Find 안에 특정 값이 들어간게 아니고, 특정 함수가 들어가 있다. 즉 값의 결과가 true/false로 떨어지는 독자적인 함수가 있으면 된다.  위의 예제는 바로 List에 담긴 내용들 중 맨 끝의 글자가 saurus가 들어 있는지 체크한 뒤 있으면 true, 없으면 false로 돌려준다.

대충 이해가 되려나 싶다.

그런데, 내가 걸린 문제는 이렇다. 위의 예제대로라면, 실제 find를 사용하는 것은 그 찾으려는 값이 밖에 있다는 사실. 만일 위의 예제대로 라면, 찾기 로직 안에 saurus 라는 값 처럼 아예 박혀 있어야 되는데, 실제로는 저 값이 외부에서 받는 값일때는 걸리게 된다.

예를 들어보자. 사용자가 검색하는 단어를 기준으로 찾는다고 하자.
입력되는 값에 따라 찾는 내용이 달라져야 되는데, 이 경우에는 위와 같은 방법을 사용하면 곤란해질 수 밖에 없다. 그렇다면?

위의 예제를 보면 함수를 넣기 위해 static private로 만들었는데, 그것을 delegate라는 대리자를 사용해서 원큐로 만드는 것이다. txtInput 이라는 Text 박스에서 입력값이 생겼을 때 찾기 명령을 실행 시키는 예제로직을 만들어보았다.

List<string> aryData = new List<string>();

public Test()
{
    aryData.Add("apple");
    aryData.Add("pineapple");
    aryData.Add("steel");
}

private void txtInput_TextChanged(object sender, EventArgs e)
{
    string sResult = aryData.Find(delegate(string s) {
        return s.Equals(txtInput.Text);
    });

    if(string.IsNullOrEmpty(sResult))
        MessageBox.Show(sResult);
}

 

대략적으로 보면 알겠지만,

Find 라는 함수 뒤에 delegate 라는 대리자를 선언하고, 그 안에 가상 함수로 들어오는 파라미터 값을 정의한다. string s 부분이 있는데, 그 부분이 바로 Find 에서 역으로 호출 될 때 들어오는 값이다. 만일 List<int> 라면 int 가 되어야 할 것이다.

그리고 최종적으로 돌려주는 값은 true, false로 나올 수 있는 값이면 된다.

그러면 실제적으로 Find의 Return 값은 찾은 값을 돌려주게 된다. 지금은 List<string> 이니 돌려주는 값은 당연히 string. 만일 int면 int가 될 것이다.

 

정리하며.

물론 사람이 만든 코드이기 때문에, 성능이 월등하리라 볼 수는 없다. 하지만, 최소한 그 분야의 대가들이며, 또 내부적인 구현 시, 순수 .NET으로 만들지 않고, 성능을 위해 억지로 Binary로 만들기도 한다. 즉 알지는 못하나, 최소한 날로 짜는 것 보다 더 나은 성능을 보여줄 수 있다는 것이다.

이런 내 함수들을 활용 방법이 의외 복잡하더라도 작정하고 사용하다 보면 지금 보다 더 나은 성능을 보장할 수 있다.

 

복합형 값용 List<T>.Find 사용방법 예제.

사람 정보 중 이름이 같은 데이터를 메시지 박스에 표현 하는 방법

class PersonData
{
    public PersonData(string sName, string sSocialNo)
    {
        _name = sName;
        _socialNo = sSocialNo;
    }

    string _name;
    public string Name
    {
        get
        {
            return _name;
        }
        set
        {
            _name = value;
        }
    }

    string _socialNo;
    public string SocialNo
    {
        get
        {
            return _socialNo;
        }
        set
        {
            _socialNo = value;
        }
    }

}

List<persondata> aryData = new List<persondata>();

public Test()
{
    aryData.Add(new PersonData("홍길동", "123444-444422"));
    aryData.Add(new PersonData("조조", "123444-444422"));
    aryData.Add(new PersonData("유비", "123444-444422"));
}

private void txtInput_TextChanged(object sender, EventArgs e)
{
    PersonData sResult = aryData.Find(delegate(PersonData p) {
        return p.Name.Equals(txtInput.Text);
    });

    if(sResult != null)
        MessageBox.Show(sResult.Name + sResult.SocialNo);
}
728x90

단순한 컨트롤인 TextBox 나 ListBox 같은 것은 그냥 쓰면 되는데, 복합 컨트롤을 만들 필요가 있는 경우 사용자 컨트롤을 만들어 사용하곤 한다. 즉 TextBox와 ListBox가 하나로 합쳐진 특수 목적 컨트롤 같은 것을 만들때다.

compositectrl1

저렇게 컨트롤 안에서 동작만 되면 문제가 없는데, 만일 외부로 이벤트를 노출 시킬 필요가 있는 경우가 있다. 위의 그림을 예로 들면 아랫쪽이 ListBox인데, ListBox의 선택이 변경되는 경우 저 통짜 컨트롤을 쓰는 곳에서 그 이벤트를 받기 위해서 구성하는 경우다.

어떻게 해야 될까 고민을 하다가 링크 하나를 발견했다. ( http://www.akadia.com/services/dotnet_user_controls.html )

만드는 방법은 간단하다. 딱 두 줄에 해당하는 내용을 넣으면 된다.

public delegate void 이벤트이름Handler();
public event 이벤트이름Handler 이벤트이름;

위와 같이 구성하면 되는데, 위의 컨트롤에서 사용한 내용은 아래와 같다.

// 컨트롤 내부 소스
public delegate void SelectChangedHander(); 
event SelectChangedHander SelectChanged;

event로 SelectChanged 라는 이름으로 하고 밖에서 연결할 때 사용하는 끈 역할을 하는 Handler를 delegate(대리자)로 선언하여 처리하는 것이다. 그러면 밖에는 이 Handler를 통해 이벤트 가입을 하는 것이다. 가입방법은 예전에도 많이 봤던 그런 형태가 된다. ( 저 이벤트를 받을 메인 프로그램에 선언하는 그 형태. )

// 컨트롤을 사용하는 메인 프로그램 소스
this.categoryCtrl.SelectChanged += new CategoryCtrl.SelectChangeHander(this.categoryCtrl_SelectChanged);

그러면 컨트롤 측에서 이벤트를 발생을 어떻게 하는 걸까?
그 역시 간단하다.

이벤트 이름을 함수로 호출하듯 하면 된다.

// 컨트롤 내부 소스 중 이벤트가 발생되는 시점
if (SelectChanged != null)
   SelectChanged();

보면 뜬금 없이 SelectChage가 null 인지 체크하는 경우가 있는데, 컨트롤이 제대로 초기화되지 않은 상황에서 호출되는 불상사를 막기 위한 안전 장치이다. 무시해도 되긴 하지만, 가급적이면 저렇게 안전장치를 거는걸 권장한다.

자,위와 같이 구성했다면, 이렇게 된다.

컨트롤내부 실행 중

-> SelectChange() 함수 호출

-> SelectChanageHandler로 연결한 모든 부분에 이벤트 발송

-> SelectChangedHandler에 인자값으로 넘긴 함수를 호출
   (위의 예제로 있는 categoryCtrl_SelecChanged() 함수 같은거)

기존에는 그냥 만들어진 이벤트를 소비하기만 했다면 자신만의 이벤트로 작업을 한다면 이런 부분을 활용해 보는 것도 나쁘지 않을 것이다.(생각해보니, 이렇게 만들 수 밖에 없기는 하다.)

728x90

+ Recent posts

728x90