학습 목표

  • ROS 1과 ROS 2에서 유지된 철학과 호환되지 않는 구현을 구분할 수 있다.
  • ROS Master와 DDS 기반 Discovery의 차이와 장애·Network 운영 영향을 설명할 수 있다.
  • Topic, Service, Action, Parameter, QoS와 CLI의 변화를 비교할 수 있다.
  • rospy·roscpprclpy·rclcpp의 실행 모델 차이를 설명할 수 있다.
  • catkin에서 ament·colcon으로 Package를 옮길 때 바뀌는 파일과 Build 절차를 찾을 수 있다.
  • Launch, Lifecycle, Nodelet·Composition, Executor의 차이를 설계 관점에서 설명할 수 있다.
  • ros1_bridge의 가능 범위와 제약을 이해하고 단계적 Migration 계획을 세울 수 있다.

1. ROS 2는 ROS 1의 다음 Version인가

이름만 보면 ROS 2는 ROS 1.9 다음에 나온 호환 Upgrade처럼 보입니다. 실제로는 철학과 핵심 개념을 계승하면서 통신·실행·Build 기반을 새로 설계한 별도의 Platform에 가깝습니다.

ROS 1과 ROS 2가 공유하는 것은 다음과 같습니다.

  • 기능을 Node로 나누는 Component 사고방식
  • Topic, Service와 Action을 통한 Interface
  • .msg, .srv, .action으로 정의하는 Data 계약
  • Package와 Workspace 중심 개발
  • TF, URDF, RViz와 Bag을 이용한 Robot Toolchain
  • REP-103·105 같은 좌표계와 단위 규약
  • Open Source Package를 조합하는 생태계 철학

하지만 Source Code를 다시 Compile하는 것만으로 옮겨지지는 않습니다. Client Library API, Discovery, Wire Protocol, Parameter, Build, Launch, Time, Action, Plugin과 Test 방식이 바뀌었습니다.

가장 좋은 관점은 “개념은 이어지지만 Runtime 계약은 새로 검토한다”입니다. Topic 이름과 Message Type이 같아 보여도 QoS, Timestamp와 실행 순서가 다르면 Robot 동작은 달라질 수 있습니다.


2. 전체 비교표

항목 ROS 1 ROS 2
핵심 Client Library roscpp, rospy rclcpp, rclpy
발견 구조 중앙 ROS Master Middleware 기반 분산 Discovery
통신 기반 자체 XML-RPC·TCPROS, 일부 UDPROS RMW 추상화 아래 DDS/RTPS 등이 중심
전달 설정 Queue, TCP/UDP 선택, Latch Reliability, Durability, History, Deadline 등 QoS
Parameter 중앙 Parameter Server의 전역 Tree 각 Node가 선언·소유, Service로 접근
Build System catkin ament_cmake, ament_python 등
Meta Build Tool catkin_make, catkin build colcon build
Workspace 결과 devel, build install, build, log
Launch 주로 XML .launch Python·XML·YAML
실행 제어 Callback Queue와 Spinner Executor와 Callback Group
Process 내 결합 Nodelet 별도 API Component Composition, 여러 Node 객체
관리 상태 Package마다 자체 구현 Managed Lifecycle 표준
Security 기본 통신 보안 없음 SROS2와 Middleware Security 기반, 별도 활성화 필요
Platform Ubuntu/Linux 중심 Linux, Windows, macOS와 Embedded 확장 고려
CLI rosrun, rostopic 등 분산 명령 ros2 run, ros2 topic의 통합 CLI
Python 후기 Noetic은 Python 3, 이전은 Python 2 중심 Python 3
공식 지원 Noetic이 2025-05-31 EOL 지원 중인 ROS 2 Distribution 중심

이 표는 출발점일 뿐입니다. 실제 Migration에서는 “명령 이름이 바뀌었다”보다 각 변화가 Runtime 동작에 미치는 영향을 봐야 합니다.


3. 가장 큰 차이 — ROS Master와 분산 Discovery

ROS 1

ROS 1 Node는 roscore에 포함된 ROS Master에 자신의 이름, Topic과 Service 정보를 등록합니다. Publisher와 Subscriber는 Master를 통해 상대의 위치를 알아낸 뒤 서로 직접 연결합니다.

Node A ──등록·조회──> ROS Master <──등록·조회── Node B
  └──────────────── 직접 Data 전송 ────────────────┘

중요한 오해가 있습니다. 모든 Message가 Master를 거쳐 흐르는 것은 아닙니다. Master는 주로 이름 등록과 연결 협상을 담당하고 실제 Topic Data는 Node 사이에서 전달됩니다. Master가 이미 맺어진 TCP 연결의 중간 Router는 아닙니다.

