SimpleIsBest.NET

유경상의 닷넷 블로그

닷넷의 발견 : Dynamic Method 라고 들어 봤나?

by 블로그쥔장 | 작성일자: 2007-05-09 오전 1:47:00
이 글은 오래된 전에 작성된 글입니다. 따라서 최신 버전의 기술에 알맞지 않거나 오류를 유발할 수 있습니다. 저자는 이 글에 대한 질문을 받지 않을 것입니다. 하지만 이 글이 리뉴얼 되면 이 글에 대한 질문을 하거나 토론을 할 수도 있습니다.

아놔... 간만에 포스트를 올립니다... T_T 최근 올린 포스트라고는 마소지에 기고한 글을 HTML로 바꾸어 포스트 한 것이 전부였기에... 뭐 저도 평범한 사람입니다. 가끔은 아니 자주 삶의 고단함과 게으름에 지쳐 술쳐마시고 놀기도 하고 다른 무엇인가에 빠져 살기도 하지요... 혹시나 새로운 글을 기다린 분이 계시다면 죄송합니다...

About Dynamic Method....

닷넷의 발견

닷넷 프레임워크 2.0에서는 다양하고 많은 기능들이 추가되었음은 독자들도 잘 알고 있을 것이다. 이러한 새로운 기능들 중 리플렉션에 대한 기능들도 많이 향상되었고 기능 추가 역시 상당부분 이루어졌다. 성능적인 향상을 위해 리플렉션 내부적인 옵티마이징을 비롯하여 새로이 추가된 Generics 지원을 위한 속성들 등등 여기서 모두 나열하면 필자만 피곤해 지는 관계로 대충 넘어가도록 하겠다. (사실 잘 모른다는 거......)

이번 포스트에서는 리플렉션을 이용한 메쏘드 호출이 갖는 단점을 어느 정도 커버해 주는 Dynamic Method에 대해 썰을 풀어 볼까 한다.

What's Dynamic Method ?

동적 메쏘드 정도로 해석할 수 있는 Dynamic Method는 동적으로 코드를 생성할 수 있는 방법 중 하나이다. 먼저 '동적'(Dynamic)이란 말을 잘 음미해 보자. 동적이란 말은 컴파일 타임이 아닌 런타임에 무엇인가를 한다는 말로 사용하곤 한다. 그렇담 "동적 메쏘드"란 얘기는 런타임에 메쏘드의 코드를 생성하고 이를 호출할 수 있다는 말이 되겠다. 물론 닷넷 프레임워크 2.0 이전의 과거에도 동적으로 메모리 상에 어셈블리를 생성하고 수행할 수 있는 방법이 있긴 있었다. 하지만 동적 메쏘드는 동적 어셈블리에 비해 보다 적은 오버헤드만을 가지며, 어셈블리가 일단 로드 되면 어플리케이션 도메인(AppDomain)이 종료될 때까지 메모리에서 해제되지 않는다는 단점을 동적 메쏘드는 갖지 않는다. 다르게 말하면 필요하면 동적 메쏘드에 의해 점유되는 메모리가 해제될 수 있다는 말도 되겠다.

동적 메쏘드를 응용 할 수 있는 분야는 생각보다 다양하다. 첫 번째로 생각해 볼 수 있는 것은 리플렉션의 InvokeMember 혹은 Invoke 메쏘드를 통해 런타임에 바인딩 하는 것 처럼 동적 메쏘드를 통해 메쏘드 호출을 수행할 수 있다. 이렇게 동적 바인딩은 컴파일 타임에 어떤 메쏘드를 호출할 수 있는지 알 수 없는 경우 자주 사용되곤 한다. 예를 들어 호출할 메쏘드의 이름을 사용자로부터 입력을 받는 경우가 되겠다.

