제0부 개관과 출발
0.3 Jazzy Jalisco의 정체 — 배포 주기·플랫폼·수명
0.3.1 이 장에서 배우는 것 / 선수 지식
"ROS 2를 쓴다"는 말은 불충분하다. 어떤 배포판(distribution)을 쓰느냐가 지원 기간·OS·컴파일러·Python 버전·기본 미들웨어·사용 가능한 API를 전부 결정하며, 이것은 프로젝트의 수명 계획과 직결된 경영적 결정이다. 출하할 로봇의 소프트웨어를 EOL이 1년 남은 배포판 위에 구축하면, 보안 패치가 끊긴 스택으로 5년을 유지해야 한다.
이 장은 Jazzy Jalisco를 계약서처럼 읽는다 — 언제까지 지원되고, 어떤 플랫폼이 보증되며, 무엇이 새로 생기고 무엇이 사라졌는지.
배우는 것:
- ROS 2 배포 주기의 규칙 — 매년 5월 릴리스, 짝수 해 LTS, Ubuntu LTS와의 페어링. 왜 이 규칙이 프로젝트 계획에 중요한가.
- Jazzy의 계약 사항 — 릴리스·EOL 날짜, Tier 1/2/3 플랫폼, 언어·컴파일러·CMake 버전, 기본 RMW와 지원 RMW 티어.
- Jazzy에서 새로 생긴 것 — 패키지별 신규 기능과, 그중 실무에 실제로 영향을 주는 것의 구분.
- Jazzy에서 사라진 것·바뀐 것 — 제거된 헤더·시그니처, 비추천 API, 그리고 조용히 동작을 바꾸는 변경(executor 콜백 순서).
- Humble에 남을 것인가 Jazzy로 갈 것인가 — ①②③ 판단 축.
선수 지식: 0.1(계층 스택), 0.2(ROS 1→2 변경). 아직 설치하지 않았어도 읽을 수 있다(설치는 0.4).
정직: 이 장의 날짜·플랫폼·버전은 ROS 2 릴리스 공지, Jazzy 릴리스 노트, REP 2000에 근거한다. 다만 REP 2000의 플랫폼 티어는 배포판 수명 동안 갱신될 수 있고, 참조한 문서들 사이에 RHEL 9의 티어 표기가 엇갈리는 것을 확인했다 — 아래에
(확인 필요)로 표시했다. 세부 패키지 버전은 패치 릴리스로 계속 오른다. 의사결정에 쓰기 전 REP 2000과 해당 배포판 문서를 직접 확인하라.
0.3.2 배포 주기의 규칙 — 왜 5월이고 왜 짝수 해인가
ROS 2는 매년 5월 23일(World Turtle Day) 즈음에 새 배포판을 낸다. 이름은 알파벳 순서로 진행된다(… Foxy → Galactic → Humble → Iron → Jazzy → Kilted → …).
| 배포판 | 릴리스 | EOL | 성격 | 기준 Ubuntu |
|---|---|---|---|---|
| Humble Hawksbill | 2022-05 | 2027-05 | LTS | 22.04 Jammy |
| Iron Irwini | 2023-05 | 2024-11 | 비LTS | 22.04 Jammy |
| Jazzy Jalisco | 2024-05 | 2029-05 | LTS | 24.04 Noble |
| Kilted Kaiju | 2025-05 | 2026-11 | 비LTS | 24.04 Noble (확인 필요) |
이 규칙이 프로젝트에 뜻하는 것:
- 출하 제품은 LTS 위에 구축한다. 비LTS는 1년 반 뒤 보안·버그 수정이 끊긴다. 연구·프로토타입이면 비LTS도 무방하지만, 필드에 나가는 로봇이면 LTS가 사실상 유일한 선택이다(견해 — 근거: 지원 종료 후 취약점 대응 부담).
- OS 업그레이드와 ROS 업그레이드가 묶인다. Jazzy를 쓰려면 Ubuntu 24.04로 가야 한다. 이 결합은 커널·드라이버·GPU 스택(CUDA 등)의 호환성까지 끌고 오므로, 마이그레이션 계획에서 가장 부담이 큰 항목이 되곤 한다(15.1).
- EOL은 "그날 갑자기 멈춤"이 아니라 "그날부터 패치 없음"이다. 코드는 계속 실행되지만, 새 취약점·새 하드웨어·새 의존성에 대한 대응이 사라진다. 5년 수명의 제품이라면 중간에 한 번은 배포판을 건너야 한다는 뜻이고, 그 비용을 처음부터 설계에 넣어야 한다(14.7·15.1).
0.3.3 Jazzy의 계약 — 플랫폼·언어·툴체인
지원 플랫폼(REP 2000 기준):
| 티어 | 플랫폼 | 아키텍처 | 의미 |
|---|---|---|---|
| Tier 1 | Ubuntu 24.04 Noble | amd64, arm64 | 모든 변경이 CI로 검증, 바이너리 제공, 회귀는 릴리스 차단 사유 |
| Tier 1 | Windows 10 (Visual Studio 2019) | amd64 | 동일 (확인 필요 — VS 버전 표기) |
| Tier 1 또는 2 | RHEL 9 | amd64 | 참조 문서 간 표기가 엇갈린다 (확인 필요) |
| Tier 3 | macOS, Debian Bookworm, Ubuntu Jammy, OpenEmbedded 등 | 다양 | 커뮤니티 기여 기반, 바이너리·CI 보장 없음 |
티어의 의미(REP 2000): Tier 1은 릴리스 전 CI에서 빌드·테스트가 모두 통과해야 하고 바이너리가 제공된다. Tier 2는 주기적 CI가 실행되지만 회귀가 릴리스를 막지는 않는다. Tier 3은 지원이 최선 노력(best effort)이며, 대개 직접 빌드해야 한다.
실무 해석: arm64가 Tier 1이라는 점이 중요하다 — Jetson·Raspberry Pi 계열 로봇 컴퓨터에서 소스 빌드 없이 apt로 설치할 수 있다는 뜻이다(단, Ubuntu 24.04 기반이어야 한다. Jetson의 L4T·JetPack이 어떤 Ubuntu를 쓰는지는 JetPack 버전에 달렸으므로 (확인 필요) — 이 결합은 로봇 프로젝트에서 흔한 함정이다).
언어·툴체인:
| 항목 | Jazzy 기준 | 비고 |
|---|---|---|
| C++ 표준 | C++17 | Noble의 GCC 13 기본이 __cplusplus == 201703L이고 ament_cmake는 따로 강제하지 않는다(실행 확인) |
| 컴파일러 | GCC 13.3.0 | Ubuntu 24.04.4 LTS 기본(실행 확인) |
| Python | Noble 기본 3.12 | ROS 2 코어·rclpy·colcon·launch가 모두 이 위에서 실행된다 |
| CMake | 3.28.3 | Noble 제공 버전(실행 확인) |
| 빌드 도구 | colcon + ament | 4.1·4.5 |
Python 3.12는 조용한 마이그레이션 부담이다. Humble(3.10)에서 넘어오면 distutils 제거(PEP 632), setuptools 동작 변화, 일부 서드파티 패키지 미호환을 만난다. 특히 setup.py 기반 ament_python 패키지에서 경고·오류가 늘어난다(4.3·15.1).
미들웨어:
| RMW | 미들웨어 | 티어 | 비고 |
|---|---|---|---|
rmw_fastrtps_cpp | eProsima Fast DDS | Tier 1 | 기본값 — 바이너리에 포함 |
rmw_cyclonedds_cpp | Eclipse Cyclone DDS | Tier 1 | apt로 설치 후 환경변수로 전환 |
rmw_connextdds | RTI Connext | Tier 1 | 상용 라이선스 필요 |
rmw_fastrtps_dynamic_cpp | Fast DDS(동적 타입) | Tier 2 | 내부 검사·도구용 |
rmw_gurumdds_cpp | GurumNetworks GurumDDS | Tier 3 | — |
rmw_zenoh_cpp | Eclipse Zenoh | (별도 릴리스) | Jazzy용 바이너리 제공 — DDS가 아닌 대안(3.10) |
0.3.4 Jazzy에서 새로 생긴 것 — 전체 목록
Jazzy 릴리스 노트에 실린 신규 기능을 패키지별로 정리한다. 이 책이 실무 영향이 크다고 판단한 항목은 굵게 표시하고, 어디서 자세히 다루는지 적었다.
rosbag2 — 이번 배포판에서 가장 크게 바뀐 패키지:
| 변경 | 실무 의미 | 상세 |
|---|---|---|
| MCAP이 기본 저장 포맷 | sqlite3 → MCAP. 기존 도구·스크립트가 깨질 수 있고, 대신 성능·상호운용성이 좋아진다 | 11.2 |
| 서비스 기록·재생 | ROS 1 시절부터 요청되던 기능. 서비스 호출까지 재현 가능 | 11.3 |
| 미들웨어 송신·수신 타임스탬프 기록 | "언제 보냈고 언제 받았나"를 분리 기록 — 지연 분석의 근거. MCAP에서만 지원 | 11.2·11.7 |
| 메타데이터를 bag 파일 자체에 저장 | metadata.yaml 분실에도 복구 가능, 자기완결적 bag | 11.2 |
| Player·Recorder를 rclcpp 컴포넌트로 노출 | 컨테이너에 넣어 intra-process 통신 가능 → 대용량 기록 성능 | 1.13·11.3 |
| 기록 시 타입 기준 필터 모드 추가 | 토픽 이름이 아닌 타입으로 골라 기록 | 11.3 |
| 압축 스레드 우선순위 설정 | 기록이 실시간 경로를 방해하는 문제 완화 | 11.3·12.3 |
시간 범위로 기존 bag 분할(start_time_ns·end_time_ns) | 대용량 bag에서 관심 구간만 추출 | 11.3 |
ROS_DISTRO를 메타데이터에 기록 | 어느 배포판에서 딴 기록인지 추적 | 11.2 |
| 키보드 제어 비활성화 옵션 | 비대화형·서비스 환경에서 필요 | 11.3·14.8 |
rcl·rclcpp·rclpy:
~/get_type_description서비스 추가(rcl) — 타입 서술 배포 기능(확인 필요: REP 번호). rcl 헤더와.srv주석은 해시 표준으로 REP-2011을 가리킨다(원문 확인 — 1.3.13·A.3.4). 노드가 자신이 쓰는 타입의 정의를 런타임에 내어줄 수 있다. 원격 도구가 소스 없이 메시지를 해석할 수 있게 하는 기반이다. Jazzy에서 이 서비스는 기본으로 켜져 있다(실행 확인 — 1.3.13).rclcpp::TimerInfo— 타이머 콜백에 "예정 시각"과 "실제 호출 시각"이 전달된다. 타이머 드리프트·지연을 코드에서 직접 측정할 수 있다(2.5).- executor가 내부적으로
rclcpp::WaitSet을 사용하도록 변경 — wait set 생성·삭제 반복이 줄어 오버헤드가 감소. 부작용으로 콜백 실행 순서의 일관성이 보장되지 않게 됐다(0.3.5에서 상술). - 서비스용 타입 지원 헬퍼
rclcpp::get_service_typesupport_handle추가. rclpy에ParameterEventHandler추가 — 다른 노드의 파라미터 변경을 구독하는 표준 방법이 Python에도 생겼다(1.9).rclpy메서드에 타입 힌트 추가 — IDE·mypy사용성이 좋아진다.
인터페이스·타입:
rosidl에 키 어노테이션(key annotation) 지원 — 데이터 멤버를 키 필드로 표시할 수 있다. DDS의 키드 토픽·인스턴스 개념과 연결되는 기반 작업이다(1.2·3.1, 실사용은(확인 필요)).common_interfaces:VelocityStamped메시지 신설,Marker.msg에ARROW_STRIP추가,geometry_msgs/Polygon·PolygonStamped에 ID 필드 추가.message_filters가 TypeAdapter를 지원 — 사용자 타입과 ROS 메시지 간 자동 변환을 동기화 필터에서도 쓸 수 있다(7.7).
도구·시각화:
rviz2: TF 디스플레이의 정규식 프레임 필터(프레임이 수백 개인 로봇에서 유용), 토픽 상태에 측정 주파수(Hz) 표시, 시간 리셋 기능(단축키R·서비스),point_cloud_transport지원,CameraInfo디스플레이, ROS 1 rviz와의 기능 격차 해소(DepthCloud·AccelStamped·TwistStamped·WrenchStamped·Effort).ros2cli:--log-file-name인자, 구독 통계에 별도 QoS 지정, 클라이언트·서비스 개수 표시.ros2 action type하위 명령 추가.image_transport: lazy subscriber 지원(구독자가 없으면 발행·인코딩을 하지 않음 — CPU 절약에 직결), 콜백 그룹 지정, 플러그인 allow list, 커스텀 QoS로 광고·구독(7.2).rcutils로깅 포맷에{date_time_with_ms}토큰 추가 — 사람이 읽는 시각을 로그에 넣을 수 있다(1.11).rcpputils에tl_expected추가 — C++23std::expected의 백포트(예외 없는 오류 전파).geometry2(tf2): Twist 보간 지원 — 움직이는 프레임의 속도를 질의할 수 있다(5.2).
0.3.5 Jazzy에서 사라진 것·바뀐 것 — 마이그레이션 함정
제거(빌드가 깨진다 — 컴파일 오류로 즉시 드러남):
| 제거 대상 | 대체 | 영향 |
|---|---|---|
rclcpp/qos_event.hpp | rclcpp/event_handler.hpp | 헤더 이름만 바꾸면 되는 경우가 대부분 |
비-const shared_ptr 구독 콜백 시그니처 | const std::shared_ptr<const T>& 등 const 형태 | 오래된 코드에서 광범위하게 발생 |
tf2_* 계열의 .h 헤더(tf2_geometry_msgs/tf2_geometry_msgs.h 등) | .hpp 버전 | 인클루드 경로 일괄 치환 |
비추천(경고만 나오고 동작은 유지 — 다음 배포판에서 제거될 수 있음):
rclcpp::get_typesupport_handle→rclcpp::get_message_typesupport_handle.
동작 변경(빌드는 통과하는데 런타임 동작이 달라진다 — 가장 위험):
- executor의 콜백 실행 순서가 일관되게 보장되지 않는다. wait set 재사용 최적화의 결과다. Iron 이전에 "타이머보다 구독 콜백이 먼저"처럼 관찰된 순서에 암묵적으로 의존하던 코드는 Jazzy에서 다르게 동작할 수 있다. 순서에 의존해야 한다면 콜백 그룹·executor를 명시적으로 설계하라(2.3·2.4·12.5). 실측(2.3.14): 지금 Jazzy는 정반대로, 타이머가 구독보다 먼저 실행되는 순서가 25/25회 결정적으로 관측됐다 — "보장되지 않는다"는 매 실행마다 바뀐다는 뜻이 아니라 배포판이 바뀌면 바뀔 수 있다는 뜻임을 이 역전 자체가 보여 준다.
tf2의wait_for_transform_async반환 타입 변경 — bool이 아니라 변환 정보를 돌려준다. 반환값을 조건문에 쓰던 코드는 의미가 달라진다(5.2).- executor의 데이터 경쟁 수정 — 이전 배포판에서 우연히 성립하던 타이밍이 바뀔 수 있다. 스레드 안전 가정을 재검토할 근거다(2.9).
- rosbag2 기본 포맷이 MCAP — 명시적으로
-s sqlite3를 주지 않으면 새 기록은 MCAP이다. 기존 파이프라인(bag을 sqlite로 열어 파싱하던 스크립트)이 조용히 깨진다(11.2).
함정: 위 4번처럼 "기본값이 바뀐 변경" 이 가장 늦게 발견된다. 마이그레이션 시 컴파일 오류를 다 고친 뒤가 아니라, 기록·재생·로그·시각화 같은 주변 도구 체인을 함께 회귀 시험해야 한다(15.1).
0.3.6 Jazzy 주변 생태계의 페어링
배포판을 고르면 함께 쓸 생태계 버전도 사실상 결정된다.
| 생태계 | Jazzy 짝 | 비고 |
|---|---|---|
| 시뮬레이터 | Gazebo Harmonic(gz-sim 8 계열) | ROS 2 apt 저장소의 vendor 패키지로 설치 가능해졌다. ros_gz 브리지가 Jazzy↔Harmonic 조합을 공식 지원(10.2) |
| 제어 | ros2_control Jazzy 브랜치 | 자체 릴리스 주기(6.1) |
| 항법 | Nav2 Jazzy 브랜치 | 자체 릴리스 주기(8.1) |
| 매니퓰레이션 | MoveIt 2 Jazzy 브랜치 | 자체 릴리스 주기(9.1) |
| 대안 미들웨어 | rmw_zenoh_cpp Jazzy 릴리스 | sudo apt install ros-jazzy-rmw-zenoh-cpp — 실재하며 Jazzy 버전은 0.2.9(실행 확인). 라우터가 사실상 필수라는 점을 포함해 3.10.12에 실측 |
함정: 생태계 패키지는 코어와 다른 속도로 움직인다. "Jazzy를 쓴다"고 해서 Nav2·MoveIt 2의 특정 기능이 있다는 보장은 없다. 의존하는 기능은 해당 프로젝트의 Jazzy 브랜치에서 직접 확인해야 한다.
0.3.7 Humble에 남을 것인가, Jazzy로 갈 것인가
실제로 자주 하게 되는 결정이다. 선택지를 펼치고 트레이드오프를 적는다.
① Humble(22.04)에 남는다
- 맞는 경우: 이미 Humble에서 출하 중이고 남은 제품 수명이 2027년 5월 이내. 의존 하드웨어 SDK·드라이버가 22.04만 지원(산업용 카메라·모션 컨트롤러·일부 GPU 스택에서 흔하다). 팀이 마이그레이션에 쓸 여력이 없다.
- 대가: 2027년 5월 EOL. Jazzy 이후의 신규 기능·수정이 백포트되지 않는다. 새 서드파티 패키지가 Humble 지원을 끊기 시작한다. 결국 한 번은 건너야 하며, 미룰수록 격차가 커진다.
② Jazzy(24.04)로 간다
- 맞는 경우: 신규 프로젝트. 2029년까지 지원이 필요한 제품. Ubuntu 24.04 기반 하드웨어·드라이버가 갖춰짐. MCAP·서비스 기록·
TimerInfo같은 신규 기능이 실제로 필요. - 대가: OS 업그레이드가 동반된다(커널·드라이버·GPU·컨테이너 이미지 전부). Python 3.12 호환성 문제. 0.3.5의 제거·동작 변경 대응. 일부 서드파티 패키지의 Jazzy 지원이 늦을 수 있다.
③ Rolling·Kilted로 앞서간다
- 맞는 경우: 코어에 기여하는 팀, 다음 LTS를 미리 준비해야 하는 플랫폼 팀, 연구 프로토타입.
- 대가: Rolling은 언제든 깨질 수 있다(의도된 성격이다). 비LTS인 Kilted는 2026년 11월 EOL. 출하 제품에는 부적합.
견해: 신규 로봇 제품이라면 Jazzy가 기본 선택이다 — 2029년까지의 지원 기간이 일반적인 제품 개발·출하 주기와 맞고, arm64가 Tier 1이며, MCAP 기반 기록 체계가 현장 데이터 운영에 실질적 이득을 준다. 반대로 이미 Humble에서 안정적으로 출하 중이고 제품 수명이 2027년 안에 끝난다면, 마이그레이션 비용을 굳이 지불할 이유가 약하다. 결정의 축은 "신규 기능"이 아니라 "제품 수명과 EOL의 관계"** 다.
0.3.8 버전 정보를 직접 확인하는 방법
책의 표를 믿지 말고 자기 환경에서 확인하는 습관이 중요하다. 아래는 Jazzy 환경에서 쓰는 확인 경로다. 이 중 ros2 doctor·ros2 pkg list·echo $ROS_DISTRO 계열은 이후 회차의 컨테이너 검증에서 실제로 쓴 명령이며, 표에 실린 버전·날짜 값은 자기 환경에서 확인해야 한다(목차 3의 검증 범위 표 참조).
# 현재 셸이 어떤 배포판을 가리키는가
echo "$ROS_DISTRO" # jazzy 여야 한다
echo "$AMENT_PREFIX_PATH" # 오버레이 순서 확인 (0.5)
# 설치된 ROS 2 패키지 버전 (Debian·Ubuntu)
apt list --installed 'ros-jazzy-*' 2>/dev/null | head
dpkg -s ros-jazzy-rclcpp | grep -E '^(Package|Version)'
# 현재 사용 중인 미들웨어
echo "${RMW_IMPLEMENTATION:-<기본값: rmw_fastrtps_cpp>}"
# 환경 전반 점검 (경고·오류를 요약해 준다)
ros2 doctor --report
ros2 doctor는 배포판·플랫폼·네트워크 인터페이스·QoS 관련 점검을 요약해 준다. 다만 통과했다고 시스템이 정상이라는 뜻은 아니다 — 디스커버리·QoS 문제는 여전히 별도로 봐야 한다(0.7·11.1). 이것은 짐작이 아니라 확인된 사실이다: 도메인이 갈려 노드가 서로 전혀 안 보이는 상태에서도 All 5 checks passed가 나온다(83차 실측, 0.7.11.4). ros2 doctor는 환경을 보지 그래프를 보지 않는다 — 그래프를 보려면 이름이 비슷한 ros2 doctor hello(11.1.15)를 써야 한다.
0.3.9 체크포인트
- ROS 2 배포 주기의 규칙(연 1회 5월, 짝수 해 LTS 5년, 홀수 해 비LTS 약 1년 반)을 말하고, Jazzy의 릴리스·EOL 날짜를 댈 수 있는가.
- Tier 1과 Tier 3 플랫폼의 실질적 차이를 "바이너리 제공·CI 보증" 관점에서 설명할 수 있는가. 지금 쓰는 로봇 컴퓨터는 어느 티어에 있는가.
- Jazzy의 기본 RMW는 무엇이며, 바꾸려면 어떤 환경변수를 쓰는가.
- rosbag2의 기본 저장 포맷이 바뀐 사실이 기존 분석 스크립트에 미칠 영향을 설명할 수 있는가. 무엇을 회귀 시험해야 하는가.
- Jazzy의 동작 변경 4가지 중 컴파일 오류로 드러나지 않는 것은 무엇인가. 그것을 어떻게 사전에 검출할 것인가.
- 담당 제품의 수명(출하일 + 지원 연수)을 적고, Humble·Jazzy 중 어느 쪽이 그 수명을 덮는지 계산해 보라. 덮지 못한다면 중간 마이그레이션 시점을 언제로 설정할 것인가(15.1).
다음 장 0.4는 이 Jazzy를 실제로 설치하고 환경을 구성한다 — apt·소스·Docker의 세 경로와, 환경변수가 만드는 함정들.