1261.18 동기식 통신과 비동기식 통신의 비교
1. 동기식 통신과 비동기식 통신의 정의
통신의 동기성(synchronicity)은 송신자(sender)와 수신자(receiver) 간의 시간적 결합도(temporal coupling)를 나타내는 근본적인 속성이다. 이 속성에 따라 통신 방식은 동기식 통신(synchronous communication)과 비동기식 통신(asynchronous communication)으로 분류된다.
동기식 통신은 송신자가 메시지를 전송한 후 수신자의 응답을 수신할 때까지 실행을 중단(block)하고 대기하는 통신 방식이다. 송신자와 수신자가 동일한 시간 구간에 통신에 참여하여야 하며, 이러한 시간적 동기화가 요청-응답의 인과성(causality)을 보장한다.
비동기식 통신은 송신자가 메시지를 전송한 후 수신자의 응답을 기다리지 않고 즉시 다음 작업으로 진행하는 통신 방식이다. 메시지의 수신은 별도의 콜백(callback) 함수, 이벤트 핸들러(event handler), 또는 퓨처/프로미스(future/promise) 메커니즘에 의해 비동기적으로 처리된다. Tanenbaum과 Van Steen(2017)은 Distributed Systems에서 비동기식 통신이 분산 시스템의 느슨한 결합(loose coupling)과 확장성을 보장하는 핵심 메커니즘임을 지적하였다.
2. 동기식 통신의 특성
2.1 실행 흐름
동기식 통신에서 호출자(caller)의 실행 흐름은 다음과 같이 진행된다.
t_{\text{call}} \xrightarrow{\text{send}} t_{\text{wait}} \xrightarrow{\text{block}} t_{\text{receive}} \xrightarrow{\text{continue}}
호출자는 t_{\text{call}} 시각에 요청을 전송하고, 응답이 수신되는 t_{\text{receive}} 시각까지 \Delta t = t_{\text{receive}} - t_{\text{call}}의 시간 동안 차단(blocking) 상태에 놓인다.
2.2 장점
프로그래밍 모형의 단순성: 동기식 통신은 순차적 프로그래밍 모형과 자연스럽게 대응하여, 코드의 가독성과 논리적 추론이 용이하다.
인과적 순서 보장: 요청의 전송과 응답의 수신이 동일한 실행 흐름 내에서 순차적으로 발생하므로, 요청-응답 간의 인과 관계가 명시적으로 보장된다.
오류 처리의 명확성: 동기식 호출의 반환 시점에서 성공 또는 실패를 즉시 판단할 수 있어, 오류 처리 로직의 구현이 직관적이다.
2.3 제약
자원 활용의 비효율성: 차단 상태에서 호출 스레드는 유의미한 작업을 수행하지 못하며, CPU 자원이 낭비된다. 서버 측의 처리 시간이 길어질수록 이 비효율성은 심화된다.
교착 상태의 위험: 복수의 프로세스가 상호 간에 동기식 호출을 수행하는 경우, 교착 상태(deadlock)가 발생할 수 있다. 특히 단일 스레드 실행자(single-threaded executor) 환경에서 콜백 내 동기식 서비스 호출은 교착 상태를 유발하는 대표적 패턴이다.
확장성의 제한: 동기식 통신의 차단 특성은 동시 처리 요청의 수를 스레드 수로 제한하며, 이는 대규모 분산 시스템에서 병목의 원인이 된다.
3. 비동기식 통신의 특성
3.1 실행 흐름
비동기식 통신에서 호출자의 실행 흐름은 다음과 같이 진행된다.
t_{\text{call}} \xrightarrow{\text{send}} t_{\text{continue}} \quad \cdots \quad t_{\text{callback}} \xrightarrow{\text{process response}}
호출자는 t_{\text{call}} 시각에 요청을 전송한 후 즉시 t_{\text{continue}} 시각에 다음 작업을 수행한다. 응답은 t_{\text{callback}} 시각에 콜백 함수에 의해 별도로 처리된다.
3.2 구현 메커니즘
비동기식 통신은 다음의 메커니즘을 통해 구현된다.
콜백 함수(Callback Function): 응답 수신 시 호출되는 함수를 사전에 등록하는 방식이다. ROS2에서는 서비스 클라이언트의 async_send_request 메서드에 콜백 함수를 전달하여 비동기식 서비스 호출을 구현한다.
퓨처/프로미스(Future/Promise): 비동기 연산의 결과를 나타내는 객체로, 결과가 아직 산출되지 않은 상태에서도 결과에 대한 참조를 유지할 수 있다. std::future(C++)나 rclpy.task.Future(Python)가 이에 해당한다.
이벤트 루프(Event Loop): 이벤트의 발생을 감시하고 해당 이벤트에 등록된 핸들러를 호출하는 실행 구조이다. ROS2의 실행자(Executor)가 이 역할을 수행한다.
3.3 장점
자원 활용의 효율성: 호출 스레드가 응답 대기 중에도 다른 작업을 수행할 수 있어, CPU 자원의 활용도가 높다.
교착 상태의 회피: 단일 스레드 환경에서도 비동기식 통신은 차단 없이 복수의 통신 연산을 처리할 수 있어, 교착 상태의 발생 가능성이 감소한다.
높은 동시성: 하나의 스레드가 복수의 비동기 요청을 동시에 발행하고 관리할 수 있어, 시스템의 동시성(concurrency)이 향상된다.
3.4 제약
프로그래밍 복잡성: 콜백의 중첩, 비동기 흐름의 추적, 그리고 공유 상태의 동시 접근 제어 등으로 인해 코드의 복잡도가 증가한다.
오류 처리의 분산: 비동기 연산의 오류가 콜백 내에서 처리되므로, 오류 처리 로직이 호출 지점과 분리되어 추론이 어려워질 수 있다.
4. 동기식 통신과 비동기식 통신의 비교
| 특성 | 동기식 통신 | 비동기식 통신 |
|---|---|---|
| 차단 여부 | 차단 (blocking) | 비차단 (non-blocking) |
| 시간적 결합 | 강한 결합 | 느슨한 결합 |
| 프로그래밍 복잡도 | 낮음 | 높음 |
| 자원 효율성 | 낮음 | 높음 |
| 교착 위험 | 높음 | 낮음 |
| 인과적 순서 | 명시적 보장 | 별도 관리 필요 |
| 오류 처리 | 호출 지점에서 즉시 | 콜백 내에서 분산 |
| 확장성 | 제한적 | 우수 |
| 동시성 | 스레드 수에 비례 | 단일 스레드에서도 가능 |
5. 로봇 행동 제어에서의 적용
5.1 동기식 통신의 적합한 사례
로봇 행동 제어에서 동기식 통신은 다음의 경우에 적합하다.
- 초기화 단계에서의 매개변수 조회 및 설정
- 단기간에 완료되는 연산의 결과를 즉시 필요로 하는 경우
- 행동 전이 시 전제 조건의 동기적 확인
- 시스템 설정 변경 등 빈도가 낮은 관리적 연산
5.2 비동기식 통신의 적합한 사례
비동기식 통신은 다음의 경우에 적합하다.
- 센서 데이터의 연속적 수신과 처리 (토픽 구독)
- 장시간 실행 행동의 목표 전달과 피드백 수신 (액션 통신)
- 복수의 서비스를 동시에 호출하여 병렬 처리하는 경우
- 단일 스레드 실행자 환경에서의 모든 통신
5.3 ROS2에서의 권장 사항
ROS2 공식 문서에서는 대부분의 경우 비동기식 통신 방식을 권장한다. 특히 콜백 함수 내에서 동기식 서비스 호출을 수행하는 것은 단일 스레드 실행자에서 교착 상태를 유발하므로 엄격히 회피하여야 한다. 비동기식 서비스 호출(async_send_request)과 콜백 기반의 결과 처리가 ROS2에서의 표준적인 통신 패턴이다.
동기식 통신과 비동기식 통신의 특성에 대한 정확한 이해와 적절한 선택은 로봇 행동 제어 시스템의 응답성, 안정성, 그리고 확장성을 보장하는 설계상의 핵심 요소이다.