하지만 Master가 없으면 새 Node가 등록되거나 새 연결을 찾을 수 없습니다. ROS_MASTER_URI, 각 Host의 주소 해석과 양방향 Network 연결도 맞아야 합니다.

ROS 2

ROS 2는 RMW가 제공하는 분산 Discovery를 사용합니다. DDS 기반 RMW에서는 Participant가 Network에서 서로를 발견하고 Publisher·Subscriber 정보를 교환합니다.

Node A/RMW <── Discovery + Data ──> Node B/RMW
      ↕                               ↕
   ROS Graph                      ROS Graph

중앙 Master라는 단일 등록 지점은 사라졌지만 설정이 없어졌다는 뜻은 아닙니다. Multicast, Firewall, VPN, Container Network, Domain ID와 DDS Vendor 설정이 Discovery에 영향을 줍니다.

운영상 Trade-off

관점 ROS 1 Master ROS 2 분산 Discovery
시작 구조 Master 주소가 명확 중앙 Process 없이 자동 발견
단일 실패 지점 Master 장애가 새 연결에 영향 중앙 Master 장애 없음
Network 진단 URI, DNS, Port 중심 Multicast, Domain, QoS, DDS 설정까지 확인
대규모 System Master와 Graph 부하 관리 Discovery Traffic과 Participant 수 관리

분산 구조는 “설정할 것이 없다”가 아니라 문제의 종류가 달라졌다는 뜻입니다.


4. Transport와 Middleware — 자체 Protocol에서 RMW로

ROS 1은 XML-RPC로 연결을 협상하고, Topic Data에는 기본적으로 TCPROS를 사용합니다. roscpp는 UDPROS도 제공했지만 모든 기능과 Client Library에서 같은 수준으로 쓰인 것은 아니었습니다.

ROS 2는 Serialization, Discovery와 Transport를 RMW(ROS Middleware) Interface 아래로 추상화했습니다. DDS/RTPS 구현이 오랫동안 중심이었으며, RMW 덕분에 Application API를 크게 바꾸지 않고 Middleware 구현을 선택할 수 있습니다.

사용자 Node
   ↓ rclcpp / rclpy
RCL 공통 계층
   ↓
RMW 추상화
   ├─ Fast DDS
   ├─ Cyclone DDS
   ├─ Connext DDS
   └─ 그 밖의 지원 Middleware

이 Architecture의 목적은 특정 Vendor에 종속되지 않으면서 산업 표준의 Discovery, QoS와 Security 능력을 활용하는 것입니다. 하지만 RMW 구현마다 성능, Discovery 방식, 설정 File과 일부 동작 차이가 있으므로 제품에서는 사용 구현과 Version을 명시하고 Test해야 합니다.


5. QoS — Queue Size보다 넓어진 통신 계약

ROS 1에서는 주로 Queue Size, TCPROS·UDPROS 선택과 Latching으로 전달 특성을 조절했습니다. ROS 2 QoS는 이를 더 명시적인 Policy 조합으로 표현합니다.

ROS 1 개념 ROS 2 대응
queue_size History와 Depth
기본 TCPROS 보통 Reliable 요구와 유사하지만 구현은 같지 않음
UDPROS Best-effort Best Effort Reliability와 유사
Latched Publisher Transient Local Durability와 Depth
직접 대응 없음 Deadline, Lifespan, Liveliness 등

ROS 2의 핵심은 Request vs Offered 호환성입니다. Subscriber는 필요한 최소 품질을 Request하고 Publisher는 제공 가능한 품질을 Offer합니다. 양쪽이 호환되어야 연결됩니다.

Reliable Subscriber ─X─ Best Effort Publisher
Best Effort Subscriber ─── Reliable Publisher

따라서 ROS 1에서는 이름과 Type이 같으면 연결되던 Topic이 ROS 2에서는 QoS 불일치로 Data를 전달하지 않을 수 있습니다.

ros2 topic info /scan --verbose
ros2 topic echo /scan --qos-reliability best_effort

“Reliable이 항상 더 좋다”는 결론은 잘못입니다. 불안정한 Wireless에서 고주기 Sensor Data를 재전송하면 오래된 Data가 밀려 지연이 커질 수 있습니다. 최신 Sample이 중요한 경우 Sensor Data QoS의 Best Effort가 더 적합할 수 있습니다.


6. Node API와 실행 모델 — 전역 Node에서 객체와 Executor로

ROS 1 rospy

rospy.init_node()가 Process의 전역 Node 상태를 초기화합니다. Publisher와 Subscriber도 Module 수준 API로 만들 수 있습니다.

import rospy
from std_msgs.msg import String

rospy.init_node('talker')
publisher = rospy.Publisher('chatter', String, queue_size=10)
rate = rospy.Rate(2)