요렇게만 말하면 이해를 못하는 독자들이 많을 것 같아서 전형적인 예를 들어 보겠다. ASP.NET 웹 서비스(ASMX)를 만들고 작성한 .asmx 파일을 브라우저로 브라우징 해 보면 웹 서비스에 포함된 웹 메쏘드들이 나열된다. 그리고 이 웹 메쏘드를 클릭하면 테스트를 위한 호출을 수행할 수 있게 된다. 만약 독자들이 이러한 웹 페이지를 만든다고 가정해 보면 어떤 방식으로 웹 페이지를 만들겠는가? 페이지는 어떤 메쏘드를 어떤 매개변수로 호출해야 하는지 전혀 알 수 없는 상황이기 때문에, 리플렉션을 통해 주어진 웹 서비스의 클래스로부터 메쏘드 이름, 매개변수를 알아내고 이 리플렉션 정보를 이용하여 동적으로 메쏘드를 호출해야 할 것이다. 이 때 리플렉션의 InvokeMember 혹은 Invoke 메쏘드를 사용해야만 한다.

리플렉션의 Invoke 씨리즈 메쏘드들은 적절한 CAS(Code Access Security) 권한만 있다면 private 멤버까지도 호출할 수 있는 능력을 가지고 있지만, 일반 메쏘드 호출에 비해 매우 느리다는 단점을 가지고 있다. 어떤 클래스의 메쏘드를 그냥 호출하는 것과 리플렉션의 Invoke 씨리즈를 통해 호출하는 것은 최대 1,000배 까지도 성능적인 차이를 나타낼 수 있다. (메쏘드의 내용이 어떠냐에 따라 성능 비교는 크게 달라진다. 메쏘드 내용이 오랜 시간을 소요한다면 리플렉션에 의한 오버헤드는 전체에서 극히 일부분이 될 수 있지만 메쏘드의 내용이 간단하다면 리플렉션의 오버헤드는 크게 작용될 수도 있음에 유의하자.)

동적 메쏘드는 리플렉션의 Invoke 씨리즈에 비해 훨씬 작은 호출 오버헤드만을 가진다. 그도 그럴 것이 Invoke 씨리즈 메쏘드들은 호출을 할 때마다 해당 타입에 메쏘드가 있는지 확인해야 하고 매개변수가 맞는지도 확인을 떠야 한다. 그리고 메쏘드에서 반환 값도 잘 추출해 내야지... 예외 발생되면 그에 따라 처리도 따로 해줘야지... 신경 써야할 일이 조낸 많기도 하다. 반면 동적 메쏘드는 타입과 메쏘드가 존재하는지에 대한 검사나 매개변수의 검사를 필요로 하지 않기 때문에 오버헤드를 크게 줄일 수 있다. 왜 동적 메쏘드가 그러한 검사가 필요하지 않는지는 이제 구체적인 예를 보면서 살펴보도록 하자.

Dynamic Invocation Using Reflection

동적 메쏘드에 대해 설명하기 전에 리플렉션을 사용하여 메쏘드 호출을 하는 예제부터 살펴 보도록 하자. 다음 코드는 리플렉션을 이용하여 String 클래스의 internal 멤버인 FillStringChecked 정적(static) 메쏘드를 호출하는 것을 보여준다. FillStringChecked 메쏘드는 주어진 문자열의 내용을 바꾸는 메쏘드로써 닷넷 프레임워크 내부에서만 사용된다. (닷넷 프레임워크 내부에서는 문자열 객체가 immutable 이란 말은 구라가 되겠다. 조낸 쉽게 바꿀 수 있다...)

Type stringType = typeof(string);

MethodInfo mi = stringType.GetMethod("FillStringChecked", BindingFlags.NonPublic | BindingFlags.Static);

string s = "xxx: The Original String";

mi.Invoke(null, new object[] { s, 0, "yyy: The Changed " });

Console.WriteLine(s);

