ROS 2 액션 마스터하기: 로봇과의 긴 호흡을 위한 대화법
ROS2 액션(Action)은 로봇의 장기 실행 작업을 위한 통신 방식으로, '목표(Goal)' 설정, '피드백(Feedback)', '결과(Result)'의 3가지 요소로 구성되어 토픽과 서비스를 결합한 형태이며, 자동차 내비게이션처럼 목적지를 설정하고 진행 상황을 지속적으로 받으며 최종 결과를 얻는 방식과 유사합니다.

로봇에게 서울역으로 가달라고 부탁했다고 가정해봅시다. 부탁을 받은 로봇이 가는 동안 아무 말도 없이 한참 뒤에야 도착했다고만 말한다면 어떨까요? 중간에 길을 잘못 든 것은 아닌지, 배터리는 충분한지 궁금해서 답답할 수밖에 없습니다. 이런 상황에서 우리에게 필요한 것이 바로 액션입니다.
액션: 서비스와 토픽 그 사이의 조화
액션은 ROS 2의 통신 유형 중 하나로 주로 장시간 실행되는 작업을 관리하는 데 사용됩니다. 감이 잘 오시지 않을 수 있어요. 쉽게 말해 서비스와 토픽의 장점만을 모아놓은 조합이라고 생각하면 편합니다. 서비스처럼 명확한 요청과 응답을 주고받으면서도, 토픽으로 작업이 진행되는 동안 끊임없이 피드백을 주고받을 수 있기 때문이죠.
우리는 액션을 이해하기 위해 세 가지 핵심 요소를 기억해야 합니다. 바로 목표, 피드백, 결과입니다. 클라이언트가 목표를 보내면 서버가 작업을 시작하고, 그 사이의 진행 상황을 피드백으로 알려주며, 마지막에 최종 결과를 반환하는 구조입니다.
마치 여러분이 택시를 타는 과정과 비슷합니다. 목적지를 말하는 것이 목표, 이동 중에 현재 어디쯤인지 알려주는 것이 피드백, 그리고 최종적으로 서울역에 도착하는 것이 결과가 됩니다. 만약 단순한 서비스 방식이었다면 목적지를 말하자마자 순간이동을 하거나, 도착할 때까지 기사님과 한마디도 나눌 수 없었을 것입니다.
물론 모든 통신을 액션으로 처리할 필요는 없습니다. 1초 안에 끝날 간단한 작업이라면 오히려 서비스가 효율적일 수 있죠. 하지만 로봇의 이동이나 로봇 팔의 제어처럼 시간이 걸리는 작업에서는 액션이 독보적인 가치를 발휘합니다.
서비스와 액션, 무엇이 다른가요?
서비스와 액션의 가장 큰 차이점은 작업이 얼마나 걸리는가와 중간에 소통이 필요한가에 있습니다. 단순히 비유하자면, 서비스는 불을 켜줘라고 요청하고 바로 결과를 받는 스위치와 같고, 액션은 저기 있는 컵을 가져다줘라고 요청하고 로봇이 움직이는 동안 상황을 지켜보는 것과 같습니다.
| 특징 | 서비스 (Service) | 액션 (Action) |
|---|---|---|
| 주요 목적 | 짧고 즉각적인 명령 수행 | 시간이 오래 걸리는 복잡한 작업 수행 |
| 통신 구조 | 요청 / 응답 | 목표 / 피드백 / 결과 |
| 피드백 | 없음 (끝나야만 알 수 있음) | 있음 (진행률 등을 실시간 확인) |
| 중단/취소 | 중간에 멈추기 어려움 | 가능 (언제든 취소 요청 가능) |
| 동작 방식 | 대기 가능 | 기본적으로 비동기 |
이해를 돕기 위해 퀴즈를 하나 내볼게요. 로봇에게 배터리 잔량이 얼마인지 알려줘라고 요청하려 합니다. 이때는 무엇을 쓰는 게 좋을까요? 정답은 서비스입니다. 배터리 잔량 확인은 로봇이 이미 알고 있는 정보를 단순히 묻고 답하는 것이라 서비스가 가장 효율적이기 때문입니다. 굳이 복잡한 액션을 써서 체크 중, 10퍼센트 확인 완료 같은 피드백을 받을 필요가 없으니까요.
액션의 내부 구조: 5개의 통신 채널
사실 액션은 완전히 새로운 통신 방식이 아니라, 우리가 이미 알고 있는 서비스와 토픽을 아주 똑똑하게 조합해서 만든 종합 선물 세트와 같습니다. 액션 하나가 제대로 작동하기 위해 내부적으로는 총 5개의 통신 채널이 유기적으로 돌아갑니다.
서비스 채널 (3개)
- Goal Service: 이 작업을 시작해줘라고 요청하고 수락 여부를 결정합니다.
- Result Service: 최종 결과가 뭐야?라고 묻고 답변을 받습니다.
- Cancel Service: 진행 중인 작업을 취소해줘라고 요청합니다.
토픽 채널 (2개)
- Feedback Topic: 작업 진행 상황을 실시간으로 계속 쏘아줍니다.
- Status Topic: 현재 서버의 상태를 알립니다.
여기서 흥미로운 질문을 하나 드릴게요. 왜 진행 상황인 피드백은 서비스가 아니라 토픽 방식을 사용할까요? 서비스는 전화를 거는 것과 같아서 상대방이 받을 때까지 기다려야 합니다. 반면, 토픽은 라디오 방송과 같아서 듣고 싶은 사람은 언제든 들으면 되고, 말하는 사람은 상대가 듣든 말든 계속 정보를 보냅니다.
만약 로봇이 컵을 가지러 가면서 서비스로 피드백을 보낸다면 로봇은 피드백을 보낼 때마다 여러분의 대답을 기다려야 할 것입니다. 그러면 움직임이 뚝뚝 끊기겠죠? 그래서 피드백은 로봇이 하던 일을 멈추지 않고 계속 정보를 쏠 수 있도록 토픽 방식을 사용하는 것입니다.
실전! 액션 명령어 정복하기
이제 이론을 넘어 실제로 액션이 어떻게 살아 움직이는지 확인해봅시다. 우리는 터미널을 통해 로봇의 상태를 점검하고 명령을 내려보려 합니다.
1. 액션 목록과 정보 확인하기
현재 시스템에서 어떤 액션들을 사용할 수 있는지 확인하는 것부터 시작해볼까요? 다음 명령어를 입력하면 현재 활성화된 액션 목록이 나타납니다.
# turtlesim을 실행합니다.
ros2 run turtlesim turtlesim_node
# 활성화된 액션 목록을 요청합니다.
ros2 action list
# 결과
/turtle1/rotate_absolute
turtlesim이 실행 중이라면 /turtle1/rotate_absolute라는 이름을 발견할 수 있습니다. 거북이를 특정 각도로 회전시키는 능력을 갖춘 액션이죠. 하지만 이름만 알아서는 부족합니다. 이 액션을 누가 제공하고 누가 사용하고 있는지 더 깊게 들여다볼 필요가 있습니다.
ros2 action info /turtle1/rotate_absolute
# 결과
# “turtle1을 radian 단위 절대 각도로 돌려라” 라는 액션 명령 이름입니다.
Action: /turtle1/rotate_absolute
# 현재 이 액션에 goal(목표) 지시를 보낸 액션 클라이언트 노드가 하나도 없다는 의미입니다.
Action clients: 0
# 이 액션을 실제로 수행해 주는 액션 서버 노드가 1개 있다는 뜻입니다.
Action servers: 1
# 아래 줄의 /turtlesim은 이 서버의 노드 이름을 뜻합니다.
/turtlesim
이 명령어를 통해 우리는 해당 액션의 서버 노드 정보와 클라이언트 수를 확인할 수 있습니다. 시스템의 연결 고리를 한눈에 파악하는 셈입니다.
2. 액션의 설계도 파악하기
액션이 어떤 데이터를 주고받는지 모른다면 제대로 된 명령을 내릴 수 없습니다. 액션의 타입 정보를 확인하여 그 구조를 파헤쳐 봅시다.
ros2 action list -t
# 출력 예시
# 왼쪽: 액션 이름 (/turtle1/rotate_absolute)
# 오른쪽: 액션 타입 (turtlesim/action/RotateAbsolute)
/turtle1/rotate_absolute [turtlesim/action/RotateAbsolute]
출력된 결과를 보면 turtlesim/action/RotateAbsolute라는 타입을 확인할 수 있습니다.
왜 액션 이름과 타입을 분리했나
/turtle1/rotate_absolute는 액션 이름(endpoint, 통로 이름)이고, turtlesim/action/RotateAbsolute는 액션 타입(메시지 형식)인데, 둘을 따로 두는 게 ROS2 설계상 필수입니다.
액션 이름 (/turtle1/rotate_absolute):
- 클라이언트가 "이 통로로 명령 보낼게요"라고 지정하는 고유 식별자입니다.
- 같은 turtlesim_node를 띄우더라도
/turtle2/rotate_absolute,/mybot/rotate_absolute처럼 다른 이름으로 여러 개 만들 수 있습니다.
액션 타입 (turtlesim/action/RotateAbsolute):
- "이 액션은 theta 값 받고, result/feedback 형식은 이래요"라는 표준화된 데이터 스펙입니다.
- 패키지명/액션명으로 구성되어 충돌 방지하고, 컴파일 시 메시지 타입을 자동 생성해 줍니다.
📍 액션 이름 = "서울역 1번 승강장" (어디서 타는지)
📋 액션 타입 = "KTX 표준 좌석 배치도" (무슨 기차인지, 좌석 어떻게 생겼는지)
- 같은 KTX 타입이라도
부산역 3번,대전역 5번처럼 승강장(이름)은 달라야 하고 - 다른 액션 타입(SRT, 무궁화호)은
KTX 승강장에 못 타죠.
그래서 이름은 자유롭게 네이밍해서 여러 로봇/시뮬레이터에 재사용하고, 타입은 표준화해서 호환성을 보장하는 구조입니다.
여기서 한 걸음 더 나아가 실제 데이터 구조가 어떻게 생겼는지 interface show 명령어로 확인해 보겠습니다.
ros2 interface show turtlesim/action/RotateAbsolute
# 결과
# The desired heading in radians
float32 theta
---
# The angular displacement in radians to the starting position
float32 delta
---
# The remaining rotation in radians
float32 remaining