while not rospy.is_shutdown():
    publisher.publish('hello from ROS 1')
    rate.sleep()

ROS 2 rclpy

Node, Publisher와 Timer가 명시적인 객체 관계를 가집니다. spin()은 Executor가 Ready Callback을 선택하고 실행하도록 합니다.

import rclpy
from rclpy.node import Node
from std_msgs.msg import String


class Talker(Node):
    def __init__(self):
        super().__init__('talker')
        self.publisher = self.create_publisher(String, 'chatter', 10)
        self.timer = self.create_timer(0.5, self.publish_message)

    def publish_message(self):
        message = String()
        message.data = 'hello from ROS 2'
        self.publisher.publish(message)


def main():
    rclpy.init()
    node = Talker()
    try:
        rclpy.spin(node)
    finally:
        node.destroy_node()
        rclpy.shutdown()


if __name__ == '__main__':
    main()

ROS 1의 Rate + while을 무조건 Timer로 바꿔야 하는 것은 아니지만, ROS 2 Callback 안에서 긴 Loop나 time.sleep()으로 Executor Thread를 점유하면 Subscription, Service와 Safety Timer가 실행되지 않을 수 있습니다.


7. Executor와 Callback Group

ROS 1 C++에는 ros::spin(), AsyncSpinner, Callback Queue가 있었지만 Node API와 Threading 관계가 ROS 2만큼 전면적인 설계 요소로 드러나지는 않았습니다.

ROS 2 Executor는 Subscription, Timer, Service, Action 등 실행 가능한 Callback을 기다리고 선택합니다.

  • SingleThreadedExecutor: 한 Thread에서 Callback을 순서대로 실행
  • MultiThreadedExecutor: 여러 Worker Thread가 Callback 실행
  • Mutually Exclusive Callback Group: Group 안에서 한 번에 하나만 실행
  • Reentrant Callback Group: 조건이 맞으면 같은 Group Callback도 병렬 실행 가능

Multi-threaded를 선택했다고 자동으로 병렬 처리되는 것은 아닙니다. Callback Group, 공유 Data Lock과 Client의 동기 호출 방식에 따라 Deadlock이 생길 수 있습니다.

Migration 때는 다음을 기록해야 합니다.

  1. 어떤 Callback이 다른 Callback을 기다리는가?
  2. 긴 I/O나 계산이 Executor Thread를 막는가?
  3. 동시에 실행되면 안 되는 Hardware 접근은 무엇인가?
  4. Safety Callback의 최악 실행 지연은 얼마인가?

8. Parameter — 전역 Tree에서 Node 소유 설정으로

ROS 1

ROS Master와 함께 실행되는 중앙 Parameter Server에 전역 Key-value Tree가 있습니다. Node가 Parameter를 선언하지 않아도 값을 넣을 수 있고 다른 Node가 같은 Key를 읽을 수 있습니다. Runtime 변경 알림이나 Validation은 dynamic_reconfigure 같은 별도 Mechanism을 사용했습니다.

ROS 2

각 Node가 자신의 Parameter를 선언하고 소유합니다. 외부 Client는 Node가 제공하는 Parameter Service를 통해 읽고 변경합니다. Node는 변경 Callback에서 Type과 범위를 검사하거나 거부할 수 있습니다.

class SpeedController(Node):
    def __init__(self):
        super().__init__('speed_controller')
        self.declare_parameter('max_speed', 0.5)
        max_speed = self.get_parameter('max_speed').value
ros2 param list /speed_controller
ros2 param get /speed_controller max_speed
ros2 param set /speed_controller max_speed 0.3

이 변화는 설정의 책임을 명확히 하지만, ROS 1의 전역 /max_speed를 그대로 옮기면 안 됩니다. 어느 Node가 소유할지, 여러 Node가 같은 설정을 어떻게 공유할지 설계해야 합니다.


9. Topic, Service와 Action Interface 변화

Type 이름

종류 ROS 1 CLI 표기 ROS 2 CLI 표기
Message geometry_msgs/Twist geometry_msgs/msg/Twist
Service std_srvs/SetBool std_srvs/srv/SetBool
Action nav_msgs/MoveBaseAction nav2_msgs/action/NavigateToPose

Action

ROS 1 Action은 actionlib가 여러 Topic으로 Goal, Status, Feedback, Result와 Cancel을 구현했습니다. ROS 2 Action은 Core Interface로 통합되며 Goal·Result·Cancel Service와 Feedback·Status Topic을 사용합니다. ROS 1 Action Server와 ROS 2 Action Server의 Source API는 호환되지 않습니다.

Header와 Time