위 코드를 수행하면 문자열 s 의 내용이 바뀌게 된다. 어찌 되었건 리플렉션을 통해 메쏘드에 대한 정보를 MethodInfo 클래스에 담아 올 수 있다. 그리고 MethodInfo 클래스의 Invoke 메쏘드를 통해 FillStringChecked 를 호출하는 것이다. 참고로 FillStringChecked 메쏘드는 3개의 매개변수를 취하며 첫 번째 매개변수는 바꾸고자 하는 문자열 객체를, 두 번째 매개변수는 문자열 내에서 바꿀 위치 인덱스를, 마지막으로 세 번째 메쏘드는 바꾸고자 하는 새로운 문자열이 되겠다. 따라서 위 코드의 결과는 "yyy: The Changed  String" 가 된다. FillStringChecked 메쏘드가 문자열을 통째로 바꾸는 것이 아니라 기존 문자열에 문자들을 복사해 넣는 것이므로 뒤 꽁무니에 String 이란 문자열이 남아 있음에 유의하자.

Using Dynamic Method

동적 메쏘드를 이용하여 위에서 보인 코드와 동등한 코드를 작성해 보도록 하자. 이 예제를 통해 어떻게 동적 메쏘드를 사용하는지 알 수 있을 것이다. 백문이 불여일견이라 했다. 코드부터 까보자.

    1 delegate void FillStringDelegate(string dest, int destPos, string src);

    2 

    3 class Program

    4 {

    5     static void Main(string[] args)

    6     {

    7         Type stringType = typeof(string);

    8         MethodInfo mi = stringType.GetMethod("FillStringChecked", BindingFlags.NonPublic | BindingFlags.Static);

    9         DynamicMethod dm = new DynamicMethod(

   10             "FillString",

   11             typeof(void),

   12             new Type[] { typeof(string), typeof(int), typeof(string) },

   13             typeof(Program).Module,

   14             true);

   15         ILGenerator iLGenerator = dm.GetILGenerator();

   16         iLGenerator.Emit(OpCodes.Ldarg_0);

   17         iLGenerator.Emit(OpCodes.Ldarg_1);

   18         iLGenerator.Emit(OpCodes.Ldarg_2);

   19         iLGenerator.Emit(OpCodes.Call, mi);

   20         iLGenerator.Emit(OpCodes.Ret);

   21 

   22         string s = "xxx: The Original String";

   23         FillStringDelegate FillString = (FillStringDelegate)dm.CreateDelegate(typeof(FillStringDelegate));

   24         FillString(s, 0, "vvv: Is Changed ?");

   25         Console.WriteLine(s);

   26     }

   27 }

먼저 리플렉션을 통해 String 클래스의 정적 메쏘드인 FillStringChecked 메쏘드의 MethodInfo 객체를 알아내는 것은 동일하다(라인 7~8). 이제 동적 메쏘드를 생성하기 위해 System.Reflection.Emit 네임스페이스의 DynamicMethod 클래스의 인스턴스를 생성한다. 이 클래스의 생성자의 상세한 내용은 MSDN을 디비보기 바란다. 이 예제에서 사용된 생성자만을 설명하자면, 첫 번째 매개변수는 동적 메쏘드의 이름으로 사용된다. 두 번째 매개변수는 동적 메쏘드의 반환형(return type)을 나타내고, 세 번째 매개변수는 Type에 대한 배열로서 동적 메쏘드의 매개변수들의 타입이 되겠다. 호출 하고자하는 String.FillStringChecked 메쏘드는 세 개의 매개변수를 가지며 각각의 타입이 문자열, 정수형, 그리고 문자열 이므로 라인 12와 같은 매개변수를 생성했다. 네 번째 매개변수는 이 동적 메쏘드를 어떤 모듈의 일부로서 간주할 것인가를 나타낸다. 이렇게 모듈에 연결된 동적 메쏘드는 해당 모듈에 선언된 public 멤버들과 internal 멤버들을 호출할 수 있게 된다. 즉, 특정 모듈에 연결된 메쏘드는 해당 모듈에 선언된 메쏘드와 동등한 자격을 갖게 된다는 말이 되겠다. 생성자의 마지막 매개변수는 JIT 컴파일러의 가시성(visibility) 검사를 스킵 할 것인가를 나타낸다. 이 매개변수가 true 이면 JIT는 가시성 검사를 수행하지 않으므로 클래스의 private 멤버나 protected 멤버를 호출하는 코드를 동적 메쏘드 내에 포함시킬 수 있게 된다.

