1291.53 노드 단위의 재사용 용이 (Ease of Node-Level Reuse)
1. 재사용성의 개념과 소프트웨어 공학적 의의
재사용성(reusability)이란 기존에 개발된 소프트웨어 구성 요소를 새로운 시스템이나 새로운 맥락에서 수정 없이 또는 최소한의 수정으로 활용할 수 있는 능력을 나타내는 설계 속성이다. McIlroy(1968)가 제안한 소프트웨어 부품(software component) 개념 이래, 재사용성은 소프트웨어 개발의 생산성 향상과 품질 보증의 핵심 전략으로 인식되어 왔다. 재사용 가능한 구성 요소는 이미 검증된 로직을 내포하고 있으므로, 새로운 시스템에서 해당 구성 요소를 재사용하면 개발 비용의 절감, 결함 발생률의 감소, 그리고 개발 기간의 단축이 달성된다.
로봇 행동 제어 시스템에서 재사용성은 특히 중요한 의미를 갖는다. 경로 계획, 장애물 회피, 배터리 관리, 비상 정지 등의 기본적 행동 패턴은 다양한 로봇 플랫폼과 다양한 임무에서 반복적으로 요구된다. 이러한 공통 행동 패턴을 재사용 가능한 단위로 구현하면, 새로운 로봇 시스템이나 새로운 임무를 위한 행동 제어 시스템의 구축 비용이 현저히 감소한다.
2. 행동 트리에서의 노드 수준 재사용
2.1 통일된 인터페이스에 의한 재사용 기반
행동 트리(Behavior Tree, BT)에서 노드 수준의 재사용이 용이한 근본적 원인은 모든 노드가 **통일된 인터페이스(uniform interface)**를 준수한다는 데 있다. 행동 트리의 모든 노드는, 노드의 유형이나 내부 구현과 무관하게, 다음의 동일한 프로토콜을 따른다.
\text{tick}(n) \rightarrow \text{Status} \in \{Success, Failure, Running\}
이 통일된 인터페이스에 의하여, 하나의 노드는 해당 노드가 삽입되는 트리의 구조나 맥락에 대한 사전 지식 없이도 정상적으로 동작한다. 노드의 부모가 Sequence인지 Fallback인지, 형제 노드가 몇 개인지, 트리의 전체 구조가 어떠한지와 무관하게, 노드는 tick 호출에 대하여 3값 반환 상태 중 하나를 반환하기만 하면 된다.
이 특성은 유한 상태 머신과 대조적이다. 유한 상태 머신에서 하나의 상태를 재사용하려면, 해당 상태로 진입하는 전이 규칙과 해당 상태에서 나가는 전이 규칙을 새로운 맥락에 맞게 재정의하여야 한다. 전이 규칙은 원천 상태와 목표 상태를 명시적으로 참조하므로, 상태와 전이 규칙은 분리 불가능하게 결합되어 있다.
2.2 포트 기반 매개변수화에 의한 맥락 적응
BehaviorTree.CPP에서 노드의 재사용성은 포트(port) 기반 매개변수화 메커니즘에 의하여 더욱 강화된다. 각 노드는 입력 포트(input port)와 출력 포트(output port)를 선언하며, 구체적인 데이터 값은 XML 정의에서 블랙보드 키(blackboard key)를 통하여 외부에서 주입된다.
class ComputePathToPose : public SyncActionNode
{
public:
static PortsList providedPorts()
{
return {
InputPort<geometry_msgs::msg::PoseStamped>("goal"),
InputPort<std::string>("planner_id"),
OutputPort<nav_msgs::msg::Path>("path")
};
}
NodeStatus tick() override
{
auto goal = getInput<geometry_msgs::msg::PoseStamped>("goal");
auto planner = getInput<std::string>("planner_id");
// 경로 계획 로직 실행
setOutput("path", computed_path);
return NodeStatus::SUCCESS;
}
};
이 노드는 목표 위치(goal)와 경로 계획 알고리즘 식별자(planner_id)를 포트를 통하여 외부에서 수신하므로, 구체적인 목표 위치나 계획 알고리즘에 의존하지 않는다. 동일한 ComputePathToPose 노드를 다양한 트리에서 서로 다른 블랙보드 키에 매핑하여 재사용할 수 있다.
<!-- 순찰 임무에서의 사용 -->
<ComputePathToPose goal="{patrol_goal}" planner_id="GridBased" path="{patrol_path}"/>
<!-- 충전 복귀 임무에서의 사용 -->
<ComputePathToPose goal="{charger_pose}" planner_id="NavFn" path="{return_path}"/>
동일한 노드 클래스가 서로 다른 임무 맥락에서 포트 매핑만을 변경하여 재사용된다. 노드의 C++ 구현에는 어떠한 수정도 필요하지 않다.
3. 재사용의 계층적 단위
3.1 개별 노드 수준의 재사용
가장 기본적인 재사용 단위는 개별 Action 노드와 Condition 노드이다. 이 노드들은 하나의 명확한 기능(하나의 행동 수행 또는 하나의 조건 평가)을 캡슐화하며, 임의의 트리에서 동일한 방식으로 사용될 수 있다.
로봇공학에서 빈번히 재사용되는 노드의 예시를 정리하면 다음과 같다.
| 노드 명칭 | 유형 | 기능 | 재사용 가능 맥락 |
|---|---|---|---|
| ComputePathToPose | Action | 목표 위치까지의 경로 계획 | 순찰, 귀환, 접근 등 |
| FollowPath | Action | 계획된 경로의 추종 | 모든 이동 임무 |
| IsBatteryLow | Condition | 배터리 잔량 임곗값 비교 | 에너지 관리 전반 |
| IsGoalReached | Condition | 목표 도달 여부 확인 | 모든 네비게이션 임무 |
| Wait | Action | 지정 시간 대기 | 대기 행동이 필요한 모든 임무 |
| Spin | Action | 제자리 회전 | 복구 행동, 탐색 등 |
이 노드들은 한 번 구현되면, 서로 다른 프로젝트, 서로 다른 로봇 플랫폼, 서로 다른 임무에서 수정 없이 재사용될 수 있다.
3.2 서브트리 수준의 재사용
개별 노드뿐만 아니라, 노드들의 조합으로 구성된 서브트리도 재사용의 단위가 된다. 예를 들어, “장애물이 감지되면 회피 기동을 수행하고, 그렇지 않으면 경로를 추종한다“는 행동 패턴을 서브트리로 캡슐화하면, 이 서브트리를 다양한 임무의 행동 트리에서 재사용할 수 있다.
<!-- obstacle_aware_navigation.xml -->
<BehaviorTree ID="ObstacleAwareNavigation">
<ReactiveFallback>
<Sequence>
<Condition ID="IsObstacleDetected" obstacle="{scan_data}"/>
<Action ID="AvoidObstacle" obstacle="{scan_data}"/>
</Sequence>
<Action ID="FollowPath" path="{current_path}"/>
</ReactiveFallback>
</BehaviorTree>
이 서브트리는 순찰 임무, 배송 임무, 탐사 임무 등 경로 추종이 포함되는 임의의 상위 트리에서 <SubTree ID="ObstacleAwareNavigation"/> 태그를 통하여 재사용된다.
4. 노드 등록과 팩토리 패턴
BehaviorTree.CPP에서 노드의 재사용은 팩토리(factory) 패턴에 의하여 실현된다. BehaviorTreeFactory 클래스에 노드 유형을 등록하면, XML 정의에서 해당 노드 유형의 이름으로 임의의 수의 인스턴스를 생성할 수 있다.
BehaviorTreeFactory factory;
factory.registerNodeType<ComputePathToPose>("ComputePathToPose");
factory.registerNodeType<FollowPath>("FollowPath");
factory.registerNodeType<IsBatteryLow>("IsBatteryLow");
등록된 노드 유형은 XML 정의에서 자유롭게 참조되며, 하나의 트리 내에서 동일한 노드 유형의 다수의 인스턴스가 생성될 수 있다. 각 인스턴스는 독립적인 상태를 가지며, 포트 매핑에 의하여 서로 다른 데이터에 연결된다.
ROS2 환경에서는 BehaviorTreeFactory에 ROS2 노드 핸들(node handle)을 주입함으로써, Action 노드가 ROS2 액션 클라이언트(action client)나 서비스 클라이언트(service client)와 연동되는 구조를 유지하면서도 재사용 가능한 형태로 구현된다.
5. 유한 상태 머신과의 재사용성 비교
유한 상태 머신에서의 재사용성과 행동 트리에서의 재사용성을 비교하면 다음과 같다.
| 비교 항목 | 유한 상태 머신 | 행동 트리 |
|---|---|---|
| 재사용 단위 | 상태 (state) | 노드 (node) 및 서브트리 (subtree) |
| 재사용 시 필요한 수정 | 전이 규칙의 재정의 필요 | 포트 매핑 변경만으로 충분 |
| 맥락 독립성 | 전이가 원천/목표 상태를 명시적 참조 | 노드는 트리 구조에 무관하게 동작 |
| 매개변수화 | 전이 조건에 매개변수 내장 필요 | 포트를 통한 외부 매개변수 주입 |
| 재사용 라이브러리 구축 | 전이 의존성으로 인해 라이브러리화 어려움 | 노드/서브트리의 라이브러리화 용이 |
유한 상태 머신에서 “경로 추종” 상태를 재사용하려면, 해당 상태로의 진입 전이(예: “경로 계획 완료 시 경로 추종으로 전이”)와 해당 상태로부터의 탈출 전이(예: “목표 도달 시 완료로 전이”, “장애물 감지 시 회피로 전이”)를 새로운 상태 머신의 맥락에 맞게 재정의하여야 한다. 전이 규칙은 상태 머신 전체의 구조에 의존하므로, 상태의 독립적 재사용이 불가능하다.
반면, 행동 트리에서 FollowPath Action 노드를 재사용하려면, 해당 노드를 새로운 트리의 적절한 위치에 삽입하고 포트를 매핑하면 된다. 노드의 C++ 구현에 대한 수정은 필요하지 않으며, 트리의 다른 부분에 대한 수정도 필요하지 않다.
6. 재사용 가능한 노드 라이브러리의 구축
6.1 Nav2의 노드 라이브러리
ROS2의 Nav2 프레임워크는 재사용 가능한 행동 트리 노드의 라이브러리를 제공한다. 이 라이브러리에는 네비게이션에 필수적인 Action 노드와 Condition 노드가 포함되어 있으며, 사용자는 이 노드들을 조합하여 자신의 네비게이션 행동 트리를 구성한다.
Nav2에서 제공하는 주요 노드 예시:
ComputePathToPose: 목표 위치까지의 경로 계획FollowPath: 계획된 경로의 추종Spin: 제자리 회전 (복구 행동)BackUp: 후진 (복구 행동)Wait: 지정 시간 대기NavigateThroughPoses: 경유지 순차 이동GoalReached: 목표 도달 여부 확인IsBatteryLow: 배터리 잔량 확인
이 노드들은 Nav2를 사용하는 모든 프로젝트에서 재사용되며, 이에 의하여 각 프로젝트에서 기본적인 네비게이션 노드를 처음부터 구현하는 비용이 제거된다.
6.2 조직 내 노드 라이브러리의 관리
로봇 개발 조직에서는 프로젝트 간 공유되는 노드 라이브러리를 체계적으로 관리함으로써 재사용성의 효과를 극대화할 수 있다. 노드 라이브러리의 관리에서 고려하여야 할 사항은 다음과 같다.
- 인터페이스 문서화: 각 노드의 입력 포트, 출력 포트, 반환 상태의 의미를 명확히 문서화하여야 한다.
- 버전 관리: 노드의 인터페이스 변경은 기존 사용처에 영향을 미치므로, 시맨틱 버저닝(semantic versioning)의 적용이 권장된다.
- 단위 테스트: 각 노드에 대한 독립적 단위 테스트를 유지하여, 노드의 정확성을 지속적으로 보증하여야 한다.
7. 재사용성의 설계 지침
노드 수준의 재사용성을 극대화하기 위한 설계 지침은 다음과 같다.
- 단일 책임 원칙: 하나의 노드는 하나의 명확한 기능만을 수행하여야 한다. 다수의 기능을 하나의 노드에 혼합하면 재사용의 범위가 축소된다.
- 하드코딩 배제: 노드 구현에서 구체적인 토픽 이름, 파라미터 값, 임곗값 등을 하드코딩하지 않고, 포트를 통하여 외부에서 주입받아야 한다.
- 플랫폼 독립성: 가능한 한 특정 로봇 플랫폼에 의존하지 않는 추상적 수준에서 노드를 구현하여, 다양한 플랫폼에서의 재사용을 가능하게 하여야 한다.
- 명확한 반환 상태 정의: 노드가 Success, Failure, Running을 각각 어떤 조건에서 반환하는지를 명확히 정의하고 문서화하여, 재사용 시 예측 가능한 동작을 보장하여야 한다.
8. 참고 문헌
- Colledanchise, M., & Ögren, P. (2018). Behavior Trees in Robotics and AI: An Introduction. CRC Press.
- Colledanchise, M., & Ögren, P. (2017). “How Behavior Trees Modularize Hybrid Control Systems and Generalize Sequential Behavior Compositions, the Subsumption Architecture, and Decision Trees.” IEEE Transactions on Robotics, 33(2), 372–389.
- Faconti, D. (2022). BehaviorTree.CPP 4.x Documentation. https://www.behaviortree.dev/
- McIlroy, M. D. (1968). “Mass Produced Software Components.” Proceedings of the NATO Software Engineering Conference, 138–155.
- Macenski, S., Martín, F., White, R., & Clavero, J. G. (2020). “The Marathon 2: A Navigation System.” IEEE/RSJ International Conference on Intelligent Robots and Systems (IROS), 2718–2725.
버전: 2026-03-31