by 쭈안 타이, .NET Framework Essentials의 공동저자
상용 소프트웨어 산업에서 마이크로소프트가 내놓은 다른 기술과 비슷하게, 마이크로소프트 닷넷은 이전에 나온 성공적인 기술에서부터 장점을 취하고, 실용성을 높였다.
마이크로소프트의 닷넷 프레임워크와 그 목표를 진정으로 이해하려면, 오늘날 소프트웨어 산업 전반에 걸쳐 사용되는 여러 가지 주요 개념을 살펴보고, 장점과 단점을 분석해 보아야 할 것이다. 다음 개념이 중요하다.
- 분산 컴퓨팅: 강력한 클라이언트와 서버 애플리케이션 개발을 단순화한다.
- 컴포넌트화: 다양한 곳에서 개발된 소프트웨어 컴포넌트 통합을 단순화한다.
- 엔터프라이즈 서비스: 트랜잭션이나 보안, 풀링을 하기 위한 코드를 작성하지 않고도 측량 가능한 엔터프라이즈 애플리케이션을 개발할 수 있다.
- 웹 패러다임 전환: 복잡한 웹 애플리케이션의 개발을 단순화해 주는, 웹 기술에 있어서의 변화
- 성숙 요인: 소프트웨어 산업에서 스케일이 큰 엔터프라이즈와 웹 애플리케이션을 만들면서 배운 교훈
위에 있는 아이템은 모두 중요한 원칙이다. 원칙 중에는 개발 편의, 컴포넌트 공유, 자원 공유, 표준화 등을 포함하는 것도 있는데, 이 모두가 웹을 편입하기 위해 필요하다.
앞으로 3부에 걸쳐 잘 알려진 여러 개념을 다시 짚어보는 기회를 갖도록 하겠다. 1부에서는 분산 컴퓨팅을 살펴보고, 그것의 목적, 문제점, 해결책 등을 조명해 볼 것이다. 이것은 마이크로소프트 닷넷의 목적과 직접적으로 연결되기 때문에, 각 개념과 장점, 목적을 익히는 것이 좋다.
분산 컴퓨팅
스케일이 큰 시스템은 한 대가 아니라 여러 대의 컴퓨터에서 실행된다. 이렇게 하는 가장 단순한 이유는 프로세스를 분산하기 위해서 이다. 각기 다른 컴퓨터에서 분산 기능을 하는 또 다른 이유는 비즈니스 로직에서 사용자 인터페이스 기능을 분리하고 시스템을 더 강력하게 하고, 보안을 강화하기 위해서 이다.
사용자 인터페이스를 비즈니스 로직에서 분리하면, 비즈니스 로직에서 사용자 인터페이스 개발을 더 쉽게 분할할 수 있다. 그러면 코드를 개발하고 관리하기가 훨씬 쉽다. 한 번 비즈니스 로직을 개발하면, 다음에도 그것을 재사용할 수 있다. 예를 들어서 두 가지 다른 사용자 인터페이스 애플리케이션에 비즈니스 로직 코드를 바꾸지 않고 동일한 비즈니스 로직을 사용할 수 있다.
후위 비즈니스 로직으로부터 사용자 인터페이스를 분리하는 또 하나의 중요한 이유는 강력함 때문이다. 클라이언트/서버 애플리케이션에서 서버는 100 개의 클라이언트에 서비스할 지도 모른다. 이 클라이언트 중 어느 하나가 일반 보호 오류(general protection fault)를 범한다 해도, 서버나 나머지 99개의 클라이언트의 실행에 영향을 끼쳐서는 안된다.
| |
|
| 이 글에서는 분산 컴퓨팅, 그것의 목적, 문제점, 해결책 등에 대해 살펴보고, 이러한 개념이 어떻게 마이크로소프트 닷넷의 목적과 직접적으로 연관되는지 설명할 것이다. |
|
| |
게다가 사용자 인터페이스, 비즈니스, 데이터 로직을 분할했을 때 시스템에 보안 속성을 추가할 수 있다. 예를 들어서 서버는 클라이언트가 서버에 접속할 때마다 인증을 하는 보안 기능을 공급할 수 있다. 심지어는 신뢰할 수 있는 클라이언트가 보내는 모든 요청을 승인하는 보안 로직을 추가할 수도 있다.
인증: 사용자 신원을 확인하는 것. "당신은 누구입니까?"라는 질문과 같다.
승인: 사용자가 특정 자원에 접근하는 것을 허용하는 것. "나는 당신을 압니다. 하지만 요청한 자원에 접근할 권한이 있습니까?" 라는 질문과 같다.
이런 이유로 클라이언트와 서버, 분산 컴퓨팅은 매우 매력적이지만, 전통적인 클라이언트와 서버 연산에는 부적합한 점도 있다. 이러한 문제와 해결책, 그리고 해결책의 바탕에 깔린 개념에 대해 알아보자.
문제점
클라이언트/서버 애플리케이션을 개발할 때마다 내무적으로 개발한 마샬링 코드(homegrown marshaling code)와 보안 기능과 같은 여러 가지 단조롭고 고된 일 등 반복적으로 일어나는 문제에 대처해야 한다.
내부적으로 개발한(homegrown) 마샬링 코드
클라이언트/서버 애플리케이션을 개발할 때, 애플리케이션 수준 커뮤니케이션 프로토콜을 디자인해야 한다. 그렇게 해야 클라이언트와 서버가 커뮤니케이션하고 서로 메시지를 주고받을 수 있다. 프로토콜 명세에는 verb나 지원 데이터의 크기를 위해 몇 바이트를 따로 두었는지 등을 정할 디자이너가 필요하다. 그러한 프로토콜을 개발하려면 네트워크 버퍼를 파스(parse)하고 프로토콜 규약 문서에 명시된 필요한 정보를 추출하기 위한 기본적인 코드가 필요하다.
애플리케이션 수준의 커뮤니케이션 프로토콜을 위한 코드에서는 애플리케이션 수준 프로토콜 네트워크 버퍼를 어셈블(assemble)하고 역어셈블(disassemble)할 수 있다. 이러한 이유 때문에 코드는 클라이언트와 서버 모두에 있다. 이것을
커뮤니케이션 층, 또는
마샬러(marshaler)라고 부른다. 애플리케이션 수준 프로토콜 네트워크 버퍼를 어셈블하고 역어셈블하는 것을 각각
마샬링(marshaling)과
언마샬링(unmarshaling)이라 한다.
애플리케이션 수준의 프로토콜을 디자인하고 개발하는 것은 사소한 일이지만, 에러가 나기 쉽고 시간이 많이 걸린다. 많은 개발자는 마샬링 코드에서 버그를 없애느라 미칠 지경이라고 한다. 하지만 일단 애플리케이션 수준 프로토콜을 디자인하고 개발하고 나면, 다른 클라이언트/서버 시스템을 개발할 때에도 똑같은 절차를 반복하면 된다.
내부적으로 개발한 보안 특성
인증과 승인 특성을 지원하고 싶다면, 스스로 그것을 디자인하고 개발해야 한다. 소프트웨어 회사에서는 다른 클라이언트/서버 시스템에서 재사용할 수 있는 자체 보안 모듈을 개발하기도 한다. 하지만 보안 모듈이 표준에 순응하지 않으며, 다른 시스템과 상호 운영성이 없다는 문제가 있다.
단조롭고 고된 일이 많다
서로 다른 네트워크 수준의 프로토콜(TCP/IP, 이름 있는 파이프, 넷바이오스(netbios) 등)을 지원하고 싶다면, 시스템에서 지원하려고 하는 네트워크 프로토콜의 각 타입에 대한 마샬러를 작성해야 한다. 각각에 대한 마샬러의 코드는 네트워크 프로토콜과 관련하여 사용한다는 사소한 차이점만 빼면 거의 같다. 모든 코드가 마샬러를 개발하기 위한 것이었으므로, 부가적인 네트워크 프로토콜을 지원하는 것은 단지 지루하고 힘든 일일 뿐이다.
이러한 일들은 운영 체제에서 모두 공급해야 한다.
해결책
| |
|
| 클라이언트/서버 애플리케이션을 개발할 때마다 내부적으로 개발한 마샬 코드(homegrown marshaling code), 내부적으로 개발한 보안 특성, 그리고 여러 가지 단조롭고 고된 일 등 반복적으로 일어나는 문제에 대처해야 한다. |
|
| |
전통적인 클라이언트/서버 애플리케이션에서는 반복적으로 해야 하는 일이 있다. 하지만 분산 컴퓨팅 환경의 원격 절차 호출(RPC: remote procedure calling) 기능을 이용하면 분산 애플리케이션 개발을 더 간단하게 할 수 있다. RPC를 사용하면 개발자는 자체 마샬링 코드를 작성할 필요가 없다. RPC 라이브러리는 특정 시스템에서 사용되는 마샬러를 제공하며, RPC 툴은 특정 애플리케이션에서 사용되는 마샬링 코드를 생성하며, 이는 윈도우 계에서
인터페이스 마샬러라고 부른다.
특정 포맷에의 네트워크 버퍼를 전송하는 대신에 RPC를 사용하면, 마치 목표로 하는 원격 함수가 동일한 프로세스 내에 있는 것처럼, 개발자는 함수 호출을 만들기 위해 단지 코드를 작성하기만 하면 된다. 생성된 인터페이스(generated-interface) 마샬러를 사용하면, RPC 라이브러리는 타겟 함수가 원격으로 실행하는 것을 보장한다. 전통적인 클라이언트/서버 개발과 마찬가지로, 마샬링이 존재하지만, 전통적인 클라이언트/서버 개발과는 달리 마샬링 코드를 작성할 필요는 없다. 원격 절차 호출의 지원 이외에도 RPC는 증명과 허가를 지원한다. RPC를 사용하면 클라이언트/서버 애플리케이션을 사용하고 싶은 대로 네트워크 프로토콜을 설정할 수 있다.
개념
RPC는
구현에서 인터페이스를 분리한다는 중요한 원칙을 사용한다. RPC에서는 RPC 인터페이스를 서술하거나 정의한다. 이렇게 한 다음, 인터페이스를 제품에 구현할 수 있다. 다른 사람들은 제품을 사용하기 위해 이러한 인터페이스 명세에 의존할 수 있다. 인터페이스에 대해서는 관심을 많이 갖지만, 내적인 구현에 대해서는 신경 쓰지 않는다. 사람들은 인터페이스 명세에 의존하기 때문에, 나중에 제품의 구현을 바꾼다 해도 그 제품을 사용할 것이다.
인터페이스 명세를 사용하면 다른 소프트웨어 판매자가 당신이 명시한 인터페이스를 구현할 수 있다는 점도 좋다. 그들이 이렇게 한다면, 당신의 인터페이스를 알고 있는 사람들은 이러한 판매자의 제품도 사용할 것이다. 소프트웨어 회사, 상호 운영성, 연결에 도움이 되기 때문에 중요하다.
애플리케이션 수준 프로토콜 명세를 작성하는 대신, RPC는 이러한 목적을 위해 IDL(Interface Definition Language)라는 언어를 준다. IDL을 사용하면 프로그래머가 함수 프로토타입의 측면에서 생각할 수 있으며, 프로그래머가 편안함을 느끼기 때문에, 애플리케이션 수준의 명세를 간단히 한다. IDL의 또 다른 이점은 구문적으로 C 언어 코드와 비슷하다는 것이다.
프로그래머의 작업이 단순화될 뿐 아니라, RPC는
속성(attribute)이라는 개념을 소개한다. 이것은 닷넷의 영역에서 매우 중요한 개념이다. 컴퓨터 이론가는 이러한 특징을 aspect-oriented 프로그래밍이라고 부를 것이다. 30줄의 코드를 작성하는 대신, aspect-oriented 프로그래밍에서는 단지 특별한 키워드에 지나지 않는 힌트(공식적으로 속성(attribute)이라고 부른다)를 사용하여 시스템에 당신이 원하는 것을 명기할 수 있다. 컴파일, 링크, 런타임에서 시스템은 속성을 통해 요청한 함수를 지원하기 위해 특별한 로직을 주입해서 이 힌트를 사용한다. 즉, 이 특성 때문에 장황하고 반복적이고 에러를 저지르기 쉬운 코드를 작성하지 않아도 되고, 시간과 비용, 노력을 절약할 수 있게 된다는 것이다.
| |
|
| 구현으로부터 인터페이스를 분리하는 것, 속성 기반 프로그래밍의 개념은 소프트웨어를 개발하는 데에 꼭 필요하다. |
|
| |
RPC가
위치 투명성의 원칙을 촉진한다는 것도 중요하다. 클라이언트 측 프로그래머는 절차 호출만 만들면 된다. 서버 컴퓨터가 어디에 있는 간에, RPC에서 절차가 서버측에서 실행될 것이라는 것을 보장한다. 서버 측 프로그래머는 ID 컴파일러(인터페이스 marshaling 코드를 생성하고 C 언어 헤더 파일을 산출하는 툴)에서 생성된 C언어 프로토타입에 따라 함수를 작성하기만 하면 된다. RPC를 사용하여 전체 애플리케이션을 개발하는 것이 왜 쉬운지 알게 될 것이다. 파싱 네트워크 버퍼도 없고, 당신이 해야 할 일은 간단한 함수 호출이 다이다.
다음 기사
여기서는 분산 컴퓨팅의 목표, 문제점, 솔루션에 대해 간략히 살펴보았다. 구현으로부터 인터페이스를 분리하는 것, 속성 기반 프로그래밍의 개념은 소프트웨어를 개발하는 데에 꼭 필요하다. 이러한 개념은 컴포넌트화와 엔터프라이즈 서비스를 가능하게 해준다. 두 번째 기사에서는 컴포넌트화와 엔터프라이즈 서비스에 대해 살펴볼 것이다.
쭈안 타이는 Learning DCOM의 저자이며, .NET Framework Essentials의 공동저자이기도 하다.