이런 맥락에서 라인 9~14까지의 코드는 String 클래스의 internal 멤버인 FillStringChecked 메쏘드를 호출하기 위해 다음 코드와 비스므레한 동적 메쏘드 선언을 수행한 것이 되겠다.

static void FillString(string arg1, int arg2, string arg3)

{

    // 메쏘드의 body는 아직 정의되지 않음

}

이제 동적 메쏘드의 본문(body)을 '작성' 해야 할 차례이다. C# 코드를 명시할 수 있었으면 얼마나 좋으련만 현실은 그렇지 않다. IL 코드를 생성해야만 한다. 이를 위해 DyanmicMehtod 클래스의 GetILGenerator() 메쏘드를 호출하여 ILGenerator 객체를 얻어 내고 이 객체의 Emit() 메쏘드를 반복적으로 호출하여 메쏘드 본문을 말 그대로 생성해 내야 한다. 이 과정을 라인 15~20까지에서 보여주고 있다. MSIL 코드를 모른다면 어쩔 수 없다. 대략 DynamicMethod 클래스와 Emit 메쏘드 호출을 통해 생성된 동적 메쏘드 코드를 C#으로 표현해 보자면 다음 정도가 될 것이다.

static void FillString(string arg1, int arg2, string arg3)

{

    String.FillStringChecked(arg1, arg2, arg3);

}

비록 FillStringChecked 메쏘드가 internal 멤버이지만 가시성(visibility) 검사를 수행하지 않도록 동적 메쏘드를 생성했으므로 호출이 가능한 것이다. 그리고 호출할 메쏘드의 정보는 리플렉션을 통해 구해 놓은 MethodInfo 객체가 사용되었음(라인 19)에도 유념하도록 하자.

이제 동적 메쏘드가 정의되었으므로 이를 호출하기만 하면 된다. 하지만 동적 메쏘드는 런타임에 생성된 메쏘드이므로 C# 코드 상에서 이를 정적으로 참조할 방법이 없다. 따라서 메쏘드에 대한 포인터 정도가 되는 delegate를 사용하면 된다. DynamicMethod 클래스의 CreateDelegate 메쏘드는 정확하게 바로 이런 용도로 사용된다. CreateDelegate 메쏘드를 호출하여 생성된 동적 메쏘드에 대한 delegate를 구할 수 있고 이 delegate를 이용하여 메쏘드 호출이 가능한 것이다. 라인 23-24 는 이러한 코드를 보여주고 있으며 필요한 delegate의 선언 역시 라인 1에서 찾을 수 있을 것이다.

Usage of Dynamic Method

동적 메쏘드의 사용법은 대충 알겠지만 이것이 정말로 동적 호출에 사용될 수 있을지는 잘 이해가 안 될 것이다. 위 코드에서 메쏘드의 정보를 구하는 코드(라인 8)가 특정 타입의 특정 메쏘드가 아닌 사용자가 입력하는 클래스의 메쏘드라고 가정을 해보자. 이 경우 프로그램은 사용자가 어떤 메쏘드를 입력할 것인가 알 수 없기 때문에 정적인 코드를 작성할 수 없다. 대신 동적 메쏘드를 생성하는 코드만을 작성해 놓고 이 코드가 사용자가 입력한 메쏘드의 MethodInfo로 부터 호출하는 동적 메쏘드를 작성할 수 있을 것이다.

