• 북마크
  • 추가메뉴
어디로 앱에서 쉽고 간편하게!
애플 중고 거래 전문 플랫폼
오늘 하루 보지 않기
KMUG 케이머그

컬럼

.NET 플랫폼 분석

본문

Microsoft .Net by DrPizza

.NET에 대해서 수많은 "명망있는" 미디어/언론들이 다뤘지만 이들의 .NET 기사들은 대부분 .NET의 성격이나 목적, 구현 방법들에 대해 잘못 전하고 있다. .NET이 무엇인지 묻는다면 아마도 답변은 수없이 많이 나올 것이다. 하지만 그중 대부분은 오답이며 그 자신이 모순된 답변들이 많으리라. 언론 자신이 혼란스러워하고 있기 때문이다.

제일 일반적인 .NET에 대한 설명으로는 .NET이 자바를 베꼈다거나, .NET은 등록 소프트웨어의 일종이라는 것이 있다. 물론 사실은 그렇지 않다. 우선은 필요한 답변을 해보도록 하겠다.

What is .NET?

.NET은 "소프트웨어 플랫폼"이다. 사용하기 쉽고 보안성 있는 프로그램 작성 환경으로서 언어-독립적이다. 특정한 하드웨어/OS 조합 대신 프로그램들은 .NET 호환의 목적을 가지며, .NET이 구현된 곳이라면 어디든 돌아간다.

또한 .NET은 .NET 플랫폼 상에서 만들어진 여러가지 소프트웨어에 주어진 이름이기도 하다. 비주얼 스튜디오 .NET이나 윈도우즈 .NET 서버와 패스포트, 헤일스톰 등과 같은 서비스도 포함한다.

.NET 플랫폼을 만드는 컴퍼넌트는 .NET 프레임웍이라 부른다.

본 기사는 .NET 프레임웍에 집중하며 그 다음에는 .NET 소프트웨어를 조명한다. 또한 표준화 과정에서 .NET과 라이벌인 J2EE의 차이점에 대해서도 다루도록 하겠다.

The .NET Framework

.NET 프레임웍은 크게 두 부분으로 나뉜다.

1. The Common Language Runtime (CLR).
2. A hierarchical set of class libraries

CLR은 .NET의 "실행 엔진"이라고 말할 수 있다. CLR은 프로그램이 돌아갈 환경을 제공하며 주요 기능으로는 다음과 같다.

* Conversion from a low-level assembler-style language, called Intermediate Language (IL), into code native to the platform being executed on.
* Memory management, notably including garbage collection.
* Checking and enforcing security restrictions on the running code.
* Loading and executing programs, with version control and other such features.

우선 세부 기능을 얘기하기에 앞서 몇 가지 단어에 대한 설명이 필요하다.

Managed Code

"매니지드 코드"는 .NET을 타겟으로 하는 코드이며, 특정한 별도의 정보(즉, 메타 데이터)를 포함한다. 런타임에서 매니지드이건 언-매니지드이건 돌아가지만 매니지드 코드만이 안전한 실행이나 상호 작용과 같은 기능을 보장한다.

Managed Data

