# 노드 간 충돌 사례와 해결 방안

#### 노드 충돌의 개념

ROS2 환경에서 여러 노드가 동시에 실행되고 상호 통신하는 과정에서, 특정 자원이나 데이터에 대한 충돌(conflict)이 발생할 수 있다. 이러한 충돌은 기능적 오류를 일으키는 단순 충돌부터 시스템 운영에 큰 지장을 줄 수 있는 심각한 문제까지 다양하게 나타난다. 노드 간 충돌은 크게 다음과 같은 상황에서 주로 발생한다.

* 주파수(또는 주기)가 서로 다른 노드 간 통신에서 데이터 유실 혹은 오버플로가 생기는 경우
* QoS 설정이 호환되지 않아 통신이 정상적으로 이뤄지지 않는 경우
* 동시에 접근하는 자원(예: 파라미터 서버, 토픽 버퍼)에 대한 동기화 문제
* 실제 물리적인 하드웨어 자원(CPU, 메모리 등)이 부족하거나 할당이 제대로 이뤄지지 않는 경우

이러한 충돌 상황은 주로 토픽 기반 통신, 서비스 요청 및 응답, 액션(Action) 서버/클라이언트 통신 등에서 빈번히 발생한다. 노드 충돌을 방지하기 위해서는 데이터 흐름을 면밀히 분석하고 적절한 QoS 정책을 설정하는 것이 중요하다.

#### QoS와 충돌의 연관성

QoS(Quality of Service)는 ROS2에서 통신 품질과 성능을 설정하기 위한 핵심 수단이다. QoS가 충돌과 연관되는 이유는 노드 간의 메시지 송수신이 “어떤 방식, 어느 정도의 신뢰성, 어느 수준의 실시간성”으로 이루어져야 하는지를 결정하기 때문이다. 서로 다른 QoS 프로파일을 사용하는 노드 간에는 비호환성으로 인해 통신이 단절되거나, 통신은 되더라도 데이터 처리 지연 혹은 메시지 손실 등의 문제가 발생한다.

예를 들어, 한 노드는 높은 신뢰성을 요구하는 “Reliable” QoS를 설정했는데, 다른 노드는 데이터 전달 속도를 우선시해 “Best Effort”로 설정했다면 일부 시나리오에서는 매우 빠른 속도로 많은 양의 데이터를 발행하지만, 수신 측이 이를 신뢰적으로 처리하려다 보니 내부적으로 재전송 요청 등이 발생해 병목이 생길 수 있다. 결국 메시지 지연(time delay)이 커지거나 수신 측의 큐(queue)가 가득 차 버릴 위험이 있다.

#### 대표적 충돌 사례

**QoS 정책 불일치로 인한 데이터 손실**

노드 A와 노드 B가 동시에 실행 중이며, 다음과 같은 QoS 프로파일을 사용한다고 하자.

* 노드 A (Publisher): Reliability = Best Effort, Durability = Volatile, Deadline = 없음
* 노드 B (Subscriber): Reliability = Reliable, Durability = Transient Local, Deadline = 1초

메시지 교환 시, 노드 A는 ‘Best Effort’ 방식이므로 네트워크 환경이 좋지 않거나 시스템 부하가 있을 때 전송을 빠뜨릴 수 있다. 반면, 노드 B는 ‘Reliable’ 설정이므로 누락된 메시지에 대해 재전송을 요청한다. 하지만 노드 A는 재전송 메커니즘이 없는 ‘Best Effort’를 유지하므로 결과적으로 노드 B가 메시지를 수신하지 못하는 문제가 빈번히 발생할 수 있다. 또한 노드 B는 ‘Transient Local’로 설정하여 특정 시점 이전에 발행된 메시지라도 버퍼에서 가져오길 원하지만, 노드 A가 ‘Volatile’로 설정되어 있기 때문에 과거의 메시지가 보관되지 않는다.

이처럼 서로 다른 QoS 설정은 특정 환경에서 통신 불능 혹은 데이터 손실 문제를 야기한다.

**메시지 퍼블리시/서브스크라이브 주기 불일치**

