Mono의 시작

Mono 프로젝트 리더인 Miguel de Icaza는 본래 Linux에 자유로운 데스크탑 환경을 구현하는 것을 목적으로 설립한 GNOME 프로젝트의 초기 리더이며, Mono는 처음에는 Linux 데스크탑 환경용 애플리케이션 개발을 쉽게 하기 위해 시작된 프로젝트이다.

당시 Miguel GNU 프로젝트에서 소프트웨어 대상을 받을 정도로 UNIX 해커이면서 마이크로소프트에 인턴 응모를 한 일이 있을 정도로 마이크로소프트 기술 열광자이고, COM 기술을 사랑하여 비슷한 기술인 CORBA를 응용한 'Bonobo'라는 소프트웨어를 개발하였고, GNOME 개발 촉진을 그렸던 역사도 있다.

그는 .NET Framework가 등장하자 바로 흥미를 여기로 옮겨서 GNOME 개발을 이것으로 하려고 당시 그가 설립한 Ximian사에서 Mono 프로젝트를 시작하였다.

 

Mono는 주로 다양한 ADO.NET 프로바이더나 ASP.NET 등 서버 사이드 기술을 구현하는 것을 시작하여(이것이 1.0) 다음은 Windows Forms을 구현하였다. 이것이 버전 2.0으로 .NET 2.0까지 구현했을 때 .NET 3.5가 나왔다. 이것을 사용하여 Paint.NET Mono로 구현한 것이 Paint-mono 이다.

 

.NET 기술은 광범위 하여 Mono 팀은 구현 대상을 조정할 필요가 있었다. 주로 런타임과 C# 컴파일러 개선, ASP.NET, WCF 등의 서버 사이드 기술 구현 등이 집중적으로 개발 되었다. 또 이것과는 별개로 Gtk#이나 MonoDevelop 개발도 병행하였다.

 

'애플리케이션을 자연스럽게 Linux에서도 동작시키자' 라는 레벨의 목적으로도 .NET Framework에 캐치업 하는 것은 쉽지 않다고 생각되지만 Mono 팀이 코어 부분을 착실하게 진행 시키는 중 하나의 전환점을 맞이하였다. MS ASP.NET MVC를 오픈소스로 공개하는 등 .NET Framework의 일부를 오픈 소스로 하는 흐름이었다. ASP.NET MVC, DLR은 오픈 소스로 공개되어서 그대로 Mono에 들어왔다.

이후 MS Entity Framework, Reactive Extensions 라는 .NET의 대규모 라이브러리를 차차 오픈 소스화 하였다. 이것들은 Mono에 그대로 들어와서 바이너리 배포 되고 있다.

 

일단 코어 부분에 집중할 수 있게 된 Mono팀은 완성도를 더욱 높이면서 대상 플랫폼을 확대할 수 있었다. C# 컴파일러는 재 빠르게 C# 5.0 기능을 구현하였다. iOS Android Xamarin 제품의 양 축이 되고 있지만 이것들을 타겟으로 하기 위해 런타임이 개선 되고 있는 측면도 크다. Mono는 현재로서는 주로 Xamarin이 제품으로 사용하는 범위의 기능을 높이는 방향을 향하고 있다.

 

 

Mono 소프트웨어 구성 요소

mono 소스 코드 저장소에는 런타임, C# 컴파일러, mono 클래스 라이브러리가 포함된다.

mono 공식 저장소: https://github.com/mono/mono

