13.4.2.2 오브젝트 팩토리(Factory) 패턴을 활용한 configuration 블록 딕셔너리(Dictionary) 주입

13.4.2.2 오브젝트 팩토리(Factory) 패턴을 활용한 configuration 블록 딕셔너리(Dictionary) 주입

단일 C++ 혹은 Python 코드로 컴파일된 Zenoh-Flow 오퍼레이터(.so 라이브러리) 하나만으로, 낮에는 흑백 이미지 필터로 동작하게 하고 밤에는 엣지 윤곽선(Canny) 검출기로 돌변하게 만들 수는 없는가?

로보틱스 엣지 노드의 유연성은 컴파일 타임(Compile-time)이 아닌, 런타임(Runtime) 시 모듈 내부로 찔러 들어오는 매개변수들의 조작 능력에 달려 있다. 본 절에서는 Zenoh-Flow 파이프라인 선언 파일(YAML) 내부의 configuration 블록을 활용하여, 노드(Node)가 가동되는 순간 팩토리 패턴(Factory Pattern)의 생성자 입구에 무거운 딕셔너리(Dictionary) 옵션 다발을 주입하고 형질을 개조하는 런북을 거행한다.

1. 컴파일된 바이너리의 닫힌 한계와 런타임 폴리모피즘(Polymorphism)

개발자가 /opt/nodes/image_processor.so 라는 범용 이미지 연산 블록(Operator)을 C++로 짜서 배포했다고 치자.
파이프라인 그래프에서 이 블록을 그냥 인스턴스화시켜 버리면, 이 노드는 소스 코드에 하드코딩된 기본값(예: 블러 처리 크기 5x5 커널)으로만 영원히 돌아가는 고철 덩어리에 불과하다.

만약 로봇의 후방 카메라는 5x5로 약하게 필터링하고, 전방 カ메라는 야간 노이즈를 밀어버리기 위해 15x15 커널 값으로 필터링하게 만들려면 소스 코드를 두 벌로 쪼개어 복사 붙여넣기(image_processor_rear.cpp, image_processor_front.cpp)하고 각각 컴파일해야 하는가?
이러한 저열한 반복 무한 복제 코딩(Copy & Paste)의 저주를 박살 내는 것이 바로 디자인 패턴의 심장, 생성자 팩토리(Factory) 패턴과 파이프라인 딕셔너리 주입(Dictionary Injection) 이다.

2. Configuration 블록의 야믈(YAML) 선언

Zenoh-Flow의 노드 인스턴스 선언부 하단에는 configuration 이라는 강력한 딕셔너리 삽입구가 제공된다.
파이프라인 아키텍트는 완전히 동일한 바이너리 파일(image_processor.so)을 두 개 선언하지만, 각각의 배 쪽 구멍(Config)에 완전히 다른 문자열/숫자 데이터를 쑤셔 넣어 노드의 속성을 180도 분기(Fork) 시킨다.

# [팩토리 딕셔너리 주입 YAML 런북]
operators:
  # 전방 카메라 15x15 필터 모드 인스턴스 
  - id: "front_vision_op"
    uri: "file:///opt/nodes/image_processor.so"
    configuration:
       mode: "heavy_blur"  # C++ 생성자가 이 딕셔너리를 파싱한다
       kernel_size: 15
       threshold: 0.88

  # 완벽히 똑같은 바이너리 구동, 허나 설정 주입으로 엣지 디텍터로 환골탈태
  - id: "rear_vision_op"
    uri: "file:///opt/nodes/image_processor.so" 
    configuration:
       mode: "edge_canny"
       kernel_size: 3
       threshold: 0.45

3. C++ 팩토리(Factory) 코어의 해독(Parsing)과 분기 체계

이제 C++ 코드 런타임의 입장으로 들어가 보자. Zenoh-Flow 데몬은 image_processor.so 안에 뚫려 있는 특정 인터페이스 함수 블록(예: operator_factory)을 동적으로 찔러 호출(dlsym)한다. 이 팩토리 엔트리포인트(Entry Point)에, 방금 YAML에 선언해 두었던 문자열 딕셔너리 전체 세트가 Map 이나 JSON 구조체의 형태 인자로 고스란히 하달 전달된다.

// [Zenoh-Flow C++ 내부 생성자 팩토리 체계 런북]

// 파이프라인에서 .so 를 켤 때 무조건 타게 되는 공장장(Factory) 함수
extern "C" zf::Operator* zf_create_operator(const zf::Configuration& config) {
    
    // 야믈(YAML)에서 밀어 넣은 딕셔너리 값을 실시간 강제 추출!
    std::string mode = config.get_string("mode", "heavy_blur" /*default*/);
    int kernel = config.get_int("kernel_size", 5);
    
    // 조건망에 따른 동적 인스턴스 반환(Polymorphism)
    if (mode == "edge_canny") {
        return new CannyDetectorOperator(kernel);
    } else {
        return new HeavyBlurOperator(kernel);
    }
}

이 구조가 작동하는 순간, 노드 라이브러리 제작자는 코드를 만질 필요가 없어져 퇴근길에 오른다.
앞으로 블러의 강도를 높이고 낮추거나, 모드를 뒤집어 엎는 일체의 행위는 C++ 컴파일의 족쇄에서 완전히 해방되어 인프라 엔지니어가 만지는 가벼운 파이프라인 YAML 서류 몇 줄의 configuration 배열 수정으로 1초 만에 격변한다(Hot-Swappable Configuration).

이 오퍼레이터 생성 팩토리 패턴(Factory Method)과 런타임 딕셔너리 지배 체제의 융합은, 분산 실시간 로보틱스 시스템에 무소불위의 재사용성(Reusability)과 다형성(Polymorphism)을 이식하는 궁극의 소프트웨어 아키텍처 코어다.