ROS2에서 노드 간 통신이 단일 토픽으로 진행될 경우, 퍼블리셔와 서브스크라이버 사이의 메시지 교환 주기가 엇박자로 동작하면 불필요한 시스템 부하가 발생하거나, 반대로 메시지가 너무 적게 전달되어 실시간 동작에 문제가 생길 수 있다.

예시로, 노드 A가 초당 100Hz(즉 0.01초 간격)로 이미지를 퍼블리시하고, 노드 B가 10Hz로 이미지를 처리해야 한다면, 노드 B가 모든 이미지를 처리할 수 없을 수 있다. 이를 단순히 “QoS에서 큐 크기를 늘리면 되지 않나?”라고 접근하면, 큐가 너무 커져 메모리 사용량이 급격히 늘 수 있으며, 처리 지연(latency)이 커져 실시간성이 떨어진다.

따라서 퍼블리시/서브스크라이브 주기를 상호 조정하거나, 동기화 메커니즘(예: 메시지 필터(Message Filter) 기법)을 적용하여 필요한 메시지만 선별적으로 전달하는 전략이 필요하다.

**여러 노드가 공유 자원을 동시에 사용할 때 발생하는 교착 상태**

ROS2에서도 콜백 그룹(Callback Group)이나 Executor 등 다양한 방법을 통해 쓰레드 자원을 제어한다. 만약 여러 노드가 공동 자원(예: 특정 파일, 하드웨어 장치)을 동시에 사용하려고 하고, 적절히 Lock이 관리되지 않으면 교착 상태(Deadlock)가 발생할 수 있다.

예컨대 노드 A가 자원 X와 자원 Y를 순서대로 잠그려 하고, 노드 B가 자원 Y와 자원 X를 반대로 잠그려 하는 경우, 서로가 상대가 풀어주길 기다리다가 무한 대기에 빠질 수 있다. 이러한 교착 상태는 QoS 설정과 직접적인 연관이 없더라도, 높은 우선순위 쓰레드가 낮은 우선순위 쓰레드를 기다리게 되는 우선순위 역전(Priority Inversion) 문제와 함께 전체 통신 성능에 치명적 영향을 준다.

**토픽 네임스페이스 충돌**

ROS2는 네임스페이스를 통해 토픽, 서비스 이름 등을 구분한다. 만약 서로 다른 두 노드가 동일한 토픽 이름을 의도치 않게 사용하거나, 네임스페이스 설정이 중복되어버리면 예상치 못한 데이터를 구독하게 되거나 무의미한 메시지를 발행할 수 있다. 예를 들어, 카메라 노드가 발행하는 토픽 이름이 `/camera/color/image_raw`인데, 다른 노드가 동일한 이름의 토픽을 사용하면 충돌이 일어나거나 의도치 않은 중복 메시지가 생긴다. 이를 방지하기 위해서는 런치 파일(launch file)에서 명시적으로 네임스페이스를 구분짓거나, 노드 내에서 잘 정의된 네임스페이스 계층 구조를 사용해야 한다.

#### 충돌을 미연에 방지하기 위한 사전 검사

노드 간 충돌은 대부분 설계 단계에서 부정확한 QoS 프로파일 설정, 메시지 주기 불일치, 혹은 네임스페이스 관리 부실 등으로 인해 발생한다. 따라서 시스템을 구성하기 전에 아래와 같은 사항을 사전에 검사하면 충돌 방지를 어느 정도 달성할 수 있다.

1. **QoS 호환성 체크**: 발행자와 구독자의 QoS 프로파일을 비교해 호환성이 맞는지 우선 검토한다.
2. **메시지 전달 주기와 시스템 부하 사이의 균형**: 퍼블리시 빈도(Frequency)와 구독자의 처리 속도(Capacity)를 사전에 측정한다.
3. **충분한 큐 크기 확보**: 메시지 처리 지연을 고려하여 적절한 큐(History와 Depth) 크기를 할당한다.
4. **네임스페이스 겹침 여부 확인**: 공용 토픽 이름 혹은 유사 네임스페이스를 사용하는 노드가 존재하는지 확인한다.
5. **콜백 동시성 관리**: Executor 사용 시 콜백 그룹을 어떻게 설정할지, 교착 상태가 발생할 여지가 없는지 검사한다.