이 명령어는 액션의 세부 명세서를 보여줍니다.
가장 먼저 눈에 띄는 것은 --- 구분선이 두 개 있다는 점일 텐데요. 이를 통해 액션의 세 가지 구성 요소를 구분합니다. 우리가 거북이(turtlesim)에게 "몸을 돌려!"라고 명령하는 상황을 상상하며 하나씩 살펴볼까요? 🐢
1. Goal (목표)
float32 theta
- 클라이언트(명령을 내리는 쪽)가 액션 서버(거북이)에게 보내는 최종 목표 값입니다.
theta는 거북이가 바라볼 **절대적인 방향(각도)**을 의미해요. 단위는 라디안(Radians)을 사용합니다.
2. Result (결과)
float32 delta
- 작업이 완전히 끝났을 때 딱 한 번 돌려받는 값입니다.
delta는 "처음 위치에서 총 얼마나 회전했는가"를 나타냅니다. 예를 들어, 거북이가 0도에서 90도로 돌았다면 결과값은 90도(약 1.57 라디안)가 되겠죠.
3. Feedback (피드백)
float32 remaining
- 작업이 진행되는 동안 실시간으로 계속 전달받는 값입니다.
remaining은 "목표까지 얼마나 남았는가"를 알려줍니다. 거북이가 천천히 도는 동안 이 값이 점점 줄어드는 것을 보면서 우리는 작업이 잘 진행되고 있는지 확인할 수 있어요.
이제 이 구조가 조금 눈에 들어오시나요? :)
목표를 던지고 과정을 지켜보기
준비는 끝났습니다. 이제 실제로 거북이에게 회전 명령을 내려보겠습니다. 액션의 진정한 묘미는 목표를 전달한 뒤 돌아오는 실시간 반응에 있습니다.
ros2 action send_goal /turtle1/rotate_absolute turtlesim/action/RotateAbsolute "{theta: 1.57}"

