# QoS(품질 서비스) 정책 이해

#### QoS 개요

ROS2에서는 노드 간의 통신이 토픽, 서비스, 액션을 통해 이루어지며, 이러한 통신의 신뢰성과 성능을 관리하기 위해 QoS(Quality of Service) 정책을 사용한다. QoS는 주로 퍼블리셔와 서브스크라이버 간 메시지 전달의 신뢰성과 일관성을 보장하는 역할을 한다. 각 메시지의 특성과 통신 환경에 따라 적절한 QoS 설정이 필요하다.

#### QoS 프로파일

QoS 정책은 여러 프로파일로 구성되며, 각 프로파일은 특정 통신 요구 사항에 맞게 설정할 수 있다. ROS2에서 제공하는 기본 QoS 프로파일은 다음과 같다:

* **Default**: 기본 설정으로, 대부분의 경우 적절한 성능을 제공한다.
* **Reliable**: 메시지 손실을 허용하지 않고 반드시 모든 메시지를 전달하도록 설정한다.
* **Best Effort**: 네트워크 상태에 따라 메시지 손실을 허용하지만 성능을 우선한다.

#### QoS 정책 요소

**Reliability (신뢰성)**

QoS 정책에서 **Reliability**는 메시지 전달의 신뢰성을 설정하는 중요한 요소이다. 이 옵션은 퍼블리셔가 전송한 메시지가 서브스크라이버에게 어떻게 전달되는지 결정한다.

* **Reliable**: 메시지가 반드시 전달되도록 보장한다. 이는 데이터 손실이 허용되지 않는 상황에 적합하며, 네트워크 지연이나 재전송을 통해 메시지 손실을 방지한다.

  예를 들어, 노드 $A$가 퍼블리셔로, 노드 $B$가 서브스크라이버일 때, Reliable 설정을 사용하면, 네트워크 지연이 발생하더라도 노드 $B$는 결국 모든 메시지를 수신하게 된다. 이를 수식으로 나타내면 다음과 같다:

$$
\text{Received Message} = \text{Sent Message}, \quad \forall t \in \[t\_0, t\_1]
$$

* **Best Effort**: 네트워크 상태에 따라 메시지가 손실될 수 있지만 가능한 한 빠르게 전달한다. 성능이 중요한 상황에서 적합하다.

  이 경우 메시지 손실이 발생할 확률 $P\_{\text{loss}}$는 네트워크 상태 $N$에 따라 달라지며, 성능 최적화를 위해서 $P\_{\text{loss}}$를 최소화하는 방향으로 네트워크를 설계해야 한다.

$$
P\_{\text{loss}} \propto f(N)
$$

#### Durability (내구성)

**Durability**는 메시지가 퍼블리셔가 중단되었거나 서브스크라이버가 나중에 연결되었을 때도 여전히 유효한지를 결정한다.

* **Volatile**: 퍼블리셔가 중단되면 이전에 발행된 메시지는 사라지고, 새로 연결된 서브스크라이버는 이전 메시지를 받지 못한다.
* **Transient Local**: 퍼블리셔가 중단되더라도 마지막 메시지가 메모리에 저장되고, 새로 연결된 서브스크라이버는 이 메시지를 수신할 수 있다.

$$
\mathbf{M}*{\text{last}} = \mathbf{M}*{t-1}, \quad \text{if Publisher stopped at } t
$$

#### Deadline (데드라인)

**Deadline** 정책은 특정 시간 내에 서브스크라이버가 퍼블리셔로부터 메시지를 수신해야 하는지 여부를 정의한다. 만약 주어진 시간 내에 메시지를 수신하지 못하면, 서브스크라이버는 '데드라인 미준수' 상태로 간주된다.

* **정의**: 데드라인 시간 $\tau$ 내에 퍼블리셔로부터 메시지가 전달되지 않을 경우, 서브스크라이버는 이를 위반으로 처리한다.

  수식으로 나타내면, 주어진 시간 $t$에서 서브스크라이버가 메시지를 수신했는지를 판단하는 기준은 다음과 같다:

$$
\text{Deadline Violation} = \begin{cases} 1, & \text{if } t\_{\text{received}} > t\_{\text{sent}} + \tau \ 0, & \text{if } t\_{\text{received}} \leq t\_{\text{sent}} + \tau \end{cases}
$$

여기서 $t\_{\text{received}}$는 서브스크라이버가 메시지를 수신한 시간, $t\_{\text{sent}}$는 퍼블리셔가 메시지를 전송한 시간, 그리고 $\tau$는 데드라인 시간이다.

**실사용 예제**

데드라인을 사용하면, 주기적으로 데이터를 수집하고 전달하는 센서 노드에서 특정 시간 간격마다 데이터가 수신되었는지 확인할 수 있다. 예를 들어, 환경 센서 노드가 100ms마다 데이터를 전송하도록 설정했다면, 서브스크라이버는 데드라인이 100ms로 설정된 상태에서 데이터를 수신해야 한다.

#### Liveliness (생존성)

**Liveliness** 정책은 퍼블리셔가 여전히 활성 상태인지 확인하는 방법을 제공한다. 이는 시스템이 노드 간의 연결 상태를 모니터링하고, 특정 노드가 활성 상태인지 확인하는 데 유용하다.

* **Automatic**: 퍼블리셔가 자동으로 생존 신호를 보낸다.
* **Manual**: 퍼블리셔가 수동으로 생존 신호를 보내는 방법을 결정한다.