ROS 2 std_msgs/msg/Header에는 ROS 1의 seq Field가 없습니다. Time과 Duration Type, Clock API와 Simulation Time 사용 방식도 바뀌었습니다. Migration에서 header.seq를 Protocol ID처럼 사용했다면 별도 Field를 설계해야 합니다.

Interface Definition

ROS 2는 bounded String·Array 같은 표현을 통해 최대 Memory 크기를 계산할 여지를 제공합니다. Real-time이나 Loaned Message를 고려할 때 무제한 가변 Data를 줄이는 설계가 중요합니다.


10. Build — catkin에서 ament와 colcon으로

catkincolcon은 같은 종류의 이름이 아닙니다.

  • catkin: ROS 1의 CMake 기반 Build System
  • ament_cmake / ament_python: ROS 2 Package의 Build Type
  • colcon: 여러 Package를 의존 순서로 실행하는 Meta Build Tool

Workspace 구조

ROS 1 catkin workspace       ROS 2 colcon workspace
├── src/                     ├── src/
├── build/                   ├── build/
└── devel/                   ├── install/
                             └── log/

ROS 2에서는 Package가 Build 후 Install되어야 사용 가능합니다. 개발 편의를 위해 --symlink-install을 사용하면 Python File과 일부 Resource 변경을 Symlink로 반영할 수 있습니다.

cd ~/ros2_ws
colcon build --symlink-install --packages-select my_robot
source install/setup.bash

package.xml

ROS 2는 Format 2 이상을 사용하며 일반적으로 Format 3을 권장합니다. Dependency Package 이름이 달라졌는지 확인하고 Build Type을 Export합니다.

<export>
  <build_type>ament_cmake</build_type>
</export>

CMake 변화

catkin_package()${catkin_LIBRARIES} 중심 구성을 ament_target_dependencies(), install()ament_package() 구조로 옮깁니다. Header 설치, Export와 Test도 명시적으로 확인해야 합니다.

Python Package

setup.py 또는 프로젝트 설정에서 console_scripts Entry Point를 등록해야 ros2 run이 실행 파일을 찾습니다. Launch와 Config File도 data_files로 Install해야 합니다.

Dependency가 아직 ROS 2로 Port되지 않았다면 내 Package부터 옮길 수 없습니다. Migration Guide가 가장 먼저 요구하는 것도 모든 Dependency의 ROS 2 가용성 확인입니다.


11. CLI와 환경 설정

ROS 1의 여러 실행 파일은 ROS 2에서 ros2 아래 Verb 형태로 통합되었습니다.

작업 ROS 1 ROS 2
Node 실행 rosrun pkg exe ros2 run pkg exe
Launch roslaunch pkg file.launch ros2 launch pkg file.launch.py
Node 목록 rosnode list ros2 node list
Topic 목록 rostopic list ros2 topic list
Topic 출력 rostopic echo /scan ros2 topic echo /scan
Service 호출 rosservice call ... ros2 service call ...
Parameter rosparam get ... ros2 param get /node name
Bag 기록 rosbag record ros2 bag record
Interface 확인 rosmsg show ros2 interface show

환경 변수도 달라집니다.

ROS 1 ROS 2
ROS_MASTER_URI 중앙 Master 주소가 없으므로 사용하지 않음
ROS_HOSTNAME, ROS_IP 일반적으로 같은 방식으로 사용하지 않음
ROS_PACKAGE_PATH Ament Index와 Prefix Path 중심
해당 없음 ROS_DOMAIN_ID, RMW_IMPLEMENTATION

CLI의 ROS Graph 정보가 의심스러우면 ROS 2 CLI Daemon 상태도 확인할 수 있습니다. 그러나 Daemon은 통신의 중앙 Master가 아니라 CLI 조회를 돕는 Process입니다.


12. Launch — XML 중심에서 확장 가능한 Launch System으로

ROS 1 Launch는 XML이 중심이며 Node, Argument, Namespace, Remap과 Parameter를 선언합니다.

ROS 2 Launch는 Python, XML과 YAML Frontend를 지원합니다. Python Launch는 조건, Event Handler, Grouping과 다른 Launch 포함을 Programming 방식으로 표현할 수 있습니다.

from launch import LaunchDescription
from launch_ros.actions import Node


def generate_launch_description():
    return LaunchDescription([
        Node(
            package='my_robot',
            executable='driver',
            name='driver',
            parameters=['config/driver.yaml'],
            remappings=[('cmd_vel', 'cmd_vel_safe')],
            output='screen',
        )
    ])

ROS 1 XML을 Python으로 기계적으로 번역하기 전에 다음을 재검토합니다.

  • Parameter YAML의 Node 이름과 ros__parameters 구조
  • type이 아니라 executable 등 바뀐 속성
  • Namespace와 상대·절대 Name
  • Launch File Install 경로
  • Process 시작 순서와 준비 완료 조건
  • 종료·재시작·Lifecycle Transition 처리