동적 메쏘드는 동적 호출 뿐만 아니라 사용자의 입력 조건에 따라 메쏘드의 본문이 바뀌는 코드를 런타임에 '생성'하는 용도로 사용될 수 있다. 실제로 MSDN에서 동적 메쏘드를 사용할 수 있는 다양한 시나리오를 제시하고 있다(Reflection Emit Dynamic Method Scenarios 문서 참조). 하지만 동적 메쏘드를 독자 여러분이 사용할 기회는 많지 않으리라고 본다. 필자 역시 실무 프로젝트에서 닷넷 프레임워크 클래스의 private 멤버를 호출하는 용도로 두 번밖에 사용해 본적이 없다.

동적 메쏘드가 많이 사용되기 어려운 또 다른 이유는 MSIL 코드를 '생성' 해야 한다는 점이다. 그렇다. MSIL 수준으로 메쏘드의 본문을 작성하기란 쉽지 않다. 아니 조낸 어렵다. 하지만 MSIL을 이용하여 메쏘드 본문을 자유로이 생성할 수 있는 능력이 있는 독자라면 동적 메쏘드를 이용하여 다양한 문제 해결에 응용할 수 있을 것이다. 시간이 뎀비는 독자라면 MSIL 도 별도로 공부를 해보는 것이 좋을 것이다.

뭐네 뭐네 해도 리플렉션의 Invoke 씨리즈를 이용하는 것보다는 동적 메쏘드가 수십 배 빠르므로 성능적인 고려를 해야 하는 상황이라면 동적 메쏘드를 사용하는 것이 보다 나은 선택이 될 수 있다는 것 정도는 알아 두도록 하자.

Epilog

조낸 어려운 토픽을 쓴 감이 없지 않다. 잘 이해가 안 갈지도 모르겠지만 언젠가 이 글의 내용에 무릎을 탁 칠 날이 온다면 스스로의 내공이 상당히 향상되었음을 자부해도 된다. 아놔... 간만에 쓴 포스트가 영... T_T



Comments (read-only)
#re: 닷넷의 발견 : Dynamic Method 라고 들어 봤나? / 정성태 / 2007-05-09 오전 9:06:00
위의 토픽을 읽으신 분들은 아래의 토픽도 같이 읽어보시면 도움이 되시겠지요. ^^

Reflection - Dodge Common Performance Pitfalls to Craft Speedy Applications
; http://msdn.microsoft.com/msdnmag/issues/05/07/Reflection/

Reflection Only Assembly Loading
; http://blogs.msdn.com/junfeng/archive/2004/08/24/219691.aspx

어쨌든... .NET 1.0 시절 보다는 2.0 에서 많은 개선이 이뤄진 것 같습니다. ^^ LINQ 가 나오는 3.5 까지도 2.0 기반의 런타임만으로 구현하는 거 보면 대단하다는.

... 항상 유수석님의 토픽을 기다리고 있답니당. ^^ 써주시기만 하면 바로 바로 읽어버리니, 많이 많이 좀 풀어주십시오. ^^
#re: 닷넷의 발견 : Dynamic Method 라고 들어 봤나? / 블로그쥔장 / 2007-05-09 오후 1:45:00
제가 찾을려다가 귀차니즘에 안 찾은 토픽을 정성태씨가 잘 소개해 주시는 군요.
Dyanmic Method와 Reflection의 성능 비교는 MSDN 매거진에 소개된 자료에
잘 나와 있습니다.
다른 분들은 적어도 MSDN 매거진의 토픽을 꼭 읽어 보시기 바랍니다.
#re: 닷넷의 발견 : Dynamic Method 라고 들어 봤나? / 위시 / 2007-05-09 오후 4:01:00
으ㅠㅠㅠㅠ 어렵습니다.
언제 이해가 될련지..털썩
#re: 닷넷의 발견 : Dynamic Method 라고 들어 봤나? / 블로그쥔장 / 2007-05-09 오후 5:18:00
예... 이번 토픽은 좀 어렵습니다... T_T
제 글은 왜들 다 이렇게 숏나게 어려운걸까요?
제가 머리에 든게 많아서... (퍼버벅... 맞아도 싸죠? 거듭 사과 드립니당...)
#MSIL로 코드를 작성하는 방법을 찼던 중에 이런 글을~ 감사. / 아름드리 / 2007-05-10 오후 5:07:00
iLGenerator.Emit() 메서드를 통해
Ldarg 호출, method Call, Ref 있는데
이 방법을 사용하면 MSIL 코드 그대로 C#에서 재현이 가능한가요?