mono 소스 상에서 앞의 3개의 요소(런타임, C# 컴파일러, 클래스 라이브러리)는 각각 다음의 디렉토리에 존재한다.

mono/   최상위 디렉토리

|- mono   런타임

|- mcs/

    |- mcs  컴파일러

    |- class  클래스 라이브러리

 

 

 

mcs: C# 컴파일러

mcs C#으로 구현 되어 있고 초기는 csc로 빌드 되었다(msc 빌드에는 mcs가 필요하므로 현재도 부트스트랩용의 빌드된 mcs.exe가 먼저 사용된다).

 

최신 mcs async/await키워드, caller info 등을 포함한 C# 5.0까지의 기능을 모두 구현하고 있다. csc와 비슷한 명령 라인 옵션을 갖추어서 기존의 C# 코드를 문제 없이 빌드 할 수 있다. 문법 에러 체크도 .NET Framework csc와 같이 엄격하게 해준다(배경에는 C# 언어 사양이 규정하는 C#코드의 흐름 분석과 mcs의 충실한 구현이 있다). csc의 에러와 경고는 Visual Studio와 친화적으로 동작하기 위해 일정한 형식으로 출력되지만 mcs에서도 그것은 답습되어 MonoDevelop에서도 마찬가지로 메시지가 목록으로 표시된다. Windows 상에서 동작하는 MonoDevelop csc를 사용하고 있으나 그 컴파일 오류는 MonoDevelop에서 올바르게 목록으로 표시될 것이다.

 

ECMA 334 ECMA 335라는 사양은 C#의 소스 수준의 호환성과 CIL(바이너리 중간 코드) 모두에 대해 호환성을 갖기 위한 것이며, mcs가 생성하는 exe파일 및 dll 파일은 csc이 생성하는 것과 호환성이 있다. 대상 플랫폼에서 읽어지는 어셈블리이면 mcs가 생성한 것을 .NET Framework에서 읽어도 csc가 생성한 것을 mono에서 읽어도 각각 실행할 수 있을 것이다(물론 대응하는 프로파일의 유무 및 대상 프로파일에서의 참조 어셈블리의 유무는 여기에서는 다른 문제이다).

 

다만 mcs-debug 옵션으로 생성하는 디버그 기호 파일은 ".mdb" 라는 자체 포맷이 되어 있다. 이것은 ECMA CLI에 디버그 기호의 규정이 없고, pdb 파일의 사양이 비공개였기 때문이다(현재는 cildb라는 pdb mdb도 아닌 포맷이 규정되고 있다). 현재의 mono에는 이들을 상호 변환하기 위한 툴 pdb2mdb mdb2pdb가 존재한다. 참고로 이들은 포맷의 차이 밖에 없으며 정보의 성질 차이는 없을 것이다.

 

mcs에 의한 LINQ, dynamic 형의 지원 조건은 csc의 경우와 별로 바뀌지 않았다. 즉 확장 방법을 쓰려면 System.Core.dll을 참고로 한 후 "using System.Linq;" 라고 기술해야 하고, dynamic 형을 쓰려면 Microsoft.CSharp.dll을 참조에 더해야 한다(이는 간접적으로 Mono.CSharp.dll 라고 하는 라이브러리도 이용한다). 이들 라이브러리만 있으면 mcs dynamic 형을 충분히 지원할 수 있다(필자는 실제로 PlayStation Mobile이 아직 "PSSuite"로 불리던 시절에 이 환경에서 이들 어셈블리를 적절한 프로파일로 빌드 후 추가하여 지원되고 있지 않을 dynamic형을 기술하고 있는 코드를 동작 시킨 적이 있다).

 

그리고 mcs csc과 달리 다수의 라이브러리를 기본적으로 참조하지 않는다. csc.rsp가 없는 것 같은 상태라고 생각하면 좋다. 이것은. NET개발자에게는 다소 혼란의 원인이지만, 사용되지 않는 어셈블리를 헛되게 해석하면 그만큼 컴파일 시간이 희생된다. 그것을 싫어한 것이다.

 

 

mcs의 설계

mcs는 소스의 해석(파서), 시맨틱 분석, 코드 생성 등 일반적인 순서에 근거하는 언어 컴파일러 구현이므로 주목 할 것은 많지 않다. 소스의 해석이 jay 이라는 LALR(1)문법 파서 생성기를 사용하고 있다(원래는 Java의 소스를 생성하는 도구이지만 C# 생성 기능을 추가했다).

* jay: https://github.com/mono/mono/tree/master/mcs/jay

 

코드 생성은 과거 .NET mscorlib에 포함된 System.Reflection.Emit를 사용하고 있었지만 이것은 "크로스 프로파일" 형태로 어셈블리를 빌드 하는 것을 막는 것으로(예를 들면 NET 4.0 호환 어셈블리를 생성하려면 .NET 4.0 프로파일의 mscorlib.dll에서 동작하는 mcs가 필요했다), 현재는 "IKVM.Reflection.Emit"라고 하는 라이브러리를 사용하고 있다. IKVM Java 바이트 코드를 .NET/Mono 상에서 실행하게 하는 프로젝트이다. 만약 당신이 언어 처리 쪽으로 작성하고 있다면 System.Reflection.Emit 대신 IKVM.Reflection.Emit 사용을 검토하는 것이 뒤에 편하게 될지도 모른다. System.Reflection.Emit을 쓰고 있었을 때는 mono에는 타깃 프로필에 맞춰 mcs, gmcs, dmcs, smcs 같은 컴파일러 툴이 난립하고 있다. 지금은 mcs의 옵션 -sdk로 모두 대응하고 있다.

 

세만틱 분석은 mcs의 가장 복잡한 부분이지만 yield 키워드와 익명형, var에 의한 형 추론, dynamic형 사용, async/await 키워드의 Task 처리 등이 어떤 논리로 생성되고 있는지 만일 흥미가 있다면 mcs의 소스를 따라가면서 확인 가능하다.

 

 

mcs의 응용 사례

mcs는 오랫동안 단일 도구로 존재해 왔지만 최근에는 Mono.CSharp.dll 이라는 독립한 라이브러리로서 재이용 할 수 있도록 되어 있다. MonoDevelop SharpDevelop 두 프로젝트 간에 C# "서비스로서의 컴파일러"(Compiler as a Service 또는 Language Service)로 개발되고 있는"NRefactory"에서도 사용되고 있다. 마이크로 소프트 기술로 말하면 "Roslyn"에 상당하는 것이다.

 

마지막으로 mcs의 흥미로운 응용으로 mono C# shell을 소개한다. 이것은 csharp.exe라는 툴로 안에서는 Mono.CSharp.dll을 사용하여 C#로 인터랙티브 셸을 실현하는 것이다. Gtk#의 도구가 콘솔에서 실행할 수 있는 환경(Linux )이라면 gsharp이라는 GUI 셸도 이용할 수 있다.

* gsharp: https://github.com/mono/mono-tools/tree/master/gsharp

 

C#의 코드를 그 자리에서 쓰고 Gtk# Widget을 만들어 표시하는 것도 가능하다(Miguel은 일찍이 이 위에 Gtk.Canvas에서 도형을 그리는 데모를 하였다). MonoDevelop 사용자 커뮤니티에서는 이 mono C# shell MonoDevelop의 패드로 쓰도록 한 add-in도 공개되고 있다. 인터랙티브 셸은 이미 F#(fsi)의 독무대가 아니다.

 

 

 

출처: http://www.buildinsider.net/mobile/insidexamarin/02

저작자 표시
신고
by 흥배 2014.02.24 08:00

티스토리 툴바