단순 구성은 XML이나 YAML이 더 읽기 쉬울 수 있습니다. Python이 지원된다고 모든 Launch를 복잡한 Program으로 만들 필요는 없습니다.


13. Nodelet과 Composition

ROS 1은 대용량 Image처럼 Process 사이 복사 비용이 큰 Pipeline을 위해 Nodelet을 제공했습니다. 여러 Nodelet Plugin을 같은 Nodelet Manager Process에 Load해 Zero-copy에 가까운 전달을 노렸습니다. 다만 일반 Node와 Nodelet의 작성 API와 배포 형태가 달랐습니다.

ROS 2 C++ Composition은 Node Component를 Shared Library로 만들고 배포 시점에 독립 Process 또는 Component Container에 배치할 수 있게 합니다.

같은 Component Code
  ├─ 독립 Process: 장애 격리·진단 용이
  └─ 같은 Container: 복사·지연 감소

ROS 2는 한 Context·Process에 여러 Node 객체를 둘 수도 있습니다. 그러나 같은 Process에 넣으면 한 Component의 Crash가 모두를 종료시킬 수 있고, Security Enclave와 Resource 격리도 함께 고려해야 합니다.

Composition은 무조건적인 성능 향상이 아니라 복사 비용과 장애 격리 사이의 배포 선택입니다.


14. Lifecycle — 준비 상태를 표준 Interface로

ROS 1 Node도 자체 State Machine을 만들 수 있었지만 공통 관리 Interface는 없었습니다. ROS 2 Managed Lifecycle Node는 대표적으로 다음 상태를 가집니다.

unconfigured ─configure→ inactive ─activate→ active
      ↑                      ↓ deactivate     ↓
      └────── cleanup ───────┘            shutdown
  • unconfigured: 아직 Resource를 구성하지 않음
  • inactive: Driver 연결과 Parameter 검증은 끝났지만 실제 출력은 비활성
  • active: Topic 발행이나 Hardware 동작 수행
  • finalized: 종료 상태

Navigation Stack이나 Hardware Driver를 Migration할 때 단순히 Node가 실행되었다는 사실과 운전 준비가 완료되었다는 상태를 구분할 수 있습니다.

Lifecycle을 사용한다고 System 시작 순서가 자동 해결되지는 않습니다. 누가 Transition을 요청하고 실패를 처리할지 Orchestrator 설계가 필요합니다.


15. Security와 Real-time의 정확한 의미

Security

ROS 1 기본 통신에는 Node 인증, Topic 접근 제어와 암호화가 없습니다. ROS 2는 SROS2와 DDS Security 등을 통해 다음 기반을 제공합니다.

  • Participant Identity 인증
  • Topic·Service 접근 권한
  • Message 암호화와 무결성

그러나 기본 설치만으로 자동 활성화되지 않습니다. Keystore, Certificate, Governance·Permissions 정책, Key 폐기와 배포 절차가 필요합니다.

Real-time

ROS 2는 Bounded Interface, Executor, Allocation 제어와 Middleware 선택 등 Real-time을 고려할 기반을 제공합니다. 하지만 다음 전체 Chain이 Deadline을 만족해야 합니다.

Sensor → Driver → Middleware → Executor → Controller → Driver → Actuator
   + RT OS + Memory + Lock + Network + Hardware

rclcpp를 쓴다는 이유만으로 Hard Real-time이 되지 않습니다. 최악 실행 시간과 Jitter를 실제 Target에서 측정해야 합니다.

Safety

ROS 2의 Security와 Real-time 기능은 Functional Safety 인증을 자동 제공하지 않습니다. Emergency Stop과 위험 에너지 차단은 별도 Risk Assessment와 Hardware Safety Architecture가 필요합니다.


16. TF, Bag, Plugin과 Test의 Migration

TF

ROS 1의 구형 tf보다 tf2를 사용하던 Code가 ROS 2로 옮기기 쉽습니다. Package 이름과 API, Duration·Time 표현은 달라집니다. Frame Tree 의미와 REP-105 규약은 유지됩니다.

Bag

ROS 1 rosbag과 ROS 2 rosbag2는 Storage와 Serialization 기반이 다릅니다. 기존 .bag File을 새 System에서 그대로 읽을 것이라고 가정하지 말고 변환 Tool, Bridge Replay 또는 원본 Data Export 전략을 검증해야 합니다.

QoS도 기록·재생에 영향을 줍니다. Recorder Subscription이 Publisher QoS와 호환되는지, Replay가 원래 Durability와 Reliability를 재현하는지 확인합니다.

Plugin