먼저 해보고 질문 드려야 하는데 궁금해서 ^^
#re: 닷넷의 발견 : Dynamic Method 라고 들어 봤나? / 키온 / 2007-05-12 오후 1:14:00
옛날 아주 옛날에... 복잡한 시스템의 경우 너무 다수의 클래스 object가 생성되어 그것 또한 문제를 일으키드라고...그래서 클래스의 숫자를 줄여 보고자 AI의 성격을 지닌 클래스를 만들어 볼라고 했는데 문제는 자신 스스로 어떤 리쿼스트를 받으면 메서드를 동적으로 생성하여 반응하는 것이 었거덩... (시간이 X나게 많았을 때 야그,,,) 결론은 잘 안되드만,,, 암튼 재미나고 새로운 글,,,좋았으!!!!
#re: 닷넷의 발견 : Dynamic Method 라고 들어 봤나? / 즈믄 / 2007-05-13 오후 9:02:00
와~~ 이런게 있는지 몰랐습니다.. 정말 신기해요~~
역시나 글 솜씨가 탁월하신 덕에.. 대략 어떤내용인지 잘 이해하고 갑니다...
강좌 감사합니다..

늘 쥔장님 강좌를 기다리거든요.. ㅎㅎㅎ
#re: 닷넷의 발견 : Dynamic Method 라고 들어 봤나? / 눈꽃천사 / 2007-07-18 오전 7:25:00
네 들어봤어요 -_-+
좋은 글 잘 보았습니다.
앞으로도 기대하겠습니다.
건강하세요.
#re: 닷넷의 발견 : Dynamic Method 라고 들어 봤나? / 이것이 / 2007-10-02 오전 2:27:00
Type stringType = typeof(string);
MethodInfo mi = stringType.GetMethod("FillStringChecked", BindingFlags.NonPublic | BindingFlags.Static);
string s = "xxx: The Original String";
Console.WriteLine("{0}", s.GetHashCode().ToString());

mi.Invoke(null, new object[] { s, 0, "yyy: The Changed " });
Console.WriteLine("{0}", s.GetHashCode().ToString());
Console.WriteLine(s);

여기서 Invoke 전과 후에 HashCode() 값이 다른 이유가 무엇인가요?
말씀 하신 내용으로는 같은 값이 나올것이라고 생각 했는데요...
#re: 닷넷의 발견 : Dynamic Method 라고 들어 봤나? / 블로그쥔장 / 2007-10-02 오전 11:36:00
닷넷에서 각 타입마다 해시 코드를 생성하는 방법은 다릅니다.
문자열의 경우, 문자열 내용에 따라서 생성되는 해시 코드가 다르게 나타납니다.
서로 다른 문자열 객체라 할지라도 내용이 같으면 해시 코드가 같다는 말이지요.
이는 같은 문자열 객체일지라도 문자열이 바뀌면 해시 코드도 바뀐다는 말과도 같습니다.
문자열은 immutable 로 간주되기 때문에 대부분 문제가 없겠지만 FillStringChecked 를 호출하여
immutable 인 문자열을 강제로 바꾸는 경우, 해시 코드도 달라지게 됩니다.