이러한 사전 검증은 특히 대규모 분산 ROS2 시스템에서 필수적이다. 적어도 토픽, 서비스, 액션의 이름과 QoS 설정이 어떻게 구성되는지 도식화하여 검토하면 충돌을 줄일 수 있다. 아래는 간단한 예시 다이어그램이다.

{% @mermaid/diagram content="flowchart LR
A\[Publisher Node<br>QoS: Reliable] -->|Topic: /example\_topic| B\[Subscriber Node<br>QoS: Best Effort]
B -->|Feedback?| A" %}

위 상황에서 발행자 A와 구독자 B가 각기 다른 QoS 프로파일을 사용하는 경우를 시각화한 것이다.

#### 대표적 충돌 해결 전략

**QoS 파라미터 재설정 (Reconfiguration)**

ROS2는 런타임에 일부 QoS 파라미터를 동적으로 재설정할 수 있다. 노드 실행 중에 “Reliable” → “Best Effort” 등으로 바꾸는 것은 불가능한 경우가 있지만, 예컨대 큐 크기(History depth)나 Deadline, Liveliness 등의 파라미터는 특정 노드에서 동적으로 조정할 수 있다. 일반적으로 “Reliable” 통신이 필수적이지 않은 경우라면, 간헐적으로 QoS를 “Best Effort”로 전환하여 데이터 전송 병목을 줄이는 전략도 가능하다. 다만 이러한 QoS 전환은 통신 연결이 재협상(Re-negotiation)되는 과정에서 일시적으로 메시지가 유실될 수 있으므로, 실시간성이 중요한 시스템에서는 주의가 필요하다.

**노드 사이의 통신 최적화**

노드 간 통신 충돌 중 상당 부분은 불필요하게 많은 트래픽(High Message Frequency) 때문에 발생한다. 예를 들어, 다양한 센서 정보가 동시에 발행되어 CPU나 네트워크 대역폭이 포화 상태에 도달하면, 이로 인해 QoS 재전송 메커니즘이 남발되거나 메시지 유실이 발생할 수 있다. 이를 해결하기 위해 다음 기법들이 적용될 수 있다.

* **메시지 필터**: 구독자가 필요한 메시지(예: 센서 수치가 임계값을 초과했을 때만)만 받도록 필터링을 적용한다.
* **샘플링**: 모든 메시지가 아닌 일정 샘플링 레이트로 발행해, 노드끼리 데이터를 간소화해 주고받는다.
* **동적 대역폭 할당**: 네트워크 레벨에서 우선순위를 부여하거나, ROS2의 Traffic Control 기능을 활용해 특정 토픽의 대역폭을 제한한다.

**콜백 함수 동시성 제어**

ROS2에서 Executor는 콜백(Callback) 함수들의 실행 스레드(thread) 풀을 관리한다. 기본적으로 SingleThreadedExecutor, MultiThreadedExecutor가 있으며, 필요에 따라 Custom Executor를 직접 구현할 수도 있다. 문제는 “동시에 처리해야 할 콜백이 많을 때, 적절한 Lock과 우선순위 제어가 이루어지지 않으면” 실행 순서에 따른 교착 상태나 우선순위 역전이 일어날 수 있다는 점이다.

이를 방지하기 위해 다음과 같은 방법을 쓸 수 있다.

1. **콜백 그룹(Callback Group) 분리**: 서로 간섭이 우려되는 콜백은 다른 그룹으로 분리하고, Reentrant or Mutually Exclusive 설정을 적절히 구성한다.
2. **우선순위 기반 스케줄링**: ROS2는 스레드 우선순위를 표준적으로 제공하지 않지만, RTOS(Real-Time OS) 환경이나 rclcpp를 직접 수정하여 우선순위를 줄 수 있는 경우가 있다. 이러한 방식을 통해 중요한 콜백이 먼저 실행되도록 설정한다.
3. **교착 상태 회피**: 자원 획득 순서를 고정하거나 Lock-Free 알고리즘, lock\_guard 같은 C++ RAII 기법을 활용해 상호 간섭을 줄인다.

**자원 할당 모니터링**

물리적 자원(CPU, 메모리, 네트워크 대역폭 등)이 부족해지면 QoS 정책이 아무리 잘 설정되어 있어도 충돌을 피하기 어렵다. 따라서 다음 방법으로 노드별 자원 사용을 모니터링하고, 한계를 넘지 않도록 제어해야 한다.

`ros2 topic hz` 명령으로 실제 퍼블리시/서브스크라이브 주기를 측정하고, 계획된 주기와 얼마나 차이가 있는지 점검한다.

```bash
$ ros2 topic hz /camera/image_raw
```

`ros2 doctor` 사용해 노드 상태, 토픽 충돌 여부 등을 확인한다.

```bash
$ ros2 doctor
```

시스템 모니터링 툴(예: top, htop, nmon 등)을 통해 CPU와 메모리 사용량을 관찰한다.

**실시간 ROS2(RT-ROS2) 고려**

일부 애플리케이션은 실시간성이 요구되는데, 이 경우 단순히 QoS 설정만으로는 충분치 않고, 실시간 스케줄러(RT 프리엠션 커널 등)를 사용하는 것이 권장된다. RT-PREEMPT 패치가 적용된 리눅스 커널에서 ROS2를 실행하면, 콜백이 시간 제약을 만족하도록 우선순위가 보장된다.

실시간 환경에서 노드 충돌은 더 치명적이므로, 각 노드의 Worst Case Execution Time(WCET)을 측정하고 스케줄러 상에서 우선순위를 정하는 방법이 사용된다. 예를 들어, $T\_i$ 주기로 동작하는 태스크(노드)가 있고, 각 태스크의 실행 시간 $C\_i$가 알려져 있을 때, 다음과 같은 고전적 스케줄링 조건을 만족해야 한다.

$$
\sum\_{i=1}^{n} \frac{C\_i}{T\_i} \leq 1
$$

이 부등식을 만족하지 못하면 이론상 실시간 스케줄링이 불가능하므로, 노드 간 충돌을 유발할 확률이 매우 높아진다. 이때 QoS 정책이나 메시지 빈도를 조정해 $C\_i$ 또는 $T\_i$를 변경하면, 충돌 가능성을 줄일 수 있다.

#### 충돌 디버깅 및 진단 기법

**로깅(Logging)과 ros2 tracing**

ROS2는 로깅을 통해 각 노드의 상태, 콜백 호출 순서, 메시지 발행 여부 등을 기록할 수 있다. `RCLCPP_INFO()`, `RCLCPP_WARN()` 등의 로깅 매크로를 적절히 배치하면, 노드 충돌 징후(메시지 유실 횟수, 콜백 충돌 등)를 빠르게 확인할 수 있다. 더 나아가 ros2\_tracing 패키지를 사용하면, 콜백 시작과 종료 시점을 정밀하게 추적하고 이벤트 간 상관관계를 시각화할 수 있다.

```bash
$ sudo apt-get install ros-humble-ros2tracing
$ ros2 trace start --session-name my_trace_session
$ ros2 run my_package my_node
...
$ ros2 trace stop
```

이후 trace 데이터를 분석하면, 콜백 호출 타이밍, Executor 스레드 분배 등을 확인할 수 있다. 이러한 정보를 바탕으로 메시지 지연이나 교착 상태 발생 시점을 파악할 수 있다.

**RQt Plugin과 RViz**

* **rqt\_graph**: 토픽 연결 관계를 그래프로 표현해준다. 토픽이 중복되거나 이름 충돌이 있는지, 원하는 QoS 설정이 적용되었는지 시각적으로 확인할 수 있다.
* **RViz**: 센서 데이터(레이저 스캔, 이미지 등)를 모니터링하며, 실제 데이터가 제대로 들어오고 있는지 여부를 직관적으로 검사할 수 있다.

**실행 시뮬레이션(Offline Simulation)**

실기기(Real Hardware)에서 직접 노드를 테스트하면 예측 불가능한 하드웨어 요인으로 인해 디버깅이 어렵다. 시뮬레이터(Gazebo, Ignition 등)를 활용하면 노드 통신 주기를 정확히 조절하고, 여러 테스트 케이스를 재현할 수 있어 충돌 상황을 쉽게 재연 가능하다.

#### 노드 충돌 예방을 위한 구조적 접근

ROS2 시스템이 커질수록 노드 간 충돌을 완전히 막기는 점점 어려워진다. 따라서 개발 초기 단계에서부터 충돌을 예방하기 위한 구조(Architecture) 설계가 필수적이다. 아래는 대표적인 구조적 접근 방법들이다.

**Lifecycle Node 도입**

ROS2의 Lifecycle Node는 노드가 일련의 상태 머신을 통해 “Unconfigured → Inactive → Active → Finalized” 형태로 변화하도록 정의한다. 이를 통해 노드를 단계별로 초기화하고, 의도한 시점에만 통신이 시작되도록 제어할 수 있다.

* **Unconfigured** 단계: 파라미터 로딩, 하드웨어 리소스 점검 등 노드 구동 준비를 수행한다.
* **Inactive** 단계: ROS2 커뮤니케이션 생성을 완료하지만, 실제 메시지 발행·수신은 하지 않는다.
* **Active** 단계: 노드가 정상적으로 동작하며 퍼블리셔·서브스크라이버가 활발히 메시지를 주고받는다.
* **Finalized** 단계: 노드를 종료하고, 모든 자원을 반환한다.

이러한 단계적 접근은 노드 간 초기화 순서를 조정할 수 있게 해준다. 예를 들어, 특정 센서 노드는 하드웨어 초기화가 오래 걸린다면, 다른 노드는 해당 센서 노드가 Active 상태가 된 이후에만 통신을 수행하도록 설계할 수 있다. 이를 통해 “노드가 준비되기 전에 데이터를 수신해버리는” 충돌 사례를 효과적으로 방지한다.

**Node Composition**

ROS1 대비 ROS2에서 강조되는 점 중 하나는 여러 노드를 ‘하나의 프로세스(Process)’ 안에서 실행하는 Node Composition 기법이다. 이를 통해 프로세스 간 통신이 아닌 프로세스 내부에서 직접 메시지를 전달함으로써 무거운 DDS(또는 RTPS) 트래픽을 줄이는 이점이 있다. 다만, 동일 프로세스 내에서 멀티쓰레드로 구동되므로, 충돌과 교착 상태가 발생할 가능성은 오히려 커질 수 있다.

* 단일 프로세스 내에서 콜백이 경쟁하게 될 때, “Mutually Exclusive Callback Group”과 “Reentrant Callback Group” 등을 적절히 배분해야 한다.
* 노드 간 자료 공유 시 Lock-Free 자료구조를 사용하는 등 세심한 주의가 필요하다.

Node Composition은 통신 비용을 줄이고 실시간성을 높일 수 있는 좋은 방법이지만, 내부 동시성 제어가 제대로 이뤄지지 않으면 상호 배제나 타이밍 충돌이 쉽게 발생한다.

**DDS 구현체(Implementation) 선택**

ROS2가 DDS를 추상화해서 제공한다 해도, 실제 사용되는 DDS 구현체(Fast DDS, Cyclone DDS, Connext DDS 등)에 따라 QoS 동작 방식이 세부적으로 달라진다. 특히 높은 Throughput 또는 낮은 Latency를 위해 DDS 설정 파일(XML or YAML)을 수정해야 할 수도 있다. 예컨대,

* **Max Samples**, **Max Instances** 파라미터가 너무 작으면 큐가 빨리 차서 메시지를 버리게 된다.
* **Latency Budget** 파라미터를 잘못 설정하면 의도치 않은 지연을 초래한다.

여러 DDS 구현체를 테스트해보고, 실제 시스템 요구사항(지연시간, 신뢰성, 보안 등)에 가장 적합한 것을 선택하되, QoS 프로파일을 DDS 설정과 함께 면밀히 검토해야 노드 간 충돌을 줄일 수 있다.

**Distributed System에서의 노드 그룹화**

ROS2는 여러 머신(Host) 간 분산 실행이 가능하다. 이때 주의해야 할 점은, 통신 지연 혹은 네트워크 장애 상황에서 노드가 서로 다른 상태를 가지게 되면 동기화가 어긋날 수 있다는 것이다. 예를 들어, 중앙 서버 노드에서 파라미터를 업데이트했는데, 일부 로봇 노드가 이를 늦게 적용하거나 적용 실패하면 기능적으로 충돌이 발생한다.

이를 완화하기 위해 다음과 같은 그룹화 전략이 쓰인다.

* **로컬 노드 그룹(Local Node Group)**: 물리적으로 가까운 장치들끼리 묶어, 그룹 내부는 높은 신뢰도로 통신하고, 그룹 간은 필수 메시지만 공유한다.
* **핵심 노드(Critical Node) 우선 배치**: 제어 로직에 필수적인 노드는 처리 능력이 높은 머신에 두고, 주변부(센서, 보조 기능) 노드는 분산시켜 네트워크 부하를 분산한다.
* **동적 파티셔닝(Partitioning)**: 네트워크 트래픽이 과도해지는 특정 구역에서는 노드 간 통신을 가상 네트워크(가령 VLAN 등)로 분리해 충돌 범위를 최소화한다.

#### 고급 테스트 및 검증 방법

**시나리오 기반 자동화 테스트**

노드 간 충돌을 찾기 위해서는 단순 유닛 테스트뿐만 아니라, 여러 노드가 다양한 타이밍과 이벤트로 상호작용하는 시나리오 테스트가 필요하다. 예를 들면 다음과 같은 시나리오를 자동화하여 실행한다.

1. 센서 노드(N1)가 초당 50Hz로 데이터를 발행한다.
2. 제어 노드(N2)가 10Hz로 데이터 처리를 시도하다가, 일정 확률로 서비스 요청을 보낸다.
3. 서비스 노드(N3)가 CPU가 바쁜 상태(부하 테스트)에서 요청을 처리한다.
4. 전체 노드 간 통신 로그를 수집해 QoS 재전송 횟수, 메시지 누락 여부, 지연 시간 등을 분석한다.

이 때 ros2\_tracing이나 rosbag record를 함께 사용해, 각 시간대별 메시지 상태를 기록하면 노드 충돌 징후를 찾기 쉽다.

**Fuzz Testing**

ROS2 메시지(토픽, 서비스, 액션)에 의도적으로 비정상적인 데이터나 타이밍을 적용해 노드 동작이 어떻게 반응하는지 살펴보는 기법이다. 예를 들어, 허용 범위를 벗어난 센서 값, 극단적으로 긴 스트링 데이터, 초고빈도의 서비스 요청 등을 주어본다. 이를 통해 예상치 못한 충돌이나 예외가 발생하는지 확인할 수 있다.

**Fault Injection**

* **네트워크 지연(Faulty network)**: 네트워크 패킷을 지연·손실시키는 시뮬레이션 환경(예: netem)을 구성한다.
* **메모리 부족(Memory limit)**: Docker나 cgroup을 사용해 노드가 사용할 수 있는 메모리를 인위적으로 제한한다.
* **CPU 스로틀링(Throttling)**: CPU 할당량을 줄여 콜백 처리 속도를 늦춘다.

이러한 Fault Injection 테스트를 통해, 노드가 예기치 않은 상황에서 어떻게 대응하며 충돌이 발생하는지 살펴보고 사전에 대처할 수 있다.

#### 보안(ROS2 Security) 관점에서의 충돌

ROS2는 DDS-Security를 통해 암호화, 인증, 권한 부여 기능 등을 제공한다. 보안 설정이 제대로 구성되지 않으면 노드 간에 통신이 차단되거나, 인증 실패로 메시지가 송신·수신되지 않는 일이 생긴다. 이는 일종의 QoS 충돌이라 볼 수 있으며, 다음 사항에 유의해야 한다.

* **미등록 Participant의 연결 거부**: 보안을 활성화하면, 인증된 Participant만 DDS 네트워크에 참여할 수 있다. 노드를 새로 추가했는데 인증서(Identity Certificate)가 준비되지 않으면, 의도치 않게 통신이 완전히 끊길 수 있다.
* **Access Control**: Topic, Service, Action별로 읽기/쓰기 권한을 할당받지 못하면 메시지 충돌이 생긴다. 예컨대 Pub/Sub관계는 맞지만, Access Control Policy가 달라서 메시지가 도착하지 않는 상황이 발생할 수 있다.

보안이 필요한 시스템이라면 보안 정책과 QoS 설정을 동시에 설계해야 하며, DDS-Security에서 제공하는 로그나 Debug 툴을 통해 인증/권한 오류를 확인할 수 있어야 한다.

#### DDS 디스커버리(Discovery)와 관련된 충돌

ROS2는 노드(Participant)와 토픽, 서비스 등이 네트워크 상에서 자동으로 발견(Discovery)되도록 DDS 기반의 디스커버리 메커니즘을 사용한다. 일반적으로 Multicast를 통해 상대를 찾은 뒤, 유니캐스트로 QoS 등 구체 정보를 교환한다. 하지만 대규모 네트워크나 WAN(Wide Area Network) 환경에서는 다음과 같은 문제가 발생할 수 있다.

* **Discovery Storm**: 짧은 시간 동안 많은 노드가 동시에 네트워크에 참여할 때, 디스커버리 관련 트래픽이 급격히 증가하여 충돌(패킷 손실)이 발생한다.
* **멀티캐스트 제한**: 일부 네트워크 설정(방화벽, 라우터 등)에서 멀티캐스트가 차단되거나, TTL(Time to live)이 충분하지 않아 노드가 서로를 찾지 못해 통신이 끊길 수 있다.
* **비호환 DDS 버전/설정**: 같은 DDS 구현체여도 버전 차이 또는 Discovery 설정(Spdp, Sedp, PDP 등)이 어긋나면, 노드가 서로를 올바르게 식별하지 못한다.

이를 완화하기 위해서는, 네트워크 구성에 맞춰 Participant, Domain ID, 그리고 Discovery 관련 파라미터(초기 타임아웃, 반복 주기 등)를 적절히 조정해야 한다. 또한 WAN 상에서는 Multicast 대신 Unicast Peer List를 명시해주는 방식으로 노드를 수동 연결하는 방법도 흔히 사용된다.

#### 복잡한 동시성 패턴(Concurrency Pattern)으로 인한 문제

노드 간 충돌은 단순 Pub/Sub만 존재할 때보다, 액션(Action)이나 서비스 요청/응답, 파라미터(Parameter) 이벤트, TF(Transform) 브로드캐스트 등이 동시에 실행되는 경우 더 복합적으로 나타난다. 예컨대,

1. **액션 서버/클라이언트**: Goal이 다수 들어오고, Cancel 신호가 뒤섞여 동시에 처리될 때, 액션 서버의 내부 상태가 꼬이거나, 피드백 메시지 큐가 넘치는 문제가 생길 수 있다.
2. **파라미터 이벤트**: 여러 노드가 같은 파라미터를 동시에 갱신하거나, 파라미터 이벤트 콜백이 너무 자주 발생해 통신 지연을 유발한다.
3. **TF 브로드캐스트**: 로봇 팔 등 조인트가 많은 시스템에서 TF 트리(Transform Tree)가 복잡해지고, 높은 빈도로 TF를 퍼블리시하면 구독 측의 TF 버퍼가 과부하 상태가 될 수 있다.

이런 복합 패턴에서는 노드 간 호출 순서(Sequence)를 명확히 정의하고, 이벤트가 동시에 발생해도 안정적으로 처리할 수 있는 로직(예: 상태머신, 동기화 객체, Lock-Free 큐 등)을 마련해야 한다.

#### Domain Bridge를 활용한 충돌 방지

ROS2에서 Domain Bridge는 서로 다른 Domain ID를 사용하는 두 ROS2 네트워크를 중계(Bridge)해주는 기능이다. 이를 이용하면, 하나의 도메인에 과도한 노드가 밀집되어 디스커버리나 트래픽 충돌이 벌어지는 문제를 해소할 수 있다.

* **도메인 분할**: 로컬 도메인(예: Domain ID=0)과 원격 도메인(예: Domain ID=1)을 분리해, 각 도메인 내부 트래픽은 독립적으로 처리하고, 정말 필요한 토픽만 Bridge를 통해 상호 교환하도록 제한한다.
* **QoS 리매핑(Remap)**: Bridge에서 노드를 연결할 때, 퍼블리시/구독 간의 QoS 프로파일을 다르게 설정해줄 수 있다. 예컨대 한쪽에서 Reliable로 보내더라도, Bridge가 Best Effort로 변환하여 다른 쪽에 전달하도록 구성할 수 있다. 이로써 노드 A와 B의 직접 충돌을 줄이고, 중간 Bridge가 트래픽을 완충(Buffer)하는 효과를 얻는다.

#### 하드웨어 연계(HIL, SIL) 테스트에서의 충돌

소프트웨어 인 더 루프(SIL) 혹은 하드웨어 인 더 루프(HIL) 시뮬레이션을 통해 실제 하드웨어(센서, 액추에이터)를 모사하거나, 실 기기를 부분적으로 연결한 상태에서 노드 충돌 가능성을 확인할 수 있다. 이를 적용할 때 다음 문제가 발생한다.

* **시뮬레이션 스텝 간격 불일치**: 시뮬레이터가 60Hz로 동작하는데, 실제 센서 노드는 100Hz로 토픽을 발행하면, 중간에 동기화 충돌이 날 수 있다.
* **하드웨어 지연**: 모사된 환경에서는 지연이 0에 가깝지만, 실제 하드웨어에서는 I/O 레이턴시가 커서 노드 간 메시지 타이밍이 달라진다.
* **필요 자원 불일치**: 시뮬레이션에서는 가상 GPU, 충분한 메모리를 사용하지만, 실제 임베디드 보드에서는 리소스가 훨씬 제한되어 충돌이 쉽게 발생한다.

따라서 실제 환경에 최대한 가깝게 시뮬레이션을 설정하고, HIL/SIL이 끝난 뒤에는 실제 하드웨어에서 다시 한 번 부하 테스트를 진행해야 한다.

#### 성능 지표(Performance Metrics) 설정

노드 간 충돌을 방지하려면 “어떤 조건에서 어떤 수준의 성능과 신뢰성을 요구하는지”를 사전에 정의해야 한다. 예를 들어,

* **메시지 손실률(Message Loss Rate)**: 예) 1% 이하로 제한
* **최대 지연시간(Max Latency)**: 예) 100ms 이하로 제한
* **처리량(Throughput)**: 초당 처리해야 할 메시지 수(예: 1000 msgs/sec)