pluginlib 개념은 이어지지만 Export Macro, XML, CMake와 Base Class API를 다시 확인합니다. Nodelet Plugin은 ROS 2 Component 또는 일반 Library 구조로 재설계할 수 있습니다.

Test

rostest 기반 Integration Test는 ROS 2의 launch_testing, ament_cmake_pytest, ament_cmake_gtest 등으로 옮깁니다. 단순 Build 성공보다 Topic 주기, QoS, Timestamp, Frame과 종료 동작을 Test해야 합니다.


17. ros1_bridge — 두 Graph 사이의 통역사

ros1_bridge는 ROS 1과 ROS 2 사이에서 대응 가능한 Message와 Service를 변환합니다.

ROS 1 Node ←→ ROS 1 Transport ←→ ros1_bridge ←→ ROS 2 RMW ←→ ROS 2 Node

Dynamic Bridge

양쪽에서 알려진 Type과 Mapping을 이용해 필요한 Topic Bridge를 Runtime에 만듭니다. Topic Type을 어느 쪽에서도 아직 확인할 수 없으면 자동 Bridge가 만들어지지 않을 수 있습니다.

Custom Interface

사용자 .msg.srv는 ROS 1·ROS 2 양쪽 Package가 Build 환경에 존재하고 Mapping이 가능해야 합니다. ros1_bridge를 Build할 때 두 Workspace를 올바른 순서로 Source하고 Bridge를 다시 Compile해야 합니다.

중요한 현재 제약

ROS 1 Noetic은 2025년 5월 EOL이며 Ubuntu 24.04는 공식 ROS 1 설치 대상이 아닙니다. ros1_bridge는 양쪽 ROS를 같은 Build 환경에서 사용할 수 있어야 하므로 최신 ROS 2 OS에서 간단히 설치하는 방식이 성립하지 않을 수 있습니다.

따라서 Bridge는 영구 Architecture보다 기간과 환경이 명확한 Migration 도구로 보는 것이 안전합니다. 별도 Focal Container·VM, Network Gateway 또는 Application-level Adapter가 필요한지 사전 검증해야 합니다.

Bridge는 QoS, Parameter, 모든 Action과 임의 Runtime 의미를 자동 번역하는 만능 변환기가 아닙니다. 연결 성공뿐 아니라 Data 의미, 주기, Latch·Durability와 Failure 동작을 Test해야 합니다.


18. 안전한 Migration 전략

1단계 — 현재 System을 동결해 기록한다

  • Node·Topic·Service·Action Graph
  • Message Type, 단위, Frame과 주기
  • Parameter와 Launch Argument
  • Package·OS·Compiler Version
  • 정상 Bag, Fault Log와 성능 기준

2단계 — Dependency를 조사한다

각 Package와 Driver가 목표 ROS 2 Distribution에서 제공되는지 확인합니다. 없으면 Port, 대체, Vendor 지원 또는 System 경계 변경 중 하나를 결정합니다.

3단계 — Interface부터 안정화한다

사용자 Message를 먼저 옮기고 의미와 단위를 문서화합니다. header.seq 의존, 전역 Parameter와 Latched Topic을 찾아 새 계약을 정합니다.

4단계 — 위험이 낮은 말단부터 이동한다

Visualization, Logging, Monitoring, Sensor Adapter처럼 다른 Component 의존이 적고 실패 위험이 낮은 곳부터 옮깁니다. Motor Control과 Safety Layer는 마지막에 충분히 검증합니다.

5단계 — 공존 구간을 운영한다

Bridge나 명시적인 Gateway로 ROS 1과 ROS 2를 연결하되, Topic별 Mapping·QoS·Rate·Latency를 Monitoring합니다.

6단계 — 같은 입력으로 회귀 Test한다

기록 Data를 사용해 Output, Timing, TF, CPU·Memory와 Fault Recovery를 비교합니다. Floating-point 값은 단순 일치가 아니라 허용 오차를 정의합니다.

7단계 — ROS 2 기능 도입을 분리한다

첫 목표는 기존 동작의 동등성입니다. 그 뒤 QoS 최적화, Lifecycle, Composition과 새 Security를 별도 변경으로 도입하면 원인 추적이 쉽습니다.

8단계 — Bridge와 ROS 1을 제거한다

잔여 ROS 1 Dependency, Master, Build Farm과 운영 절차를 제거하고 Recovery Plan과 Documentation을 ROS 2 기준으로 갱신합니다.


19. Migration 결정표