매니지드 코드에는 매니지드 데이터가 따른다. CLR은 메모리 배정과 회수 기능, 가비지 콜렉션을 제공한다. 어떤 .NET 언어(C#, 비주얼 베이직.NET, J스크립트.NET)는 기본적으로 매니지드 데이터를 이용하지만 C++과 같은 다른 언어는 기본적으로 사용하진 않는다. 사용하는 언어에 따라서, CLR은 몇 가지 제한을 줄 수 있다. 이를테면, C++는 다중 상속 기능을 사용할 수 없다. 매니지드와 언매니지드 코드에서 .NET 애플리케이션은 매니지드 데이터와 언매니지드 데이터를 모두 사용할 수 있다. 단 가비지 콜렉션이 누락되며, 대신 언매니지드 코드에서 다뤄야한다.

Common Type System

CLR은 Common Type System (CTS)으로 type-safety를 강요한다. 즉 호환성을 갖는 모든 클래스에 일괄적인 묘사 타입을 확인한다는 의미이다. CTS는 런타임할 때의 타입(선언과 사용)을 정의려서 언어간에 상호 작용을 가능하게 한다. 또한 런타임 자신도 배정받지 않은 메모리에 접근을 막는(즉 코드가 type-safe 상태이다) 기능을 갖는다.

Assemblies

.NET 프로그램은 "어셈블리"로 이뤄져있다. 어셈블리는 핵심 기능 유닛을 이루는 코드와 메타 데이터의 조합을 컴파일시키고 버전화시킨 것이다. 모든 어셈블리는 어셈블리 이름과 버전, 로케일을 포함하는 Manifest를 갖고 있으며 어셈블리를 이루는 파일의 리스트도 갖고 있다.

컴파일러에서 .NET을 타겟할 경우, 만드는 코드는 네이티브가 아니다. 대신 이 코드는 데이터 블럭 세 개를 감싸는 작은 Portable Executable(PE)이며, Win32 프로그램을 담는데 사용하는 바이너리 포맷이 바로 PE이다.

PE 파일은 하위 MS-DOS 프로그램(DOS에서 Win32 프로그램을 실행하려하면 "이 프로그램은 마이크로소프트 윈도우즈를 필요로 합니다."의 메시지를 출력한다.)을 담고 있으며, .NET 바이너리는 Win32프로그램(이를테면 "이 프로그램은 .NET을 필요로 합니다"라고 출력할 수도 있을 것이다)을 담고 있다.

PE 안에 있는 첫 번째 데이터 블럭은 IL 그 자체이다. IL은 어셈블러처럼 보이지만 실제로 컴파일되고 실행할 수 있다.

두 번째는 메타 데이터이며, 메타 데이터는 파일 내용을 묘사한다. 이를테면 파일이 제공하는 메써드와 패러미터, 리턴 값과 같은 정보를 갖고 있다.

세 번째는 마니페스트이다. 마니페스트는 실행을 필요로하는 컴퍼넌트를 묘사하며, 외부 컴퍼넌트에 대해 퍼블릭 키를 갖고 있기 때문에 CLR은 외부 컴퍼넌트를 실행시킬 수 있도록 확인 과정을 거친다.

실행이 가능하면 CLR은 Just-In-Time 컴파일을 사용한다. 각 메써드에서, 코드는 네이티브로 컴파일되며, 같은 메써드로의 하부 호출은 동일한 컴파일을 거치지 않기 때문에 오버헤드 현상은 단 한 번만 일어난다.

JIT 컴파일에는 몇 가지 문제가 있다. 우선 메모리와 프로세서 사양이 좋아야한다. 여기에 대해 MS는 두 가지 JIT 컴파일러를 제공한다. 하나는 일반적인 컴파일러로서 프로세서/메모리를 많이 잡아먹는다. 또 한 가지는 "EconoJIT"로서 코드 자체를 최적화시키지는 않지만 더 적은 사양의 메모리와 프로세서를 요구한다. 메써드의 컴파일 폼을 프로그램이 버리도록 하기 때문에 메모리에 여지를 주는 방식이다. 세 번째로는(버전 1 릴리즈에는 포함되지 않았다) "OptJIT"이며, 약간 다른 방식으로 작동한다. OptJIT는 부가적인 정보를 갖는 IL의 하부셋이다. 즉, IL을 좀더 최적화시킴으로써 JIT 컴파일 과정에 머신 코드의 질을 떨어뜨리지 않고 오버헤드도 줄인다.

다른 문제는 당연히 퍼포먼스이다. JIT 컴파일은 프로그램의 실행 자체의 결과는 좋게 만들지만, 로딩 시간이 매우 길어질 수 있으며, 컴파일러 수행의 최적화를 수행할 필요가 사라질 수도 있다. 이 문제를 다루기 위해, form — ahead-of-time (AOT) 컴파일의 메커니즘이 있다. 원래는 "PreJIT"라고 불렸지만 현재는 NGen (for Native [code] GENeration)이라 불리며, 수많은 핵심 프레임웍 파일이 로딩 오버헤드를 줄이기 위해 이 방식으로 컴파일 되고 있다. IL 버전은 아직이며, PreJIT이 어떠한 이유로 시스템에 부담을 준다면, 원래의 JIT 컴파일로 돌아갈 수 있다. 불행히도, CLR 버전 1은 AOT 파일을 재조작을 할 수 없으며 수동으로 일일이 해줘야한다.

현재의 NGen은 단순히 똑같은 JIT 컴파일러를 사용하고 있으며 더이상의 최적화를 하고 있지 않으며 특별히 JIT 컴파일러가 프로파일링이나 재컴파일을 하는 것도 아니다. 어느 정도 실망스럽다고 하고 있으나 PreJIT가 보통의 JIT를 이용해야할 이유는 없다. 보통의 JIT 역시 컴파일을 일방통행식으로 해야할 이유도 없다. 그러나 마이크로소프트의 첫 번째 릴리즈에는 이 기능들이 없다. 가령, JIT 컴파일러의 프로파일링은 자바에서 거의 일반화되어가고 있으며, 네이티브 코드 컴파일러의 최적화는 득이면 득이지 전혀 해가될 수 없다.

JIT 컴파일링이 특정 프로세서를 가리는 것 때문에 아이태니엄(Itanium, 즉 모든 IA64 프로세서)과 같은 프로세서에 대한 우려가 나오고 있다. IA32/x86 세계에서 표준화된 프로세서는 실행을 효율적으로 하기 위해, 머신 코드를 리스케쥴링하지만, IA64 디자인에서는 퍼포먼스를 높이기 위해, 인스트럭션을 지시하는 컴파일러에 의존한다. 즉, 프로세서의 다이나믹 인스트럭션 리스케쥴링은 IA64의 디자인 전체에 위반한다. IA64 아키텍쳐에서의 인스트럭션 오더링은 명쾌하기에, 컴파일링은 더욱 어려워졌다. 즉, 앞으로는 가능할 때 코드의 리-오더링을 할 때 프로세서에 의존할 수가 없다. AOT로 처리하기는 어려운 일이기 때문에 다이나믹하게 처리를 할 수 있을 지 어떨 지는 두고봐야할 일이다. IA64 급 프로세서에서 퍼포먼스를 어느 정도 납득할 수 있도록 하려면, 모든 것을 AOT로 컴파일해야한다.

singleFileAssembly.pngmultiFileAssembly.png


어셈블리는 싱글 파일도 될 수 있고 멀티 파일도 될 수 있다. 한 파일은 마니페스트를 가지며, 어셈블리의 다른 부분은 그 구현을 갖고 있다. 싱글이건 멀티이건 어셈블리는 단일 유닛을 구성하며, .NET이 관여하는 한 하나의 핵으로 간주한다.

싱글 파일 어셈블리는 단일 파일 안에 마니페스트와 필요한 모든 리소스를 모두 갖고 있으며, 멀티 파일 어셈블리는 외부 리소스(비트맵, 아이콘, 사운드 등)를 갖거나 코드 코어나 다른 헬퍼-라이브러리를 갖는 다른 파일로 구성되어있다. 멀티 파일 어셈블리에서 마니페스트는 PE에 있거나, PE 그 자체, 혹은 IL과 메타데이터에 따라서 있는 PE이다.

어셈블리는 공유를 하거나 하지 않는 편도 가능하다. 프라이빗 어셈블리는 애플리케이션의 디렉토리 안에서 GAC(the Global Assembly Cache)라고 불리는 커먼 어셈블리 리포지토리(현재 %systemroot%\\Assembly)를 공유한다. 버전 콘트롤은 저작자에게 맡겨져 있으며, 어셈블리 이름은 단순히 마니페스트를 갖는 파일 이름일 뿐이다.

공유 어셈블리는 다중의 저자가 사용할 수 있기 때문에 엄격한 버전 콘트롤과 어셈블리 이름이 단일해야한다는 메커니즘을 가지고 있다. 또한 몇 가지 부가적인 정보가 있으며, 보안 키, "퍼블릭", "프라이빗" 키도 갖추고 있다. 프라이빗 키는 어셈블리 크리에이터가 보호하며, 퍼블릭 키는 마니페스트에 존재하며, 마니페스트를 갖는 파일은 프라이빗 키 값을 hash한다. hash는 입력으로부터 수치를 제어하는 과정(이경우는 마니페스트를 갖고 있는 파일이다)을 일컬으며, 인풋->hash만 가능하다. 또한 이 알고리즘으로 조금만 파일에 변화를 가해도 hash는 다른 결과를 내며, 서명한 hash는 곧 어셈블리의 디지탈 서명을 의미한다.

공유 어셈블리를 읽을 때 어느 어셈블리를 읽어들일 지 인증을 위해 사용하는 요소들은 다음과 같다.

* its name
* its public key
* its version
* its locale

위의 정보가 모두 있어야 동일한 어셈블리의 다중 버전 공존을 허용할 수 있다.(GAC는 1.0.0.0/영어와 1.0.0.0/서반아어, 2.0.0.0영어 어셈블리를 갖고 있는 듯 하다. 그래야 프로그램이 원하는 버전을 사용할 수 있다.) 어셈블리를 GAC로 설치할 때 시스템은 마니페스트 파일 자신을 hash한 다음에, 저장된 서명을 퍼블릭 키를 이용하여 확인한다. 디지탈 서명의 작동 원리에 대해서는 다음의 사이트를 확인하기 바란다.

나머지 확인은 런타임할 때 일어난다. GAC에서 어셈블리를 읽어드릴 때, 제일 먼저 하는 일은 GAC 안에 있는 어셈블리의 퍼블릭 키와 기록상의 관련 어셈블리 퍼블릭 키의 비교이다. 매치가 안되는 경우는 "예외"를 보내고, 어셈블리가 다중 파트로 이뤄져 있다면 각 부분을 읽을 때 hash한다. 이 hash는 마니페스트에 저장된 값과 다시 비교하여, 매치가 안될 경우 역시 예외를 보낸다.

gacThumbnail.png

The GAC in Explorer

특정한 어셈블리의 이용이 필요할 때면, 이름 매치와 퍼블릭 키, 버전, 로케일 등에 대해 GAC가 있어야한다. PE 파일의 확인에서처럼, 어셈블리의 컴퍼넌트도 hash를 이용하여 같은 방식으로 확인을 하며, 어셈블리가 매치된다면, 애플리케이션은 어셈블리를 읽을 수 있다.

Why is this important?

.NET은 ".dll 지옥"에서 해방됐다. 똑같은 어셈블리의 다중 버전이 GAC 안에서 공존할 수 있으며, 더이상 하위 호환성을 위해 라이브러리를 필요로하고 있지 않다. 즉, (심지어 같은 프로그램 안에서도)프로그램은 기대하는 버전을 언제나 얻는다. 웹 서버를 운영한다면, 서버 안에서 같은 애플리케이션의 다중 버전을 사이드-바이-사이드로 돌릴 수 있다는 의미이다.

이러한 보호책은 한 번 나온 파일을 변경시키지 않는, 이를테면 바이러스와 같은 것을 막기 위함이다.

Metadata

매니지드 코드의 중요한 기능 중에 하나가 메타데이터이다. 메타데이터는 데이터를 묘사하는 데이터이며 .NET에서는 모든 방식의 메터데이터가 쓰인다. 언급했듯이, 특정 어셈블리를 일컫는 정보가 존재하며, 어셈블리 위의 어셈블리도 존재한다. 이때 어셈블리가 필요로하는 보안 자체도 정보화된다.

이 정보에는 어셈블리가 제공한 타입/클래스와 함께 메써드의 인터페이스, 멤버의 정의도 포함한다. 메타데이터가 중요한 이유는 꽤 있다. 메터데이터로 어셈블리를 자기설명하게 할 수 있다. 메타데이터의 정보는 C/C++ 헤더 파일과는 달리 언제나 정확하다. C/C++에서 헤더에 있는 인터페이스는 라이브러리의 변화에 따라 변화할 수 있으며, "부정확"한 문제를 가지고 있다. 또한 메타데이터는 COM 개발에서 사용하는 Interface Description Language (IDL)과 같은 인터페이스가 필요없으며, (다른 언어의) 클래스가 상속할 수 있도록 클래스를 정의내리기도 한다.

메타데이터로 속성(attributes)도 있다. 속성은 그 자체로 기사를 하나 따로 써야할만큼 중요하다.

Attributes

속성은 컴파일-타임과 런-타임 환경을 변경하는 융통성 있는 방법을 제공한다. 실제로 DllImport라는 속성이 있다. 이 속성은 .NET 라이브러리보다는 네이티브 라이브러리(DLL)로부터 입수해야하는 함수를 지시하는데 쓰인다. DLL에서 함수를 호출하기 위해, 적절한 함수 프로토타입을 작성하고, 이 프로토타입이 런타임을 나타내도록 속성을 연결한다. 즉 "이 라이브러리로부터 이 함수에 대한 코드가 필요하다"고 말하는 것이다. 런타임 자신은 복잡한 사항은 숨겨서--이러한 입수 함수는 IL이 아니며, 네이티브 코드이다-- 다른 중요한 일에 집중할 수 있도록 배려해준다.

이를테면 속성은 컴파일-타임에도 필요할 때가 있다. 가령 필요없어진 함수를 표시해서 컴파일-타임에서 해당 함수의 업데이트가 필요하다는 경고 메시지를 내는 속성도 있다.

원하는 방식으로 움직이는 속성이 없다면 여러분 자신이 속성을 정의내려야한다. 예를 들어서, 마지막으로 변경했을 때 누가 변경했는 지를 알리는 속성이 필요할 때가 있다. 이 속성을 정의하려면, System.Attribute을 유도하는 클래스를 작성하기에, "이름" 정보와 "변경 날짜" 정보를 갖는 속성을 정의내릴 수 있다. 코드를 작성하는 프로그래머들은 이 속성으로 코드의 주해를 달기도 한다. 그러면, 런타임에서 각 클래스를 누가 언제 작성했는지 알 수 있기 때문이다. 물론 복잡한 기능(이를테면, COM 코드를 전혀 사용하지 않고서도 .NET 클래스를 COM 클래스로 바꿔주는 속성도 있다)을 갖는 속성도 존재한다.

Language neutrality

IL을 타겟으로 삼을 수 있다면 그 언어는 .NET의 근본 기능을 갖추고 있는 셈이다. 여기서 클래스(.NET에서는 "types")를 정의내리는 건 Common Type System (CTS)이며, CTS는 클래스가 가질 수 있는 멤버 함수(메써드)나 멤버 변수(필드), 프로퍼티 등의 각기 다른 기능들을 갖고, 이들 아이템이 가질 수 있는 다른 종류의 "visivility"를 갖는다. 또한 클래스 상속 방법을 정의내리며, 모든 클래스는 결국 System.Object에서 유도해야하기 때문에, 단일 상속만 지원하게된다.

OO(객체 지향) 언어를 디자인해본 이들이라면 친숙한 개념일 것이다. 각기 다른 컴파일러로 호환성 있는 객체를 만들기 위해 이런 표준화는 중요하다. C#이건 VB이건, JScript이건 다른 언어이건 똑같은 아웃풋을 낼 수 있기 때문이다.

또한 아웃풋은 특정한 방식으로 돌아가며 원래 어떻게 만들어진 것과는 더이상 상관이 없다. C#에서 작성한 클래스를 VB에서 상속받을 수도 있으며, 곧바로 C++로부터 끌어낼 수도 있다. 차이 없이 모두 투명하게 작동한다.

CTS를 될 수 있는 한 투명성있게 디자인했다고 하지만 제한이 없는 건 아니다. C++ 프로그래머들은 다중 상속(단, 다중 인터페이스는 허용한다)을 포기해야하며, 대소문자 구분도 사라진다.

.NET은 상당히 언어 독립적이다. 아직 많은 언어들이 베타단계이고, 수많은 그룹들이 .NET 디자인에 이들 언어를 연결하는 시도를 벌이고 있다. 그 결과 IL은 특별한 인스트럭션을 갖게 됐다. 이중 하나로 "tail call" 인스트럭션이 있는데, 이 함수 호출은 한 루틴의 최종 호출(엄격한 언어에서는, 규정하지 않은 결과값을 되돌리는데 이때 사용하는 함수 호출이 tail call이다)이다. 구조적인 언어에는 꽤 중요한 기능으로서 보통 iteration보다는 recursion을 사용한다. 귀납(recursive) 함수는 tail call을 사용해서 상당한 최적화를 이루기 때문이다. IL은 그러한 호출을 tail call 인스트럭션으로 표현하며, 컴파일러를 그만큼 쉽게 최적화시키고, JIT도 그만큼 최적화된 코드를 낼 수 있게 한다.

Safety

CLR의 장점 중에 하나는 프로그래머들이 모험을 못하게 막는 것이다. 최근에 이렇게 바뀐 언어로는 C++가 있다. 원래 C++는 모든 종류의 트릭이나 실수를 허용했다. 가령, 한 메모리 블럭을 배정해서 데이터를 과도하게 투입했을 때 원래 메모리 블럭 이상의 점유가 가능하도록 하거나, 한 타입이 다른 타입인양 꾸미고, 메모리에 접근해서 콘텐트를 바꿔버릴 수도 있었다.

물론 해가 없을 수도 있지만 위험할 경우도 많다. 제일 잘 알려진 사례로는 버퍼 오버플로우가 있다.

이런 문제를 막기 위해, 런타임에서, 권한이 없는 한 그런 프로그램을 못돌리게 할 수 있다. 만약 버퍼 이상을 작성한다면 이를 예외로 처리해버릴 수도 있을 것이다. 안전하지 않은 타입을 사용하려할 경우에도 마찬가지이다. 문제가 없는 건 아니다. 런타임이 코드가 안전한 지 모를 경우도 있기 때문이다. 이경우에는 권한을 이용(즉, 신뢰성있는 소스에서 나온 코드임을 보이는 등이다)할 수 있다.

CLR은 Windows for ActiveX 컨트롤에서 사용하는 제한과 비슷한 제한을 사용하기도 한다. 즉, 웹에 임베딩된 객체가 화면상에 나타날 때 하드 디스크에 대한 접근은 하지 못하도록 하는 등이다. CLR에서 돌아가는 프로그램에 모래 상자를 배치하는 격이다. 관리자는 기본 설정을 바꿔서, 특정한 디지탈 서명이 있는 경우 컴퍼넌트를 다운로드받을 수 있도록 할 수도 있다.

이런 보안은 "stack walk" 조사에 의존한다. 이 호출 스택은 스택 "위(above)"의 함수가 호출한 활성(끝나지 않은) 함수를 표현한다. 호출 스택은 메모리 안 어디엔가 존재하며(각 쓰레드 중 하나이다), 함수를 호출할 때마다 스택상의 위치는 메모리 아래로 움직인다. 위로 움직이는 스택은 현재의 함수를 호출한 함수로 향한다는 의미를 갖는다(결국, 첫 번째 호출 함수가 데이터를 갖고 있는 스택의 맨 앞으로 갈 수 있다). 함수는 특정한 권한을 요구할 수 있으며, 그럴 경우 런타임은 콜 스택을 조사해서 권한이 정당한 지를 판단한다.

stackWalk.png


예를 들어서, 인터넷에서 어셈블리를 다운로드한 다음에 하드 디스크에서 읽어야할 때가 있다. 다운로드받은 어셈블리(표에서 A1)는 시스템 어셈블리에 호출을 만들어야하며, 다른 시스템 어셈블리를 호출하기도 한다. 결국, 실제로 도달하는 장소는(어셈블리 A4 내부) 하드 디스크 내부가 된다. 여기에는 권한(P)이 필요하며, 권한이 없는 경우 "exception"으로 나와버린다. 여기서 ActiveX 보안 모델과의 차이가 있다. 액티브X의 경우는 전체 컴퍼넌트가 안전하다는 전제를 하기 때문에 위험할 경우가 많다. .NET에서의 보안은 호출을 만들어내는 코드가 필요한 권한이 있는 지를 확인함으로써 이 문제를 해결하였다.

The class library

.NET은 상속 클래스의 단일-루트 계층을 제공한다. 네임스페이스의 루트는 System이며, 시스템은 Byte, Double, Boolean, String, Object와 같은 기본 타입을 갖고 있으며 모든 객체는 System.Object에서 유도한다. 객체는 물론, value type도 있는데, 스택상에 value type을 배치(힙 상에 배치하는 것보다 일반적으로 더 빠르다)해서 유용한 융통성을 제공할 수 있다. 원한다면 value type을 객체 타입으로 바꿔주는 효율적인 방법들도 존재한다.

클래스 집합은 콜렉션과 파일, 스크린, 네트웍 I/O, 쓰레딩 등은 물론 XML과 데이터베이스 커넥션도 제공한다.

클래스 라이브러리는 몇 가지 집합으로 나뉘어져 있으며 각기 다른 영역을 가지면서 의존도를 최소한으로 줄인다. 필요한 클래스만 제공하여 더 구현하기 쉽게 하기 위함이다.

What it's all for

CLR과 라이브러리는 소프트웨어 개발 플랫폼으로서 매우 다재다능하다. 많은 부분이 서버/웹 애플리케이션 용이긴 하지만 .NET은 클라이언트-사이드 개발도 노리고 있다. 전통적인 애플리케이션은 물론 강력한 웹-기반의 애플리케이션도 마찬가지이다. 좀더 간결해진 보안 컨트롤이 가능해졌을 뿐만 아니라, 좀더 강력한 UI 기능을 더 쉽게 만들 수 있기 때문이다. 마이크로소프트에 따르면 보안성이 없는 ActiveX는 이제 한 물 갔으며, (윈도우즈 폼을 이용하는).NET은 진정한 보안을 구현하기 때문에 이제까지 VB나 MFC를 이용해온 Win32 개발을 결국 대체하리라고 한다.

서버 애플리케이션 개발의 주요 기능 중 하나는 웹 서비스이다. 웹 서비스는 전통적인 클라이언트 애플리케이션이나 웹 기반의 클라이언트 애플리케이션, 혹은 또다른 웹 서비스가 "소비(사용)"하는 컴퍼넌트를 웹 서버에서 돌린다. 소비는 접근 콘트롤로써 WSDL (Web Service Description Language)과 연계하여 XML을 이용해 HTTP로 원격 프로시져를 호출하는 메커니즘인 Simple Object Access Protocol (SOAP)으로 이뤄진다. WSDL은 웹 상에 올라가는 인터페이스를 설명하는 데 사용하기 때문에 서비스 소비자는 이를 어떻게 이용할 지를 미리 알고 있다. SOAP은 실제로 소비할 때 이용하며, .NET 라이브러리의 클래스들이 이 과정을 쉽게 만든다.

또한 .NET으로 CLR 외에 존재하는 코드나 .NET 내부의 언매니지드 코드를 이용할 수 있다. 언매니지드 코드는 계속 .NET 클래스 라이브러리의 장점을 취할 수 있으면서 IL로 컴파일도 가능하지만, 가비지-콜렉션 힙을 사용하진 못한다. 다만, 네이티브 코드를 만들어서 더 나은 퍼포먼스를 위해 .NET으로 방출할 수 있다.

프레임웍은 두 가지 컴퍼넌트, CLR과 클래스 라이브러리를 갖는다. 하지만 마이크로소프트는 .NET이 세 개의 주 컴퍼넌트(여전히 마이크로소프트는 .NET이 무슨 플랫폼인 지에 대해 왔다갔다하고 있다. 나머지 하나는 ASP.NET이다.)를 갖는다고 보고 있다. 하지만 세 개의 컴퍼넌트일 경우에는 문제가 있다. ASP.NET은 이름이 말하듯, .NET 기술을 이용하는 Active Server Pages의 한 버전일 뿐이며, .NET 호스팅 애플리케이션의 사례를 나타내는 것 이상이 아니다. ASP.NET이 웹 애플리케이션 저작에 멋진 환경을 제공하긴 하지만, 근본 기술이라고는 할 수 없다. ASP.NET은 .NET 환경 안에서 애플리케이션을 돌리며, 이들 애플리케이션에 클래스를 제공하는 역할만을 하기 때문에 그 자체가 .NET의 주요 부분이랄 수는 없다. CLR을 호스팅하는 기능은 다른 프로그램(확장성을 위해 액티브X 스크립팅 랭귀지를 호스팅하는 등 오히려 더 유용한 방법들이 존재한다)에도 개방되어있기 때문이다.

Is this MS's [latest] attempt to kill Java?

.NET이 무엇이고 뭘 하는 지에 들었을 때, 자바와의 비교는 필연적이다. 두 플랫폼은 여러가지 측면에서 비슷하기 때문이다. 우선 간단하게나마 비교해보겠다.

자바는 다음 세 가지 기능을 위해 사용한다.

* The Java language. C 스타일의 객체-지향 언어
* The Java class library. 포괄적인 클래스 라이브러리 상속
* The Java Virtual Machine (JVM). 자바 바이트코드로 컴파일하여 자바 가상머신에서 실행한다.: 전통적으로 네이티브 코드로 컴파일하진 않지만, 높은 퍼포먼스를 갖는 가상 머신의 경우 하드웨어에 네이티브 명령을 내리는 on-the-fly 컴파일을 한다.

.NET은 여기에서 두 번째와 세 번째에 해당하지만 첫 번째는 아니다(.NET은 IL을 가지며, 하이-레벨 언어라기보다는 자바 바이트 코드와 비슷하다고 볼 수 있다). .NET은 언어에 그리 구애받지 않는다. C# 클래스에서 VB.NET 클래스를 유도할 수도 있고, 매니지드 C++ 프로그램에서 사용할 수도 있다. (각기 다른 언어의 사용은 프로그래머가 직접 볼 수 없다) 자바 바이트코드 역시 여러가지 언어로 컴파일할 수 있지만, 자바를 언어에 중성적으로 만들진 못한다. 이들 언어는 자바로 작성한 스크립트 인터프리터에 불과하며(자바 바이트코드를 만들지 못하며, 이들 스크립트는 자바 플랫폼이 인식하지 않기 때문에 자바 기능들을 이용할수 없다), 자신의 여러가지 기능들을 포기해야한다. 자바 클래스와 연동하는 언어들도 있긴 하다(예를 들어서, Jython이 있다). 사용하는 언어의 혼합과 매치하는 기능으로 한 언어 클래스를 작성한다든 지, 다른 언어에서 상속받는다던지 등의 기능은 자바에는 없다.

클래스 라이브러리는 꽤 일반성을 갖추고 있으며 어느정도 현재 .NET보다는 더 확장적이다. 물론 .NET이 더 잘 개발된 영역도 존재한다. (이를테면 폼 제작)

현재 자바 가상 머신은 원래의 JVM 아이디어(가상 머신에서의 바이트코드 수행)에 기초하고 있으며 퍼포먼스 향상을 위해 바이트코드를 네이티브 코드로 컴파일시키고 있다. .NET은 여기에서 바이트코드->네이티브 코드 컴파일에 해당한다. IL 가상 머신(혹은 매직-MAJC;썬의 프로세서-스타일의 물리적인 머신)을 작성할 수 없기 때문은 아니다. .NET은 이점을 가상 머신에서의 수행을 염두에 두고 있지 않다. JIT 컴파일은 AOT로 컴파일한 특정 클래스를 갖춘 전형이다.

매개 언어의 성격은 꽤 다르다. IL은 일반적인 인스트럭션(이를테면, 수가 정수이건 플로팅 포인트이건, 두 개의 수를 더하는 연산)을 이용하기 때문에 인터프리팅으로는 적합하지 않다. 인터프리터는 모든 종류의 정보를 다뤄야하며, 자바 바이트코드는 인스트럭션 그 자체에 특화되어있다. 즉, 자바 바이트코드는 정수와 플로팅 포인트 연산을 따로따로 한다. 다르게 말해서, 자바 바이트코드는 자바 언어가 갖고 있는 한계를 가지고 있기 때문에 오히려 IL이 더욱 일반성을 갖췄다고 할 수도 있다. IL 디자인은 다른 언어들의 영향을 받아서필요한 기능들을 더했다고 할 수 있다. 결과적으로 IL은 앞서 언급한 tail call 인스트럭션과 같은 기능을 가지고 있으며, 그런 언어의 구현에는 자바의 바이트코드보다 더 적합하다.

These differences add up.

우선, 개발자들에게 제일 분명한 차이점은, 환경이 사용하라고 강요하는 것이 아닌, 원하는 언어, 혹은 보다 적합한 언어(.NET 컴파일러와 관계된 언어)를 사용할 수 있는 쪽이 .NET이다. C++이나 비쥬얼 베이직 프로그래머들도 쉽게 .NET으로 이주할 수 있기 때문이다. 또한 MS는 비쥬얼 J# 베타 버전을 출시했는데, 비쥬얼 J#은 비쥬얼 J++ 프로그래머들을 위한 업그레이드로서 .NET 컴파일러와 여러 클래스 라이브러리가 들어있다. 여기에서 자바 언어와 자바 클래스 라이브러리(버전 1.1.4를 요구한다)를 구현할 수도 있다.

.NET and COM.

MS는 그동안 언어와 플랫폼을 상호 독립적으로 만들었으며, Component Object Model (COM)으로 나타났다. .NET와 COM은 겹치는 부분이 꽤 있다. .NET은 프로그래머들이 COM에서 다뤄야하는(적어도 C/C++ 프로그래머나 비쥬얼 베이직 프로그래머들인 이점에서 더 차이점이 없어진다) 자질구레한 사항들을 숨긴다. COM은 모두 네이티브 코드이며 완전히 기술을 활용하기 위해 수많은 로우-레벨의 사항들을 숙지해야한다. .NET은 이문제를 숨겼고 알아서 해결해준다.

다르게 말하자면, COM은 이점에서 장점을 지니고 있다. COM/DCOM의 기반(Win32 머신이면 어디든 쓸 수 있다고 볼 수 있다)은 막대하며, 윈도우즈의 새 버전일 수록 COM/DCOM을 십분 활용하고 있다. 수많은 윈도우즈 파트들이 COM 컴퍼넌트에 의존(대표적으로 윈도우 탐색기/인터넷 익스플로러가 있다)하고 있으며, 수많은 애플리케이션 역시 COM과 밀접한 관계를 가지고 있다. 당분간은 어느정도로라도 .NET이 COM을 대체할 수는 없다. 물론 언젠가는 COM도 발목을 잡는 옛날 기술이 될 테지만 말이다.

하지만 좋은 소식도 있다. .NET에서 COM 컴퍼넌트를 사용할 수 있으며, .NET 객체를 COM 컴퍼넌트로 낼 수 있다. 프로그래머는 코드에 약간의 속성을 추가하면, COM 컴퍼넌트처럼 .NET 클래스를 사용할 수 있다. 따라서 .NET과 COM 사이에 연결 통로가 있다고 할 수 있다. 모든 자질구레한 사항은 속성이 다루는 한편, .NET과 COM이라는 두 가지 별다른 기술을 몇 라인의 코드만으로 연결할 수 있다는 의미이다.

Why haven't I mentioned C#?

C#은 MS의 새로운 언어이며, C-스타일로서, "C++ for Rapid Application Development"라고 부를 수 있다. C#은 갑자기 나타난 괴물이나 다름없다. 다른 언어, 특히 C와 C++와는 달리 C#의 스펙은 언어 문법만이 전부이고, 자신만의 표준 라이브러리(즉, "studio.h"나 "iostream"과 같은 라이브러리)가 없고, 대신 .NET 라이브러리를 자신의 라이브러리로 사용한다. 즉, 이점때문에 C#은 .NET에 매우 의존적인데, C#이 .NET의 부분은 아니다. .NET에서 C#만의 특별한 역할이랄 것은 그저 다른 .NET 언어들처럼 IL로 컴파일한다는 것 뿐이다. 따라서 .NET 없이 C#은 살아남을 수가 없는(.NET이 없다면 C#은 수많은 네이티브 라이브러리를 잃고 만다) 반면, .NET이 꼭 C#을 필요로하진 않으며, 오히려 C#이 없음으로써 더 완전해질 수도 있다. C#은 .NET이 없으면 안되는 반면 .NET의 대부분의 기능은 C#을 요구하지 않는다.

.NET and standards

여러 공개 표준이 .NET에서 쓰인다. 웹 서비스는 SOAP(HTTP상에서 XML 데이터를 사용한다)를 이용하며, 웹 서비스 학습에는 UDDI가 쓰인다.

.NET 그 자체도 표준화 노력의 일환이다. CLR은 CLI — Common Language Infrastructure — ECMA 멤버인 Technical Committee 39에서 관장하는 표준이며, C#과 CLI 표준을 정하여 ISO에 등록한다.-라고 불리는 것의 수퍼셋이다. 이 기술 위원회 39는 그 외에 ECMAScript(자바스크립트/J스크립트 기반의 스크립팅 언어이다) 표준도 작업하고 있다.

CLI은 타입과 클래스, CLI 코드의 메써드, 코어 클래스 라이브러리 등을 밝히는데 사용하는 Common Language Specification (CLS)도 관장한다. 언급한데로 C#의 스펙도 이와 함께 개발되고 있다.

우선 확실히 밝혀야할 점은, .NET 그 자체가 "공개"는 아니라는 점이다. .NET은 하나의 구현일 뿐이며 "공개"를 의미하지는 않는다. 물론 .NET은 공개 표준에 대한 하나의 구현이며, .NET의 핵심은 ECMA 등의 표준을 구현한다.

.NET은 수많은 영역의 스펙을 넘나든다. 특히, .NET 스펙에는 ADO.NET(MS의 하이레벨 데이터베이스 API인 ADO의 .NET 버전이다)이나, WinForms(윈도윙 기능을 제공한다)를 포함하고 있지 않다. 이들은 ADO/OLEDB(MS의 데이터베이스 접근 아키텍쳐)와 GDI+(Win32 OS를 위한 새로운 객체 지향 그래픽 API 애드온이다), ASP.NET(훨씬 향상된 ASP 버전이다)을과 밀접한 관련을 맺고 있으며, 현재 ECMA 방침은 "기본 클래스 약간"만을 제공하고 있기 때문에 이들이 누락되어버렸다. 물론 앞으로 표준 클래스 라이브러리가 이들을 모두 통합할 것임은 의심의 여지가 없다.

CLI 구현을 MS만 하고있지는 않다. MS 외에 FreeBSD에서 제공하는 프로젝트로 Mono가 있다. 모노는 Ximian이 개발했으며, 모노에는 ADO.NET과 WinForms가 포함되어있다. WinForms 컴퍼넌트는 GTK+를 사용하며, ADO.NET은 GNOME-DB를 사용한다. 열거한 사항에 대해서는 여기서 읽을 수 있다.

이제까지 .NET의 근본을 다뤘다. 언급하지 않은 부분은 등록 소프트웨어인데, 등록 소프트웨어 부분은 그동안 수많은 컴퓨터 관련 매체에서 다뤘으며, .NET 자체가 등록 소프트웨어는 아니다. 즉, 여기서 의문을 가질 수 있다. 왜 .NET이 등록 소프트웨어로 알려져 있을까? 아마도 등록 소프트웨어의 메커니즘으로 사용할 수 있는 .NET의 웹 서비스 메커니즘 때문일 테지만 여기에 대해서는 다음 기사에서 다루도록 하겠다. 다음 기사는 .NET 애플리케이션의 구축과 .NET 상에서 만드는 소프트웨어/서비스에 대해 알아본다.

A big thank you to Handor, for your invaluable feedback input.

Assembly and stack walk images © Microsoft Corporation. Public-key encryption and digital signing images © Netscape Communications Corporation. Article text © Peter Bright.

위민복님의 글입니다.
http://casaubon.tv
0 0
로그인 후 추천 또는 비추천하실 수 있습니다.
회원사진
포인트 765,229
가입일 :
2002-05-23 22:53:10
서명 :
KMUG 애플에 대한 모든 것. 케이머그
자기소개 :
2000년 3월 1일 부터 시작 http://www.kmug.co.kr webmaster@kmug.co.kr

최신글이 없습니다.

최신글이 없습니다.

댓글목록 0

등록된 댓글이 없습니다.
전체 2,464 건 - 243 페이지
2003.01
31

[wave] around my office my apple note (photo 3)

안녕하세요 제 오피스를 궁금해 하시는 분들이 있어서 사진을 올립니다. 아울러 제가 가지고 있는 애플 로고 컬렉션의 사진과 "To the crazy ones"의 원본 스캔을 올립니다. 요즘 글을 쓸 시간이 없네요. 당분간 제가 좀 바쁜 관계로…

2003.01
31

[wave] 초기의 APPLE Computer my apple note (photo 2)

안녕하세요 요즘 새로나온 아이맥때문에 들썩거리는군요. 오늘은 머리도 식힐겸 과거로 돌아가 보실래요 애플 초기의 컴퓨터 사진들을 올려 보았습니다. 아마 처음 보시는 분들도 많으리라 생각됩니다. 참고로 이 사진들은 제가 직접 찍은 것들입니다^^…

2003.01
31

[wave] OS X의 탄생 my apple note (4)

안녕하세요 새해를 맞이하는 애플 노트입니다. 오늘은 오에스 텐의 개발과정에 대해 써 보겠습니다. *__* 4. Mac OS X의 탄생 2001년 맥유저들의 화제는 단연 오에스 텐이었다고 할 수 있겠습니다. 물론 애플을 큐브의 실패 …

2003.01
31

[wave] 애플 주변 사진들 my apple note (photo1)

안녕하세요 요즘 연말이라 바쁘시죠 원래는 소프트웨어와 하드웨어의 테스팅에 관해 써보려하다가 도저히 시간이 안나길래 그냥 사진 몇장 올립니다. 참고로 이 사진들은 일전에 회사내의 쇼트 무비 콘테스트 할 적에 다운받았던 퀵타임화일에서 뽑아낸 것입니다…

2003.01
31

[wave] 애플의 분위기 my apple note (2)

안녕하세요 2. 애플의 분위기 미국 서부의 회사들이 동부에 비해 훨씬 자유분방하고 격식을 덜 차린다는 것은 널리 알려진 사실입니다. 그중에서도 특히 애플은 격식을 잘 안따집니다. 다른 회사에서 일하던 경험이 있는 사람들은 실리콘 밸리 어느곳…

2003.01
31

[wave] 애플의 위치 my apple note(1)

안녕하세요 어느덧 직접적이던 간접적이던 실리콘 밸리와 인연을 맺고 이곳 물을 먹은지 5년이 지났군요. 5년전 미국에 생전 처음 발을 디디고, 그 말로만 듣던 실리콘 밸리라는게 이 지역인줄 그때야 알았습니다. 아시는 분은 아시겠지만 실리콘 밸리라…

2002.09
23

피터 드러커가 말하는「지식 사회」

요사이 새로 리믹스되어 다시 불리는 '노래를 찾는 사람들'의 노래 '4계(四季)'는 시간을 노래하고 있다. 가사를 가만히 듣고 있노라면 어떤 직공이 공장에서 보낸 1년의 세월이 보인다. 4번의 계절이 바뀌면 1년의 세월이 흐른다는 것을 말해주고 있는데…

2002.09
21

열람중 .NET 플랫폼 분석

Microsoft .Net by DrPizza .NET에 대해서 수많은 "명망있는" 미디어/언론들이 다뤘지만 이들의 .NET 기사들은 대부분 .NET의 성격이나 목적, 구현 방법들에 대해 잘못 전하고 있다. .NET이 무엇인지 묻는다면 아마도 답…

2002.09
02

랑데부의 잠재성

Rendezvous: It's Like a Backstage Pass to the Future Introduction 샌프란시스코에서 맥월드 엑스포 기조연설을 하기 전에 애플은 "그 어떤 PC도 못따라올 정도", "루머 사이트 이상"이라는 …

2002.09
02

휴대폰의 일상화

When the Cellphone Is the Home Phone By SIMON ROMERO 최근, 부인과 함께 맨하탄의 Upper West Side에서 할렘의 더 큰 아파트로 이사왔을 때였다. 이사 자체는 지도상의 짧은 여행에 불과했지만 기술…