티스토리 뷰

반응형

 

 

소프트웨어 아키텍처 101 - YES24

막막했던 아키텍처가 쉬워지는 실무 지침서소프트웨어 아키텍트는 전 세계 연봉 10위 안에 드는 직업이지만, 지금까지 ‘개발자가 아키텍트’로 전향하는 데 실질적으로 도움이 될 만한 지침이

www.yes24.com

Basic Component Struture

이름에서 알 수 있듯이, micro한 커널(kernel) 아키텍처이다.

또한 플러그인(plug-in) 아키텍처라고도 불리는데, 위 그림에서 알 수 있듯이 코어 시스템을 중심으로 플러그인을 붙여나가는 형태이기 때문이다.

일반적으로 모놀리식 형태에서 많이 사용되며, 가장 좋은 예시는 Eclipse IDE와 같은 Plugin 기반의 IDE이다.

즉, Eclipse core system 자체는 단순한 텍스트 에디터지만, 여기에 플러그인을 어떤걸 붙이느냐에 따라 C++ 응용프로그램용 IDE부터 임베디드 장치를 위한 크로스 컴파일이 가능한 IDE로도 변모할 수 있다.

덧붙여서, Eclipse IDE 뿐만 아니라, Jira, Jenkins 등이 이 아키텍처를 사용하고 있으며, Chrome, Firefox 같은 웹 브라우저도 이 아키텍처를 응용하여 만든 것이다 (온갖 extention/plugin을 떠올려보자)

 

코어 시스템

시스템을 실행시키는 데 필요한 최소한의 기능

코어 시스템은 말그대로 핵심/중심이 되며, 이 시스템을 통해서 Plugin을 연결하고 사용하는 방식이다.

또한, 의존성을 최소화하기 위하여 다양한 기능들을 각 Plugin에 구현해 놓고 필요에 따라 붙여 사용한다.

따라서, 위의 설명처럼 "코어 시스템으로써 최소한의 기능"만을 구현해 놓는 것이 확장성에 용이하다.

코어 시스템 내부는 레이어드 아키텍처를 사용할 수도 있으며, 도메인 분할로써 구현할 수도 있으며, 핵심은 최소한의 기능만 갖추고서 외부 Plugin을 붙일 수 있게 디자인한다는 것이다.

 

플러그인

특정 처리 로직, 부가 기능뿐만 아니라 코어 시스템의 기능 변경을 위한 Add-on 스타일을 지원하는 standalone 컴포넌트

여기서 중요한 포인트는 추가적인 로직/기능 뿐 아니라 코어 시스템 자체를 개선/확장할 수 있는 역할을 한다는 것과 standalone 이어야 한다는 것이다. 즉, 다른 플러그인이 없으면 동작할 수 없는 형태가 아닌 단독 플러그인으로써의 동작을 보장해야한다는 것이다.

일반적으로 플러그인은 코어시스템과 point-to-point 관계이며, 따라서 대부분의 연결고리는 entry-point class를 호출해주는 메서드나 함수이다.

아래는 C++ Boost.DLL 라이브러리인데, 여기 있는 코드를 보면 어떤식으로 이 포인트를 잡는지 이해할 수 있을 것이다.

// Plugin side

#include <boost/dll/alias.hpp>                          // for BOOST_DLL_ALIAS
#include <boost/shared_ptr.hpp>
#include "../tutorial_common/my_plugin_api.hpp"

namespace my_namespace {
    boost::shared_ptr<my_plugin_api> create_plugin();   // Forward declaration
} // namespace my_namespace

BOOST_DLL_ALIAS(
    my_namespace::create_plugin,                        // <-- this function is exported with...
    create_plugin                                       // <-- ...this alias name
)
// Core System side

#include <boost/dll/shared_library.hpp>         // for shared_library
#include <boost/dll/runtime_symbol_info.hpp>    // for program_location()
#include "static_plugin.hpp"                    // without this headers some compilers may optimize out the `create_plugin` symbol
#include <boost/function.hpp>
#include <iostream>

namespace dll = boost::dll;

int main() {
    dll::shared_library self(dll::program_location());

    std::cout << "Call function" << std::endl;
    boost::function<boost::shared_ptr<my_plugin_api>()> creator
        = self.get_alias<boost::shared_ptr<my_plugin_api>()>("create_plugin");

    std::cout << "Computed Value: " << creator()->calculate(2, 2) << std::endl;
}
 

Tutorial - master

This Tutorial is provided to give you an idea of how to create and use plugins. As noted in documentation to the boost::dll::import variables and functions returned from those functions hold a reference to the shared library. However nested objects and obj

www.boost.org

 

컴파일 기반과 런타임 기반

플러그인은 컴파일 기반과 런타임 기반으로 구현할 수 있다.

즉, 컴파일을 통해서만 플러그인 배포가 가능한 경우와 동작 중에 플러그인 배포를 할 수 있는 것이다.

당연히 둘 간에는 트레이드오프가 있으며, 컴파일 기반이 관리포인트가 더 적어 관리하기에 용이하지만, 컴파일을 해야하기때문에 해당 플러그인이 포함된 모놀리식 어플리케이션 전체를 재배포해야 한다.

런타임 기반 플러그인을 위한 프레임워크로는 OSGi, Penrose(자바), Jigsaw(자바), Prisim(닷넷) 등이 있다.

 

레지스트리 (Registry)

플러그인들의 정보를 등록/관리하는 곳

코어시스템은 어떤 플러그인들이 존재하는지 알아야 로드해서 사용할 수 있을 것이다.

이러한 시스템을 위한 가장 일반적인 구현 방법은 "플러그인 레지스트리" 이다

레지스트리에는 플러그인을 사용하기 위한 정보들. 즉, 어떠한 플러그인들이 존재하고, 이름은 무엇인지 데이터 입출력은 어떤지, 어떻게 로드할 수 있는지(프로토콜) 등등의 정보를 넣고 관리할 수 있다.

 

계약 (Contract)

코어시스템에서 플러그인을 사용하기 위한 행위

코어 시스템에서 플러그인을 사용하기 위해서는 레지스트리로부터 플러그인에 대한 정보를 가져온 다음 이것은 시스템에 등록하고 사용해야한다. 그리고 사용이 다 끝나면 해제(메모리와 관련됨)해주어야 한다.

일반적으로 이 계약은 XML이나 JSON형태를 통해 코드 없이 하는 방식을 채택한다. 이것은 코어 시스템과 플러그인이 의존성 없이 독립적으로 존재할 수 있게 해준다. 즉, 레지스트리로부터 이 정보들을 얻어 플러그인을 로드하고 사용하면 된다.

컨트랙트의 플로우는 assess, register, deregister 의 흐름이며, 먼저 플러그인에 대한 정보를 확인하고, 등록(로드)하고 사용하다가 더 이상 사용하지 않는다면 해제(언로드)하는 방식이다.

 

아키텍처 특성

아키텍처 특성 별점
분할 유형 도메인 및 기술
퀀텀 수 1
배포성 ★★★
탄력성
진화성 ★★★
내고장성
모듈성 ★★★
전체 비용 ★★★★★
성능 ★★★
신뢰성 ★★★
확장성
단순성 ★★★★
시험성 ★★★

 

반응형
댓글