모노 프로젝트의 발단은 유닉스 계열 시스템이 데스크톱 시장에서 보다 경쟁력을 갖추는 것을 목적으로 하는 그놈 프로젝트에서 시작한다.
언어 독립적인 환경의 중요성을 일찍부터 확신한 그놈 개발자들은 다양한 언어를 지원할 수 있게 표준을 지켜가며 그놈 API를 작성했다. 점차 이 API를 캡슐화하기 위한 방법이 요구됐고, CORBA(Common Object Request Broker Architecture)를 사용해 인터페이스를 정의했다. 이것은 재사용 가능하고 언어 독립적인 컴포넌트를 쉽게 만들 수 있는 표준 그놈 인터페이스의 집합체인 보노보(Bonobo)로 보완이 됐다.
하지만 C로 작성된 API를 다른 언어로 바인딩하는 데에는 많은 시간과 노력이 필요하게 되는 문제가 발생했다. 에볼루션(Evolution, 그놈 그룹웨어)의 경우 약 75만줄의 소스 코드로 구성됐다. 많은 조직이 그러는 것처럼 지미안(Ximian, 미구엘이 일하는 회사)은 규모가 큰 프로그램 개발시 드는 비용의 최소화를 원한다. 그리하여 지미안은 다음과 같은 특징을 갖는 닷넷의 CLI(Common Language Infrastructure) 플랫폼에 관심을 갖는다.
◆ 가비지 컬렉션·쓰레딩·가상 실행 시스템(VES, Virtual Execution System)을 제공하는 런타임 환경
◆ 포괄적인 클래스 라이브러리
◆ C#은 닷넷 런타임시의 모든 기능을 사용할 수 있다.
◆ 언어 통합을 가능케 하는 CLS(Common Language Specification)
CLI 플랫폼은 언어에 상관없이 프로그래밍을 하고자 하는 그놈의 목적과 가깝다. CLS 제공 언어를 사용해 작성된 API는 어떤 언어일지라도 서로 호환돼 사용될 수 있다. 컴파일러는 CIL(Common Intermediate Language) 형식의 코드를 생성한다. CIL은 쉽게 원시 코드로 컴파일되거나 JIT(Just-in-Time) 엔진을 사용해 컴파일될 수 있다.
사실 특별히 혁신적인 것은 없지만, 기술을 아주 잘 조합?통합시킨 점이 개발자들의 관심을 갖게 했다. 2001년 3월, 이러한 이유로 모노의 프로토타이핑이 시작됐다.