상황 권장 접근
작은 교육 Project ROS 2로 새로 작성하며 개념만 재사용
순수 Algorithm Library ROS 의존을 Adapter 밖으로 분리한 뒤 양쪽 Wrapper 유지
Custom Message가 많은 System Interface Package와 Bridge Mapping을 먼저 검증
오래된 Vendor Driver 의존 ROS 2 Driver 지원, 대체 Hardware 또는 Gateway 검토
24시간 운영 제품 단계별 Rollback, 성능·Fault 회귀 Test와 장기 지원 계획 필수
Safety-critical Control Bridge 지연에 의존하지 않고 Safety Boundary를 독립 유지
Ubuntu 24.04 기반 신규 제품 ROS 1 동시 설치를 가정하지 말고 ROS 2 Native 또는 격리 Gateway 설계

Migration 비용은 Source Line 수만으로 계산하면 안 됩니다. Driver 가용성, Test Coverage, Field Data, Tooling, Team 경험과 제품 인증 영향이 더 큰 비용일 수 있습니다.


20. 흔한 오해와 교정

“ROS 1 Data는 모두 Master를 통과한다”

아닙니다. Master는 주로 발견과 연결 협상을 담당하고 Topic Data는 Node 사이에서 직접 전달됩니다.

“ROS 2는 UDP라서 Data를 잃는다”

Transport와 Reliability 의미를 혼동한 말입니다. DDS/RTPS가 UDP를 사용하더라도 Reliable QoS는 확인과 재전송 Mechanism을 제공할 수 있습니다.

“ROS 2는 Master가 없어 Network 설정이 쉽다”

중앙 URI는 사라졌지만 Multicast, Firewall, Domain, VPN, Container와 DDS Configuration을 관리해야 합니다.

“Nodelet은 ROS 2에서 처음 생긴 기능이다”

ROS 1에도 Nodelet이 있었습니다. ROS 2 Composition은 일반 Node Component와 배포 시 Process 배치를 더 일관되게 다루려는 발전입니다.

“Bridge가 있으니 Migration은 자동이다”

Bridge는 알려진 Data Type을 전달할 뿐 Application 동작, Parameter, Timing, QoS와 Safety 의미까지 보장하지 않습니다.

“Build가 되면 Migration이 끝났다”

Compile 성공은 시작입니다. Graph, 주기, Latency, TF, QoS, Shutdown, Restart와 Fault 시 안전 동작을 검증해야 합니다.


핵심 정리

  • ROS 2는 ROS 1의 철학을 계승하지만 Wire Protocol과 Runtime 계약이 호환되는 단순 Upgrade가 아닙니다.
  • ROS 1 Master는 발견과 협상을 담당하며 Data 전체의 Router는 아닙니다.
  • ROS 2는 RMW 아래 Middleware의 분산 Discovery와 QoS를 사용합니다.
  • QoS는 Queue Size, Reliability, Durability, Deadline 등을 명시하며 호환되지 않으면 연결되지 않을 수 있습니다.
  • ROS 2 Node는 객체이고 Executor·Callback Group이 Callback 실행을 제어합니다.
  • Parameter는 전역 Server에서 Node 소유·선언·검증 Model로 바뀌었습니다.
  • catkin은 ament Build Type과 colcon Meta Build Tool 구조로 전환되었습니다.
  • ROS 1 Nodelet의 목적은 ROS 2 Composition으로 이어졌지만 Process 배치와 API가 더 일관되게 설계되었습니다.
  • Security와 Real-time은 지원 기반일 뿐 자동 보장이 아니며 System 전체 설계와 검증이 필요합니다.
  • ros1_bridge는 유용하지만 EOL·OS·Custom Interface·QoS 제약이 있는 임시 Migration 도구입니다.
  • 안전한 Migration은 Interface와 기준선을 먼저 기록하고, 낮은 위험부터 단계적으로 이동하며, 동등성 검증과 ROS 2 기능 도입을 분리합니다.

용어 전에 읽는 공식 참고자료


ROBOT GLOSSARY

용어 정리

