ROS 2 계층 구조와 DDS 무마스터 자동 디스커버리
웹 서버나 ROS 1의 roscore 같은 중앙 브로커 없이도 ROS 2 노드들이 서로를 자동 탐색해 연결하는 DDS 디스커버리 과정과 rclpy·rclcpp·rcl·RMW 4단계 계층 구조를 설명합니다.
무료 공개 · 최근 수정
ROS 1의 중앙 마스터 한계와 ROS 2의 설계 전환
웹이나 백엔드 프로그래밍에 익숙한 개발자가 ROS 2를 처음 접하면 신기한 장면을 목격합니다. 터미널 두 개를 열어 한쪽에서 카메라 발행 노드를 실행하고 다른 쪽에서 구독 노드를 실행하면, IP 주소나 포트 번호, 중앙 메시지 브로커 URL을 설정하지 않았는데도 두 프로그램이 즉시 서로를 찾아 데이터를 주고받습니다.
어떻게 별도의 등록 서버 없이 서로 다른 프로세스, 나아가 같은 공유기에 연결된 다른 컴퓨터의 노드를 자동으로 찾아낼 수 있을까요? 그 답은 ROS 1에서 ROS 2로 넘어오며 완전히 새로 설계된 4단계 계층 구조와 통신 미들웨어에 있습니다(로봇 코드를 노드로 나누는 이유와 ROS 2 분산 구조 참조).
초기 세대인 ROS 1에서는 모든 노드가 통신을 시작하기 전에 반드시 roscore(ROS Master)라는 중앙 전화번호부 프로세스를 먼저 띄워야 했습니다. 새 노드가 켜지면 마스터에 자신의 이름과 토픽을 등록하고, 상대 노드의 주소를 마스터에 물어본 뒤에야 연결을 맺을 수 있었습니다.
| 비교 항목 | ROS 1 (roscore 기반) | ROS 2 (DDS 기반) |
|---|---|---|
| 노드 탐색 방식 | 중앙 ROS Master에 등록 및 조회 | 피어 투 피어(P2P) 자동 탐색 |
| 단일 장애점(SPOF) | 마스터 프로세스 종료 시 신규 연결 불가 | 중앙 마스터 없음 (개별 노드 독립 생존) |
| 다중 로봇·무선 환경 | 단일 로봇·안정적 유선망 전제 | 무선 손실·다중 로봇 환경을 기본 지원 |
| 통신 프로토콜 | 자체 구현 프로토콜 (TCPROS, UDPROS) | 국제 산업 표준 미들웨어 (DDS / RTPS) |
이 구조는 대학 연구실에서 로봇 한 대를 유선 네트워크로 실험할 때는 큰 문제가 없었습니다. 그러나 물류 창고에서 수십 대의 이동 로봇이 무선 와이파이(Wi-Fi)를 통해 협업하거나, 로봇이 통신 음영 구역을 지날 때는 중앙 마스터가 치명적인 단일 장애점(Single Point of Failure; SPOF)이 되었습니다. 마스터 프로세스가 멈추거나 마스터와의 무선 연결이 끊기면, 로봇 내부에서 정상 동작하던 새 노드들까지 서로를 찾지 못해 시스템이 마비되었기 때문입니다.
ROS 2는 이 한계를 뿌리부터 없애기 위해 자체 통신 프로토콜을 버리고, 국방·항공·자율주행 산업에서 검증된 분산 통신 표준을 밑바탕에 도입했습니다.
사용자 코드부터 네트워크까지 이어지는 4단계 계층 구조
ROS 2의 내부는 작성한 파이썬·C++ 코드가 특정 네트워크 라이브러리에 직접 묶이지 않도록 네 개의 층으로 나뉘어 있으며, 상위 호출이 하단 네트워크 탐색으로 전달되는 흐름을 도식화하면 다음과 같습니다.
그림: 애플리케이션 노드부터 클라이언트·RMW·DDS로 이어지는 4단계 계층과 자동 탐색
첫 번째는 사용자가 직접 작성하는 애플리케이션 노드 계층입니다. 그 바로 아래에서 파이썬이나 C++ 문법으로 토픽·서비스·타이머를 만들 수 있게 돕는 도구가 클라이언트 라이브러리(Client Library)입니다. 파이썬 개발자는 rclpy를, C++ 개발자는 rclcpp를 호출합니다.
흥미로운 점은 rclpy와 rclcpp가 각자 통신 로직을 따로 구현하지 않는다는 것입니다. 두 라이브러리는 모두 그 아래에 있는 공통 C 라이브러리인 rcl(ROS Client Library)을 감싸고 있습니다. 덕분에 파이썬으로 짠 AI 추론 노드와 C++로 짠 모터 제어 노드가 토픽 이름 규칙, 시간 처리, 파라미터 관리를 똑같은 방식으로 수행하며 매끄럽게 대화할 수 있습니다.
세 번째 층은 ROS 미들웨어 인터페이스(ROS Middleware Interface; RMW)입니다. rcl 계층이 하위 통신 엔진과 대화할 때 사용하는 표준 어댑터 창구입니다. 이 추상화 계층 덕분에 ROS 2 코드는 아래쪽 통신 엔진이 어느 회사의 제품인지 전혀 몰라도 됩니다.
가장 아래 네 번째 층에 실제 네트워크 탐색과 패킷 전송을 책임지는 DDS(Data Distribution Service) 구현체가 자리 잡습니다. OMG(Object Management Group)가 제정한 국제 실시간 데이터 분산 표준으로, 실제 유무선 네트워크 위에서는 RTPS(Real-Time Publish-Subscribe) 전송 프로토콜을 사용해 데이터를 실어 나릅니다.
Ubuntu 24.04 기반의 장기 지원(LTS) 배포판인 ROS 2 Jazzy Jalisco는 기본 DDS로 eProsima의 Fast DDS(rmw_fastrtps_cpp)를 사용합니다. 만약 프로젝트 특성에 맞춰 Eclipse Cyclone DDS나 Zenoh 기반 미들웨어로 바꾸고 싶다면, 소스 코드를 고칠 필요 없이 RMW_IMPLEMENTATION 환경변수 하나만 바꿔 실행하면 됩니다.
ros2 doctor --report | grep middleware
export RMW_IMPLEMENTATION=rmw_cyclonedds_cpp
ros2 run demo_nodes_cpp talkerDDS 자동 디스커버리와 도메인 ID 네트워크 격리
그렇다면 중앙 마스터 없이 노드들은 어떻게 서로를 알아볼까요? 노드가 시작될 때 DDS 계층이 자동으로 수행하는 디스커버리(Discovery) 절차 덕분입니다. 이 과정은 크게 두 단계로 진행됩니다.
- 참여자 탐색(SPDP, Simple Participant Discovery Protocol): 새 노드가 켜지면 DDS는 로컬 네트워크의 정해진 멀티캐스트(Multicast) 주소로 "나 여기 새로 들어왔어!"라는 출석 패킷을 주기적으로 보냅니다. 같은 네트워크에 있던 다른 노드들이 이 신호를 듣고 서로의 존재(IP 주소와 포트)를 파악합니다.
- 엔드포인트 매칭(SEDP, Simple Endpoint Discovery Protocol): 서로의 존재를 확인한 노드들은 유니캐스트(Unicast)로 각자 어떤 토픽을 발행하고 구독하는지(Endpoint 정보) 교환합니다. 이때 토픽 이름, 메시지 데이터 타입, 그리고 ROS 2 토픽·서비스·액션 비교와 QoS 선택 기준에서 다룰 서비스 품질(QoS) 설정이 모두 호환되면 즉시 두 노드가 1:1 또는 1:N으로 직접 연결됩니다.
이 자동 탐색은 편리하지만, 한 강의실이나 연구실에서 여러 사람이 같은 와이파이에 접속해 동시에 실습할 때는 옆 사람의 로봇 토픽이 내 컴퓨터로 섞여 들어오는 혼선을 빚기도 합니다. ROS 2는 이를 분리하기 위해 ROS_DOMAIN_ID 환경변수를 제공합니다. 첫 번째 팀은 도메인 ID를 11로, 두 번째 팀은 22로 지정하면 서로의 토픽이 완전히 격리됩니다.
export ROS_DOMAIN_ID=11
ros2 run demo_nodes_py listener
export ROS_DOMAIN_ID=22
ros2 run demo_nodes_cpp talkerDDS는 ROS_DOMAIN_ID 숫자에 따라 디스커버리에 사용하는 UDP 포트 번호를 수학적으로 다르게 계산합니다. 기본값은 0이며, UDP 포트 번호 충돌 없이 안전하게 쓸 수 있는 권장 범위는 0부터 101까지입니다. 같은 숫자를 지정한 노드끼리만 서로를 발견하고 대화하며, 다른 도메인 ID를 가진 노드들은 같은 공유기에 묶여 있어도 서로 보이지 않습니다.
또한 시뮬레이션과 테스트를 내 컴퓨터 안에서만 조용히 돌리고 싶다면, ROS 2 Jazzy부터 도입된 ROS_AUTOMATIC_DISCOVERY_RANGE 환경변수를 LOCALHOST로 설정해 외부 네트워크로 패킷이 나가는 것을 막을 수 있습니다.
export ROS_AUTOMATIC_DISCOVERY_RANGE=LOCALHOST노드들이 계층 구조를 거쳐 서로를 자동으로 찾아 연결했다면, 이제 그 연결 통로 위로 어떤 형태의 데이터를 흘려보낼지 결정해야 합니다. 다음 글인 ROS 2 토픽·서비스·액션 비교와 QoS 선택 기준에서는 세 가지 통신 패턴과 데이터가 오가지 않을 때 가장 먼저 의심해야 할 QoS 설정을 다룹니다.
참고 문서
설명이 어렵거나 잘못된 부분을 발견하셨나요?
문서 수정 의견 보내기