## 0.1 rclcpp Multi-Threaded Executor 기반 동시성 병렬 스레딩 제어 모델

rclcpp의 단일 스레드 이그제큐터(Single-Threaded Executor)는 콜백 큐에 적재된 작업을 직렬로만 처리하므로, CPU 사이클이 길게 소요되는 시각 기반 정밀 착륙(Visual Servoing) 처리 알고리즘이 가동될 경우 후행하는 IMU 센서 데이터 구독 콜백이 정체(Starvation)되는 심각한 지연(Latency) 현상을 유발할 수 있다. 이러한 병목을 공학적으로 돌파하기 위해 ROS2 아키텍처는 C++의 네이티브 스레드 환경인 std::thread를 추상화한 rclcpp::executors::MultiThreadedExecutor를 제공하여, 다중 코어 프로세서의 물리적 병렬성(Parallelism)을 극한으로 활용할 수 있게 한다.

0.1.1 스레드 풀(Thread Pool) 생성 및 병렬 디스패치 구조

다중 스레드 이그제큐터가 생성되면 초기화 단계에서 지정된 개수만큼의 스레드가 스레드 풀(Thread Pool)의 형태로 메모리에 스폰(Spawn)된다. 스레드 개수를 명시적으로 주입하지 않을 경우, 기본적으로 std::thread::hardware_concurrency()의 반환값을 참조하여 호스트 머신의 논리적 CPU 코어 수와 동일한 개수의 워커 스레드(Worker Thread)를 할당한다.
이그제큐터 내부의 메인 스핀(Spin) 스레드는 대기 집합(WaitSet)으로부터 이벤트 마스크를 받아 실행 가능한 콜백(Ready Callback) 목록을 도출한 뒤, 이 작업 단위(Work Item)들을 현재 유휴 상태(Idle)인 스레드 풀 내부의 워커들에게 분산 위임(Dispatch)한다. 이 아키텍처는 IO 바운드 모듈(네트워크 송수신)과 CPU 바운드 모듈(경로 생성, 군집 회피 연산)이 물리적으로 각기 다른 코어에서 진정한 의미의 병렬 연산을 수행하도록 보장한다.

0.1.2 콜백 그룹(Callback Group)의 상호 배제(Mutually Exclusive)와 재진입성(Reentrant) 제어

다중 스레딩 모델을 노드(Node)에 안전하게 적용하기 위해서는 동시성 런타임 환경에서 흔히 발생하는 임계 구역(Critical Section)에서의 경쟁 조건(Race Condition)을 원천적으로 제어해야 한다. 프레임워크는 이를 위해 콜백 그룹(Callback Group)이라는 객체 지향적 논리 단위를 제공한다.
노드 생성 시 기본 할당되는 콜백 그룹은 ’상호 배제형(Mutually Exclusive)’이다. 이 속성을 지닌 콜백들은, 설령 다중 스레드 이그제큐터의 워커 스레드가 남아돌더라도 절대로 두 개 이상이 동시에 병렬 실행될 수 없도록 락(Lock)을 통해 직렬화(Serialization)된다. 즉, 동일한 멤버 변수에 접근하는 타이머 콜백과 서브스크라이버 콜백이 동시에 트리거되어 자원을 훼손하는 사태를 프레임워크 차원에서 방어하는 것이다.
반대로, 상태가 격리되어 서로 간섭하지 않는 병렬 처리 루틴(예: 다채널 라이다 포인트 클라우드 병렬 필터링)의 경우 개발자는 해당 콜백들을 명시적인 ‘재진입 가능형(Reentrant)’ 콜백 그룹으로 재할당해야 한다. 이 경우 이그제큐터는 동일한 콜백 함수라 할지라도 이전 호출의 완료를 기다리지 않고 다른 가용 스레드에 중첩 할당하여 시스템 리소스를 최대로 이끌어낸다.

0.1.3 프로그래머 관점의 스레드 안전성(Thread Safety) 구현 의무

재진입형 콜백 그룹이나, 서로 다른 상호 배제형 콜백 그룹 다수를 운용하는 다중 스레드 아키텍처 하에서는 개발자의 엄격한 메모리 안전성(Memory Safety) 보장 의무가 수반된다. 두 개 이상의 스레드가 std::vectorstd::map과 같은 C++ 표준 컨테이너 혹은 전역 상태 변수에 동시에 쓰기 및 읽기 접근을 시도하면 즉각적인 세그먼테이션 결함(Segmentation Fault)으로 수렴한다. 따라서 다중 스레드 이그제큐터 환경에서는 std::mutexstd::shared_mutex (C++17)와 같은 동기화 원시 타입(Synchronization Primitives)을 std::lock_guard 혹은 std::unique_lock 형태의 RAII 패턴으로 엄격히 캡슐화하여 임계 구역 데이터 무결성을 수학적으로 입증할 수 있도록 설계해야 한다.