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

한빛출판네트워크

한빛랩스 - 지식에 가능성을 머지하다 / 강의 콘텐츠 무료로 수강하시고 피드백을 남겨주세요. ▶︎

IT/모바일

.NET Framework Essentials 저자가 제공한 팁: 2부. 컴포넌트화와 엔터프라이즈 서비스

한빛미디어

|

2001-08-13

|

by HANBIT

8,177

by 쑤안 타이, .NET Framework Essentials의 공동 저자 1부. 분산 컴퓨팅에서는 분산 컴퓨팅과 그 목적 및 문제점, 해결책 등에 대해 간략히 설명했으며, 그 중에서도 RPC(remote procedure calls)를 가장 중요하게 다루었다. 이번 글에서는 소프트웨어 통합을 쉽고 빠르게 할 수 있는 컴포넌트화(componentization)와 개발자가 수많은 사용자를 수용할 수 있는 소프트웨어를 구축하게 해 주는 엔터프라이즈 서비스에 대해 살펴볼 것이다. 컴포넌트화 RPC는 다른 기술과 많이 연결되는데, 그 중 하나가 컴포넌트화이다. RPC는 원격 프로시저 호출(remote procedure calls)만을 지원하기 때문에, 소프트웨어 벤더는 원격 객체 지향 프로그래밍을 지원하기 위해 RPC의 위에 내부적으로 만드는 래퍼(wrapper) 층을 만든다. 이렇게 하면 소프트웨어 벤더는 풍부한 C++ 클래스 라이브러리를 개발할 수 있으며 분산 컴퓨팅을 위한 RPC의 이점을 계속 이용할 수 있다.
.NET Framework Essentials
게다가 어떤 사람들은 구현에서 인터페이스를 분리하는 것이 플러그 앤 플레이를 지원하는 소프트웨어를 만드는 데 도움이 된다는 개념을 인식하고 있다. 하드웨어에서는 완전한 컴퓨터를 만들기 위해 몇 개의 보드를 꽂아 넣으면 된다. 인터페이스를 다른 보드에서도 사용할 수 있도록, 보드에서 특정 인터페이스를 드러내기 때문에 이러한 일이 가능하다. 몇 년 전부터 하드웨어의 플러그 앤 플레이 기능을 사용했지만, 상용 소프트웨어 산업에서는 RPC의 성공을 인식하고 나서야 소프트웨어 플러그 앤 플레이나 컴포넌트화에 뛰어들었다. 하드웨어 컴포넌트의 플러그 앤 플레이와 마찬가지로, 플러그 앤 플레이 소프트웨어 컴포넌트는 레고 블록처럼 서로 잘 맞는다. 1990년대 초반에 상업적으로 소개된 소프트웨어 플러그 앤 플레이는 단지 지난 6~10년간 있어 왔다. 컴포넌트 소프트웨어 구조는 다양하며, 모두가 객체 지향적이다. 여기에는 컴포넌트 객체 모델(COM: Component Object Model), 시스템 객체 모델(SOM: System Object Model), 공통 객체 요청 브로커 구조(CORBA: Common Object Request Broker Architecture), 자바 빈즈 등이 있다. 이러한 컴포넌트 기술은 비슷한 원칙이 있으며, 비슷한 특성을 지원하고, 비슷한 곳에 적용될 수 있다. 몇 가지 원칙들 컴포넌트 기술에는 원칙이 많이 있지만, 컴포넌트화를 할 때에 없어서는 안 될 중요한 것만 짚어 보겠다. 이러한 원칙에는 인터페이스 계약(interface contract), 이진 표준(binary standard), 와이어 프로토콜(wire protocol), 브리지(bridge) 등이 있다.
  • 인터페이스 계약 인터페이스와 구현을 분리한다는 원칙은 컴포넌트 소프트웨어에 동화되는 데에 성공한 것 중 주요한 것이다. 컴포넌트 소프트웨어에서 컴포넌트 소비자(클라이언트)는 컴포넌트 공급자(혹은 단순히 컴포넌트)를 블랙박스라고 본다. 소비자는 인터페이스를 잘 알고 있지만 컴포넌트가 어떻게 구현되는지 신경 쓰지 않는다. 인터페이스가 명기되고 문서화된 대로 정확하게 실행되기만 하면 소비자는 만족한다. 이 때문에, 인터페이스는 컴포넌트와 소비자 사이의 계약이 된다. 나중에 구현을 통해 컴포넌트의 배포를 바꿀 수 있지만, 인터페이스는 동일하게 남아있어야 한다. 만약 인터페이스를 바꿔야 할 경우가 생긴다면, 새로운 인터페이스는 전형적으로 덧붙여질 것이며, 결과적으로 새로운 클라이언트는 새로운 인터페이스를 사용할 수 있으며, 이전의 클라이언트는 충돌하지 않을 것이다. 인터페이스 계약이라는 개념을 통해 컴포넌트를 구현하고 재사용하는 것이 훨씬 쉬워졌다.
     몇 년 전부터 하드웨어의 플러그 앤 플레이 기능을 사용했지만, 상용 소프트웨어 산업에서는 RPC의 성공을 인식하고 나서야 소프트웨어 플러그 앤 플레이나 컴포넌트화에 뛰어들었다.
  • 이진 표준 컴포넌트 기술의 목적이 소프트웨어 플러그 앤 플레이를 허용하는 것이기 때문에, 컴포넌트 기술은 컴포넌트 통합을 소스 코드 수준 뿐 아니라 이진 수준에서 지원해야 한다. 다시 말하면, 소비자에게 타깃 컴포넌트에 대한 소스 코드가 없더라도 다른 컴포넌트를 이용하는 것을 허용해야 한다는 것이다. 사실, 소비자는 컴포넌트의 공적인 헤더 파일이나 정적인 라이브러리를 가질 필요가 없다. 인터페이스 계약과 컴포넌트 타입 정보, 혹은 메타데이터가 종종 컴포넌트와 함께 운반되기 때문이다. 타입 정보에는 컴포넌트와 컴포넌트가 호스트하는 클래스, 클래스가 구현하는 인터페이스, 인터페이스가 지원하는 메소드 등에 대한 정보가 있다. 이진 상호 운영성을 얻기 위해서는 시스템에서 정보의 타입을 알고 있어야 하며, 레이아웃과 메모리에 있는 객체의 실행을 알거나 지원해야 한다. 대부분의 C++ 프로그래머는 많은 C++ 컴파일러에서 가상 테이블(vtbl)과 가상 포인터(vptr)를 사용하여 다형성(polymorphism)을 지원해야 한다는 것을 알고 있다. 이러한 vptr와 vtbls는 명기되고 일관된 레이아웃을 메모리에 가지고 있으며, 이진 상호 운영성을 허용한다. 다시 말해, 이진 레이아웃에 따르는 실행 가능한 소프트웨어 프로그램은 바이너리 수준에서 서로 상호 운영할 것이다. 각도를 바꿔서 생각해 보면, 이진 표현(binary representation)을 생성할 수 있는 컴퓨터 언어를 위한 컴파일러는 모두 표준에 따르는 다른 소프트웨어와 함께 작동하는 소프트웨어를 만들 수 있다. vptr과 vtbl은 이진 표준이라고 생각할 수 있다. 1980년대 후반에는 COM에서 이진 표준을 필요로 했기 때문에, 마이크로소프트는 C++의 구현을 이용했고, vtbl과 vptr을 무료로 획득할 수 있었다.
  • 와이어 프로토콜 컴퓨터 한 대에 한정된 컴포넌트 상호 운영성은 놀라운 업적이지만, 컴포넌트가 사이버 공간에서 상호 운영하는 것을 허용하는 컴포넌트 배포를 지원하지 않으면 컴포넌트 기술은 성공적일 수 없다. 이러한 마술을 허용하려면, 컴포넌트가 전선을 통해 의사소통할 수 있는 와이어 프로토콜을 명시해야 한다. 마이크로소프트는 전적으로 새로운 RPC 메커니즘을 마지못해 내놓는 대신에, 성공적인 RPC 표준을 이용했다. 그것은 객체 지향을 지원하지 않았기 때문에, 마이크로소프트는 객체 레퍼런스(OBJREF: object reference)라는 부가적인 타입을 RPC에 덧붙였으며, 결과적으로 마이크로소프트 RPC(MSRPC)라고 불리는 RPC를 만들었다. 와이어 프로토콜은 분산 컴포넌트 상호 운영성을 지원하는 하부구조 역할을 한다. 이것이 매우 복잡할 수 있지만, 일단 정의되고 구현되면, 이러한 종류의 하부 구조를 다시 개발할 필요가 없다. 마이크로소프트는 개발자들이 고유의 와이어 프로토콜을 만들지 않아도 되도록 이 부분을 처리하였다.
  • 브리지 다른 컴포넌트 기술이 몇 가지 있기 때문에, 몇몇 회사에서는 두 가지 다른 컴포넌트 기술을 서로 합쳐서 매개로서 작용하는 소프트웨어 컴포넌트를 구축하여 판매하기 시작했다. 이러한 종류의 소프트웨어는 적절하게 브리지를 수여하며, 둘 사이에서 상호 운영성을 허용하면서 서로 다른 컴포넌트 구조에서 브리지 역할을 하기 때문에, 적절하게 브리지를 수여한다. 예를 들어서 COM-CORBA 브리지를 사용하면 COM 객체에서 CORBA 객체를 사용할 수 있고, 그 반대도 가능하다.
