Chapter 29. 클라이언트-서버(Service) 프로토콜 및 비동기 요청(Async Request) 응답 구조
자율 에이전트 드론 소프트웨어 아키텍처를 구성하는 두 번째 핵심 통신 축은 클라이언트-서버(Client-Server) 모델에 기반한 ‘서비스(Service)’ 프로토콜이다. 앞서 다룬 퍼블리셔-서브스크라이버 메커니즘이 수백 헤르츠(Hz)로 유입되는 센서 데이터의 단방향 연속 스트림(Continuous Stream) 처리에 특화되어 있다면, 서비스 통신망은 시스템의 특정 동작을 촉발하고 그에 대한 ’확정적 결과(Deterministic Result)’를 반환받아야 하는 간헐적이고 신뢰성 높은 제어 시나리오를 전담한다.
1. 양방향 1:1 통신 모델과 서비스 인터페이스(SRV) 구조
드론 제어 시스템에서 이륙(Takeoff) 명령 하달, 비행 모드(Flight Mode) 전환, 모터 암/디스암(Arm/Disarm) 수행, 또는 맵 크기 초기화와 같은 작업은 단순한 브로드캐스팅(Broadcasting)으로 처리될 수 없다. 노드는 특정 명령을 송신한 후 해당 명령의 성공 여부, 실패 원인, 또는 질의한 설정값을 반드시 동기화된 구조로 회신받아야만 다음 상태 머신(State Machine) 단계로 안전하게 전이(Sequence Transition)할 수 있다.
이러한 양방향 상호작용을 보장하기 위해 ROS2의 서비스 아키텍처는 클라이언트(요청자) 하나와 서버(제공자) 하나를 1:1로 매칭하는 지점 간(Point-to-Point) 통신 구조를 확립한다. 시스템 컴파일러는 통신 계약(Contract)을 명문화하기 위해 .srv라는 전용 인터페이스 정의 언어(IDL) 형식을 채택한다. .srv 파일 내부에는 마이너스 기호 세 개(---)를 경계선으로 하여 상단에는 클라이언트가 전송할 요청(Request) 데이터 구조를, 하단에는 서버가 회신할 응답(Response) 데이터 구조를 엄격한 강타입(Strongly Typed) 형식으로 정의하게 된다. 기저 계층의 미들웨어는 이 명세를 해석하여 한 쌍의 내부 통신 토픽(주입 토픽과 회신 토픽)을 은닉된(Hidden) 형태로 자동 생성하고 제어한다.
2. 클라이언트-서버 간의 동기(Synchronous) 블로킹 역학의 한계
초기 로보틱스 개발 시 서비스 클라이언트 모듈은 요청 메시지를 송신함과 동시에 응답이 도착할 때까지 대기(Wait)하는 동기식 블로킹(Synchronous Blocking) 호출 방식을 암묵적으로 사용하곤 하였다. 이 방식은 절차적 지향 프로그래밍 시각에서는 코드의 가독성을 극대화하지만, 복잡한 분산 멀티스레딩(Multi-threading) 환경에서는 치명적인 교착 상태(Deadlock)를 촉발하는 안티 패턴(Anti-pattern)으로 간주된다.
예를 들어, 드론의 중앙 제어 노드가 단일 스레드 실행자(Single-threaded Executor) 위에서 동작할 때 다른 노드로 동기적 서비스 요청을 보낼 경우, 해당 노드의 메인 스레드는 즉각 차단(Blocked)된다. 만약 서버 측의 연산이 예상치 못하게 지연되거나 네트워크 패킷이 유실되면, 클라이언트 노드는 멈춰버린 스레드 상에서 타이머 콜백이나 센서 서브스크립션 콜백을 전혀 갱신할 수 없게 되어 비행 중인 기체의 물리적 제어 권한을 영구적으로 상실하는 대형 사고로 이어진다.
3. 미래 객체(Future Object) 기반의 비동기 요소(Async) 스케줄링 모델
현대적 ROS2 아키텍처는 이러한 블로킹 위험을 원천적으로 배제하기 위해 비동기 요청(Asynchronous Request) 응답 함수(e.g., async_send_request())와 퓨처(Future)/프로미스(Promise) 디자인 패턴을 서비스 인프라에 의무화하였다.
비동기 서비스 모델 하에서 클라이언트는 서버로 요청 패킷을 발송한 즉시 스레드의 제어권을 실행자(Executor)에게 반환하여 다른 콜백 연산을 중단 없이 지속할 수 있도록 허용한다. 동시에 미들웨어는 클라이언트 측에 ’미래 객체(Future Object, std::shared_future 등)’를 반환한다. 이 객체는 연산이 종결되지 않은 유보 상태(Pending State)의 메모리 주소를 지시하는 일종의 논리적 영수증(Receipt)으로 기능한다.
서버가 연산을 마치고 네트워크 망으로 응답 페이로드를 회신하면, ROS2 이벤트 루프(Event Loop)는 이를 가로채어 앞서 발급된 퓨처 객체의 상태를 완료(Ready)로 갱신하고 연관된 상태 콜백을 조건부 역호출한다. 이 고도화된 비동기 스케줄링 메커니즘을 통해 자율 비행 인프라는 데이터 송수신 I/O 병목에 코어 자원을 낭비하지 않는 무결점 제어의 안정성을 학술적, 공학적으로 확보하게 된다.