컴포넌트 기반 소프트웨어 개발 방법론은
소프트웨어 재사용이란 주제에서 출발한 개념인걸 아셨나요?
이번 포스팅에서는 컴포넌트 기반 소프트웨어 공학, CBSE 개념에 대해 알아 보겠습니다.
이 글은 Ian Sommervile의 "Software Engineering, 9th Edition"에 기반하여 정리되었습니다.
1. 컴포넌트 기반 소프트웨어 공학 (Component-based Software Engineering)
컴포넌트 기반 소프트웨어 공학(CBSE)은 1990년대 후반에 소프트웨어 컴포넌트의 재사용을 기반으로 한 소프트웨어 시스템 개발 접근 방식으로 등장했습니다. CBSE의 탄생은 객체 지향 개발이 처음 제안되었을 때 예상했던 광범위한 재사용으로 이어지지 않았다는 디자이너들의 좌절에서 비롯되었습니다.
단일 객체 클래스는 너무 세부적이고 구체적이며, 종종 컴파일 시 애플리케이션과 결합되어야 했습니다. 클래스를 사용하려면 해당 클래스에 대한 자세한 지식이 필요했으며, 이는 일반적으로 컴포넌트의 소스 코드를 가지고 있어야 함을 의미했습니다. 이로 인해 객체를 개별 재사용 가능한 컴포넌트로 판매하거나 배포하는 것이 사실상 불가능했습니다.
컴포넌트는 객체보다 높은 수준의 추상화이며 인터페이스로 정의됩니다. 컴포넌트는 일반적으로 개별 객체보다 크며, 모든 구현 세부 사항은 다른 컴포넌트로부터 숨겨집니다. CBSE는 느슨하게 결합된 독립적인 컴포넌트를 시스템에 정의하고 구현하며 통합하거나 구성하는 과정입니다.
컴포넌트 기반 소프트웨어 공학의 필수 요소는 다음과 같습니다:
- 독립적인 컴포넌트: 컴포넌트는 그 인터페이스에 의해 완전히 정의되며, 컴포넌트 인터페이스와 구현 간의 명확한 분리가 있어야 합니다. 즉, 시스템의 다른 부분을 변경하지 않고도 하나의 컴포넌트를 다른 것으로 교체할 수 있습니다.
- 컴포넌트 표준: 컴포넌트 통합을 촉진하는 표준입니다. 이러한 표준은 컴포넌트 모델에 포함됩니다. 최소한의 요구 사항으로 컴포넌트 인터페이스의 명세 방법과 컴포넌트 간의 통신 방법을 정의합니다. 일부 모델은 더 나아가 모든 적합한 컴포넌트가 구현해야 하는 인터페이스를 정의합니다. 컴포넌트가 표준을 준수하면 그 운영은 프로그래밍 언어와 무관해집니다. 즉, 다른 언어로 작성된 컴포넌트도 동일한 시스템에 통합될 수 있습니다.
- 미들웨어: 컴포넌트 통합을 위한 소프트웨어 지원을 제공합니다. 독립적이고 분산된 컴포넌트가 함께 작동할 수 있도록 하려면 컴포넌트 통신을 처리하는 미들웨어 지원이 필요합니다. 컴포넌트 지원을 위한 미들웨어는 저수준 문제를 효율적으로 처리하고 애플리케이션 관련 문제에 집중할 수 있도록 도와줍니다. 또한, 컴포넌트 지원을 위한 미들웨어는 자원 할당, 트랜잭션 관리, 보안 및 동시성에 대한 지원을 제공할 수 있습니다.
- 개발 프로세스: 컴포넌트 기반 소프트웨어 공학에 맞춰진 개발 프로세스가 필요합니다. 사용 가능한 컴포넌트의 기능에 따라 요구 사항이 진화할 수 있는 개발 프로세스가 필요합니다.
CBSE 관점에서 볼 때, 컴포넌트를 재사용하는 것이 아니라 신규로 개발해야 하는 경우에도, 컴포넌트를 사용하여 시스템을 설계하는 것이 합리적입니다. 이를 위해 CBSE는 다음과 같이 기본적 설계 원칙에 입각하여, 이해 가능하고 유지 관리 가능한 소프트웨어를 구축하는데 도움을 줄 수 있습니다.
- 컴포넌트는 독립적이므로 서로의 작동에 간섭하지 않습니다.
구현 세부 사항은 숨겨집니다. 컴포넌트의 구현은 시스템의 나머지 부분에 영향을 주지 않고 변경될 수 있습니다. - 컴포넌트는 잘 정의된 인터페이스를 통해 통신합니다.
이러한 인터페이스가 유지되는 한, 추가 또는 향상된 기능을 제공하는 다른 컴포넌트로 교체할 수 있습니다. - 컴포넌트 인프라는 응용 시스템에서 사용할 수 있는 다양한 표준 서비스를 제공합니다.
이를 통해 개발해야 하는 새로운 코드의 양이 줄어듭니다.
2. 컴포넌트와 컴포넌트 모델 (Components and Component Models)
CBSE(컴포넌트 기반 소프트웨어 엔지니어링)에서는 컴포넌트란 "다른 구성 요소와 조합하여 소프트웨어 시스템을 만들 수 있는 독립적인 소프트웨어 단위"로 정의하는 것이 일반적입니다. 그러나 그 외에도 소프트웨어 컴포넌트에 대한 다양한 정의가 제시되었습니다.
Councill과 Heineman(2001)은 컴포넌트를 다음과 같이 정의합니다:
“표준 컴포넌트 모델을 준수하고 수정 없이 독립적으로 배포 및 구성할 수 있는 소프트웨어 요소.”
이 정의는 본질적으로 표준에 기반한 것으로, 이러한 표준을 준수하는 소프트웨어 단위가 컴포넌트로 간주됩니다.
Szyperski(2002)는 컴포넌트의 정의에서 표준을 언급하지 않고, 대신 컴포넌트의 핵심 특성에 초점을 맞춥니다:
“소프트웨어 컴포넌트는 계약에 명시된 인터페이스와 명시적인 컨텍스트 의존성만을 가진 구성 단위입니다. 소프트웨어 컴포넌트는 독립적으로 배포될 수 있으며, 제3자에 의해 조합될 수 있습니다.”
이 두 정의는 모두 시스템에서 참조되는 서비스가 아니라 시스템에 포함된 요소로서의 컴포넌트 개념을 기반으로 합니다. 그러나 이들은 서비스도 하나의 컴포넌트로 간주할 수 있는 개념과도 호환됩니다.
위의 정의들이 공통적으로 가지고 있는 것은 컴포넌트가 독립적이며, 시스템의 구성에 있어서 기본적인 단위라는 점입니다. 제 의견으로는, 이러한 제안을 결합하여 컴포넌트의 더 나은 정의를 도출할 수 있다고 생각합니다. 다음 표는 CBSE에서 사용되는 컴포넌트의 필수적인 특성을 보여줍니다.
컴포넌트 특징 | 설명 |
표준화 (Standardized) |
CBSE 프로세스에서 사용되는 컴포넌트가 표준 컴포넌트 모델을 준수해야 함을 의미합니다. 이 모델은 컴포넌트 인터페이스, 컴포넌트 메타데이터, 문서화, 조합 및 배포를 정의할 수 있습니다. |
독립성 (Independent) |
컴포넌트는 독립적이어야 합니다. 특정 컴포넌트를 사용하지 않고도 이를 조합하고 배포할 수 있어야 합니다. 컴포넌트가 외부에서 제공되는 서비스가 필요할 경우, 이러한 서비스는 인터페이스 명세서에 "requires" 라고 명확히 명시되어야 합니다. |
조합성 (Composable) |
컴포넌트가 조합 가능하려면 모든 외부 상호작용이 공개된 인터페이스를 통해 이루어져야 합니다. 또한, 컴포넌트는 자체 메서드와 속성과 같은 정보를 외부에서 접근할 수 있도록 제공해야 합니다. |
배포 가능성 (Deployable) |
컴포넌트 모델이 구현된 플랫폼에서 독립적인 엔터티로 운영할 수 있어야 합니다. 이는 보통 컴포넌트가 바이너리 형태로 제공되어야 하며, 배포 전에 컴파일할 필요가 없음을 의미합니다. 컴포넌트가 서비스로 구현된 경우, 사용자가 직접 배포할 필요 없이 서비스 제공자가 배포합니다. |
문서화 (Documented) |
컴포넌트는 잠재적인 사용자들이 컴포넌트가 그들의 요구를 충족시키는지 판단할 수 있도록 완전히 문서화되어야 합니다. 모든 컴포넌트 인터페이스의 문법과 이상적으로는 의미론까지도 명시되어야 합니다. |
컴포넌트는 마치 하나 이상의 서비스를 제공하는 "서비스 제공자"로 생각해도 될 것입니다. 시스템이 서비스가 필요할 때, 해당 서비스를 제공하는 컴포넌트를 호출하며, 이때 컴포넌트가 어디에서 실행되고 있는지, 또는 컴포넌트를 개발하는 데 사용된 프로그래밍 언어가 무엇인지 신경 쓰지 않습니다.
예를 들어, 도서관 시스템에서 사용자가 여러 도서관 카탈로그를 검색할 수 있게 하는 검색 서비스를 제공하는 컴포넌트가 있을 수 있습니다. 다른 예로, 한 그래픽 형식을 다른 형식으로 변환하는 컴포넌트(TIFF를 JPEG로 변환)가 데이터 변환 서비스를 제공할 수 있습니다.
컴포넌트를 서비스 제공자로 보는 것은 재사용 가능한 컴포넌트의 두 가지 중요한 특성을 강조합니다:
- 컴포넌트는 인터페이스로 정의된 독립 실행형 엔터티입니다.
이를 사용하기 위해 소스 코드를 알 필요가 없습니다. 외부 서비스로 참조되거나 프로그램에 직접 포함될 수 있습니다. - 컴포넌트가 제공하는 서비스는 인터페이스를 통해 제공되며, 모든 상호작용은 그 인터페이스를 통해 이루어집니다.
컴포넌트 인터페이스는 매개변수화된 작업의 형태로 표현되며, 컴포넌트의 내부 상태는 절대 노출되지 않습니다.
컴포넌트는 제공하는 서비스와 컴포넌트가 올바르게 작동하기 위해 필요한 서비스를 반영하는 두 개의 관련 인터페이스를 가지고 있습니다(그림 17.2 참조):
- "Provides Interface"는 컴포넌트가 제공하는 서비스를 정의합니다. 이 인터페이스는 본질적으로 컴포넌트 API로, 컴포넌트 사용자가 호출할 수 있는 메서드를 정의합니다. UML 컴포넌트 다이어그램에서, 컴포넌트의 ‘제공’ 인터페이스는 컴포넌트 아이콘에서 선 끝에 있는 원으로 표시됩니다.
- "‘Requires Interface"는 컴포넌트가 올바르게 작동하기 위해 시스템의 다른 컴포넌트가 제공해야 하는 서비스를 명시합니다. 이러한 서비스가 제공되지 않으면 컴포넌트는 작동하지 않습니다. 이는 컴포넌트의 독립성이나 배포 가능성을 훼손하지 않습니다. ‘필요’ 인터페이스는 이러한 서비스가 어떻게 제공되어야 하는지를 정의하지 않기 때문입니다. UML에서 ‘필요’ 인터페이스의 기호는 컴포넌트 아이콘에서 선 끝에 있는 반원으로 표시됩니다. ‘제공’ 및 ‘필요’ 인터페이스 아이콘은 공과 소켓처럼 결합할 수 있습니다.
이러한 인터페이스를 설명하기 위해, 그림 17.3은 센서 배열에서 정보를 수집하고 정리하도록 설계된 컴포넌트의 모델을 보여줍니다. 이 컴포넌트는 일정 기간 동안 데이터를 자율적으로 수집하며, 요청 시 수집된 데이터를 호출하는 컴포넌트에 제공합니다. ‘제공’ 인터페이스에는 센서 추가, 제거, 시작, 중지 및 테스트 메서드가 포함됩니다. report 메서드는 수집된 센서 데이터를 반환하고, listAll 메서드는 연결된 센서에 대한 정보를 제공합니다. 여기에서 표시하지 않았지만, 이러한 메서드에는 센서 식별자, 위치 등을 지정하는 매개변수가 연결되어 있습니다.
"Requires Interface"는 컴포넌트를 센서에 연결하는 데 사용됩니다. 이는 센서가 센서 데이터에 접근할 수 있는 데이터 인터페이스(sensorData)와 관리 인터페이스(sensorManagement)를 가지고 있다고 가정합니다. 이 인터페이스는 다양한 유형의 센서에 연결할 수 있도록 설계되었으므로, Test, provideReading 등과 같은 특정 센서 작업은 포함하지 않습니다. 대신, 특정 유형의 센서에서 사용되는 명령은 문자열에 포함되며, 이는 "Requires Interface"의 작업에 대한 매개변수로 전달됩니다. 어댑터 컴포넌트는 이 문자열을 분석하여 포함된 명령을 각 유형의 센서의 특정 제어 인터페이스로 변환합니다.
외부 서비스로서의 컴포넌트와 프로그램 요소로서의 컴포넌트 간의 중요한 차이점은 서비스가 완전히 독립적인 엔터티라는 것입니다. 이러한 서비스는 ‘필요’ 인터페이스를 가지지 않습니다. 다양한 프로그램이 이러한 서비스를 사용하면서 서비스에 필요한 추가 지원을 구현할 필요가 없습니다.
컴포넌트 모델
컴포넌트 모델은 컴포넌트 구현, 문서화, 배포를 위한 표준의 정의입니다. 이러한 표준은 컴포넌트 개발자가 컴포넌트 간의 상호 운용성을 보장할 수 있도록 하며, 컴포넌트 실행 인프라를 제공하는 공급업체가 컴포넌트 운영을 지원하기 위해 미들웨어를 제공하는 데에도 사용됩니다.
Weinreich와 Sametinger(2001)은 이상적인 컴포넌트 모델의 기본 요소를 논의했습니다. 도표 17.4에서는 이러한 모델 요소를 요약하고 있습니다. 이 다이어그램은 컴포넌트 모델의 요소들이 컴포넌트 인터페이스를 정의하고, 프로그램에서 컴포넌트를 사용하는 데 필요한 정보와 컴포넌트를 배포하는 방법을 정의하는 것을 보여줍니다:
1. 인터페이스
컴포넌트는 인터페이스를 명시하여 정의됩니다. 컴포넌트 모델은 인터페이스를 정의하는 방법과 인터페이스 정의에 포함되어야 할 요소들(예: 작업 이름, 매개변수, 예외 사항)을 규정합니다. 모델은 또한 컴포넌트 인터페이스를 정의하는 데 사용되는 언어를 지정해야 합니다. 일부 컴포넌트 모델은 특정 인터페이스를 컴포넌트가 정의해야 한다고 요구합니다. 이러한 인터페이스는 보안 및 트랜잭션 관리와 같은 표준화된 서비스를 제공하는 컴포넌트 모델 인프라와 컴포넌트를 결합하는 데 사용됩니다.
2. 사용
컴포넌트가 분산되고 원격으로 액세스되기 위해서는 고유한 이름이나 핸들러가 있어야 합니다. 이 핸들은 전 세계적으로 고유해야 합니다. 서비스에는 고유한 URI(Uniform Resource Identifier)가 있습니다. 컴포넌트 메타데이터는 컴포넌트 자체에 관한 데이터로, 컴포넌트의 인터페이스 및 속성에 대한 정보를 포함합니다. 메타데이터는 컴포넌트 사용자들이 제공된 서비스와 필요한 서비스를 파악할 수 있게 해줍니다. 컴포넌트 모델 구현에는 일반적으로 이 컴포넌트 메타데이터에 접근하는 특정 방법이 포함됩니다.
컴포넌트는 일반적인 엔터티이며, 배포 시 애플리케이션 시스템에 맞게 구성되어야 합니다. 예를 들어, 데이터 수집기 컴포넌트(그림 17.2)를 센서 배열의 최대 수를 정의하여 구성할 수 있습니다. 따라서 컴포넌트 모델은 이진 컴포넌트를 특정 배포 환경에 맞게 어떻게 사용자 지정할 수 있는지를 지정할 수 있습니다.
3. 배포
컴포넌트 모델은 독립적이고 실행 가능한 엔터티로 컴포넌트를 배포하는 방법을 명시한 규격을 포함합니다. 컴포넌트는 독립적인 엔터티이므로, 컴포넌트 인프라에서 제공되지 않거나 "Requires Interface"에 정의되지 않은 모든 지원 소프트웨어와 함께 패키지되어야 합니다. 배포 정보에는 패키지의 내용물과 이진 구조에 관한 정보가 포함됩니다. 새로운 요구 사항이 나타나면 컴포넌트는 변경되거나 교체되어야 합니다. 따라서 컴포넌트 모델에는 컴포넌트 교체가 허용되는 시기와 방법을 규정하는 규칙이 포함될 수 있습니다.
마지막으로, 컴포넌트 모델은 생성되어야 하는 컴포넌트 문서를 정의할 수 있습니다. 이 문서는 컴포넌트를 찾고 적합성을 판단하는 데 사용됩니다.
프로그램 단위로 구현된 컴포넌트의 경우, 컴포넌트 모델은 실행 중인 컴포넌트를 지원하는 미들웨어가 제공해야 하는 서비스를 규정합니다. 그림 17.5는 컴포넌트 모델 구현이 제공할 수 있는 몇 가지 서비스를 보여줍니다.
컴포넌트 모델 구현에서 제공하는 서비스는 두 가지 범주로 나뉩니다:
1. 플랫폼 서비스: 이는 컴포넌트가 분산 환경에서 통신하고 상호 운용할 수 있도록 합니다. 이러한 서비스는 모든 컴포넌트 기반 시스템에 필수적으로 제공되어야 합니다.
2. 지원 서비스: 이는 다양한 컴포넌트에서 필요할 가능성이 높은 일반적인 서비스입니다. 예를 들어, 많은 컴포넌트는 컴포넌트 서비스를 사용하는 사용자가 권한이 있는지 인증하는 것을 필요로 합니다. 모든 컴포넌트에서 사용할 수 있는 표준 미들웨어 서비스를 제공하는 것이 합리적입니다. 이는 컴포넌트 개발 비용을 줄이고 잠재적인 컴포넌트 간의 호환성 문제를 방지할 수 있습니다.
미들웨어는 컴포넌트 서비스를 구현하고 이러한 서비스에 대한 인터페이스를 제공합니다. 컴포넌트 모델 인프라에서 제공하는 서비스를 사용하려면 컴포넌트를 ‘컨테이너’에 배포하는 것으로 생각할 수 있습니다.
컨테이너는 지원 서비스를 구현한 것과 컴포넌트를 컨테이너와 통합하기 위해 컴포넌트가 제공해야 하는 인터페이스의 정의를 포함합니다. 컴포넌트를 컨테이너에 포함시키면, 컴포넌트가 지원 서비스에 접근할 수 있으며, 컨테이너는 컴포넌트 인터페이스에 접근할 수 있습니다. 사용 중에는 컴포넌트 인터페이스 자체에 다른 컴포넌트가 직접 접근하지 않고, 대신 컨테이너 인터페이스를 통해 컴포넌트의 인터페이스에 접근하는 코드를 호출합니다.
컨테이너는 크고 복잡하며, 컴포넌트를 컨테이너에 배포하면 모든 미들웨어 서비스를 사용할 수 있습니다. 그러나 간단한 컴포넌트는 지원 미들웨어에서 제공하는 모든 기능을 필요로 하지 않을 수 있습니다. 웹 서비스에서 공통 서비스 제공을 위한 접근 방식은 다소 다릅니다. 웹 서비스의 경우, 트랜잭션 관리와 보안과 같은 공통 서비스에 대한 표준이 정의되었으며, 이러한 표준은 프로그램 라이브러리로 구현되었습니다. 서비스 컴포넌트를 구현하는 경우, 필요한 공통 서비스만 사용하면 됩니다.
'Software Engineering' 카테고리의 다른 글
소프트웨어 공학: 임베디드 소프트웨어 모델링 (9) | 2024.10.03 |
---|---|
소프트웨어 공학: 컴포넌트 컴포지션 (Composition) - 새로운 컴포넌트의 효율적 재구성과 조합 (3) | 2024.09.29 |
소프트웨어 공학: 소프트웨어 신뢰성 정의 (Software Reliability) (0) | 2024.09.29 |
소프트웨어 공학: 재사용 기반 소프트웨어 엔지니어링 - 비용 절감과 품질 향상을 위한 전략 (0) | 2024.09.29 |
소프트웨어 공학: 요구사항 확인 및 관리 - 소프트웨어 품질과 변화 대응을 위한 방법 (1) | 2024.09.28 |