특성 컴포넌트 기술은 위치 투명성, 역동적인 활성화, 역동적인 호출, 보안, 접속 관리 등 인기 있는 특성을 많이 지원해야 한다.
  • 위치 투명성 이 특성은 원격 컴퓨터의 위치나 어느 네트워크 프로토콜을 사용하고 있는지 등에 대한 지식 없이도 원격 컴퓨터에 구현된 메소드를 불러내는 능력을 지칭한다. 클라이언트의 측면에서는, 단순히 메소드를 불러내기 위해 코드를 작성한다. 서버 측면에서는, 클라이언트가 호출할 메소드를 구현한다. 다른 모든 것은 와이어 프로토콜이라는 마법으로 처리해야 한다. 이에 대한 예는 분산(Distributed) COM 와이어 프로토콜과 COM 라이브러리이다.


    그림 1. COM 프록시와 스텁

    그림1과 같이, COM은 클라이언트 쪽에 있는 프록시 객체, 서버 쪽에 있는 스텁(stub) 객체, 그리고 지원받는 인터페이스를 위한 양쪽 모두의 마샬링 코드를 사용하여 투명성을 지원한다. 원격 메소드를 호출할 때, 클라이언트는 단순히 프록시 객체에 의해 차단된 메소드를 불러온다. 프록시 객체는 COM 하부구조를 통해 스텁 객체와 의사소통하는 방법을 알고 있다. 스텁 객체가 프록시 객체로부터 호출을 받았을 때, 그것은 원격 클라이언트의 장소에서 행동하고, 타깃 메소드를 호출한다. 메소드 호출이 끝난 뒤에는, 스텁(stub) 객체가 반환 값을 프록시 객체에 전달하며, 그 다음에는 동일한 값을 클라이언트에 돌려 보낸다.
  • 동적 활성화 이 특성은 클라이언트가 컴포넌트를 요청할 때마다 컴포넌트의 게으른 시작을 지원한다. 이러한 지원이 있기 때문에 컴포넌트 프로세스를 시작할 필요가 없고, 전통적인 RPC에서와 같이 클라언트와 연결되기를 기다리지 않아도 된다. 동적 활성화를 사용하면 시스템에서 사용되는 자원을 절약할 수 있다. 동적 활성화를 COM에서 이용하려면, 컴포넌트에 특정 식별자가 있다는 것을 COM에 알리기만 하면 된다. 컴포넌트가 시스템 레지스트리로 드러나는 COM 클래스의 클래스 식별자(CLSID)를 등록하면 이렇게 할 수 있다. 일단 클래스가 등록되면, COM 라이브러리는 클라이언트가 COM에 객체를 필요로 한다고 말할 때마다 컴포넌트를 찾아서 시작할 것이다. † 레지스트리를 다루는 것은 COM 프로그래머에게 고통스러운 일이 될 수 있다. 이러한 고통을 해소하기 위해, 닷넷에서는 컴포넌트 디스커버리와 플러그 앤 플레이에서 레지스트리를 사용하는 것을 금지했다.
     레지스트리를 유지하고, 감시하고 업데이트 하는 것에 대해 더 알고 싶으면 Managing the Windows 2000 Registry 를 참고하라.
  • 동적 호출 동적 호출은 컴포넌트가 런타임에서 서로에 대한 사전 지식 없이 역동적으로 상호 운영하는 것을 허용하기 위한 특성이다. 만약 동적 호출을 어떻게 이용하는지 알고 있는 클라이언트 애플리케이션을 개발하고 있다면, 클라이언트는 동적 호출의 특성을 구현하는 현재와 미래의 모든 컴포넌트를 호출할 수 있을 것이다 비주얼 베이직(Visual Basic) 6.0을 그 예로 들 수 있다. 몇 년 전에 개발된 비주얼 베이직 6.0은 동적 호출을 지원하는 모든 COM 객체를 호출할 수 있다. 심지어는 오늘날 개발하고 있는 COM 객체도 지원한다. 비주얼 베이직 6.0과 마찬가지로, COM에서도 클라이언트를 자동화 제어기(automation controller)라고 부르며, 그것이 사용하는 컴포넌트를 자동화 서버(automation server)라고 한다. 자동화 제어기는 IDispatch 인터페이스를 사용하는 방법을 알고, 자동화 서버는 IDispatch 인터페이스를 구현하는 COM 컴포넌트이다. 그리고 또 한 가지 동적 호출의 강점은 그것이 클라이언트가 개발되는 것을 허용한다는 것이지만, 나중에 클라이언트를 재컴파일 할 필요가 전혀 없이 똑같은 클라이언트는 나중에 작성될 자동화 서버에서 메소드를 불러올 수 있다.
  • 보안 컴포넌트 배포는 컴포넌트 기술에서 핵심적인 것이기 때문에, 보안은 통합되어 있어야 한다. 그렇지 않으면, 보안 침해를 예방하기 힘들 것이다. 앞에서 언급했듯이, 보안에서 중요한 두 가지 특성에는 인증(authentication)과 승인(authorization)이 있다. 인증은 방문자가 누구인지의 문제이고, 이미 인증을 받은 방문자가 특정 자원에 접근할 수 있는지를 확인하는 것이다. "인증"은 여권 같은 것이라고 생각하면 되고, "승인"은 비자라고 생각하면 이해하기 쉬울 것이다.
     컴포넌트 기술에는 원칙이 많이 있지만, 컴포넌트화를 할 때에 없어서는 안 될 중요한 것만 짚어 보겠다. 이러한 원칙에는 인터페이스 계약(interface contract), 이진 표준(binary standard), 와이어 프로토콜(wire protocol), 브리지(bridge) 등이 있다.
    또 한 가지 보안 개념은 위장인데, 이것은 서버에서 클라이언트의 신원을 가정하게 한다. 이 특성은 서버에서 클라이언트가 접근할 수 있는 모든 자원에 접근할 수 있게 하는 등 서버가 일시적으로 클라이언트가 되는 것을 허용한다. 서버 컴포넌트가 보통 특정 서버측 시스템 계정에서 실행되며, 특정 보안 제약을 가지고 있으며 방문자에게 부적절하게 될 수도 있기 때문에 위장은 중요하다. 그리고 다른 클라이언트가 서버에 접근하기 때문에, 다양한 보안 허가의 모든 클라이언트를 지원할 강력한 서버 아이덴티티는 필요 없다. 그 대신 가장 적절한 일은 클라이언트와 서비스가 보안 허가를 이용하여 요청을 위장하는 것이다. 물론 이것이 가능하기 전에 클라이언트에서 서버가 클라이언트를 위장하도록 허용해야 한다.
  • 가비지 컬렉션 분산 환경, 컴포넌트 기반 시스템에서는 많은 컴포넌트가 서로 상호 운영한다. 전형적인 컴포넌트 기반 시스템에는 클라이언트가 더 이상 객체가 필요 없을 때까지 객체에 대한 레퍼런스를 가지고 있는다는 간단한 규칙이 있다. 하지만 클라이언트가 이러한 규칙에 부합하지 못할 때나 네트워크가 작동하지 못하는 경우에는 레퍼런스가 무효로 된다. 컴포넌트 구조나 미들웨어는 이렇게 명백한 문제를 완화할 수 있을 정도로 강력해야 한다. 무효인 레퍼런스를 없애는 능력을 가비지 컬렉션에 제공해야 하며, 그렇지 않을 경우 컴퓨터에서는 자원이 계속 부족할 것이다. 분산 COM(DCOM)은 분산된 가비지 컬렉터를 구현하기 위해 핑을 사용한다. 핑 메시지를 사용하면, 클라이언트가 원격 서버를 핑하고 응답이 없을 경우, 서버와의 연결이 끊겼다고 가정한다. 이런 경우에는 가지고 있던 서버 레퍼런스를 제거하고, 그 레퍼런스와 관련된 할당된 자원을 지운다. 서버 측에서는, 설정된 시간 안에 클라이언트로부터 핑 메시지를 받지 못하면, 클라이언트가 죽었다고 생각하고 서버 측에서 클라이언트에 할당한 자원을 지울 것이다. 핑 메시지가 네트워크를 방해할 수 있기 때문에, DCOM은 지금 있는 레퍼런스를 찾아내기 위해 델타 핑이라는 핑 메커니즘을 발명했다. 이론적으로, 클라이언트 측에 있는 컴포넌트 미들웨어는 서버 컴퓨터를 다른 인터벌로 핑 한다. 핑을 하나의 그룹에 모으기 위해 특별한 알고리즘을 사용하고, 단 한 개의 핑 메시지를 서버에 보내기 때문에 네트워크의 대역폭(bandwidth)을 절약해 준다.