도움이 되셨기를...
#re: 닷넷의 발견 : Dynamic Method 라고 들어 봤나? / 이것이 / 2007-10-03 오전 2:04:00
아..그렇구나..감사합니다.
GetHashCode() 를 object.ReferenceEquals() 과 비슷한 것으로 생각 했습니다.
무식한 질문을 해서...시간 낭비를 하게 해서 죄송합니다. 이곳에 왜 질문/답변 게시판이 없나 다시 한번 상기 하겠습니다.

감사합니다.
#re: 닷넷의 발견 : Dynamic Method 라고 들어 봤나? / 지나가는 이 / 2007-10-29 오전 2:38:00
쥔장님은 항상 설명하실때 IL얘기 하시기 즐기시는데 본래 어셈블러에 흥미를 가지고 있은 겁니까?
닷넷이 있기 이전에도요? 어떠한 기회가 있었는지 얘기 해주시면 감사하겠습니다.
#re: 닷넷의 발견 : Dynamic Method 라고 들어 봤나? / 블로그쥔장 / 2007-10-31 오후 3:12:00
저는 중학교 2학년 때 Z80 이라 불리는 8비트 CPU 부터 프로그램이란 걸 작성했습니다.
이 컴퓨터는 BASIC을 사용했기 때문에 빠른 처리가 필요한 경우 어셈블리 언어를 혼용하곤
했지요. 그래서 저는 중2 때부터 Z80 어셈블리를 했었고
그 이후에는 8086, 80386 어셈블리를 다루었었습니다.
8086 은 MS-DOS 시절에 시스템 프로그래밍을 위해서 어쩔 수 없이 사용해야만 했고
80386 어셈블리는 제 전공이 운영체제인 지라 커널 코드를 작성하기 위해서
능숙해져야 했지요.

닷넷의 MSIL은 일반 8086, 80386 어셈블리에 비하면 매우 쉬우며 직관적입니다.
심지어 8비트 Z80 어셈블리보다 쉽지요.
그리고 MSIL을 잘 알면 닷넷 내부의 작동 방식에 대해서도 아주 잘 알 수 있게 됩니다.
시간이 나신다면 공부해 보는 것도 좋습니다.
주위에 한 닷넷 한다는 사람들은 모두 MSIL 코드를 읽을 줄 알고
심지어 MSIL로 닷넷 코드를 작성하는 인간들도 있습죠.
(저도 해봤는데 재밌드라구요... ^^)
#re: 닷넷의 발견 : Dynamic Method 라고 들어 봤나? / 미지 / 2007-11-01 오후 7:32:00
대학때 일입니다.
그때는 32비트 컴퓨터가 나오고 Windows98이 어떻다 떠들때 입니다.
제가 z80 CPU와 주변 처리소자(8251, 8269...)에 대한 책을 보니 한 선배님이 핀잔을 주더군요
그거 이젠 낡은것 아니냐고 말입니다.
그래도 마지막까지 보았습니다. 그때 재미있었고 컴퓨터에 흥미를 가지였습니다.

후에 와서 보니 그때 그 선배가 한 말이 전혀 맞지 않음을 알았습니다.
무엇이나 기초를 알아야 한다고 생각합니다. 기초가 든든하면 무서운것이 없다는 얘깁니다.
쥔장님 글들을 볼때 가장 마음에 드는 부분이 그것입니다.
어셈블리 준위에 이르기까지 원리를 설명하는것!

저도 실행 이미지 파일들의 어셈블리는 많이 보았는데 닷넷은 기능의 풍부성에 현혹이 되서
어셈블리 들여다보는것 게을리 했는데 이제부터는 볼랍니다.

좋은 답변 주셔 감사 합니다.
#re: 닷넷의 발견 : Dynamic Method 라고 들어 봤나? / 미지 / 2007-11-04 오전 10:25:00
8269->8259
인터럽트 컨트롤러를 의미 합니다.