제12부 실시간·성능
12.1 실시간이란 무엇인가 — ROS 2에서의 한계
12.1.1 이 장에서 배우는 것 / 선수 지식
"실시간"만큼 오해받는 용어가 드물다. 대부분의 대화에서 "실시간"은 "빠르다"를 뜻하지만, 공학적으로는 다른 것 — 정해진 시간 안에 반드시 끝난다는 보장이다. 평균 1 ms에 최악 500 ms인 시스템은 빠르지만 실시간이 아니고, 항상 10 ms 안에 끝나는 시스템은 느리지만 실시간이다.
이 구분이 실무에서 중요한 이유는 요구가 잘못 설정되기 때문이다. "실시간 제어가 필요합니다"라고 하지만 실제로 필요한 것은 "지연이 대체로 낮으면 됨"인 경우가 많고, 반대로 실제 데드라인이 있는데 그것을 인식하지 못한 경우도 있다.
이 장은 ROS 2가 실시간에 대해 무엇을 주고 무엇을 주지 않는지 정직하게 정리한다. 결론을 먼저 말하면 — ROS 2 전체는 실시간 시스템이 아니고, 특정 경로를 실시간에 가깝게 만들 수는 있으며, 실제 하드 실시간은 대개 ROS 2 밖에 둔다.
배우는 것:
- 정의 — 하드·펌·소프트.
- WCET — 최악 실행 시간과 그 어려움.
- 계층별 비결정성 — 어디서 시간이 새는가.
- ROS 2의 실제 위치 — 정직한 평가.
- 판단 — 언제 실시간이 필요한가.
- 대안 — 하드 루프를 어디에 둘 것인가.
선수 지식: 2.2~2.6(실행 모델), 2.5.6(지터), 6.6(실시간 제어 — 하드웨어 관점), 6.8(micro-ROS), 11.7(측정).
정직: 이 장은 실시간 인증·안전 인증에 관한 조언을 제공하지 않는다. 기능 안전(IEC 61508·ISO 13849 등) 요구가 있는 시스템은 해당 표준과 전문가의 판단을 따라야 하며, 이 책의 서술을 근거로 삼아서는 안 된다. 성능·지연 수치는 제시하지 않는다(3.6.1). 이 환경에서 검증하지 않았다(목차 3).(→ 197차 확인:
realtime_tools의 RT 헬퍼 API(configure_sched_fifo·lock_memory·has_realtime_kernel)와 ROS 2 공식 실시간 데모(pendulum_control)를 Docker 컨테이너에서 실제로 컴파일·실행했다. 결정성 관련 부분(12.1.4)은 12.5의 기존 실측(93~97차, 실행기별 순서 확정)을 인용했다. 아래 각 절의 실행 확인(197차) 참고 — 지연 수치는 3.6.1 방침대로 이 특정 컨테이너 환경의 예시로만 인용하며 일반화하지 않는다.)
12.1.2 정의 — 빠름이 아니라 보장
실시간 시스템의 정의: 결과의 정확성이 값뿐 아니라 시점에도 달린 시스템.
| 등급 | 데드라인 초과 시 | 예 |
|---|---|---|
| 하드 | 치명적 실패 | 모터 전류 루프·안전 정지 |
| 펌 | 그 결과는 버려짐 | 관절 제어 주기 |
| 소프트 | 품질 저하 | 항법 갱신·시각화 |
| 오해 | 사실 |
|---|---|
| "실시간 = 빠름" | 실시간 = 예측 가능 |
| "평균이 좋으면 실시간" | 최악값이 기준 |
| "실시간 OS면 실시간" | OS는 조건일 뿐, 전체 경로가 필요 |
| "실시간이면 성능이 좋다" | 오히려 처리량은 떨어질 수 있다 |
견해: "실시간은 최악값의 문제"라는 인식이 출발점이다. 11.7.3에서 "평균이 아니라 꼬리를 보라"고 한 것이 여기서 극단으로 간다 — 실시간에서는 꼬리가 곧 사양이다.
견해: 실시간은 대가를 요구한다. 최악값을 낮추려면 평균 성능·처리량·개발 편의를 희생해야 한다(무할당 경로·고정 크기·동적 기능 포기 — 12.3). 필요 없는 곳에 적용하면 손해다.
12.1.3 WCET — 최악 실행 시간
하드 실시간의 근거는 WCET(Worst-Case Execution Time)다.
$$\sum_{i} \frac{C_i}{T_i} \le U_{\max}$$
주기 $T_i$의 작업이 최악 $C_i$ 걸릴 때, 이용률이 한계 이하여야 스케줄 가능하다(확인 필요: 구체적 스케줄링 이론은 이 책 범위를 넘는다).
문제는 $C_i$(WCET)를 아는 것이 매우 어렵다는 점이다.
| 어려움 | 설명 |
|---|---|
| 캐시 | 히트·미스에 따라 배수 차이 |
| 분기 예측 | 경로 의존 |
| 동적 메모리 | 할당 시간이 비결정적(12.3) |
| 페이지 폴트 | 디스크 접근 |
| 알고리즘 자체 | 반복 횟수가 데이터 의존(계획·탐색) |
| 라이브러리 | 내부가 불투명 |
| 인터럽트·다른 작업 | 간섭 |
견해: 측정으로 얻은 최댓값은 WCET가 아니다. 관측하지 못한 더 심각한 경우가 있을 수 있다. 실무에서는 충분히 오래·다양한 조건에서 측정한 최댓값에 여유를 곱해 쓰지만, 이것은 보장이 아니라 근거 있는 추정임을 알아야 한다.
함정: 데이터 의존적 알고리즘은 WCET가 사실상 없다. 경로 계획(8.5)·역기구학(9.1)·SLAM은 입력에 따라 시간이 크게 변한다. 이런 것을 하드 실시간 경로에 두지 말라 — 두려면 반복 횟수·시간 제한(anytime 알고리즘)을 적용해야 한다.
12.1.4 계층별 비결정성
ROS 2 애플리케이션의 시간은 여러 층에서 샌다.
| 계층 | 비결정성 원천 | 장 |
|---|---|---|
| ① 앱 | 동적 할당·데이터 의존 알고리즘·락 | 12.3 |
| ② rclcpp | 실행기 선택 순서·대기 집합 재구성·할당 | 2.2.5·2.4 |
| ③ rcl·rmw | 내부 할당·타입 변환 | 3.4 |
| ④ DDS | 직렬화·큐·재전송·디스커버리 | 3.1~3.3 |
| ⑤ OS | 스케줄링·페이지 폴트·인터럽트 | 12.2 |
| ⑥ 하드웨어 | 캐시·메모리 경합·주파수 변동 | 12.2.7 |
견해: 어느 한 층만 수정해도 실시간이 되지 않는다. RT 커널을 설치했는데 콜백에서
std::string을 만들면(12.3.6) 거기서 지터가 난다. 가장 취약한 층이 전체를 결정한다.
②의 구체적 문제(2.2~2.4의 재확인):
| 문제 | 설명 |
|---|---|
| 선택 순서 불명확 | 여러 준비된 콜백 중 무엇을 먼저(2.2.5) |
| 대기 집합 재구성 | 엔티티 추가·삭제 시 |
| 긴 콜백이 막음 | 단일 스레드에서(2.3.4) |
| 동적 할당 | 메시지·내부 자료구조 |
정직: rclcpp 실행기의 결정성 개선은 진행 중인 주제이며 배포판마다 다르다
(확인 필요). 정적 실행기·이벤트 기반 실행기 등이 존재하지만, Jazzy에서의 정확한 선택지·특성은 문서로 확인해야 한다. 12.5에서 다룬다.(→ 197차 확인: 12.5이 이미 실측을 끝냈다 —SingleThreadedExecutor는TIMER→SUB→SRV→CLIENT→WAITABLE순서(93~95차),MultiThreadedExecutor는 이 순서가 16~47% 확률로 깨짐(95차),EventsExecutor는 완전히 정반대 순서(SUB→CLIENT→SRV→TIMER, 97차, 14/14 재현). 이 장이 미룬 질문에 대한 답은 12.5.4·2.3.14 실행 확인 블록 참고.)
12.1.5 ROS 2의 실제 위치
정직한 평가다.
| 항목 | 상태 |
|---|---|
| ROS 2 전체가 하드 실시간인가 | 아니다 |
| 실시간을 고려해 설계됐나 | 부분적으로 — 그렇다 |
| 특정 경로를 실시간에 가깝게 | 가능하다 |
| 인증 가능한 실시간 보장 | 일반적으로 아니다(확인 필요: 특수 구성)(→ 197차 확인: 이 환경(표준 Ubuntu 커널)에서 realtime_tools::has_realtime_kernel()이 정확히 false를 보고함 — 아래 실행 확인(197차) 참고) |
| 소프트 실시간 | 충분히 가능 |
ROS 2가 실시간을 위해 제공하는 것:
| 제공 | 설명 |
|---|---|
| 무할당 경로 지향 설계 | rcl·rclcpp 일부 |
| 커스텀 할당자 지원 | 12.3.4(→ 197차 확인: ROS 2 공식 실시간 데모 pendulum_control이 실제로 tlsf_cpp(TLSF 커스텀 할당자)에 의존함을 package.xml로 확인 — 아래 실행 확인(197차) 참고) |
| 대여 메시지(loaned) | 제로 카피(12.3.5, 170차 갭점검에서 이미 실행 확인 — can_loan_messages()로 고정/가변 크기 조건 실측) |
| 콜백 그룹·실행기 선택 | 격리 |
| QoS 설정 | 전달 제어(1.6) |
realtime_tools | 락프리 버퍼(6.5.6)(→ 197차 확인: 락프리 버퍼 외에도 configure_sched_fifo·lock_memory·has_realtime_kernel·set_thread_affinity RT 헬퍼 API가 실재하고 실제로 동작함을 컴파일·실행으로 확인 — 아래 실행 확인(197차) 참고) |
제공하지 않는 것:
| 미제공 | 결과 |
|---|---|
| WCET 보장 | 스스로 측정해야 |
| 전 경로 무할당 보장 | 검증 필요 |
| 결정적 실행 순서 보장 | 12.5 |
| 실시간 인증 | 표준·전문가 영역 |
실행 확인(197차) — 위 두 표의 구체적 항목들을 Docker 컨테이너(
osrf/ros:jazzy-desktop-full)에서 직접 실행해 확인했다. ①realtime_tools(3.11.0)의 RT 헬퍼 API가 실재하고 정확히 동작한다.realtime_helpers.hpp(configure_sched_fifo·lock_memory·has_realtime_kernel·set_thread_affinity·get_number_of_available_processors)로 소형 테스트 프로그램을 작성·컴파일해 실행하니,has_realtime_kernel()이 이 환경(호스트 커널7.0.0-29-generic, 표준 Ubuntu)에서 정확히false를 보고했다. ② 컨테이너 권한에 따라 RT 스케줄링·메모리 잠금의 성공 여부가 갈린다는 것을 3단계로 대조 확인했다 — 권한 추가 없는 플레인 도커에서는configure_sched_fifo(80)·lock_memory()둘 다 실패("No proper privileges to lock the memory!");--cap-add=sys_nice하나만 추가하면configure_sched_fifo는 성공하지만lock_memory는 여전히 실패;--cap-add=sys_nice --cap-add=ipc_lock --ulimit memlock=-1:-1까지 추가해야 둘 다 성공("Memory locked successfully!") — SCHED_FIFO와 mlockall이 서로 다른 capability를 요구한다는 것을 정량으로 구분했다. ③ ROS 2 공식 실시간 데모pendulum_control(0.33.11)이osrf/ros:jazzy-desktop-full에 기본 포함돼 있었고,package.xml에서 실제로tlsf_cpp(TLSF 할당자)·rttest(실시간 측정 도구)에 의존함을 확인했다.pendulum_demo를 두 권한 조건에서 각 5회씩 반복 실행한 결과 — 메모리 잠금이 실패하는 조건에서는 실행 중 Minor pagefault가 매번 4~5개 발생(5/5)했지만, 잠금이 성공하는 조건에서는 5/5 모두 정확히 0개로, mlockall의 "실행 중 페이지 폴트 제거" 효과 자체는 완벽하게 재현됐다. 그러나 평균 지연은 두 조건이 사실상 같았고(5,165 ns vs 5,180 ns, 5회 평균의 평균), 최댓값 범위는 오히려 메모리 잠금 조건에서 다소 높은 쪽으로 나타났다(평균 최댓값 38,854 ns vs 55,853 ns) — RT 커널·CPU 격리 없이 메모리 계층 하나만 고쳐서는 지연이 개선되지 않음을 실측으로 보여 준다(12.1.4의 "가장 취약한 층이 전체를 결정한다"와 정합). 이 지연 수치는 3.6.1 방침대로 이 특정 컨테이너 환경의 예시일 뿐 일반화하지 않는다. 확인하지 못한 것: 실제 PREEMPT_RT 커널을 준비하지 못해 "RT 커널을 더하면 개선되는지"는 대조하지 못했다(이번엔 메모리 잠금 단독의 한계만 보였다), CPU 격리(isolcpus)는 적용하지 않았다, 표본이 조건당 5회뿐이라 통계적 유의성 검정은 하지 않았다. 원본:tools/gap_harness/gap196/rt_test/(rt_helpers_test.cpp,logs/rt_helpers_cap_test/·logs/pendulum_baseline/·logs/pendulum_memlocked/,findings_summary.txt).
견해: "ROS 2로 하드 실시간 제어를 한다"는 주장에는 조건이 많이 붙어야 한다. 특정 노드·특정 경로를, 커스텀 할당자와 RT 스케줄링과 무할당 코드로 구성하고, 측정으로 검증한 경우에 한한다. 일반적인 ROS 2 애플리케이션은 소프트 실시간이다.
견해: 소프트 실시간으로 충분한 응용이 대부분이다. 항법·인지·작업 계획은 수십~수백 ms 지연이 허용되며, 여기에 하드 실시간 기법을 적용하는 것은 낭비다. 실시간 요구를 계층별로 나누는 것(12.1.7)이 핵심이다.
12.1.6 언제 실시간이 필요한가
| 요구 | 예 | 처리 |
|---|---|---|
| 하드 | 전류 루프·안전 정지·힘 제어 | MCU·전용 하드웨어(12.1.8) |
| 펌 | 관절 위치 제어 1 kHz | RT 설정된 ROS 2 또는 MCU |
| 소프트 | 궤적 생성·항법 | 일반 ROS 2 |
| 없음 | 로깅·시각화·보고 | 일반 |
견해: "제어 주파수가 높다 = 하드 실시간"이 아니다. 1 kHz 루프라도, 한 주기를 놓쳤을 때 제어가 안정적으로 회복되면 펌·소프트에 가깝다. 놓쳤을 때 무슨 일이 벌어지는가가 등급을 정한다.
견해: 안전 기능은 실시간 논의와 별개로 다뤄야 한다(8.7.7·9.6.1의 반복). 비상정지·안전 감시는 소프트웨어 스택의 실시간성에 의존하지 않는 독립 경로로 두는 것이 원칙이며, 그 설계는 안전 표준과 전문가의 영역이다.
요구를 정하는 절차:
| 단계 | 질문 |
|---|---|
| 1 | 데드라인이 실제로 있는가 |
| 2 | 초과하면 무슨 일이 |
| 3 | 얼마나 자주 허용되나 |
| 4 | 데드라인 값은 무엇에서 나오나 |
| 5 | 측정 가능한가 |
견해: 4단계가 자주 생략된다. "1 kHz가 필요하다"는 요구가 물리(모터 대역·기계 공진)에서 나온 것인지, 관행에서 온 것인지 확인해야 한다. 근거 없는 고주파 요구가 시스템을 불필요하게 어렵게 만든다.
12.1.7 계층 분리
실시간 요구가 다른 것들을 섞지 않는다.
| 계층 | 위치 | 주기 |
|---|---|---|
| 하드 | MCU·모터 드라이브 | 수 kHz~ |
| 펌 | ros2_control 노드(6.2) | 수백 Hz~1 kHz |
| 소프트 | ROS 2 노드 | 수~수십 Hz |
| 비실시간 | 별도 프로세스·원격 | 임의 |
견해: "실시간 요구가 높은 것을 아래로 밀어내는" 설계가 표준적 방법이다. 전류·전압 루프는 드라이브에, 관절 제어는 MCU나 RT 설정된 컨트롤러에, 궤적·항법은 일반 ROS 2에. 이렇게 나누면 상위 계층이 실시간이 아니어도 시스템이 동작한다.
견해: 6.6에서 다룬
ros2_control루프가 실무의 경계선이다. 그보다 아래(전류 루프)는 대개 하드웨어·펌웨어가, 그보다 위는 일반 ROS 2가 맡는다.ros2_control노드를 RT로 만드는 것이 ROS 2 실시간 노력의 주 대상이다.
경계에서의 통신:
| 방식 | 특성 |
|---|---|
락프리 버퍼(realtime_tools) | RT 스레드↔비RT 스레드(6.5.6) |
| micro-ROS | MCU↔ROS 2(6.7) |
| EtherCAT 등 필드버스 | 결정적 통신(6.1.5) |
| 공유 메모리 | 프로세스 간 |
함정: 경계에서 RT 스레드가 비RT 자원(락·할당·I/O)을 사용하면 그 순간 실시간이 깨진다. 6.5.6에서 락프리 버퍼를 쓰라고 한 이유이며, RT 경로에서 로깅·서비스 호출·동적 할당을 하지 않는 것이 원칙이다.
12.1.8 하드 루프를 밖에 두기
가장 확실한 방법은 ROS 2에 의존하지 않는 것이다.
| 위치 | 특성 |
|---|---|
| 모터 드라이브 내부 | 전류·속도 루프 — 벤더 제공 |
| MCU(micro-ROS 또는 커스텀) | 관절 제어·센서 융합(6.7) |
| FPGA·전용 하드웨어 | 극한 요구 |
| 산업용 컨트롤러 | PLC·모션 컨트롤러 |
| 안전 릴레이·안전 PLC | 안전 기능 — 별도 경로 |
견해: 이 구조가 산업 로봇의 일반적 형태다. 상위는 유연하고 기능이 풍부하되 실시간이 아니고, 하위는 단순하고 결정적이다. ROS 2를 상위에 두는 것이 그 강점(생태계·유연성)을 살리는 방향이다.
견해: "모든 것을 ROS 2에서" 하려는 시도가 어려움을 자초한다. 하드 실시간 요구를 Linux·ROS 2 스택으로 만족시키는 것은 가능하더라도 비용이 크다. 요구를 아래로 밀 수 있는지 먼저 검토하라.
정직: 다만 이 분리에도 대가가 있다 — 개발·디버깅이 두 환경으로 나뉘고, MCU 펌웨어 갱신 절차가 필요하며, 상하위 인터페이스 설계가 추가된다(6.7.8). 어느 쪽이 나은지는 요구와 팀 역량에 달렸다.
12.1.9 실시간 달성의 전체 그림
ROS 2 경로를 실시간에 가깝게 만들려면 모든 층을 다뤄야 한다.
| 층 | 조치 | 장 |
|---|---|---|
| OS | RT 커널·스케줄링·CPU 격리 | 12.2 |
| 메모리 | 잠금·프리폴트·무할당 | 12.3 |
| 통신 | QoS·제로 카피·DDS 설정 | 1.6·12.3.5 |
| 실행 | 실행기·콜백 그룹·결정성 | 12.5 |
| 코드 | 무할당·경계 있는 알고리즘 | 12.3.6 |
| 설계 | 지연 예산 | 12.4 |
| 검증 | 측정·장시간 시험 | 11.7 |
견해: 순서는 "설계 → 측정 → 개선"이다. 지연 예산을 먼저 세우고(12.4), 측정으로 어디가 초과하는지 보고(11.7), 그 층을 개선한다. 근거 없이 RT 커널부터 까는 것은 순서가 틀렸다 — 문제가 어디인지 모른 채 비용을 지불하는 것이다.
견해: 검증 없는 실시간 주장은 의미가 없다. RT 설정을 했다고 실시간이 되는 것이 아니라, 장시간·최악 조건에서 데드라인을 지키는지 측정해야 한다. 12.2.8의
cyclictest와 11.7의 방법론이 그 수단이다.
12.1.10 함정 카탈로그
| # | 함정 | 증상 | 대처 |
|---|---|---|---|
| 1 | 실시간을 "빠름"으로 이해 | 잘못된 요구 | 정의 확립 |
| 2 | 평균으로 판정 | 데드라인 초과 | 최악값 |
| 3 | 측정 최댓값을 WCET로 확신 | 미관측 사례 | 여유·추정임을 인지 |
| 4 | 데이터 의존 알고리즘을 RT 경로에 | WCET 없음 | 시간 제한·분리 |
| 5 | 한 층만 개선 | 효과 없음 | 전 경로 |
| 6 | RT 커널부터 설치 | 순서 오류 | 측정 먼저 |
| 7 | 근거 없는 고주파 요구 | 불필요한 난이도 | 물리에서 역산 |
| 8 | 안전을 실시간성에 의존 | 위험 | 독립 경로·전문가 |
| 9 | 모든 것을 ROS 2에서 | 과도한 비용 | 아래로 밀기 |
| 10 | RT 경로에서 로깅·할당 | 지터 | 금지 규칙 |
| 11 | 검증 없이 실시간 주장 | 근거 없음 | 장시간 측정 |
| 12 | 소프트로 충분한데 하드 기법 | 낭비 | 등급 분류 |
12.1.11 체크포인트
- 실시간의 공학적 정의와, "빠름"과의 차이를 설명할 수 있는가.
- 하드·펌·소프트의 구분 기준과 각각의 예는?
- 실시간에 관한 네 가지 흔한 오해를 반박할 수 있는가.
- WCET가 무엇이며, 아는 것이 어려운 이유 일곱 가지는?
- "측정 최댓값은 WCET가 아니다"의 의미와, 실무적 대처는?
- 데이터 의존 알고리즘을 RT 경로에 두면 안 되는 이유와 대안은?
- 계층별 비결정성 원천을 여섯 층에 대해 말할 수 있는가.
- "가장 취약한 층이 전체를 결정한다"의 함의는?
- ROS 2가 실시간을 위해 제공하는 것 여섯 가지와 제공하지 않는 것 네 가지는?
- "ROS 2로 하드 실시간을 한다"는 주장에 붙어야 할 조건들은?
- 실시간 등급을 정하는 다섯 단계 질문과, 자주 생략되는 것은?
- 계층 분리 설계의 원칙과, ROS 2 실시간 노력의 주 대상은?
- 하드 루프를 밖에 두는 다섯 위치와, 그 분리의 대가는?
- 실시간 달성의 순서는 무엇이며, 왜 "RT 커널부터"가 틀렸는가.
다음 장 12.2은 첫 번째 층 — OS를 다룬다. RT 커널·스케줄링 정책·CPU 격리.