메뉴 바로가기 검색 및 카테고리 바로가기 본문 바로가기

한빛출판네트워크

컬럼/인터뷰

C# 심층 분석: 마이크로소프트의 기술부장 앤더스 헤즐스버그와의 인터뷰

한빛미디어

|

2001-07-27

|

by HANBIT

14,460

오스본:언론에서 C#에 대해 보도한 기사를 읽었는데, 많은 기사에서 C#은 마이크로소프트가 자바를 대체하기 위해 내놓은 복제품일 수도 있다고 하였습니다. 이 언어에 대해 어떻게 생각하는지 간략히 말씀해 주십시오.
C# 에센스
헤즐스버그: 우선 C#은 자바의 복제품이 아닙니다. C#을 디자인할 때 우리는 많은 언어를 살펴보았습니다. C++, 자바는 물론이고 모듈라 2(Modula 2), C, 스몰토크(Smalltalk) 등을 보았지요. 객체지향(object-orientation), 객체단순화(object-simplification) 등 우리가 관심을 가졌던 주요 개념이 비슷한 언어는 많았습니다. C#과 이러한 언어들(특히 자바)의 중요한 차이점은, 디자인 측면에서 C++에 가깝게 하려고 했다는 점입니다. C#에 있는 연산자, 키워드, 선언 중에는 C++에서 디자인을 직접 따온 것이 많습니다. C#에는 자바에는 없지만 다른 언어에는 있는 특징들도 많이 있습니다. 예를 들어서 자바에는 열거형(enum)이 없어야 할 이유는 없습니다. C++에서는 열거형이 의미 있는 개념입니다. C#에서는 열거형을 보존하였으며, 타입에 상관없이 사용할 수 있도록 만들었습니다. C#에서 열거형은 단순한 정수가 아닙니다. 닷넷(.NET) 기반의 클래스 라이브러리에 있는 System.Enum에서 나온 값 타입으로 형이 강하게 정해져 있습니다. "foo"라는 타입의 열거형은 캐스트 없이 "bar"라는 타입의 열거형과 바꾸어 사용할 수 없습니다. 이것은 중요한 차이입니다. 우리는 C#에서 연산자 오버로딩과 형 변환도 보존했습니다. 네임 스페이스에 대한 전체적인 구조는 C++에 더 가깝습니다. 하지만 언어를 바라보는 전통적 관점을 넘어서, 디자인의 주요 목적 중 하나는 컴포넌트를 작성할 때에 언어 자체에서 필요한 개념을 모두 추가하기 위해, C#을 "컴포넌트지향"적으로 만드는 것입니다. 특성(property), 메소드(method), 이벤트, 속성(attribute), 문서화(documentation) 등이 모두 언어 구조에서 중요합니다. 우리는 속성(attribute)에 새롭고 혁신적인 것들을 추가하였습니다. 다른 프로그래밍 언어에서는 이렇게 하지 않았습니다. 게다가 C#은 컴파일러에서 소스 코드에서 바로 읽을 수 있는 문서화를 생성하는 데에 사용하는 XML 코멘트 태그와 협업하여 사용할 수 있는 최초의 언어입니다. C#에서 중요한 또 한 가지 개념은 "모든 것이 들어있는" 소프트웨어라는 점입니다. C#으로 코드를 작성하면, 한 곳에서 모든 것을 작성할 수 있습니다. 헤더 파일, IDL(Interface Definition Language), GUID나 복잡한 인터페이스가 필요 없습니다. 그리고 이런 식으로 스스로를 묘사하는(self-describing) 코드를 작성할 수 있게 되면, 이것이 스스로를 포함(self-containing)하는 유닛이기 때문에 소프트웨어에 이식할 수 있습니다. ASP 페이지에 슬롯할 수 있으며, 전에는 불가능했던 다양한 환경에 호스트할 수 있습니다.
† 역주 : C# 컴파일러로 컴파일된 코드는 CLR Header와 CLR Data를 갖게 된다. CLR Data는 스스로를 설명하는 Metadata와 IL Code를 갖고 있다.
하지만 다시 주요 컴포넌트 개념으로 돌아가서, 언어가 특성(property)나 이벤트를 지원해야 하는지에 대해서는 논쟁이 있어왔습니다. 물론 우리는 메소드로 이러한 개념을 표현할 수 있습니다. 또한, 프로퍼티를 구현하는 get 블록이나 set 블록 등과 같은 패턴을 정의할 수 있습니다. 인터페이스와 포워드(forward)를 객체에 구현하는 인터페이스와 접속기(adapter)를 가질 수 있습니다. C에서 객체지향 프로그래밍이 가능하듯이, C#에서는 이 모든 것이 가능합니다. 단지 더 어렵고 정리작업(housekeeping)이 더 많으며, 개념을 표현하기 위해 이 모든 것을 해야만 할 뿐입니다. 우리는 컴포넌트를 보다 쉽게 작성할 수 있도록 해 줄 수 있는 언어에 대해 생각할 때라고 생각합니다. 오늘날 개발자들은 소프트웨어 컴포넌트를 작성하고 있습니다. 단일 애플리케이션이나 단일 클래스 라이브러리를 작성하는 것이 아니라, 호스팅 환경이 제공하는 기본 컴포넌트에 기반한 컴포넌트를 작성하고 있습니다. 이러한 컴포넌트들은 어떤 메소드나 프로퍼티를 오버라이드하며, 몇 가지 이벤트를 조작하며, 컴포넌트를 감쌉니다. 이러한 개념을 가지는 것이 중요합니다. 오스본: 당신은 C#이 C/C++에 속하는 언어 중 첫 번째 컴포넌트 지향 언어라고 하였습니다. 헤즐스버그: 네, 이것이 주된 목적입니다. 우리는 어떻게 모든 것이 객체이자 핵심이 되는지 이야기했습니다. 스몰토크나 리스프(Lisp) 등에서도 이러한 일을 전에 했습니다. 하지만 그에 따르는 비용도 만만치 않았지요. C#에는 boxing과 unboxing 등 컴포넌트 개발을 쉽게 해 주는 흥미롭고 혁신적인 내용이 많습니다. boxing을 하면 값 타입이 무엇이든 상관 없이, 객체로 전환될 수 있게 해 주며, unboxing은 객체의 값을 단순한 값 타입으로 변환합니다. 전에는 이런 것이 불가능했다는 것이 아니라, 우리가 언어에 적용한 방법이 혁신적이라는 것입니다. C#과 닷넷 프레임워크를 엔지니어링할 때에 "상아탑"적인 접근을 하지 않으려 노력했습니다. 소프트웨어를 모두 다시 쓸 만한 여력도 없었습니다. 인터넷 시대로 전환하고 있었기 때문에 소프트웨어 산업에서도 여력이 없었지요. 현재 가지고 있는 것에 효과를 더하려면, 상호 운용성을 갖도록 해야 할 것입니다. 우리는 HTTP, HTML, XML, 마이크로소프트의 기술 등가 상호 운용성 있는 솔루션을 만드는 데에 초점을 맞추었습니다. 따라서 새로운 것에 의해 무엇인가가 API 컴포넌트의 힘을 높이지 못해서나, 닷넷 환경에서 지원되지 않는 것 때문에 좌절하는 일은 없을 것입니다. 우리는 언어와 런타임에 COM 상호 운용성을 구축하였습니다. 또한 DllImport 속성을 사용하여 DLL(Dynamically Linked Libraries)을 임포트할 수 있습니다. 불안전(unsafe) 코드라는 개념이 있어서, 인라인 C 코드를 포인터로 작성할 수 있으며, 불안전 캐스트를 할 수 있으며, 메모리를 고정하여 불시에 가비지 컬렉션이 일어나지 않게 할 수도 있습니다. 불안전 코드에 대해서는 많은 논의가 있어 왔고, 사람들은 이것을 마약 취급 합니다. 하지만 이것은 오해입니다. 코드가 "unsafe"라고 표시된다고 해서 관리할 수 없다는 것은 아닙니다. 물론 우리는 불안전한 포인터를 단지 내버려두고 인터넷에서 사람들이 불안전한 코드를 내려받는 데에 노출시켜놓지는 않을 것입니다. 불안전 코드는 보안 시스템에 묶여 있습니다. 유연성이 있기 때문에 관리되는 코드 박스 안에 머물면서 실패하지 않고 작업을 마칠 수 있으며, 다른 언어를 사용하거나 원시 코드를 사용하기 위해 다른 프로그래밍 모델로 바꿀 필요가 없습니다. 그리고 박스 안에 머물기 때문에, 코드가 더 안전해질 수 있습니다. 시스템에서 무슨 일이 진행되는지 이해하기 때문이지요. 불안전한 코드를 작성한다는 것이 관리 공간을 떠난다는 것을 의미하지는 않습니다. 그래서 불안전한 코드는 효율성이 더 높아집니다. 오스본: 관리형 환경(managed environment)에서 불안전한 코드를 다루는 것에 대해 좀더 말씀해 주십시오 헤즐스버그: 네, 스몰토크, 자바, .NET 공통 언어 런타임(CLR: common language runtime)과 같은 관리 실행 환경의 특징 중 하나는 가비지 컬렉션을 제공한다는 것이며, 적어도 구식이 아닌 가비지 컬렉터를 제공하려면 관리되지 않는 전통적인 코드를 다룰 때 보다 실행되는 코드에 대해 좀더 이해하고 있어야 합니다. 제외(exclusion)를 통해 없어진 객체를 찾기 위해서는, 스택을 검토하며, 모든 경로를 추적하고, 어떤 객체가 살아있으며 어떤 객체에 방문하지 않았었는지를 추론할 수 있어야 합니다. 하지만 그렇게 하려면, 실행하고 있는 코드와 더 밀접하게 협력해야 합니다. 코드가 더 서술적으로 되어 있어야 한다는 말이지요. 스택의 레이아웃을 어떻게 잡고 있는지, 로컬 변수가 어디에 있는지 등을 알 수 있어야 합니다. C#에서 불안전한 코드를 작성하고 있을 때, 포인터로 작업하는 것같이 형(type)의 제약을 받는 일을 할 능력이 있어야 합니다. 물론 그 코드는 "unsafe"라고 표시되며, 신뢰성이 없는 환경에서 전혀 실행되지 않습니다. 이것을 실행하려면, 신뢰를 보장 받을 수 있어야 하며, 그렇지 않을 경우 코드가 실행되지 않습니다. 여기서 차이는 관리되는 공간 안에서는 아직 실행이 되고 있다는 데에 있습니다. 작성한 메소드는 설명 테이블이 있어서 어떤 객체가 살아있는지 알 수 있습니다. 따라서 이 코드로 작업하려 할 때, 넓은 범위를 살펴볼 필요가 없습니다. 설명적이지 않으며, 관리되지 않는 코드(예를 들면 자바 네이티브 인터페이스(Java Native Interface)를 사용할 때)를 사용할 때에는, 워터마크를 설정하거나 스택에 울타리를 쳐 둘 수도 있습니다. 이 때에는 모든 인자를 박스 밖에서 다시 정리해야 합니다. GC(Garbage Collector)가 다른 스레드에서 실행되고 있기 때문에 객체를 사용할 때에는 어느 객체를 건드렸는지 항상 주의해야 합니다. 어떤 메소드를 사용하여 객체를 잠가서 고정시켜놓지 않는다면 객체를 옮길지도 모릅니다. 그렇게 하는 것을 잊었다면, 운이 없다고 말할 수 밖에요. 우리는 다른 식으로 접근했습니다. 우리는 "언어 속으로 이것을 모두 통합합시다. 고정 선언처럼, 선언을 공급하여, 객체를 GC와 협동할 수 있도록 고정하고 통합할 수 있게 합시다."라고 말했습니다. 우리는 이런 식으로 코드를 던져버리는 대신 존재하는 코드를 가져올 수 있는 가장 좋은 방법을 공급하였습니다. 우리는 디자인 형식을 달리 했습니다. 오스본: 그러면 불안전 코드로 작업하는 메모리는 사실 가비지 컬렉터의 감시를 받고 있는 것입니까? 헤즐스버그: 네, 그렇습니다. 하지만 그것이 불안전하다는 것에 주의해야 합니다. 포인터를 얻을 수 있지만 해로운 일을 하게 될 수도 있습니다. 하지만 원시 코드로도 에러를 저지르는 경우는 있습니다. 오스본: C#이 어디까지 새롭고, 공통 런타임과 비슷한 부분은 어디부터인지 혼란의 여지가 있을 것 같군요. C# 자체에서 혁신은 무엇이며, CRL에서 따온 것은 무엇입니까? 헤즐스버그: 아, 제 생각엔 사람들이 자바에 대해 말할 때, 어떤 것이 언어이고 어떤 것이 런타임인지 모르기 때문에 이러한 혼란이 생기는 것 같습니다. 사람들이 자바에 대해 이야기할 때 이런 혼동이 생기는 경우가 있습니다. 어떤 것이 언어이고 어떤 것이 런타임인지, 어떤 의미로 자바라는 말을 사용하는지, 언어인지, 구문인지, 플랫폼인지 등의 문제 말입니다. 사람들은 이러한 차이점들을 하나로 뭉뚱그립니다. 우리는 다중언어적인 플랫폼을 원합니다. 우리는 다중 프로그래밍 언어를 구현하는 플랫폼을 구축할 것이며 공통적인 API(Application Programming Interfaces)의 집합을 공유하도록 할 것입니다. 코볼, 베이직, C++, C# 등 사람들이 선호하는 프로그래밍 언어는 각기 다를 것입니다. 하지만 지금까지 했던 것을 모두 잊으라고 말하려는 것은 아닙니다. 우리는 이제 이 언어만 있으면 더 이상의 혁신은 있을 수 없다고 말하지도 않을 것입니다. 우리는 소프트웨어 산업의 진보는 유연성에서 온다고 주장합니다. 자바는 어떻게 생겨났습니까? 자바도 그 이전에 프로그래밍 언어가 있었기 때문에 생겼으며, 자바 이후에도 프로그래밍언어가 생길 것입니다. 우리는 모든 사람이 각자가 선호하는 언어를 사용할 수 있는 플랫폼을 만들고 싶습니다. 우리는 혁신이 일어날 수 있는 플랫폼을 만들고 싶습니다. 오늘날 코볼 프로그래머를 지원하는 소프트웨어는 누가 만들고 있습니까? 누가 그들이 웹에서 작업할 수 있도록 합니까? 닷넷 플랫폼에서만 ASP 페이지에 후지쯔(Fujitsu)의 코볼을 이식할 수 있습니다. 이것은 정말 혁명적인 일입니다. 오스본: 닷넷 플랫폼에서 다양한 언어를 사용할 수 있다고 했는데, 그렇다면 왜 비주얼 베이직, C++, 코볼이 아니라 C#을 사용해야 하는 것입니까? 왜 C#이 꼭 필요한 것입니까? 헤즐스버그: 우선 C#을 가지고 작업을 하면, 백지 상태로 시작하는 것과 같습니다. 우리는 역 호환성 요구가 전혀 없기 때문에 구현의 관점에서 뿐 아니라 사용의 관점에서도 모든 것이 더 간단해 집니다. 예를 들면 C#에서 한 종류의 클래스만 있으며, 항상 가비지 컬렉트가 됩니다. 반면 Managed C++은 가비지 컬렉션이 되지 않는 프로그래밍이기 때문에, 클래스가 두 종류 있습니다. 그래서 C#을 사용할 때에는 이해해야 하는 개념이 더 적습니다. 언어는 재미있습니다. 사람들은 취향에 따라 언어를 선택합니다. 언어는 종교적인 것이며, 프로그래머들에게는 삶의 방식을 선택하는 것이기도 합니다. 즉, "하나의 언어만 사용할 수 있는 플랫폼이 있다"고 말할 수 없습니다. 어떤 플랫폼에서 언어 하나만 사용하고 있더라도 그 언어의 구문이 마음에 안들 수도 있습니다. 그리고 우리는 C++이 너무 복잡하다고 생각하는 C++ 프로그래머나 번역 과정에서 사라진 C나 C++의 특성을 살리고 싶어하는 자바 프로그래머에게 대안으로서 C#을 제공할 것입니다. 우리는 C++을 단순화할 수 있는 방법을 모색하였으며, 상호 운용성이 크고 컴포넌트 개념을 모두 주는 등 다중 언어 플랫폼을 만들 수 있는 방법을 모색했습니다. 굿휴: 개발자 트랙킹 스터디에서 발견한 재미있는 사실 중 하나는 60 퍼센트 이상의 전문 개발자 시장에서 애플리케이션을 만들 때에 두 개 이상의 언어를 사용한다는 것입니다. 그리고 우리가 프로그래머가 어떤 툴을 사용하는지를 생각할 때, 이 결과가 말해주는 바는 앞으로도 새로운 프로그램 언어는 계속 생길 것이며, 사용자가 없는 언어는 없을 것이라는 점입니다. 앤더스(Anders)가 전에 말했듯이, 사람들은 하고 있는 일이나 감정에 따라 특정 신택스를 원합니다. 이것은 개인적인 취향입니다. 그리고 이것이 닷넷 플랫폼 전체에서 연관되어 있는 것입니다. 개발자가 구현할 언어에 있어서 선택의 폭을 넓혀 주자는 것이지요. 이것은 훌륭한 일이라고 생각합니다. 비주얼 베이직, 닷넷, C#으로 기본적으로 거의 같은 일을 할 수 있습니다. 하지만 모두 장단점이 있는데, 비주얼 베이직은 개발자가 접근하기 더 쉽고, C#은 VB보다 강력한 언어입니다. 오스본: C#을 사용하면 적은 선언으로 더 많은 것을 얻을 수 있다는 것입니까? 헤즐스버그: 불안전 코드에 대한 조항을 통해 더 많은 힘을 얻을 수 있다는 것이지요. 오스본: 그렇다면 VB로는 불안전 코드를 작성할 수 없나요? 헤즐스버그: 네, 없습니다. 굿휴: 하지만 기본적으로 두 언어는 같은 일을 처리할 수 있습니다. 그것이 비주얼 스튜디오 6로부터의 중대한 변화입니다. VB 프로그래머가 비주얼 스튜디오 6.0을 사용하여 멀티스레드 MTS 객체를 구축하고 싶어도 그렇게 할 수 없습니다. 이 때에는 C++을 사용해야 합니다. 하지만 닷넷 프레임워크에서는 둘 다 사용할 수 있습니다. 헤즐스버그: 그것은 제가 일반 세션 연설에서 말했던 부분입니다. 닷넷 프레임워크는 프로그래밍 모델을 통합하였습니다. 언어와 프레임워크의 진보에 있어서 우리는 항상 특정 API와 프로그래밍 언어를 특정 API와 특정 프로그래밍 형식과 통합하는 것으로 끝나는 것 같았습니다. VB는 빠른 애플리케이션 개발과 형식에 관한 것이었으며, MFC(Microsoft Foundation Classes)는 서브 클래싱(sub-classing)에 관한 것이었으며, ASP는 웹 페이지에 무엇을 등록하는 데에 관련되어 있습니다. 각 경우에 어떤 프로그래밍 모델을 선택하느냐에 따라 프로그래밍 언어와 사용 가능한 API의 종류가 결정되었습니다. 따라서 일을 할 때에는 새로운 언어를 익혀야 한다는 부담이 생길 때도 있고 프레임워크를 바꿀 때 마다 API를 바꿔야 한다는 난점이 있었습니다. 우리는 비주얼 디자인 툴을 지원하는 오직 하나의 API를 공급합니다. 그리고 닷넷을 사용하면 자신에게 맞는 언어를 무엇이든 선택할 수 있는 유연성이 있습니다. 오스본: VB스크립트와 J스크립트 등과 같은 스크립팅 언어는 닷넷에서 어떻게 사용합니까? 헤즐스버그: 닷넷 프레임워크가 좋은 점 중 하나는 스크립팅 언어가 컴파일될 수 있다는 것입니다. ASP+를 보십시오. 이제 페이지에 실제로 컴파일된 코드를 실행하기만 하면 됩니다. ASP+ 개발자는 이제 VB스크립트가 아니라 비주얼 베이직 닷넷의 힘을 완전히 이용할 수 있습니다. 그리고 마음만 먹으면 펄, 파이썬 등도 사용할 수 있게 되었습니다. 페트루샤: 서버 쪽 자바스크립트도 컴파일 됩니까? 헤즐스버그: 네, 그렇습니다. 굿휴: 닷넷 프레임워크를 사용하면 진정한 프로그래밍 프레임워크와 같은 기본 클래스 API에 접근할 수 있기 때문에 스크립팅 언어를 완전한 언어로 사용할 수 있습니다. J스크립트 구현을 하는 사람들이 어떤 일을 해냈는지 알아야 합니다. [편집자 주: J스크립트는 마이크로소프트가 구현한 ECMA 262 언어 규약이다. 중요하지 않은 부분에서 예외가 있기는 하지만, J스크립트는 ECMA 표준을 완전히 구현하였다.] 그래서 닷넷 플랫폼은 공통 언어 프레임워크를 제공하는데, 그것은 스크립트 작성자에게 큰 이익이 될 것입니다. 오스본: 우리는 자바, C++, 스크립팅에 대해 살펴보았습니다. 닷넷 IL(IL은 모든 컴파일러가 닷넷 프레임워크에서 실행되기 위해 만들어야 하는 중간 언어(Intermediate Language)이다.)과 자바 가상 머신에서 사용되는 자바 바이트 코드는 사실 별 차이가 없는 데에도 사람들은 PDC에 대해 논쟁합니다. 헤즐스버그: 물론입니다. 무엇보다도 IL은 매우 오래된 개념입니다. USUD 파스칼 p- 머신(개인용 컴퓨터에서 구현한 초기 파스칼)이나 스몰토크에서도 그러한 개념을 볼 수 있습니다. P-코드는 베이직과 비주얼베이직에서 사용합니다. P-코드는 전혀 새로운 개념이 아닙니다. 우리가 IL에 접근한 방식은 IL의 컴파일이나 번역을 원시 코드로 한다는 점에서 재미있습니다. 그래서 C#이나 VB뿐 아니라 Managed C++에서도 IL을 생성할 수 있습니다. 그리고 코드를 설치할 때 그 지점에 컴파일할 수 있는 옵션을 줍니다. JIT 컴파일러가 과부하 없이 실행할 수 있도록 하기 위해서죠. 코드를 역동적으로 실행하고 컴파일할 수 있는 JIT 컴파일 옵션도 있습니다. 물론 IL을 사용하면 다른 CPU 구조로 이동할 수 있고 형 안전성 검증을 소개할 수 있으며, 보안 시스템을 최상위에 둘 수 있는 등 여러 장점이 있습니다. IL 디자인과 자바 바이트 코드 사이의 중요한 차이점은, IL 디자인에는 인터프리터가 없다는 것입니다. 우리의 코드는 항상 있는 그대로 실행될 것입니다. 그래서 IL을 만들 때에도 인터프리터를 사용하지 않습니다. 우리는 다른 타입의 JIT도 있습니다. 콤펙트 프레임워크에서는 매우 간단한 JIT인 EcomoJIT를 사용합니다. 그리고 데스크탑에서는 좀더 독립적인 JIT를 사용하고, C++ 컴파일러와 동일한 후위(back end)를 사용하는 JIT도 있습니다. 하지만 시간이 더 많이 걸리기 때문에 설치할 때에만 사용할 지도 모르겠습니다. 인터프릿(interprete)보다 원시 코드를 선호한다면, IL 디자인도 많이 변화할 것입니다. 포함되는 명령, 정보 타입이나 그것이 전달되는 방식도 바꿔야 합니다. 바뀌기 전, 후의 IL은 서로 많이 다릅니다. 우리가 만든 IL은 형 중립적(type-neutral)입니다. 명령에는 인자의 형을 지시하는 정보가 없습니다. 단지 스택에 나온 것을 보고 추론할 수 있습니다. 이러한 접근 때문에 IL이 좀더 압축될 수 있습니다. JIT 컴파일러에는 어쨌든 그런 정보가 필요하기 때문에, 명령에는 포함할 필요가 없습니다. 그래서 결국 디자인 선택이 좀 다를 것이며, IL을 원시 코드로 만들기 쉬워집니다. 오스본: 당신이 설명하는 접근법과 인터프릿 사이에 어떤 차이점이 있습니까? 헤즐스버그: 번역기의 중심에는 p-코드 스트림에서 바이트를 인출하는 루프가 있습니다. 그것은 "이건 ADD 명령이야. 그래서 여기서 이렇게 되야 하는데, 그렇지 않군."라고 말하는 등의 기능을 하는 큰 스위치 선언 상태가 됩니다. 번역기는 CPU를 모방합니다. 우리는 그것을 뒤집고, 명령을 기계 코드로 전환하는 곳에서 단일 패스(one pass)를 합니다. 항상 단일 패스를 하지요. EconoJIT의 경우 기계 코드는 호출의 목록을 작성하고 명령을 내놓으며 런타임 헬퍼(runtime helper)를 호출한다는 점에서 실제로는 매우 단순합니다. 그 다음에 그것을 목록 대신에 올려둡니다. 물론, 그 코드는 인터프릿되는 코드보다 더 빨리 실행됩니다. 오스본: 그렇다면, 이것에 대해 제게 더 자세히 설명해 주세요. 당신이 코드를 모두 컴파일하고 있습니다. 그리고 컴파일이 끝났을 때, IL에서 기계어로 번역되는 지점이 다양할 지라도, 조각들이 완전히 실행할 준비가 되어 있다는 것인가요? 헤즐스버그: 예, 하지만 메모리의 제약을 받는 작은 장치에서는 실행 후에 코드를 버립니다. 오스본: 다시 언어의 구문 문제로 돌아가겠습니다. C#이 정규 표현식을 내장 지원하는지 궁금합니다. 언어 레퍼런스에서는 그런 지원이 되는지 보지 못했지만, 가능할 지도 모르겠군요. 헤즐스버그: 우선 기본 클래스 라이브러리 안에 정규 표현식 클래스가 있습니다. 우리는 언어에 있는 정규 표현식을 직접적으로 지원하지는 않지만, 유사한 기능이 몇 가지 있습니다. 대단하게 볼 것은 아니지만, 예를 들어서 하나의 역슬래쉬를 지정하기 위해 매번 두 개의 역슬래쉬를 작성하지 않아도 되는 축어적(verbatim) 문자열 리터럴을 사용할 수 있습니다. 이는 정규 표현식을 작성할 때나 인용 내에 인용을 작성할 때 전체적으로 도움이 됩니다. 이것은 사소한 일면일 뿐입니다. 닷넷 프레임워크에는 핵심적인 부분이 있는데, 그것은 바로 모든 프로그래밍 언어에서 공유될 수 있다는 것입니다. 오스본: 우리가 C#과 자바의 이름공간(namespace)을 보는 방식에는 차이점이 있을 것 같습니다. 두 가지가 개념적으로 동일한 것인지, 아니면 다르게 구현되는지 궁금합니다. 헤즐스버그: 개념적으로는 동일하지만, 구현은 상당히 다릅니다. 자바에서는 패키지 네임이 소스 코드 파일의 디렉토리 구조를 지시하기도 하는 물리적인 것입니다. 하지만 C#에서는 물리적 패키지와 로컬 네이밍을 완전히 분리하였습니다. 그래서 이름공간을 뭐라고 부르던 간에 실제로 코드를 물리적으로 패키지화하는 데에는 아무 상관이 없습니다. 그래서 디렉토리를 가질 필요 없이 물리적인 배포 유니트에 여러 가지를 패키지로 묶어 놓을 수 있기 때문에 더 유연합니다. 언어 자체에도 명백한 차이점이 있습니다. 자바에서는 패키징이 물리적인 구조이기도 했고, 자바 소스 파일이 올바른 디렉토리에 있어야 했고, 퍼블릭 타입과 퍼블릭 클래스만 포함할 수 있었습니다. C#은 물리와 논리가 결합되어 있지 않기 때문에, 소스 파일에 이름을 마음대로 붙일 수 있습니다. 각 소스 파일은 다중 이름공간을 지원할 수 있습니다. 그리고 마음만 먹으면 모든 소스 코드를 큰 파일 하나에 다 기록할 수도 있으며, 여러 개의 작은 파일에 나누어 놓을 수도 있습니다. 개념적으로는, 컴파일할 때에 C#에 생기는 일은 컴파일러에 프로젝트를 구성하는 모든 소스 파일을 넣으면 컴파일러에서 스스로 무엇을 할 지 판단한다고 보면 됩니다. 오스본: 일반적(generic) 프로그래밍 대해 질문이 있습니다. 이것이 객체 지향 언어의 일부분이 될 만한 중요한 개념이라고 생각합니까? 만약 그렇다면, 일반적 프로그래밍을 C#에 포함시키기 위한 계획이 있습니까? 굿휴: 글쎄요, 우리가 넣고 싶어했던 것 중 몇 가지는 처음에는 포함시키지 못했습니다. 자원이 제한되어 있기 때문이죠. 그래서 포함할 수 있는 것과 그렇지 않은 것을 결정하는 데에 어려움이 있었습니다. 오스본: C#은 몇 명이 개발하였습니까? 헤즐스버그: 언어 디자인 팀은 4명이고, 컴파일러 팀은 5명으로 되어 있습니다. 페트루샤: 그러면 프레임워크는요? 헤즐스버그: 그 쪽은 인원이 훨씬 많습니다. 회사 전체가 투입되었죠. 굿휴: 전체 비주얼 스튜디오와 닷넷 플랫폼 그룹의 관점에서 볼 때, 우리는 1000 명으로 구성된 부서라고 볼 수 있습니다. 프로그램 관리자, 개발자, 테스터, 내장 함수, 프레임워크, 런타임, ASP 프로그래밍 모델, 그리고 저 같은 사람이나 위에 있는 관리직들이 모두 거대한 팀입니다. 헤즐스버그: 당신이 아까 물었던 일반적 프로그래밍에 대해 이야기 하자면, 저는 일반적 프로그래밍이 매우 유용한 개념이며 학계와 산업계에서 일어나는 일반적 조사와 그것을 구분할 수 있습니다. 템플리트(template)는 그 문제에 대한 해결책 중 하나입니다. 내부 토의 결과 우리는 새로운 플랫폼에서 이것을 잘 사용할 수 있겠다고 결론을 내렸습니다. 하지만 우리가 정말 하고 싶었던 것은 기저에 있는 런타임에서 일반적 프로그래밍을 수용하는 것이었습니다. 이것은 일부 일반적 프로토타입이 만들어진 것과 다소 다릅니다. 시스템에 일반적 프로그래밍에 대한 지식이 정말로 없는 자바의 "erasure"라는 개념을 가져와 봅시다. 공통 언어 런타임을 가지면 "일반적(generics)"이라는 개념, 즉 다중 언어가 함수를 공유할 수 있다는 개념을 이해할 수 있습니다. C#에서 한 장소에 일반적 클래스를 작성하고, 다른 사람이 다른 언어를 통해 그것을 사용할 수 있습니다.
† 역주 : 일반적 프로그래밍(Generic Programming) 개념은 효율적인 자료의 관리를 위해 STL에 의해 템플릿으로 어디서나 나타나는 자료구조를 표현하기에 적절한 형태를 말한다.
하지만 일반적인 측면을 런타임에 만들면 훨씬 효과적으로 할 수 있는 일도 있습니다. generics를 런타임에 인스턴스화(instantiation)하는 것이 이상적입니다. C++을 사용하면, 템플리트를 컴파일 시 인스턴스화 하며, 이 때 취할 수 있는 옵션이 두 가지 있습니다. 하나는 코드가 커지게 내버려두는 것이고, 또 하나는 링커에서 쓸데 없이 코드가 커지는 부분들을 없애는 것입니다. 하지만 여러 애플리케이션을 사용한다면, 이런 방법을 사용해서는 안됩니다. 불필요하게 덩치가 커진 코드(bloated code)를 갖게 될 것입니다.
† 역주: "bloated code"란 불필요한 기능 추가로 인해 점점 덩치가 커지는 프로그램을 비꼬는 뜻
만약 generics에 관한 지식을 공통 언어 런타임(common language runtime)에 적용한다면, 런타임에서는 애플리케이션이나 컴포넌트가 "Foo"s"의 리스트를 요청하는 시간을 이해할 수 있습니다. 그것은 "이미 "Foo"의 리스트의 인스턴스화(instantiation)가 있는가?"라고 질의할 것이며, 만약 그렇다면, 그것을 사용할 것입니다. Foo가 레퍼런스 타입이고, 우리가 디자인을 제대로 하고 싶을 경우에는 우리는 모든 레퍼런스 타입의 인스턴스화를 공유할 수 있습니다. int나 float 등의 값 타입의 경우에는 값 타입 당 하나의 인스턴스화를 만들 수 있습니다. 하지만 이것은 애플리케이션에서 요청할 때에만 가능합니다. 우리는 런타임에 generics를 추가하는 데 필요한 디자인과 기반 작업을 많이 하였습니다. 아까 IL에 대해 질문한 것은 흥미롭군요. generics를 추가하기로 결정하는 것이 IL의 디자인에 영향을 미치기 때문이죠. IL에 있는 명령이 타입 정보를 이식한다면, 예를 들어서 Add 명령은 Add가 아니라 Add int나 Add float, Add double이라면, 타입을 명령 스트림으로 굽고, IL은 그 시점에서 일반적이지 않습니다. 우리의 IL 포맷은 정말 형 중립적입니다. 그리고 그것을 중립으로 유지함으로써 generics를 나중에 덧붙일 수 있으며, 문제도 거의 발생하지 않습니다. 이게 IL이 자바 바이트 코드와 달라 보이는 이유 중 하나이지요. 우리는 형 중립적인 IL이 있습니다. Add 명령은 두 가지가 스택의 윗부분에 있는 어떤 것이든 덧붙입니다. generic이 구체화되면, 그것은 다른 코드로 번역될 수 있습니다. ADD 명령은 스택 윗 부분에 무엇이든 두 가지를 더합니다. 일반적 프로그래밍에서, 그것은 Generic이 인스턴스화될 때 다른 코드로 번역될 수 있습니다. 오스본: 닷넷 언어 전체에서 그렇게 할 수 있나요? 헤즐스버그: 예. 캠브리지에 있는 마이크로소프트 리서치(Microsoft Research)에서는 공통 언어 런타임과 C# 컴파일러의 generics 버전을 만들었습니다. 우리는 지금 어떻게 그것을 진행할 지 생각 중입니다. 첫 번째 배포판에서는 이렇게 할 수 없겠지만, generics가 전체와 조화될 수 있도록 할 것입니다. 오스본: C#을 ECMA(역주: 표준화 기구)에 제출한 것으로 알고 있습니다. 표준화를 정말 목적으로 하고 있는 것입니까? C#을 다른 플랫폼에서도 사용하기를 원하는 것인지요? 헤즐스버그: 물론입니다. 업계에 C#을 표준이 될 수 있는 것으로 제시하는 것이 우리의 목적입니다. 그래서 ECMA에 제출하였습니다. 우리는 ECMA의 지원을 얻어서 공통 언어 하부구조를 가진 공통적으로 디자인된 언어를 만들고 싶습니다. 공통 하부구조라는 것은 이러한 규약이 수반하는 핵심적인 클래스 라이브러리를 뜻합니다. 다른 회사에서 그것을 구현하기 위해 다른 플랫폼을 사용한다면, 그들은 프로그램에 맞는 클래스를 찾기를 기대할 것입니다. 굿휴: 우리는 ECMA와 함께 진정으로 열린 표준에 접근하고 있습니다. ECMA가 C#과 공통 언어 하부구조에 대한 표준에 도달할 때, 그 결과는 ECMA의 저작권과 라이선스 정책에 따라 아래 사용할 수 있을 것이며, 이것은 정말로 열려 있습니다. 모든 소비자가 ECMA C# 표준을 사용할 라이선스를 얻을 수 있으며, 그것을 subset하거나 superset할 수 있고, 로열티를 전혀 지불할 필요가 없습니다. 모든 플랫폼이나 디바이스에서 그것을 사용하고 구현할 수 있을 것입니다. 우리는 사람들이 그렇게 할 것을 기대하고 있습니다. 이것은 언어의 소유권을 확실히 하기 위해 표준 단체 주변을 맴돌았던 경쟁자들과 근본적으로 다른 점입니다. 존: 저는 점심과 저녁때 "마이크로소프트의 COM이 하부구조에 없는 플랫폼에서 어떻게 이식성이 있을 수 있습니까?"라는 질문을 들었습니다. 이에 대해 어떻게 생각하십니까? 헤즐스버그: 그것은 확실히 가능합니다. COM은 절대로 C#과 공통 언어 하부구조의 표준화를 위한 필수사항이 아닙니다. C#에는 풍부한 클래스 모델이 있는 반면, COM은 애플리케이션이 상호 운용성을 어떻게 가질 수 있는가에 대한 또 한 가지 시각일 뿐입니다. 하지만 C#이나 핵심적인 공통 런타임에는 COM, GUIDS, HRESULTS, AddRefs, Release가 없습니다. 닷넷 공통 언어 런타임에서는 그것을 완전히 없앴습니다. 하지만 닷넷은 COM과 상호 운용성이 있습니다. 하지만 이것이 전제가 되는 것은 절대로 아닙니다. 굿휴: 이런 코멘트 중에서는 우리가 대중에 공개했던 언어 레퍼런스에서 영감을 얻은 부분도 있다고 생각합니다. 마이크로소프트는 플랫폼에 대해 회의하는 자리에서 이것을 작성했습니다. 결과적으로 우리는 규약에 있는 COM이나 DLL 등에 대한 레퍼런스를 만들었습니다. 표준 기관의 심의를 받고, IBM 등과 함께 일했을 때(SOAP 규약을 함께 작업했다.)의 장점 중 하나는 앞으로 나올 규약의 버전에서 COM 프레임워크 같이 우리를 속박할 레퍼런스가 더 이상 생기지 않을 수 있다는 것입니다. 앤더스가 말했듯이, COM 상호 운용성과 COM 지원은 우리에게는 물론 고객에게도 매우 중요합니다. 우리는 닷넷 플랫폼에서 COM을 지원하는 대단한 일을 해냈다고 생각합니다. 하지만 업계의 사람들은 우리가 COM과 DLL이라는 용어를 사용한 기사를 너무 많이 읽었습니다. 그들은 닷넷 플랫폼이 윈도우만을 위한 것이라고 생각할 지도 모르겠는데, 그런 생각은 틀린 것입니다. 헤즐스버그: COM 상호운영성이 마이크로소프트와 마이크로소프트 플랫폼에 솔루션을 구축하는 고객에게 중요한 것처럼, C#과 공통 언어 구조(CLI)의 표준화는 언어를 구현하기 위해 선택하는 어떤 플랫폼에서도 유용한 상호 운용성을 위해 다른 구현을 허용할 것입니다. 오스본: 그래서 "순수 C#"이나 "순수 닷넷" 구현을 고집하지 않는 것이군요. 헤즐스버그: "순수"라는 게 뭐죠? "순수" 자바 애플리케이션은 정말 존재합니까? 저는 아주 아주 적다고 감히 말하고 싶습니다. 사람들은 지금 있는 코드를 가지고 더 많은 것을 하기를 원합니다. 지금 쓰고 있는 것을 모두 버리라고 할 수는 없습니다. 오스본: C#에 대해 말하고 싶었는데 앞에서 말하지 못한 부분이 있다면, 지금 얘기해 주십시오. 헤즐스버그: 전체 닷넷 프레임워크에 대해 하고 싶은 말이 있습니다. 여기에는 C#도 관련되어 있겠지요. 닷넷은 분산 애플리케이션을 구축하는 방법을 전환할 것입니다. 얼마전까지만 해도 우리는 CORBA, IIOP, RMI, DCOM과 같은 객체 프로토콜로 두 계층으로 된 클라이언트/서버 애플리케이션을 만들었습니다. 이러한 종류의 프로그래밍은 실제로는 CORBA나 RMI 기반에서 구현되는 EJB의 토대입니다. 우리는 이러한 강력하게 연결된 분산 시스템을 구축할 수 있다는 것은 배웠지만, 규모 가변적이지는 않습니다. 그런 것들은 상태를 가지며, 서버에 상태를 유지하며, 다른 머신에 단순히 넣는 것만으로 서버 농장에 그것을 플러그 인 할 수도 없고, 자체적으로 복제할 수도 없기 때문에 웹에서는 규모 가변적이지 않습니다. 닷넷(.NET) 프레임워크를 처음 디자인할 때에, 우리는 한 걸음 물러서서 웹에서는 어떤 일이 일어나고 있는지 살펴보았습니다. 웹은 느슨하게 연결된, 아주 분산되어 있는 환경이었습니다. 그리고 우리는 기본적인 프로그래밍 모델로 할 수 있는 것이 무엇인지 이해하려고 했습니다. 그래서 우리는 분산 애플리케이션은 가용성을 제공하는 상태를 유지하지 않는 특성(stateless fashion)을 가지며, 느슨하게 연결된 곳에 구축된다는 가정 아래 디자인 했습니다. 여러분은 규모만 정하면 됩니다. 여러분은 보다 많은 공간에 집어넣고, 그것들을 플러그 인 할 수 있습니다. 여러분이 기초적인 가정을 만들고 나면, 그것은 모든 것을 바꿀 수 있습니다. 여러분의 기본 서비스를 디자인 하는 방법, 여러분의 모든 메시지를 디자인 하는 방법을 바꾸는 것이 아니라 심지어 여러분의 UI를 디자인하는 방법을 바꿀 수도 있습니다. 이것이 새로운 프로그래밍 모델입니다. 우리는 이 모델이 작동할 수 있는 수단으로 XML과 SOAP를 사용하기로 결정했습니다. XML과 SOAP은 닷넷에 깊이 통합되었고, 이러한 통합은 .NET 프레임워크를 디자인할 때 결정을 내리는 데 큰 영향을 주기 때문에, 가볍게 보아서는 안됩니다. 오스본: 프로그래머가 어떤 부분에서 이러한 변화를 명확하게 인식할 수 있습니까? 헤즐스버그: 그 좋은 예로 XML과 C#이 어떻게 통합되는지를 들 수 있겠지요. C#에는 이러한 "속성(attribute)"의 개념이 있으며, 선언 정보를 형(type)과 멤버(member)에 덧붙일 수 있습니다. 멤버가 public인지 private인지 구분할 수 있는 것처럼, 트랜잭션이 일어났는지, 웹 서비스에 사용될 것인지, XML처럼 직렬화가 가능한지 등을 구분할 수 있기를 바랄 것입니다. 그래서 우리는 이와 같은 일반적(generic) 메커니즘을 제공할 수 있는 속성을 추가했지만 지금은 이것은 웹 서비스와 XML 구조 전체에서 사용하고 있습니다. 또한 이것은 여러분의 클래스에 있는 필드나 속성을 넣을 수 있도록 했습니다. this 클래스를 XML로 이동할 때, XML에 "this" 태그가 필요하며, "this" XML 네임스페이스로 이동하는 것이 필요합니다. 한 위치에 특정 필드가 요소(element)가 되어야하고, 다른 것은 속성(attribute)이 되기를 원할 수 있습니다. 여러분이 작성한 클래스 선언을 제어하고, 추가적인 선언 정보를 이용할 수 있도록 XML의 스키마를 제어를 원할 수도 있습니다. 이런 방식으로 속성(attribute)이 적절하게 사용되어 C# 코드를 꾸며줄 때, 시스템에서는 단지 특정 클래스를 XML로 변환하고, 변환된 것을 전송하여, 다른 곳에서 객체를 재구성할 수 있도록 할 수 있습니다. 이러한 모든 일이 하나로 완료됩니다. 추가적인 정의 파일, 분류된 정보, 네이밍 패턴과 같은 것이 아닙니다. IDE에서 그것을 작성할 때 문장 완성을 사용할 수 있고, 이러한 방식으로 동작하는 보다 높은 수준의 도구를 제공할 수 있습니다. 주제에서 벗어난다는 것은 알지만, 우리가 제공하는 몇몇 구조들은 매우 흥미로운 것입니다. 단순히 우리는 이러한 속성을 갖고 있기 때문에, 어떤 주어진 클래스를 XML로 변환하기 위해 XML 직렬화(serialization) 구조나 웹 서비스를 사용할 수 있습니다. 여러분이 그렇게 할 때, 우리는 실제로 클래스에 대한 스키마, 즉 XSD 스키마를 갖고 되고, 닷넷의 기본 클래스인 일반(generic) XML 파서에서 상속받아, 스키마에 적절하게 파서안에 메소드를 오버라이드하고, 로직을 추가하여 고유의 파서를 작성할 수 있습니다. 그래서 우리는 XML을 통해서 원시 코드 속도로 립(rip)할 수 있는 파서(parser)를 인스턴스화 했습니다. 만약, 인스턴스화가 올바르지 않다면, 여러분은 무엇이 잘못되었는지를 정확히 알려주는 적절한 에러 메시지를 받게 됩니다. 인스턴스화된 파서는 우리의 코드 캐싱 구조에 들어가고, 동일한 스키마를 가진 클래스가 있을 때까지 보존됩니다. 다시 말해서, 이것은 상당히 효율적으로 동작합니다. 오스본: 기술적으로 다루어야 할 것 중에 재미있는 부분이 정말 많군요. 헤즐스버그: 예, 그리고 저는 우리는 이러한 생각에 있어서는 한 세대 앞서간다고 생각합니다. 오스본: 시간 내 주셔서 감사합니다. 헤즐스버그: 별말씀을요.
TAG :
댓글 입력
자료실