실용성 컴포넌트화를 통해 얻을 수 있는 이익은 많다. 이의 도입과 거의 동시에 컴퓨터 한 대에만 국한된 것이 아니라 네트워크 전체에서 DCOM 와이어 프로토콜의 도움으로 모든 사람이 컴포넌트를 만들고 재사용하고 있었다. 하지만 개발자들은 여기에 머무르지 않았다. 값진 컴포넌트를 인터넷에서 공유하고 싶어했기 때문이다. 그들이 직면한 문제는 DCOM이 IP 주소를 네트워크 데이터 재현(NDR: Network Data Representation) 버퍼에 내장하여, DCOM이 방화벽과 네트워크 주소 번역(NAT: Network Address Translation)을 넘어서서 일하는 것을 방지하는 것이다. 마이크로소프트는 이에 대한 해결책인 COM을 인터넷에 빨리 내놓았다. 하지만 좀더 공개적이고 표준 메커니즘인 단순 객체 접근 프로토콜(SOAP: Simple Object Access Protocol)이 곧 소개되었고, 널리 수용되었다. SOAP은 전적으로 XML에 기반하고 있다. COM이 지닌 또 한 가지 문제는 그것이 시스템 레지스트리에 너무 많이 의존한다는 것이다. 그로 인해 COM 프로그래밍과 컴포넌트 설치 및 설정이 개발자나 관리자 모두에게 어려운 일이 되었다. COM 자체는 어렵지 않지만, COM 학습 곡선을 따라 가는 것이 힘들다. 특히 초심자들은 각각의 COM 관련 레지스트리 하이브와 엔트리의 의미를 파악하는 데에 시간이 많이 걸릴 것이다. 그래서 모든 레지스트리 관련 정보가 컴포넌트 자체에 구축되어 있어서 시스템 레지스트리가 필요 없어지는 것이 더 나을 것이다. 닷넷이 어떻게 이 문제를 푸는 지에 대해 더 자세히 알고 싶은 사람은 .NET Framework Essentials를 참고하라. 엔터프라이즈 서비스 앞에서 언급한 대로, 컴포넌트화는 소프트웨어 컴포넌트의 플러그 앤 플레이를 허용하고, 사람들이 소프트웨어를 개발하는 방법에서 혁명을 일으켰다. 이러한 인기를 등에 업고 많은 사람이 스케일이 크고 엔터프라이즈에서 사용될 수 있는 프로그램을 만들고 있다. 스케일이 큰 시스템은 다수의 사용자를 지원하는 경향이 있기 때문에, 프로그램 설계자는 이러한 시스템을 시간을 넘어 측량할 수 있고 공유 자원을 지원할 수 있도록 디자인해야 한다. 즉, 개발자들은 스레드 풀링, 자원 풀링, 보안 체킹 등과 같은 서비스를 개발해야 한다. 엔터프라이즈 서비스는 사람들이 만드는 엔터프라이즈 시스템에 따라 도처에서 만들어졌다. 분산 프로그래밍에서 볼 수 있었던 마샬링 문제처럼, 이러한 서비스를 개발하는 것은 단순한 일이 아니었다. 데이터베이스에서 자원 풀을 지원하기 위해 컴포넌트를 한 번 만들면, 다음 엔터프라이즈 애플리케이션을 위해 다른 것을 만드는 것은 어려운 일이 아니다. 하지만 이러한 서비스는 복잡하기 때문에, 결함과 버그가 많은 끔찍한 일이 될 것이다. 게다가 이러한 서비스를 개발하는 것은 지루하고, 에러가 생기기 쉬우며, 방대한 작업이 될 것이다. 게다가 이러한 서비스는 표준에 순응하지 않으며, 다른 엔터프라이즈 시스템에서는 쓸모가 없는 경우도 있다. 이러한 문제점을 해결하기 위해, 마이크로소프트 트랜잭션 서버(MTS: Microsoft Transaction Server), COM+ 서비스, CORBA 서비스, EJB 등의 컴포넌트 구조에서는 이러한 엔터프라이즈 서비스에 대한 지원을 제공한다. 이러한 지원이 있기 때문에 엔터프라이즈 애플리케이션을 개발할 때 같은 타입의 코드를 반복해서 작성하지 않아도 된다. 그래서 엔터프라이즈 서비스 이면에 있는 원칙을 이해하는 것과 이러한 엔터프라이즈 서비스가 제공하는 특성을 이해하는 것이 중요하다. Aspect-Oriented 프로그래밍 엔터프라이즈 서비스는 aspect-oriented 프로그래밍(AOP)의 개념 위에 구축되었다. 이는 설정이나 런타임 변화를 지원하는 시스템에서 매우 핵심적인 요소이다. 이 패러다임 아래에서 소프트웨어를 일단 개발하지만, 설정에 따라 운영이 다르게 된다. 이에 대한 간단한 예로 윈도우 초기화(INI) 파일에서 정보를 획득하는 프로그램을 들 수 있다. INI 파일을 사용할 때에는 프로그램이 암호를 풀고 필요한 요소를 제공해야 하지만, AOP는 시스템 수준에서 접속 풀(connection pooling)과 같은 요소를 제공하기 때문에, 사용자는 단 한 줄의 코드도 작성할 필요가 없다. AOP에서는 런타임이나 프로그램이나 설정을 할 때 필요한 시스템 특성을 정할 수 있다. 프로그램할 때, 특정 키워드나 특성을 메소드나 클래스에 추가하면 된다. 하지만 이러한 것들을 지원하기 위해 커스텀 코드를 작성할 수는 없다. 런타임에서는 시스템이 메소드나 클래스에 대한 모든 호출을 차단하고, 이러한 속성(attribute)을 조사하며, 컴포넌트에 사용자에게 필요한 특성을 삽입할 것이다. 프로그램할 때 이러한 속성을 명기하는 대신, 선언을 설정할 때까지 연기할 수도 있다. 이렇게 하면, 설정과 설치를 할 때에 필요한 서비스를 선언할 수 있을 것이다. 이러한 능력이 있기 때문에 동일한 시스템이 다른 방식으로 운영되도록 설정할 수 있으며, 다른 특성을 지원할 수 있다. 다시 말해서, 서로 다른 두 회사가 단지 설정을 달리 선언하기만 하면 동일한 시스템을 사용할 수 있다는 것이다. 시스템이 하나밖에 없어도, AOP 패러다임을 사용하면 시스템의 서로 다른 인스턴스를 설정 시에 초기화할 수 있다. 이것을 개념적인 측면에서 보면, C++에 있는 클래스를 초기화할 수 있다. 하지만 AOP 패러다임에서는 전체 시스템을 초기화할 수 있다. MTS와 COM+ 서비스는 AOP라는 개념을 사용해서, 사용자는 사용하기를 원하는 서비스의 종류를 지시하기 위해 특정 속성을 설정하거나 선언하고, MTS나 COM+는 런타임의 모든 호출을 차단할 것이며, 사용자가 지시한 서비스만을 실행할 것이다. 엔터프라이즈 서비스 엔터프라이즈 서비스의 목적은 공유, 측량 가능성, 강력함, 빠른 응답 시간 등의 특성을 지원하는 것이다. 이러한 특성을 지원하려면, 컴포넌트 기술이 스레드 풀링(thread pooling), 객체 풀링(object pooling), 접속 풀링(connection pooling), 보안 관리, 트랜잭션 관리, 접속되지 않은 처리(disconnected processing) 등 다양한 일반 엔터프라이즈 서비스를 공급해야 한다.
 데이터베이스에서 자원 풀을 지원하기 위해 컴포넌트를 한 번 만들면, 다음 엔터프라이즈 애플리케이션을 위해 다른 것을 만드는 것은 어려운 일이 아니다.
  • 스레드 풀링 대칭형 다중처리(SMP: Symmetric Multiprocessing) 시스템에서 스레드를 만들 수 있는 능력을 가지고, 개발자는 작업 생산성을 높이기 위해 스레드를 많이 산출할 수 있다. 스케일이 큰 시스템을 개발할 때에는 대개 한 사람이 아니라 여러 개발자의 노력이 필요하다. 그런데 개발자의 경험은 서로 다르기 때문에, 모든 프로그래머가 단일 스레드 애플리케이션을 작성하는 것처럼 코드를 작성하도록 하는 것이 현명할 것이다. 스레드 풀링 엔터프라이즈 서비스에서는 작업량을 자동으로 넓히는 것에 대해 걱정할 것이다. 시스템은 여러 개의 스레드를 낳고 그것을 하나의 풀에 넣을 것이다. 스레드가 필요할 때마다, 시스템은 풀에서 스레드를 가져온다. 이렇게 하면 시스템 자원이 절약될 뿐 아니라, 개발 노력도 적게 들일 수 있다.
  • 객체 풀링 참조 테이블을 초기화하는 데 20초가 소요되는 것처럼, 어떤 객체는 만들 때 시간이 오래 걸린다. 크고 측량 가능하며 강력한 시스템에서 후위 데이터의 일관성과 통합성을 유지하기 위해 빠른 시간 안에 객체가 생성되며 사용되고 없어진다. 하지만 만드는 데 20초가 걸리는 객체를 항상 만들고 없애게 되면, 시스템이 느려질 지도 모르며, 나중에 자원 활용을 잘 할 수 없을 수도 있다. 이러한 타입의 객체를 일단 만들고, 다른 객체와 같은 방식으로 이 객체도 사용할 수 있는 것이 더 나을 것이다. 객체 풀링이 필요한 것이 바로 이런 이유 때문이다. 만드는 데 시간이 오래 걸리는 객체는 생성된 후 풀에 저장될 수 있다. 객체가 요청될 때마다 시스템에서는 객체를 풀에서 꺼내어 서비스와 요청에 응답할 수 있다.
  • 접속 풀링 데이터베이스 접속은 정말 귀중하고, 만드는 데 돈이 많이 들며 메모리에 저장하려면 자원 집약적이고, 스케일이 큰 시스템에서는 데이터베이스 접속을 공유해야만 한다. 예를 들어서 데이테베이스 라이선스는 10 개밖에 없는데 100 명의 사용자를 지원하고 싶다면, 10 개의 접속을 공유해야 할 것이다. 만약 클라이언트 하나를 열어놓고 데이터베이스에 접속된 것을 하나 닫는다면, 접속 초기화와 자원 활용에 문제가 생긴다는 것을 알아차리지 못할 지도 모른다. 하지만 1000 명의 사용자가 동시에 이렇게 한다고 생각하면, 스케일이 큰 시스템에서는 어떤 일이 생기겠는가? 스레드나 객체 풀링과 마찬가지로, 접속 풀링에는 접속 풀이 담겨 있다. 만약 요청된 접속이 풀에 있다면, 시스템은 그 접속을 풀에서 꺼내어 그것이 요청에 대한 서비스를 하도록 할 것이다.
  • 보안 관리 보안 관리를 위해 코드를 작성하는 것은 복합적인 업무이다. 관리자는 특정 프로세스에서만 보안을 설정할 수 있지만, 프로세스를 제공하는 객체와 메소드는 설정할 수 없다. 보안을 더 쉽게 관리하기 위해, 컴포넌트 기술에서는 역할 기반의 보안이라는 개념을 제공한다. 롤이란 일련의 사용자나 사용자 그룹을 대표하는 통칭이다. 역할 기반의 보안은 보안이 공급하는 시스템을 추상화(abstraction) 한 것인데, 이를 사용하면 프로그래머가 아주 간단한 코드 만으로 보안을 관리할 수 있으며, 시스템 관리자가 컴포넌트, 객체, 인터페이스, 메소드의 보안 설정을 쉽게 할 수 있다.
  • 트랜잭션 관리 대형 시스템에서, 단일한 객체는 혼자 작동하지 않는다. 그것은 트랜잭션을 수행하기 위해 많은 다른 객체와 상호 작용한다. 트랜잭션을 통해 한 개 이상의 데이터베이스를 업데이트할 수 있다. 트랜잭션은 원자성(atomicity)를 포함한 ACID 속성에 따라야 하기 때문에, 데이터베이스 통합성을 지원한다. 즉 트랜잭션에 의해 작동하는 모든 것이 완전히 수행되거나 아니면 되돌아온다는 것이다. 일관성이란 트랜잭션의 결과가 무엇이든 간에 데이터가 일관성이 있어야 한다는 뜻이다. 그리고 격리(isolation)란, 트랜잭션이 고립되어서 처리된다는 뜻이다. 그리고 영속성(durability)은 시스템이 다운된다 해도 일단 수행된 데이터는 지속된다는 것이다.
  • 접속되지 않은 처리 세상에서 가장 큰 시스템은 메시지 큐(queue)에 기반한다고 사람들은 종종 말한다. 메시지 큐를 사용하면 비동기식이고 접속이 느슨한 시스템을 개발할 수 있다. 애플리케이션은 나중에 다른 애플리케이션에 의해 언제든지 디큐(deque)될 수 있는 메시지를 인큐(enque)할 수 있다. 다시 말해서, 두 번째 애플리케이션은 요청이 인큐될 때에는 전혀 필요 없다는 것이다. 게다가 일단 첫 번째 애플리케이션이 요청을 인큐하면, 즉시 다른 것을 처리할 수 있다. 시스템이 이러한 서비스를 공급하기 때문에, 프로그래머는 커스텀 코드를 작성할 필요가 없다. 그 대신에 프로그램을 할 때 아니면 설정을 할 때 특성을 선언하면서 속성을 추가하여 필요한 서비스의 타입에 대한 정보를 시스템에 보내면 된다. 시스템은 모든 호출을 런타임에서 차단하고, 필요한 특성을 삽입할 것이다. 마이크로소프트가 COM+ 서비스의 1.x 판에서 이 모든 서비스를 지원한다는 것은 아무 가치가 없다.
다음 번에는... 이 글에서는 컴포넌트화와 엔터프라이즈 서비스에 대해 간략히 살펴 보았다. 컴포넌트화와 엔터프라이즈 서비스는 소프트웨어를 통합하고 스케일이 큰 시스템을 관리하는 데에 가장 중요한 개념이다. 측량 가능한 소프트웨어 시스템 중 어떤 것은 웹에 기반하고 있으므로, 시리즈의 세 번째 부분에서는 웹에 기반한 개념과 발달 요인에 대해 서술할 것이다.
TAG :
댓글 입력

최근 본 상품0