mcs : C#으로 만든 C# 컴파일러
C#으로 C# 컴파일러를 만들면 다음과 같은 이점이 있다. SharpDevelop(오픈소스 C# IDE, 비주얼 스튜디오를 생각하면 된다)과 같은 도구의 컴포넌트로 재사용될 수 있고, System.CodeDom.Compiler 클래스를 구현한 것이 된다.
또 어휘 분석기는 파싱시 개체를 나타내기 위해 C# 객체를 사용할 수 있다. 이것으로 리터럴(literals) 처리와 상수 폴딩(컴파일러가 컴파일시 필요한 연산을 수행해 복잡한 상수식을 줄여주는 것) 실행을 쉽게 만들 수 있다. 모노는 C# 파서로 Jay(구문분석기 생성 도구인 버클리 Yacc을 자바로 포팅한 것)를 C#으로 포팅해 사용한다. 좀더 좋은 것을 고려해 볼 수도 있지만 사실 C# 자체는 파싱하기엔 간단한 언어이고 대부분 의미 분석 단계에서 할 일이 많기 때문이다.
컴파일러 드라이버는 컴파일 진행을 주도한다. 파서와 어휘 분석기는 클래스를 구성해 나가며 입력 파일의 내부적인 표현을 생성한다. 에를 들어, if문은 if 클래스로 표현될 수 있는데 if 클래스는 Statement 클래스에서 파생된 것이다. 마찬가지로 각 표현식은 Expression 추상 클래스에서 파생된다. 이런 구성 방법은 C++로 쓰인 프리(free) 자바 컴파일러 Guavac과 유사하다.
한편 완벽한 타입 시스템을 구현하는 대신 C# 객체 모델의 다양한 기능으로 이를 극복할 수 있다. System.Reflection 네임스페이스를 타입 저장소로 설정해 이로부터 타입을 사용하고 System.Reflection.Emit은 타입을 바로 바로 생성한다. System.Reflection 타입은 런타임시 타입을 검사하고 다룬다(예를 들면 System.String에 노출된 모든 public 메쏘드를 셀 수 있다).
System.Reflection.Emit은 System.Reflection 기반 메모리나 디스크 타입을 생성한다. 이 두 네임스페이스는 타입을 위한 빌딩 블럭을 제공한다. 따라서 모노 C# 컴파일러는 타입을 생성하고 멤버(프로퍼티, 이벤트, 메쏘드, 필드)를 추가하고 System.Reflection.Emit으로 PE(Portable Executable) 헤더와 CIL를 포함하는 EXE나 DLL인 어셈블리에 타입을 기록한다.
닷넷 네임스페이스에 있는 클래스인 기본 클래스 라이브러리를 구현하는 일 역시 모노 프로젝트의 일부다. 구현된 클래스 라이브러리 테스트는 닷넷 언어를 위해 포팅된 역행 테스팅 프레임워크인 NUnit을 사용한다. 그리고 XML을 사용한 NAnt를 클래스 라이브러리 빌드 시스템으로 사용한다. 클래스 라이브러리는 모노 프로젝트에 참여하기 좋은 곳이니 모노 프로젝트에 공헌해보는 것도 좋을 듯 싶다.
mint : CIL 바이트코드 인터프리터
이제 모노가 구현하는 CLR(Common Language Runtime)을 살펴보자.
모노는 mint(Mono Interpreter)와 JIT 컴파일러라는 두 개의 가상 실행 시스템(VES)을 가진다. 둘 다 CIL 명령어를 포함하는 PE/COFF 이미지에 접근하고 다룰 수 있는 메타데이터 라이브러리를 사용한다.
mint는 원래 모노의 개념을 증명하려고 개발됐다. 디버깅하기 쉽고, 조사하기 쉬운 포괄적인 용도로 설계된 mint는 JIT 엔진의 디버깅 문제를 참조하는데 사용된다. mint는 JIT보다 넓게 응용될 수 있어 x86 계열 플랫폼이 아닌 다른 아키텍처에서 돌리는데 필요한 수고를 줄일 수 있다. 속도가 중요하지 않다면 말이다. 그래서 mint는 프로토타이핑 테스트에 유용하다.
mono : 모노 JIT 엔진
모노의 JIT은 런타임시 CIL 명령어를 원시 코드로 번역한다. JIT은 전체 어셈블리를 한번에 또는 메쏘드가 호출될 때마다 메쏘드를 하나씩 컴파일 할 수 있다. JIT은 메모리 버퍼에서 코드를 생성하는 매크로의 집합을 사용한다. 각 아키텍처마다 하나의 매크로 집합이 필요하며, 매크로는 코드 생성 디버깅과 프로토타이핑을 간소화 시켜준다.
x86 계열 컴퓨터 플랫폼의 코드 생성 인터페이스는 mono/arch/x86/x86-codegen.h 파일이다. 이 매크로는 인텔의 오픈 리서치 플랫폼 자바 가상 기계(ORP JVM)에서 비롯된 것이다.
CIL 바이트코드를 원시 명령어로 바꾸는 것 역시 흥미롭다. 모노는 아래에서 위로 다시 쓰는 방식(BURS)인 트리 패턴 매칭에 기반한 명령어 선택기를 사용한다. BURS는 연산(말단에 있는 노드)의 집합을 대상 아키텍처에 맞는 말단이 아닌 요소에 사상하는 문법을 사용한다. 이 문법은 monoburg라는 코드 생성 프로그램에 공급된다.
첫 번째 하는 일은 CIL 명령어의 연속을 트리의 포리스트(forest, 근 노드의 가지 수 만큼 생기는 서브 트리)로 바꾼다. 각 트리는 명령어 선택기에 각기 공급된다. 이 포리스트/트리를 만드는 과정에서 표준 CIL 명령어는 명령어 선택기에 의해 알맞는 코드로 바뀐다. 이 때문에 BURS 문법이 진짜 CIL 옵코드(opcode, 연산 코드)를 실제로는 포함하지 않지만 의사(pseudo, 작동 논리를 설명하기 위해 사용됨) 옵코드랑 유사하다.
코드를 생성하기 위해 많은 패스(pass)가 노드의 포레스트에서 행해진다. 첫 번째 패스는 모든 노드에 표시를 하고 최단경로의 트리를 찾는다. 두 번째 패스는 레지스터 할당을 수행한다. 마지막 단계에선 x86 코드를 내보낸다.
그 밖에 CLR과 그걸 돌리는 어떤 플랫폼간의 브릿지 역할을 하는 플랫폼 호출(P/Invoke), 인텔 ORP에 기반한 가비지 컬렉션도 모노에서 구현되고 있다.
모노 프로젝트 진행 상황
현재 모노 프로젝트는 지미안의 개발자를 비롯해 많은 공헌자들이 참여하고 있다. 주로 메일링 리스트와 IRC를 통해 커뮤니케이션이 이뤄지고 있다. 저마다의 생각을 진지하게 토론하고 작업한 부분과 패치에 대한 것, 질문 답변도 하면서 말이다.
작업한 소스는 CVS를 통해 관리되고 있다. 모든 소스가 공개돼 있는 것은 말할 필요도 없는 것. 또한 홈페이지에 작업 상황, 각종 정보를 정리해 알리고 있다. 현재 모노가 구현한 것은 다음과 같다.
◆ C# 컴파일러 : 일부 기능을 제외하고는 거의 완성됐다.
◆ 모노 JIT 엔진 : 갖춰야 할 특성을 모두 완성했고 속도를 개선 중이다.
◆ mint : 현재 모노 C# 컴파일러를 돌릴 수 있고 컴파일러는 유효한 코드를 생성한다.
◆ 메타데이터 라이브러리 : 닷넷 모듈(EXE이나 DLL)의 정보를 파싱하고 읽어들일 수 있다.
◆ 역어셈블러 : 닷넷 모듈을 역어셈블하는 게 가능하다. 아직 예외를 다루는 디버깅 툴이 부족하다.
◆ 클래스 라이브러리 : 아직 구현되지 않은 클래스 목록은 모노 홈 클래스 상태 페이지에서 알 수 있다.
모노의 완성일을 예정하기에는 아직 너무 이르다. 하지만 2002년 중반 정도에 완성을 기대하고 있다.
모노 한글 페이지
이 글은 Dr.Dobb 저널 2002년 1월 ‘모노와 닷넷 프레임워크’란 글을 바탕으로 작성된 것이다(http://www.ddj.com/documents/s=1818/ddj0201a/0201a.htm). 이 글을 쓰면서(번역?) 부족한 게 너무 많음을 느껴 하나씩 배워갈 참이다. 끝으로 모노에 대해 함께 공부하고 싶은 국내 개발자들은 모노 한글 페이지에 들려 정보 교류를 했으면 한다.@