명확한 성능 지표가 있어야, 실제 측정 결과와 비교하여 충돌 가능성을 빠르게 발견하고, QoS와 노드 구조를 튜닝해 나갈 수 있다. 이를 위해 ros2\_perf, apex\_performance 등 ROS2 성능 측정 툴을 사용하거나, DDS 레벨에서 제공하는 모니터링 API를 연동하기도 한다.

#### 마이크로 ROS(micro-ROS)에서의 충돌

임베디드 장치나 마이크로컨트롤러(MCU) 환경에서 ROS2의 일부 기능을 경량화하여 사용하는 마이크로 ROS(micro-ROS)는 더 제한된 자원(CPU, RAM, RTOS)에서 구동된다. 이 때문에 노드 간 충돌이 다음과 같은 형태로 발생하기 쉽다.

* **메모리 오버플로**: 메시지 버퍼가 작아 대용량 토픽 발행 시 오버플로 발생
* **실시간 스레드 부족**: MCU는 동시 실행 가능한 스레드 개수가 제한되므로, QoS의 Reliable 설정을 유지하기 어렵거나, 재전송 자체가 큰 부담이 될 수 있다.
* **RTOS 동기화 제약**: POSIX 쓰레드와는 달리 RTOS 스케줄링이 제한적이어서, 콜백 동시성 제어가 복잡해진다.

이 경우 QoS를 매우 제한적으로 설정(Best Effort, Small Depth 등)하고, 메시지 주기를 낮추거나, 필요한 서비스만 사용해 통신량을 줄이는 전략이 필요하다. 또한 micro-ROS 전용 프로파일(대폭 줄인 메시지 타입 등)을 통해 충돌 발생 확률을 줄일 수 있다.