전체 용어 찾아보기 →
ROS MasterROS 1 중앙 발견 Registry
ROS 1 Node의 이름, Topic과 Service 위치 등록·조회를 담당하며 Node 사이 연결 협상을 돕는 중앙 Service입니다.
XML-RPCROS 1 제어 통신 방식
ROS 1에서 Master 등록, 조회와 Node 사이 연결 협상에 사용하는 HTTP·XML 기반 원격 호출 Protocol입니다.
TCPROSROS 1 TCP Topic Transport
연결 협상 후 ROS 1 Node 사이에서 직렬화된 Topic Message를 TCP로 전달하는 기본 Transport입니다.
UDPROSROS 1 UDP Topic Transport
일부 ROS 1 C++ 통신에서 Message 유실을 허용하고 UDP로 전달하도록 제공된 선택적 Transport입니다.
Distributed Discovery분산 발견
중앙 Master 없이 Middleware Participant가 Network에서 서로의 Publisher와 Subscriber를 발견하는 방식입니다.
Request vs OfferedQoS 요청·제공 호환 Model
Subscriber가 요구하는 최소 품질과 Publisher가 제공하는 품질을 비교해 연결 가능 여부를 결정하는 ROS 2 QoS Model입니다.
Latched Publisher마지막 Message 보존 발행자
ROS 1에서 늦게 연결된 Subscriber에게 마지막으로 발행한 Message를 즉시 전달하는 Publisher 설정입니다.
Transient Local발행자 보존 내구성
ROS 2에서 Publisher가 보관한 과거 Sample을 늦게 참가한 호환 Subscriber에게 제공하는 Durability Policy입니다.
ExecutorROS 2 Callback 실행기
Ready 상태인 Subscription, Timer, Service와 Action Callback을 기다리고 실행할 Thread와 순서를 관리하는 구성요소입니다.
Callback GroupCallback 동시 실행 규칙
ROS 2 Executor가 관련 Callback을 상호 배타적으로 또는 재진입 가능하게 실행할지 지정하는 Group입니다.
Parameter ServerROS 1 전역 설정 저장소
ROS 1 Master와 함께 전역 이름 Tree의 Parameter 값을 저장하고 조회하도록 제공하는 중앙 Service입니다.
catkinROS 1 Build System
CMake를 확장해 ROS 1 Package의 의존성, Code 생성, Build와 Workspace 환경을 관리하는 Build System입니다.
amentROS 2 Package Build 기반
ament_cmake와 ament_python 등 ROS 2 Package의 Build, Install, Export와 Test Convention을 제공하는 Build 체계입니다.
colcon범용 Meta Build Tool
여러 Package와 Build Type을 발견하고 의존 순서에 따라 Build·Test하는 ROS 2의 대표적인 Command-line Tool입니다.
NodeletROS 1 Process 공유 Component
여러 Plugin을 한 Manager Process에 Load해 대용량 Message의 직렬화와 복사 비용을 줄이는 ROS 1 구조입니다.
CompositionROS 2 Component 조합
Node Component를 독립 Process 또는 같은 Container Process에 배치해 격리와 통신 성능을 선택하는 ROS 2 기능입니다.
Managed Lifecycle관리형 Node 상태 전이
Node의 구성, 비활성, 활성과 종료 상태 및 전이를 공통 Interface로 노출하는 ROS 2 Model입니다.
SROS2Secure ROS 2
Middleware Security 기능을 이용해 ROS 2 Participant 인증, 접근 제어와 통신 암호화를 구성하는 Tool과 기능의 모음입니다.
rosbag2ROS 2 Data 기록·재생 Framework
Storage와 Serialization Plugin을 통해 ROS 2 Topic Data를 시간과 함께 기록하고 재생하는 Framework입니다.
ros1_bridgeROS 1·2 통신 Bridge
양쪽에서 Mapping 가능한 Message와 Service Type을 변환해 ROS 1 Graph와 ROS 2 Graph 사이 Data 교환을 돕는 Package입니다.

연습 문제

  1. ROS 2를 ROS 1의 호환 Upgrade가 아니라 별도 Platform으로 봐야 하는 이유는 무엇인가요?
  2. ROS 1 Master의 역할과 실제 Topic Data 경로를 설명하세요.
  3. ROS 2에서 중앙 Master가 사라져도 Network 설정 문제가 남는 이유를 설명하세요.
  4. RMW 계층이 특정 Middleware Vendor 종속성을 줄이는 방법은 무엇인가요?
  5. ROS 1의 Queue·Latch와 ROS 2의 QoS Policy 관계를 설명하세요.
  6. Reliable Subscriber와 Best Effort Publisher가 연결되지 않을 수 있는 이유는 무엇인가요?
  7. rospy의 전역 Node 방식과 rclpy의 Node 객체 방식 차이를 설명하세요.
  8. MultiThreadedExecutor를 사용해도 Deadlock이 생길 수 있는 이유는 무엇인가요?
  9. ROS 1 전역 Parameter를 ROS 2로 옮길 때 반드시 결정해야 할 것은 무엇인가요?
  10. catkin, ament와 colcon의 역할 차이를 설명하세요.
  11. ROS 1 Nodelet과 ROS 2 Composition의 공통 목적과 차이를 설명하세요.
  12. Lifecycle Node가 “Process가 실행됨”과 “운전 준비 완료”를 어떻게 구분하나요?
  13. ROS 2가 Security와 Real-time을 자동 보장하지 않는 이유는 무엇인가요?
  14. ros1_bridge에서 Custom Interface와 Ubuntu Version이 문제가 되는 이유를 설명하세요.
  15. Migration에서 기존 동작의 동등성 확보와 ROS 2 신기능 도입을 분리해야 하는 이유는 무엇인가요?