협업이 필요한 이유

최근의 소프트웨어 개발은 점차적으로 엔터프라이즈화 되어 가고 있습니다. 대용량/대규모화 되어가고 있는 현대의 소프트웨어 생태계에서 마치 새로운 트랜드로 자리잡고 있는 엔터프라이즈 2.0 이 자리를 잡고 그 규모를 넓혀가고 있습니다. 엔터프라이즈 2.0 은 Web 2.0 과 결합된 의미로써 즉, Enterprise social software(http://en.wikipedia.org/wiki/Enterprise_2.0) 라고 보아도 크게 의미는 다르지 않습니다.    

엔터프라이즈 소프트웨어는 대용량/대규모/보안 등의 핵심 키워드로 그 아키텍처가 매우 민감한 부분이기도 합니다. 하지만 엔터프라이즈 2.0은 기존 엔터프라이즈에 개방/공유 등을 강조하면서 바로 협업과 맞물리는 부분이기도 합니다. 그리고 이러한 움직임은 국가적인 차원의 거버먼트 2.0(http://blog.powerumc.kr/252)과 매우 유사하기도 합니다.    

즉, 중요한 것 중 현대의 소프트웨어 개발은 더 이상 폐쇄적인 환경을 거부하며, 최소한의 자원과 리소스를 아끼고, 남은 자원을 극대화하여 새로운 가치를 생산하고자 한다는 것입니다. 단지, 소프트웨어 개발은 개발자 역량만 훌륭하다고 되는 것이 아니며, 개발자간의 원활한 커뮤니케이션, 각 팀과의 원활한 커뮤니케이션, 더 나아가 조직과의 커뮤니케이션과도 연관 고리가 존재하게 됩니다.    

콩 심은 곳엔 콩이 나고, 팥 심은 곳엔 팥이 나야 하지만, 실제 프로젝트에서는 콩 심은 곳에 팥이 나기도 합니다. 협업을 하다 보면 협업 자체가 어려운 것이 아니라, 사람을 대하는 것이 가장 어렵다는 것을 느낄 수 있을 것입니다. 그래서 애자일(Agile) 한 방법론이 최근 팀과 조직에서 관심의 대상이 되는 것과 같은 이치입니다. 애자일 방법론을 잘 하기 위해서는 사람과 인간성을 이해하고 신뢰를 쌓는 것이지만, 그렇게 애자일하게 너그러운 사람과 팀, 조직은 그리 흔하지 않습니다.    

그렇다면 뭐가 문제일까요? 사람을 대하는 것이 어렵고, 고로 협업을 하는 것이 어렵고, 고로 전체 프로젝트를 수행하는게 어렵습니다. 개개인의 인격과 인간성을 존중하기엔 시간이 넉넉치 않을 뿐더러, 그들 간의 업무를 조율하는 것은 더 어려워지고, 점점 위태로운 프로젝트가 되기도 합니다. 물론 필자 또한 이런 문제의 발원지가 되기도 해보았고, 이것을 조율하는 입장도 되어 본 경험입니다.    

그럼 이미 답은 나왔습니다. 바로 "강제성" 을 부여하는 것입니다. 강제성이라고 하면 오히려 비 애자일하다고 할 수 있겠지만, 바꾸어 말하면 "당신 하나 때문에~" 애자일을 하는 것이 아니라는 것입니다. 가장 표준적이면서도 쉬운 방법을 통해 목표의 방향성을 가지고 간다는 것이 더 중요할 수 있기 때문입니다.

      

어떻게 커뮤니케이션을 할 것인가?

사람과 사람, 팀과 팀, 조직과 조직, 기업과 기업, 이들 간의 커뮤니케이션은 매우 다양합니다. 메신저, 이메일, 그 밖에 다양한 방법이 존재합니다.    

   

사람마다 선호하는 방법은 틀리겠지만, 개인적으로는 메신저야말로 가장 업무적으로 방해가 되는 커뮤니케이션 방법이라고 생각합니다. 언제나 급한 분들에게는 가장 좋은 커뮤니케이션 방법이 메신저가 될 수 도 있을 것입니다.    

제가 가장 좋아하는 커뮤니케이션 방법은 이메일입니다. 제가 이메일을 열람하고 싶을 때 보고 업무를 처리하면 되니까요. 하지만 이메일은 기록되고 보관되기 때문에 가장 책임감을 발휘해야 하는 커뮤니케이션 방법이기도 합니다. 하지만 요즘 스마트폰의 열풍으로 직장이든 가정이든 이메일을 볼 수 밖에 없는 현실이 되었죠^^;    

최근에는 SNS 와 같은 방법으로 커뮤니케이션을 하기도 합니다. 우리가 흔히 알고 있는 트위터(Twitter) 와 같은 Public SNS 도 존재하지만, 기업 내에서 사용할 수 있는 Private SNS 도 있습니다. 간단 명료한 메시지라는 강점으로 최근 유행하는 방식이기도 합니다.    

 

Team Foundation Server 의 구성 요소를 통한 커뮤니케이션

Team Foundation Server(이하 TFS) 는 단독적으로 사용할 때 보다 여러 가지 구성 요소를 갖출 때 비로소 가장 효과적인 커뮤니케이션 방법을 제공해 줍니다.    

최소한으로 TFS 는 SQL Server 를 필요로 하며, SQL Server 는 TFS 를 통해 소스 제어(Source Control), 리포팅(Reporting) 서비스를 제공해 줍니다. Team Foundation Server 를 사용하는 목적으로 SQL Server 라이선스를 일부 무료로 제공하기 때문에 가장 저렴한 비용으로 커뮤니케이션을 할 수 있는 방법입니다.

이를 이용하여 최소한으로 이행할 수 있는 여러 가지 기능이 있습니다.

  • 소스 제어(Source Control)
  • 소스 코드 브랜치(Branch)
  • 리포팅 서비스 및 데이터 웨어하우스(Reporting Services and Data Warehouse)
  • 일부 오피스(Office) 제품 연동

       

   

하지만 위의 방법으로는 조금 부족한 감이 있습니다. 마찬가지로 Team Foundation Server 를 사용하게 되면, SQL Server, Sharepoint Server 의 일부 라이선스를 무료로 제공하기 때문에 더욱 효과적인 커뮤니케이션 인프라를 구축할 수 있습니다. 특히 SharePoint 는 팀 포털과 문서 관리의 이점 뿐만 아니라, 팀 워크플로우를 개선할 수 있는 다양한 방법을 제공합니다. 특히 큰 규모에서는 의사 결정권이라는 막강한 권한이나 프로세스가 존재하게 되는데, SharePoint 는 이러한 워크플로우를 상당히 효과적으로 개선할 수 있는 솔루션이기도 합니다.

  • 소스 제어(Source Control)
  • 소스 코드 브랜치(Branch)
  • 리포팅 서비스 및 데이터 웨어하우스(Reporting Services and Data Warehouse)
  • 다양한 오피스(Office) 제품 연동
  • 팀 포털, 문서 관리, 팀 프로세스 개선

   

최근 가상화(Virtualization) 를 기반으로 클라우드 서비스가 매우 큰 개발 및 비즈니스 영역으로 자리잡고 있습니다. 소프트웨어 가상화는 물론이고 우리가 흔히 알고 있는 하드웨어 가상화 등 이러한 서비스 가상화를 통해 이전에는 상상하기 힘들거나 환경을 구성하기 힘든 영역까지 모두 커버하고 있습니다. Microsoft 에서는 이것을 가리켜 Dynamic IT 라고 칭하고 있습니다.

   

그 중, System Center 솔루션은 매우 다양한 역할을 수행합니다. 가상화 인프라와 서버 모니터링을 위해 다양한 솔루션은 아래와 같습니다.

솔루션

설명

SCVMM

(System Center Virtual Machine Manager)

물리적인 서버 또는 가상화의 서버를 관리, 배포, 최적화하는 솔루션이다. Hyper-V 또는 VMWare 등 여러 가상화 플랫폼을 지원한다.

SCOM

(System Center Operation Manager)

데이터센터의 운영을 중앙 관리를 위한 솔루션이다. 분산되어 있는 서버의 상태, 성능 정보, 구성 또는 보안 상태를 감지한다. 윈도우 운영체제와 리눅스(Linux), 유닉스(Unix) 운영체제 의 리소스나 그 하위 구성요소를 모니터링 할 수 있다.

SCCM

(System Center Configuration Manager)

운영체제 배포, 보안 패치, 서버/데스크탑 정책, 모바일 정책 등 총체적인 서버 및 클라이언트의 구성을 관리하는 솔루션이다. 기업의 네트워크 내의 모든 컴퓨터를 대상으로 강제 업데이트, 필수 구성 요소 등을 정책적으로 강제화 할 수 있다.

   

SCVMM(System Center Virtual Machine Manager) 은 가상화를 통한 동적 서버 관리, 가상화를 통한 유지 관리 계획, 가상화를 통한 테스트 및 개발 환경 의 작업을 관리하고 단순화 위한 가상화 관리 솔루션입니다. 가상화 서버를 관리를 용이하게 하고, 물리적인 서버를 가상화로 쉽게 전환하거나 가상 호스트에 여러 개의 물리적 서버를 통합할 수 있습니다.

특히 이 솔루션은 ALM(Application Lifecycle Management) 솔루션 중 Team Foundation Server 2010 에서 테스트 가상화를 사용하기 위해 필요한 구성 요소이기도 합니다.

   

SCOM(System Center Operation Manager) 는 분산되어 있는 데이터 센터를 통합 관리를 하며 윈도우 운영체제 뿐만 아니라 다양한 리눅스, 유닉스 기반의 운영체제를 지원합니다. 이 솔루션을 이용하면 특정 장애나 서비스 성능, 가용성을 보장하기 위해 자동으로 조치를 취하도록 할 수 있습니다.

   

SCCM(System Center Configuration Manager) 는 네트워크 인프라에 존재하는 클라이언트 컴퓨터, 서버 컴퓨터 등의 구성을 중앙에서 관리합니다. 예를 들어, 일부 클라이언트 사용자의 컴퓨터는 윈도우의 업데이트를 꾸준히 사용하지 않는 경우가 있습니다. 이러한 경우 강제적으로 업데이트를 수행하도록 정책적으로 관리를 할 수 있습니다. 그 밖에 윈도우 방화벽 설정, 자동 업데이트 및 백신 프로그램 등을 정책적으로 설치되거나 구성하도록 강제화 할 수 있습니다.

   

   

현재 협업을 위한 기본적인 기반 환경은?

단지, 필자가 오늘 하고 싶은 이야기는 여러분들에게 여러 가지 솔루션이 이를 대체할 것이라는 암시를 주는 것이 아닙니다. 단지 협업은 혼자만의 노력으로는 불가능 한 것이며, 이것을 뒷받침해 줄 수 있는 도구가 있다는 것에 감사할 뿐입니다.    

대부분의 우리나라 조직은 상하 수직적인 관계입니다. 일을 던져주고, 그것을 받고 일을 하는 수직적인 줄타기 방식은 작업의 결과를 매우 가시적이고 평가하기 쉬운 방법입니다. 그리고 이런 방식에 저 또한 매우 길들여져 있으며, 일을 수행하는 입장에서도 매우 수월합니다. 수행 결과를 보여주기도 쉽고, 처리하기도 쉽습니다.    

다만 수평적인 조직(절대적인 수평은 없을 것이지만)에서는 오히려 상하 수직적인 방식과는 다릅니다. 항상 중간 과정에 서로의 동의와 협력이 필요하며, 그 성과 또한 개인의 성과가 아닌 우리의 성과가 될 테니까요.    

하지만, 여러 조직과 기업이나 프로젝트에서 일을 해 본 경험으로, 절대적인 상하 수직적, 수평적인 조직은 없다는 것입니다. 그리고 필자 또한 어떤 것이 바람직한지 아직은 확신을 하기 어렵습니다. 다만, "그때 그때 잘~" 이라는 것밖에는 ^^    

팀워크(Team Work) 란 팀이 무너지지 않고 존재할 수 있는 가장 큰 힘을 발휘합니다. 반대로 팀 워크가 수년간 같은 방식이고 개선되지 않고 제자리에 머물러 있다면 썩은 우물과도 같습니다. 왜냐하면 시대가 변함에 따라 개개인의 커뮤니케이션 방식은 바뀔 것이며, 점차적으로 개선되어 지지 않는다면 팀 워크가 아닌 커뮤니케이션 자체의 문제의 한계에 부딪히게 될 것입니다.    

일단 오늘은 협업에 대해 썰을 풀어 보았습니다. 그리고 협업을 위한 많은 노하우를 여러분들에게 알려드리고 개선해 나가고자 합니다. 언제든지 불편한 내용이나 피드백을 주시면 참고하여 개선하고자 하도록 하겠습니다.

Welcome to Dynamic C#(21) - 인덱스의 힘.

C# 2010. 5. 21. 09:00 Posted by 알 수 없는 사용자

- 인덱스는 왜 나오는 고냐...?

인덱스는 방대한 정보를 특정한 기준으로 잘 분류해 놔서 정보를 금방 찾을 수 있도록 해주는 고마운 장치이죠. 아무리 두꺼운 사전이 있다고 해도, 그 사전이 가나다 순이나 알파벳순으로 잘 인덱싱이 되어있지 않으면 쓸모없겠죠. C#도 그래서, 대화하기 여러운 COM과 잘 지내기 위해서 인덱스 가능한 프로퍼티를 사용하기 시작했쬬!


- 인덱스 가능한 프로퍼티가 몬데?

이름 그대로입니다. 그냥 이름 그대로 프로퍼티인데, 프로퍼티의 값을 가져올 때 인덱스로 특정 요소에 접근가능한 프로퍼티죠. 아래와 같은 모양이 인덱스로 접근하는 프로퍼티의 모습입니다.

myObject.MyIndexedProperty[index];

인덱스 가능한 프로퍼티는 내부적으로 그냥 간단한 접근자 메서드와 일반적으로 쓰이는 인덱서와 유사한 인덱서로 구성됩니다. 그냥 일반적으로 쓰는 인덱서처럼 생각할 수도 있죠. 그러면 일반적인 인덱서와의 차이점을 예제를 통해서 한번 확인해 보겠습니다. 우선 일반적인 인덱서의 예제를 보시죠.

class D
{
    private int[] nums = new int[] { 1, 2, 3, 4, 5, 6, 7, 8 };

    public int this[int x]
    {
        get
        {
            return nums[x];
        }
    }
}

class C
{
    static void Main()
    {
        D d = new D();
        for (int i = 0; i < 8; i++)
        {
            Console.WriteLine(d[i]);
        }
    }
}


그리고 인덱스 가능한 프로퍼티의 사용예제입니다.

using System;
using Excel = Microsoft.Office.Interop.Excel;
using System.Collections.Generic;

namespace OfficeInteropExam2
{
    public class Account
    {
        public int ID { get; set; }
        public double Balance { get; set; }       
    }

    class Program
    {
        static void DisplayInExcel(IEnumerable<Account> accounts)
        {
            var excelApp = new Excel.Application();
            excelApp.Visible = true;
                       
            excelApp.Workbooks.Add();

            Excel._Worksheet workSheet = (Excel.Worksheet)excelApp.ActiveSheet;

            workSheet.Cells[1, "A"] = "ID Number";
            workSheet.Cells[1, "B"] = "Current Balance";

            var row = 1;
            foreach (var acct in accounts)
            {
                row++;
                workSheet.Cells[row, "A"] = acct.ID;
                workSheet.Cells[row, "B"] = acct.Balance;
            }

            workSheet.Range["A1", "B3"].AutoFormat(
                Excel.XlRangeAutoFormat.xlRangeAutoFormatClassic2);
        }

        static void Main(string[] args)
        {
            var bankAccounts = new List<Account> {
                new Account {
                  ID = 345678,
                  Balance = 541.27
                },
                new Account {
                  ID = 1230221,
                  Balance = -127.44
                }
            };

            DisplayInExcel(bankAccounts);
        }
    }
}


전자는 간단하게 인덱서를 사용하는 예제이구요, 두번째는 엑셀에 데이터를 표시하는 COM 프로그래밍 예제입니다. 두번째 예제에서 밑줄친 부분이 바로 인덱스 가능한 프로퍼티를 사용한 부분입니다. 겉으로 보기에는 별 차이가 없어 보이는데요. 내부적으로는 어떨까요? 리플렉터로 우선 첫번째 예제를 보겠습니다.


위에서 붉은 선으로 표시된 대로, 일반적인 인덱서 앞에는 'Item'이라는 이름이 붙습니다. 그리고 이 인덱서를 사용하는 부분의 코드는,

private static void Main()
{
    D d = new D();
    for (int i = 0; i < 8; i++)
    {
        Console.WriteLine(d[i]);
    }
}

위와 같이 소스코드와 큰 변화가 없는 걸 볼 수 있습니다. 그러면 두번째 예제는 어떨까요? 인덱스 가능한 프로퍼티가 사용된 부분만 리플렉터로 보면,

workSheet.get_Range("A1", "B3").AutoFormat(XlRangeAutoFormat.xlRangeAutoFormatClassic2, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value);

'Range["A1", "B3"]'이라고 썼던 부분이 'get_Range'라는 메서드 호출로 바뀐걸 보실 수 있습니다. 그러면 저 get_Range를 한번 찾아볼까요?


위에서 보시듯이 'Item'이라는 표시가 없습니다. 즉 일반적인 인덱서가 아니라는 이야기죠. 그리고 접근자 메서드를 가지고 있는 걸 보실 수 있습니다. 위에서 인덱스 가능한 프로퍼티가 '접근자 메서드와 일반적으로 쓰이는 인덱서와 유사한 인덱서로 구성'된다고 이야기 한 부분이 바로 이걸 가리키는 말이었던 거죠.


- 찝찝하지만..

인덱스 가능한 프로퍼티를 그동안 추가하지 않았던 이유는 C#팀의 디자인 철학과 맞지 않아서 였다고 합니다. C#팀에서는 'C라는 타입안에 있는 P라는 프로퍼티에 접근해서 값을 가지고 온다. 그리고 그 결과값에 대해서 인덱스로 접근한다'는 시나리오가 더 옳다고 생각한다고 하네요.

하지만, 인덱스 가능한 프로퍼티를 사용하는 COM이 무척이나 많이 퍼져있다는 게 문제였다고 합니다. 그래서 이전 포스트에서 언급 해드렸던 이유와 같은 이유로 COM 프로그래밍을 지원하기 위해서 이런 기능이 추가되었다고 하네요.

비록 인덱스 가능한 프로퍼티를 사용할 수 있긴 하지만, C#에서는 인덱스 가능한 프로퍼티를 선언할 수는 없습니다. COM 라이브러리가 tlbimp라는 툴을 이용해서 만들어 지기 때문에, C#에서는 만들수 없다고 하네요. 즉 C#에서는 COM 라이브러리에 대해서만 인덱스 가능한 프로퍼티를 사용할 수 있는 것이죠.

컴파일러는 COM 타입에서 인덱스 가능한 프로퍼티로 보이는 걸 모두 임포트해둔다고 합니다. 그래서 해당 프로퍼티에 대해서는 이름을 붙인 인덱서 문법을 이용해서 사용할 수 있도록 한다고 하네요. 즉, '컴파일러는 이름을 붙인 인덱서 문법을 통해서 인덱스 가능한 프로퍼티를 사용할 수 있도록 한다'는 것이죠. 위의 예제에서 보여드렸듯이 일반적인 프로퍼티는 접근자 메서드를 통해서 바로 접근할 수 없습니다. 하지만 문법적으로는 매우 유사한 형태를 취하면서 내부적으로는 다른 일이 벌어지고 있는 것이죠.


- 오버로드 판별도 해보자.

인덱스 가능한 프로퍼티가 추가되면서 또 오버로드 판별에 변수가 생겼습니다. 아래의 예제를 가지고 설명을 해보면요,

myObject.MyIndexedProperty[index];

우선 컴파일러가 이 구문을 보게 되면, '.'왼쪽을 그 객체의 타입과 연결시킨다고 합니다. myObject의 타입이 예를 들어서 MyType이라고 하면, 그 둘을 연결시키는 것이죠. 그 다음에는 MyIndexedProperty라는 이름을 MyType에서 쭉 훑어보면서 찾습니다.

하위 호환성을 유지하기 위해서, 컴파일러가 만약 검색중에 같은 이름을 가진 평범한 프로퍼티를 보더라도 무조건 그 프로퍼티와 호출을 바인딩하게 됩니다. 하지만, MyType에서 MyIndexedProperty라는 프로퍼티를 발견했다고 해도, MyType에 인덱서가 없다면 이 프로퍼티에 호출을 바인딩하지는 않습니다.

이렇게 인덱스 가능한 프로퍼티를 제외한 일반적인 바인딩이 실패 했다면, 컴파일러는 MyType이 ComImport타입인지 확인합니다. ComImport타입이 맞다면, MyType에서 사용가능한 인덱스 가능한 프로퍼티의 리스트를 만들어서, 후보군에 대해서 오버로딩 판별을 하는데, 이때의 판별 알고리즘은 평범한 프로퍼티와 동일하게 진행됩니다. 그저 이름으로 인덱서를 취급하듯이 하는 것이죠.

그리고 인덱스 가능한 프로퍼티를 사용했다고 해서 특별한 일이 일어나는 건 아닙니다. 그저 예전버전에서 값을 가져오려면 적어야 했던 내용을 그대로 생성해주는 syntactic sugar일 뿐이기 때문이죠. 이 부분은 아래의 예제를 보시면 좀 더 명확해 집니다.

//인덱스 가능한 프로퍼티를 사용한 경우
workSheet.Range["A1", "B3"].AutoFormat(
    Excel.XlRangeAutoFormat.xlRangeAutoFormatClassic2);

//기존버전에서 작업해야 했던 경우
workSheet.get_Range("A1", "B3").AutoFormat(Excel.XlRangeAutoFormat.xlRangeAutoFormatClassic2,
    Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing,
    Type.Missing);

위에서 보여드렸던 예제중에서 인덱스 가능한 프로퍼티를 사용한 코드를 리플렉터에서 보면 아래와 같았습니다.

workSheet.get_Range("A1", "B3").AutoFormat(XlRangeAutoFormat.xlRangeAutoFormatClassic2, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value);

똑같죠? 넵. syntatic sugar일 뿐이니까요. 낄낄낄.


- 마치면서

이번 포스트는 내용을 정리하면서 좀 힘들었습니다. 내공의 부족 때문인지 내용이 제대로 이해가 안됐기 때문이죠. 그런데 예제를 만들고 확인해보고 하니깐 조금씩 이해가 되더군요. 정리가 잘 된건지 모르겠습니다. 그럼 오늘은 여기까지~~!!!


- 참고자료

1. http://blogs.msdn.com/samng/archive/2009/11/03/com-interop-in-c-4-0-indexed-properties.aspx
2. http://msdn.microsoft.com/en-us/library/dd264733%28VS.100%29.aspx

Welcome to Dynamic C#(20) - 어르신과 대화하는 법.

C# 2010. 5. 17. 09:00 Posted by 알 수 없는 사용자
- 어르신과 대화하려면 어케 해야 되는거임?

간단합니다. 말씀하시는 내용을 잘 경청하고, 대꾸는 딱 필요한 만큼만 하면 되는 거죠. COM은 아마 그동안 C#이 못마땅 했을 겁니다. VB.NET은 공손하게 필요한 말만 딱 하는데, C#은 'Type.Missing'이 어쩌고 저쩌고 주저리주저리 말이 많았기 때문이죠. C#도 이제 99년도 부터 출발했다고 볼때, 11년이나 되었으니 꽤 성숙한 셈이죠. 이제 예의를 갖추기 시작한 겁니다. 낄낄낄.


- C#의 버릇없던 옛 시절.

그러면 C#얼마나 버릇이 없었는지 아주 간단한 예제를 통해 알아보시죠.

using System;
using Word = Microsoft.Office.Interop.Word;

namespace ConsoleApplication3
{
    class Program
    {
        static void CreateIconInWordDoc()
        {
            var wordApp = new Word.Application();
            wordApp.Visible = true;

            object useDefaultValue = Type.Missing;

            wordApp.Documents.Add(ref useDefaultValue, ref useDefaultValue,
                ref useDefaultValue, ref useDefaultValue);
        }

        static void Main(string[] args)
        {
            CreateIconInWordDoc();
        }
    }
}


위 예제는 그냥 오피스 워드 창을 하나 띄우는 예제입니다. 그런데 평소에 오피스 COM 프로그래밍을 접해보지 못한 분이라면, 뭔가 특이한 점을 발견하셨을 겁니다. 'Type.Missing'같은 독특한 걸 object형 변수에 넣고, Add메서드에 여러번 반복해서 써넣기 때문이죠. 딱히 값을 리턴받아서 뭘 하는 것도 아닌 것 같고, Missing이라면 뭔가 없다는 것 같은데, 없는 값을 왜 저렇게 반복해서 넣어야 할까... 하는 생각이 드는 것이죠. 이제 COM이 왜 C#을 싫어했는지 아시겠나요? 말이 많았거든요.

지난 포스트에서 보셨듯이, C# 4.0은 다른 런타임과의 상호운용에 신경을 무척 많이 썼으며, 그중의 하나가 COM과의 상호운용이었습니다. C# 4.0에서는 COM과 대화할 때 좀더 말을 적게 하면서 예의를 갖춰서 대화를 하게 된 것이죠. 컴파일러가 COM 객체를 대상으로 작업하고 있다는 걸 눈치채는 순간, 컴파일러는 매개변수에 'ref'키워드를 안붙이고 메서드나, 인덱서, 프로퍼티에 넘길 수 있도록 해줍니다.

using System;
using Word = Microsoft.Office.Interop.Word;

namespace OfficeInteropExam2
{
    class Program
    {
        static void CreateIconInWordDoc()
        {
            var wordApp = new Word.Application();
            wordApp.Visible = true;

            object useDefaultValue = Type.Missing;

            wordApp.Documents.Add(useDefaultValue,
                useDefaultValue, useDefaultValue, useDefaultValue);
        }

        static void Main(string[] args)
        {
            CreateIconInWordDoc();
        }
    }
}


즉 C# 4.0에서는 위 처럼 ref를 빼고 작업할 수 있도록 도와줍니다. 그리고 컴파일러가 나중에 각 매개변수 앞에 ref를 붙여서 컴파일 하는 것이죠. 일종의 syntactic sugar인 것입니다. 그런데 여기에 지난 포스트까지 설명드렸던 Named and Optional Arguments를 이용하면 아예 매개변수를 생략할 수 있습니다.

using System;
using Word = Microsoft.Office.Interop.Word;

namespace OfficeInteropExam2
{
    class Program
    {
        static void CreateIconInWordDoc()
        {
            var wordApp = new Word.Application();
            wordApp.Visible = true;

            wordApp.Documents.Add();
        }

        static void Main(string[] args)
        {
            CreateIconInWordDoc();
        }
    }
}


지난 포스트까지 설명드렸듯이 아예 매개변수를 생략하면 기본값으로 설정된 값이 넘어가게 됩니다. 그러면, Add메서드의 각 파라미터에는 기본값이 어떻게 설정되어 있을까요? Add메서드의 정의를 보면 아래와 같습니다.

Document Add(ref object Template = Type.Missing, ref object NewTemplate = Type.Missing, ref object DocumentType = Type.Missing, ref object Visible = Type.Missing);

위에서 보시듯이, 기본값은 'Type.Missing'으로 설정되어 있습니다. 즉 매개변수를 생략하고 Add메서드를 호출하면, 기본값으로 Type.Missing이 넘어가고 컴파일러는 거기에 자동으로 ref를 붙여서 호출을 완성시켜 주는 것이죠. 지금은 겨우 파라미터가 4개정도라서 감흥이 없으실지도 모르겠지만, 파라미터가 30개정도 되는 메서드들을 자주만나다보면 아마 이 기능이 너무나도 고맙게 느껴지시겠죠? ㅋㅋㅋㅋ


- 마치면서

오늘은 아주 짧게 향상된 COM 프로그래밍에 대해서 알아봤습니다. COM이 안쓰이길 바랬음에 불구하고 많이 쓰이니 어쩔 수 없이 C# 4.0에서 COM에 대한 지원이 많이 들어갔다고 하는걸 보니, 역시 기술의 생명은 벤더에게만 달린게 아니라는 생각을 해봅니다. 그럼 오늘은 여기까지 하고 다음에 또 뵙죠!


- 참고자료

1. http://blogs.msdn.com/samng/archive/2009/06/16/com-interop-in-c-4-0.aspx
2. http://msdn.microsoft.com/en-us/library/dd264733%28VS.100%29.aspx

Welcome to Dynamic C#(19) - 위너 고르기.

C# 2010. 5. 13. 09:00 Posted by 알 수 없는 사용자

- 위너를 고르는 방식!

위너라니, 무슨 위너이야기 일까요? 넵. 메서드 오버로딩에서 호출에 맞는 메서드를 고를때, 어떤 경우에 어떤 메서드가 더 적합한지 고르는, 즉 메서드 오버로딩 중에서 위너를 고르는 거에 대한 이야기 입니다. 아마도 이런 경우는 생각보다 자주일어날 것 같은데요. 과연 컴파일러는 어떤 방식으로 위너를 고를까요? 키로? 얼굴로? 능력으로? 한번 알아보시죠.


- 첫번째 경우

일단 두 메서드의 파라미터 개수가 같다고 할때는 매개변수가 어떤 타입의 파라미터로 형변환하는게 더 나은것인지를 기준으로 판단합니다.

class C
{
    public void Foo(object o) { Console.WriteLine("object"); }
    public void Foo(int x) { Console.WriteLine("int"); }

    static void Main(string[] args)
    {
        C c = new C();
        c.Foo(10);
    }
}


그럼 위의 예제에서는 누가 위너가 될까요? 10은 정수니까, object로 형변환도 가능하고, int로도 형변환이 가능합니다. 하지만 정수는 object보다는 int로 형변환 되는게 더 적합한 형변환이죠. 그래서 여기서는 'Foo(int x)'가 위너가 됩니다. 'Foo(int x)' ㅊㅋㅊㅋ


- 두번째 경우

두번째 경우는 파라미터 배열이 끼어듭니다.

class C
{
    public void Foo(int x, int y) { Console.WriteLine("int twins"); }
    public void Foo(params int[] x) { Console.WriteLine("params"); }

    static void Main(string[] args)
    {
        C c = new C();
        c.Foo(10, 20);
    }
}


첫번째 예제를 약간 변형시킨 건데요. 컴파일러는 파라미터 배열을 보자마자 이 파라미터 배열을 확장시켜서 메서드의 시그니처를 'Foo(int x_1, int x_2)'같이 만들고 이 시그니처를 가지고 오버로딩의 후보군에 끼워넣는다고 합니다. 그런데 컴파일러가 파라미터 배열을 확장만 시키는게 아니라, 파라미터 배열에서 확장되었음을 표시한다고 하네요. 그리고 파라미터에서 확장된 시그니처의 경우는 오버로드 판별에서 2등급으로 취급된다고 합니다. 즉 메서드 시그니처가 동일할 경우에 파라미터 배열은 2등급이기 때문에, 다른 일반적인 1등급 파라미터에 우선순위에서 밀리게 된다고 합니다. 위의 예제에서는 'Foo(int x, int y)'가 위너네요. ㅊㅋㅊㅋ


- 세번째 경우

이제 드디어 지금까지 열심히 이야기 해온 옵셔널 파라미터가 끼어들 차례입니다.

class C
{
    public void Foo(int x) { Console.WriteLine("int"); }
    public void Foo(int x, int y = 0, int z = 10)
    { Console.WriteLine("optionals"); }

    static void Main(string[] args)
    {
        C c = new C();
        c.Foo(10);
    }
}


위 예제는 쫌 난감합니다. 'c.Foo(10)'라는 호출만 보자면, 둘다 똑같이 해당되기 때문이죠. 첫번째 Foo는 시그니처가 완전히 일치하고, 두번째 Foo도 x를 제외한 값은 모두 기본값이 사용될 수 있으니까요. 이 경우에는 파라미터 배열과 같이 옵셔널 파라미터를 2등급으로 취급한다고 합니다. 즉 첫번째 Foo메서드가 옵셔널 파라미터가 하나도 없기 때문에 첫번째 Foo가 위너가 되는 것이죠. 그런데 만약에 첫번째 메서드에도 옵셔널 파라미터가 있다면 어떻게 될까요?

class C
{
    public void Foo(int x, int y = 0) { Console.WriteLine("optional1"); }
    public void Foo(int x, int y = 0, int z = 10)
    { Console.WriteLine("optional2"); }

    static void Main(string[] args)
    {
        C c = new C();
        c.Foo(10);
    }
}


위와 같이 작성된 경우 말이죠.


이런 에러를 보게됩니다. 즉, 둘간의 차이를 분별해낼 수 없기 때문에 모호한 호출이라는 것이죠.


- FAQ!

옵셔널 파라미터는 그동안 아주 꾸준히 C#에 추가해달라고 요청하던 기능입니다. 특히 오피스같은 COM과 연동하는 작업을 하는 프로그래머들이 많이 요청을 했었습니다. 왜 이런 기능을 예전에 안하고 지금하느냐? 하는 질문이 있을 법한데요. C#개발팀의 Sam Ng가 답변한 내용을 옮겨볼까 합니다.

1. 왜 이걸 좀 더 일찍하지 않았냐?

- 왜 이걸 좀 더 일찍 하지 않았느냐 하면 말이죠. 우린 진짜 이 기능이 C#에 포함되지 않았으면 했습니다. 이걸 그동안 계속해서 미뤄온 건, 이건 우리가 원했던 패러다임이 아니었기 때문이었죠.

2. 그럼 왜 지금은 이걸 추가했느냐?

- 이게 다 COM 때문이죠. 진짜 이건 사라지지를 않더라구요! 이걸 없앨려고 노력했지만, 사람들은 계속 이걸 사용하고 있고, 앞으로도 계속 사용하려고 하더군요. C#이랑 COM이랑 무슨 관계냐구요? 오피스. 오피스 PIAs때문이죠. 오피스 PIAs는 대부분 30개정도의 파라미터를 갖는 메서드로 이루어져 있죠. 그 파라미터의 대부분은 옵션이구요. 대부분의 경우에는 한개정도의 매개변수만 적어주고 나머지는 다 기본값을 사용하면 되는거죠.

이제 Named and Optional Parameters를 통해서 옵션인 파라미터는 안적고도 메서드를 호출할 수 있죠. 오피스 메서드를 호출할때도 모든 매개변수마다 Type.Missing같은거 안적어주고도 호출할 수 있는거죠. 그리고 매개변수에 해당하는 파라미터 이름을 적을 수 있기 때문에, 딱 필요한 거만 매개변수로 넘겨주고, 나머지는 생략할 수 있죠.

그리고 ref 없이 COM을 사용할 수 있도록한 기능과 조합해서 사용하면 COM 코드가 더 간결해지고 지루한 작업은 매우 줄어들겁니다. 컴파일러가 옵션인 ref 파라미터에 넘겨줄 임시값을 만들어서 매개변수를 넘겨주거든요.

제가 예전에 이야기 했듯이 C# 4.0의 큰 테마중의 하나가 다른 런타임(COM, 동적언어 등)과의 상호운용이에요. 그런 테마가 이런 기능을 반드시 갖추도록 했던거죠.


- 마치면서

아~ 이제 Named and Optional Parameters에 대해서 할말은 다 한것 같습니다. 자료를 읽으면서 저도 많이 배우고 재밌는 내용도 많이 읽었네요. 여러분은 어떠셨나요? 호호호호-_- 그럼 오늘은 여기까지 하고~ 다음에 또 다른 이야기 가지고 오겠습니다!


- 참고자료

1. http://blogs.msdn.com/samng/archive/2009/04/17/named-and-optional-arguments-ties-and-philosophies.aspx