뇌를 자극하는 C# 4.0 프로그래밍/ dynamic 형식

dynamic 형식 소개

// dynamic 예시
class MyClass
{
    public void MethodA()
    {
        // ...
    }
}

class MainApp
{
    static void Main (string[] args)
    {
        dynamic obj = new MyClass();
        obj.MethodA();
        obj.MethodB(); // dynamic으로 선언되어 있기 때문에 컴파일 에러가 발생하지 않는다.
    }
}
  • dynamic 형식은 int, string과 달리 형식 검사가 실행시에 이루어진다는 특징이 있다.

오리 타이핑

“오리처럼 걷고 오리처럼 헤엄치며 오리처럼 꽉꽉거리는 새를 봤을 때, 나는 그 새를 오리라고 부른다.” –제임스 위트콤 라일리

  • dynamic은 오리 타이핑을 구현하기 좋은 형식이다. 어느 형식으로 상속 받는지는 따지지 않고 오리처럼 걷고, 오리처럼 헤엄치고, 오리처럼 꽉꽉거리기만 하면 오리라고 인정할 수 있다.
  • (오리 타이핑과 관련한 구현 코드 생략. 그냥 인터페이스 상속 받아 쓰는 게 나아 보임. 아래 내용을 보면 dynamic 형식은 다른 언어와의 상호 운용성을 위해서만 사용하는게 좋아 보인다.)

COM과 .NET 사이의 상호 운용성을 위한 dynamic 형식

  • COM이란 Component Object Model의 약자로 MS의 소프트웨어 컴포넌트 규격을 뜻한다. OLE, ActiveX, COM+와 같은 파생 규격들이 모두 COM을 바탕으로 만들어졌다.
  • C#을 비롯한 .NET 언어들은 RCW(Runtime Callable Wrapper)를 통해 COM 컴포넌트를 사용할 수 있다.
  • 그러나 RCW가 있어도 C#은 COM과 잘 어울리지 못했는데 그 이유는 다음과 같다.
    1. COM은 메소드가 결과를 반환할 때 실제 형식이 아닌 object 형식으로 반환한다. 이 때문에 C# 코드에서는 이 결과를 실제 형식으로 변환을 해줘야 하는 번거로움이 발생하였다.
    2. COM은 오버로딩을 지원하지 않는다. 대신 메소드의 선택적 매개변수와 기본 값 매개변수를 지원한다.
  • C# 4.0에 이르러서야 dynamic 형식의 도입으로 1번 문제를 해결 했고, 메소드의 선택적 매개 변수와 기본 값 매개 변수 도임을 통해 2번 문제를 해결하여 C#은 비주얼 베이직처럼 COM 친화적인 언어가 되었다.
  • (COM 컴포넌트 붙이는 부분 생략)

동적 언어와의 상호 운용성을 위한 dynamic 형식

  • CLR은 IL로 컴파일 할 수 있는 언어들은 지원하지만, 파이썬이나 루비처럼 실행시에 코드를 해석해서 실행하는 방식의 동적 언어는 지원할 수 없었다. 그래서 MS는 동적 언어를 실행할 수 있도록 해주는 플랫폼인 DLR(Dynamic Language Runtime)을 만들었다.
  • DLR은 CLR 위에서 동작하며, 파이썬이나 루비 같은 동적 언어를 실행할 수 있다. DLR의 장점은 그저 동적 언어를 .NET 플랫폼에서 실행할 수 있다는 정도가 아니라 C#이나 VB 같은 정적 언어의 코드에서 파이썬이나 루비 같은 동적 언어의 코드에서 만들어진 객체에 접근할 수 있게 해준다. 쉽게 말해 C# 코드에서 직접 파이썬이나 루비 코드를 실행하고 그 결과를 받아 볼 수 있다는 이야기.
  • CLR 입장에서 보면 DLR API를 기반으로 구현된 동적 언어라도 호스팅 할 수 있다는 장점이 있다. 가령 파이썬을 줄곧 사용해 오다가 파이썬에는 없는 라이브러리가 루비에 있는 경우, C# 프로그래머는 별도의 학습 없이 바로 루비 라이브러리를 이용하는 코드를 호스팅 할 수 있다.
  • COM과 .NET의 상호 운용성 문제에 사용했던 dynamic을 CLR과 DLR 사이의 상호 운용성 문제를 해결하는데도 사용할 수 있다.

파이썬 코드를 C#에서 실행하는 예제

// 1. 파이썬 소스 코드 파일을 C#에서 실행하는 예제
ScriptRuntime runtime = Python.CreateRuntime();
dynamic result = runtime.ExecuteFile("namecard.py");

// 2. 문자열에 담긴 파이썬 코드를 실행하는 예제
// ScriptEngine, ScriptScope, ScriptSource 클래스를 사용한다.
ScriptEngine engine = Python.CreateEngine();
ScriptScope scope = engine.CreateScope();

scope.SetVariable("n", "박수영");
scope.SetVariable("p", "010-1234-5678");

ScriptSource source = engine.CreateScriptSourceFromString(
    @"
    // 이하는 파이썬 코드, 파이썬 코드 전체를 string으로 넘기고 있다.
    class NameCard :
        name = ''
        phone = ''

        def __init__(self, name, phone) :
            self.name = name
            self.phone = phone

        def printNameCard(self) :
            print self.name + ', ' + self.phone

    NameCard(n, p)
");

dynamic result = source.Execute(scope);
result.printNameCard();

Console.WriteLine("{0}, {1}", result.name, result,phone);
  • dynamic 형식은 ScriptRuntime을 이용해서 소스 파일에 담긴 코드를 실행하든, ScriptEngine, ScriptScope, ScriptSource를 이용해서 문자열에 담긴 코드를 그 자리에서 실행하든 C# 코드가 호스팅하고 있는 파이썬 코드 안에서 만들어진 객체를 그대로 받아낸다. 이렇게 받아낸 파이썬 출신의 객체는 C# 코드에서 직접 메소드를 호출할 수도 있고 필드에 접근하는 것도 가능하다.
It's only fair to share...Share on FacebookShare on Google+Tweet about this on TwitterShare on LinkedIn

The author

지성을 추구하는 디자이너/ suyeongpark@abyne.com

댓글 남기기