생존 신호가 특정 시간 $\lambda$ 안에 도달해야 하며, 이를 수식으로 표현하면 다음과 같다:

$$
\text{Liveliness Violation} = \begin{cases} 1, & \text{if } t\_{\text{last heartbeat}} > t\_0 + \lambda \ 0, & \text{if } t\_{\text{last heartbeat}} \leq t\_0 + \lambda \end{cases}
$$

여기서 $t\_{\text{last heartbeat}}$는 마지막 생존 신호가 도달한 시간, $\lambda$는 생존 신호 주기이다.

#### History (히스토리)

**History** 정책은 퍼블리셔가 전송한 메시지의 기록을 관리하는 방법을 설정한다. 이는 서브스크라이버가 과거 메시지를 어떻게 처리할지 결정하는 중요한 요소이다.

* **Keep Last**: 마지막으로 전송된 $\mathbf{k}$개의 메시지만 유지한다. 과거 메시지 중 마지막 $k$개의 메시지를 저장하는 방식으로, $k$는 사용자가 설정할 수 있다.

  이를 수식으로 나타내면, $\mathbf{M}\_{\text{history}}$는 마지막 $k$개의 메시지로 구성된다:

$$
\mathbf{M}*{\text{history}} = { \mathbf{M}*{t-1}, \mathbf{M}*{t-2}, \dots, \mathbf{M}*{t-k} }
$$

* **Keep All**: 모든 메시지를 유지하며, 이는 메모리 자원을 많이 소모할 수 있다.

#### Depth (깊이)

**Depth**는 History 정책의 세부 설정으로, 특정 시점에서 저장할 수 있는 메시지의 최대 개수를 의미한다. 이는 주로 **Keep Last** 설정과 함께 사용된다. 퍼블리셔는 설정된 깊이만큼 메시지를 유지하며, 이를 초과하는 메시지는 삭제된다.

* 예를 들어, $k = 10$으로 설정된 경우, 퍼블리셔는 최근 10개의 메시지만 유지한다. 메시지가 새로 들어올 때마다 가장 오래된 메시지는 삭제되고 새로운 메시지가 추가된다. 이를 수식으로 표현하면 다음과 같다:

$$
\mathbf{M}*{\text{history}} = { \mathbf{M}*{t-1}, \mathbf{M}*{t-2}, \dots, \mathbf{M}*{t-k} }, \quad k = 10
$$

메시지 $\mathbf{M}\_t$가 새로 수신되면, 다음과 같이 업데이트된다:

$$
\mathbf{M}*{\text{history}} = { \mathbf{M}*t, \mathbf{M}*{t-1}, \dots, \mathbf{M}*{t-k+1} }
$$

따라서 깊이는 데이터의 손실을 방지하면서 메모리 사용량을 제어하는 데 중요한 역할을 한다.

#### Deadline과 Liveliness 간의 상호작용

QoS 정책에서 **Deadline**과 **Liveliness**는 종종 함께 사용된다. 노드 간의 메시지 통신에서 퍼블리셔의 상태가 중요할 때, 데드라인과 생존성 정책을 결합하면 메시지가 일정한 시간 간격으로 전달되고 퍼블리셔의 상태가 유지되는지 확인할 수 있다.

* 예를 들어, 특정 시간 $\tau$ 이내에 메시지를 수신하지 못하거나 생존 신호가 오지 않으면 시스템은 퍼블리셔가 비활성 상태에 있거나 문제가 발생했다고 판단할 수 있다.

  두 개의 조건을 결합한 수식은 다음과 같다:

$$
\text{System Status} = \begin{cases} \text{Alive}, & \text{if } t\_{\text{received}} \leq t\_{\text{sent}} + \tau \text{ and } t\_{\text{last heartbeat}} \leq t\_0 + \lambda \ \text{Failed}, & \text{otherwise} \end{cases}
$$

#### QoS 설정에 따른 성능 영향

각 QoS 정책은 시스템의 성능과 자원 사용에 영향을 미친다. 예를 들어, **Reliable** 설정은 메시지 손실을 방지하지만 네트워크 트래픽이 증가하고, **Best Effort** 설정은 성능을 우선시하나 메시지 손실이 발생할 수 있다. 따라서, 애플리케이션의 특성에 따라 적절한 QoS 설정이 필요하다.

**네트워크 환경과의 상호작용**

QoS 정책은 네트워크 환경의 상태와 밀접하게 연결되어 있다. 높은 네트워크 트래픽이나 지연 시간이 발생할 수 있는 환경에서는 **Reliable** 설정을 사용할 때 메시지 재전송이 빈번하게 발생할 수 있으며, 이로 인해 통신 지연이 커질 수 있다. 반대로, **Best Effort** 설정을 사용하면 네트워크 상태에 따라 일부 메시지가 손실될 수 있지만, 메시지가 빠르게 전달된다.

**최적의 QoS 설정**

애플리케이션의 요구 사항에 맞게 적절한 QoS 설정을 선택하는 것이 중요하다. 예를 들어, 로봇의 제어 시스템에서는 **Reliable**과 **Deadline** 정책을 조정하여 정확한 데이터 전달을 보장하고, 퍼블리셔의 생존성을 모니터링하는 것이 유리할 수 있다. 반면, 센서 데이터의 경우 일부 손실을 허용하고 성능을 우선시하는 **Best Effort**와 **Volatile** 설정이 적합할 수 있다.