위 명령어는 거북이를 약 90도 회전시키는 명령입니다. 명령을 실행하는 순간, 터미널에는 목표가 수락되었다는 메시지와 함께 남은 각도를 알려주는 피드백이 실시간으로 쏟아질 것입니다. 로봇이 지금 무엇을 하고 있는지 우리가 실시간 피드백러가 되어 지켜볼 수 있는거죠.
과연 이 과정에서 우리는 단순히 결과만 기다리는 것이 아니라, 로봇의 현재 상태에 맞춰 다음 행동을 설계할 수 있는 유연성을 얻게 됩니다. 이것이 바로 액션이 가진 강력한 힘입니다.
마음이 바뀌었다면? 액션 취소하기
세상일이 항상 계획대로만 흘러가지는 않습니다. 로봇이 이동하던 중에 장애물이 나타나거나 사용자가 명령을 철회해야 할 상황이 생기기 마련입니다. 서비스는 한 번 요청하면 끝날 때까지 기다려야 하지만, 액션은 다릅니다. 우리에겐 취소라는 강력한 카드가 있습니다.
우선 피드백을 확인하며 실행되는 액션을 하나 실행해 봅시다.
ros2 action send_goal /turtle1/rotate_absolute turtlesim/action/RotateAbsolute "{theta: 3.14}" --feedback
그리고 다른 터미널에서 다음 명령어를 입력해 보세요.
ros2 action cancel_goal /turtle1/rotate_absolute
명령을 내리는 즉시 진행 중이던 작업이 중단되고 취소되었다는 상태 메시지가 뜹니다. 비동기 통신의 자유로움이 느껴지시나요? 로봇에게 명령을 내린 후에도 상황에 따라 유연하게 대처할 수 있다는 점은 복잡한 로봇 시스템을 구축할 때 엄청난 이점이 됩니다.
요약하며
이번 시간에는 ROS 2의 핵심 통신 방식인 액션에 대해 깊이 있게 살펴보았습니다.
액션은 목표, 피드백, 결과라는 삼박자를 갖춘 장기전 통신 방식입니다. ros2 action list와 info를 통해 시스템의 액션 현황을 파악할 수 있습니다. send_goal 명령어로 직접 목표를 전달하고 진행 과정을 모니터링할 수 있습니다. 언제든 cancel_goal을 통해 실행 중인 작업을 중단시킬 수 있는 유연함을 제공합니다.
로봇이 단순히 시키는 일만 하는 기계가 아니라, 자신의 상태를 공유하며 소통하는 파트너로 느껴지기 시작하셨나요? 액션을 제대로 활용하는 순간, 여러분의 로봇은 훨씬 더 똑똑하고 안전하게 움직이게 될 것입니다.