1291.48 행동 트리의 선언적 설계 원칙
1. 선언적 설계와 절차적 설계의 구분
프로그래밍 패러다임에서 선언적(declarative) 접근과 절차적(procedural, imperative) 접근은 근본적으로 다른 명세 방식을 나타낸다. 절차적 접근은 “어떻게(how) 수행할 것인가“를 단계별 절차로 기술하는 반면, 선언적 접근은 “무엇을(what) 달성하고자 하는가“를 기술하며 구체적 실행 절차는 런타임 시스템에 위임한다.
행동 트리(Behavior Tree, BT)의 선언적 설계 원칙이란, 로봇의 행동 명세를 절차적 코드가 아닌 **구조적 선언(structural declaration)**으로 정의하며, 제어 흐름의 구체적 전개가 트리의 계층 구조와 노드의 의미론(semantics)에 의하여 자동으로 결정되는 설계 속성을 의미한다.
2. 행동 트리에서의 선언적 표현
2.1 구조가 곧 명세
행동 트리에서 개발자는 각 노드의 배치 순서와 계층 관계를 정의함으로써 로봇의 행동을 명세한다. 이때 상태 간 전이 조건이나 실행 순서에 대한 절차적 코드를 작성하지 않는다. 제어 흐름은 Sequence, Fallback, Parallel 등 제어 흐름 노드의 미리 정의된 의미론에 의하여 **암묵적(implicit)**으로 결정된다.
예를 들어, “배터리가 충분하면 순찰을 수행하고, 그렇지 않으면 충전소로 이동한다“는 행동을 선언적으로 명세하면 다음과 같다.
<Fallback>
<Sequence>
<Condition ID="IsBatteryAbove" threshold="0.2" />
<Action ID="ExecutePatrol" />
</Sequence>
<Action ID="NavigateToChargingStation" />
</Fallback>
이 XML 정의에서 개발자는 “어떤 순서로 조건을 확인하고, 어떤 경우에 어떤 행동으로 전환하는가“를 절차적으로 기술하지 않는다. Fallback 노드의 의미론(“첫 번째 자식이 실패하면 다음 자식을 시도한다”)과 Sequence 노드의 의미론(“모든 자식이 성공하여야 성공한다”)이 제어 흐름을 자동으로 결정한다.
2.2 의도의 직접적 반영
선언적 설계의 핵심적 이점은, 행동 명세가 개발자의 **의도(intent)**를 직접적으로 반영한다는 점이다. 절차적 코드에서는 의도가 구현 세부 사항(변수 선언, 조건 분기, 루프 등)에 의하여 가려지는 경우가 빈번하다. 반면, 행동 트리의 구조를 관찰하면, 로봇이 “무엇으로부터 무엇을 우선하여 수행하는가“가 트리의 좌우 배치에 의하여 즉시 파악된다.
이와 같은 특성을 **의도 투명성(intent transparency)**이라 한다. 의도 투명성은 행동 트리의 설계 검토(design review), 안전성 감사(safety audit), 그리고 임무 요구 사항과의 추적성(traceability) 확보에 직접적으로 기여한다.
3. XML 기반 선언적 정의의 구조
3.1 행동 트리의 XML 표현
BehaviorTree.CPP 4.x는 행동 트리를 XML 형식으로 선언적으로 정의하는 표준 방법을 제공한다. XML 기반 정의에서 트리의 구조, 노드의 유형, 매개변수의 연결이 단일 문서로 캡슐화된다.
<root BTCPP_format="4">
<BehaviorTree ID="MainTree">
<ReactiveFallback>
<Sequence>
<Condition ID="IsEmergencyDetected" />
<Action ID="EmergencyStop" />
</Sequence>
<Sequence>
<Condition ID="IsBatteryAbove" threshold="0.15" />
<SubTree ID="PatrolMission" route="{patrol_route}" />
</Sequence>
<Action ID="NavigateToChargingStation" />
</ReactiveFallback>
</BehaviorTree>
</root>
이 XML 문서는 로봇의 행동 논리를 완전히 기술하며, C++ 소스 코드의 수정 없이 행동을 변경할 수 있다. XML 파일의 편집만으로 서브트리의 추가·제거, 매개변수의 변경, 노드 배치의 재구성이 가능하다.
3.2 코드와 명세의 분리
선언적 설계 원칙의 실용적 결과는 **코드와 명세의 분리(separation of code and specification)**이다. 행동 트리에서:
- C++ 코드: 개별 노드의 구현(액션 수행, 조건 평가)을 담당한다. 이는 절차적 코드이며, 컴파일 시점에 고정된다.
- XML 명세: 노드의 배치, 매개변수 연결, 트리 구조를 선언한다. 이는 선언적 명세이며, 실행 시점에 로딩된다.
이 분리에 의하여, 노드의 구현을 담당하는 개발자와 행동 논리를 설계하는 로봇 공학자 또는 임무 설계자가 독립적으로 작업할 수 있다. 임무 설계자는 C++ 코드를 수정하지 않고, 기존 노드 라이브러리를 조합하여 XML에서 새로운 행동을 정의한다.
| 구성 요소 | 표현 방식 | 변경 시점 | 담당자 |
|---|---|---|---|
| 노드 구현 | C++ 절차적 코드 | 컴파일 시 | 소프트웨어 개발자 |
| 트리 구조 및 매개변수 | XML 선언적 명세 | 실행 시 로딩 | 임무 설계자 |
4. 선언적 설계와 절차적 설계의 비교
동일한 행동 논리를 절차적 코드와 행동 트리의 선언적 표현으로 각각 구현하여 비교하면, 선언적 설계의 장점이 명확히 드러난다.
절차적 구현 (의사 코드):
function execute_mission():
while mission_active:
if is_emergency():
emergency_stop()
return FAILURE
if battery_level < 0.15:
navigate_to_charging_station()
return FAILURE
if is_obstacle_detected():
avoid_obstacle()
else:
follow_path()
if reached_waypoint():
next_waypoint()
선언적 구현 (행동 트리 XML):
<ReactiveFallback>
<ReactiveSequence>
<Inverter>
<Condition ID="IsEmergencyDetected" />
</Inverter>
<Condition ID="IsBatteryAbove" threshold="0.15" />
<Fallback>
<Sequence>
<Condition ID="IsObstacleDetected" />
<Action ID="AvoidObstacle" />
</Sequence>
<Action ID="FollowPath" />
</Fallback>
</ReactiveSequence>
<Action ID="EmergencyStop" />
</ReactiveFallback>
두 구현의 차이점을 분석하면 다음과 같다.
| 특성 | 절차적 구현 | 선언적 구현 |
|---|---|---|
| 제어 흐름 표현 | if-else, while 등 명시적 분기 | 노드 배치에 의한 암묵적 제어 |
| 행동 추가 시 수정 범위 | 기존 조건 분기 구조 전체 | 트리의 해당 위치에 노드 삽입 |
| 의도 파악 용이성 | 분기 논리 추적 필요 | 트리 구조 관찰로 즉시 파악 |
| 형식적 검증 가능성 | 프로그램 검증 문제 (일반적으로 난해) | 트리 구조의 속성 분석으로 검증 |
| 비개발자 접근성 | 프로그래밍 지식 필수 | XML 편집 또는 시각적 도구 사용 |
5. 선언적 설계의 이론적 기반
5.1 구성적 의미론과의 관계
행동 트리의 선언적 설계는 프로그래밍 언어 이론의 **구성적 의미론(denotational semantics)**과 구조적 유사성을 갖는다. 구성적 의미론에서 프로그램의 의미는 구성 요소의 의미의 합성(composition)으로 정의된다. 행동 트리에서도 전체 트리의 동작은 각 노드의 의미론과 트리 구조의 합성으로 결정된다.
Colledanchise와 Ögren(2017)은 행동 트리의 동작을 시간에 따른 반환 상태의 함수로 형식화하였다.
\mathcal{T}: \mathcal{E} \times \mathbb{N} \rightarrow \{\text{Success}, \text{Failure}, \text{Running}\}
여기서 \mathcal{E}는 환경 상태의 집합이고, \mathbb{N}은 Tick 인덱스이다. 전체 트리의 동작 함수 \mathcal{T}는 각 자식 서브트리의 동작 함수와 루트 제어 노드의 의미론의 구성(composition)으로 정의된다.
이 형식화는 행동 트리의 선언적 특성을 수학적으로 정당화한다. 개발자가 정의하는 것은 트리의 구조(즉, 합성 규칙)이며, 구체적인 실행 흐름은 이 합성 규칙으로부터 자동으로 도출된다.
5.2 영역 특화 언어로서의 행동 트리
행동 트리의 XML 기반 선언적 정의는 **영역 특화 언어(Domain-Specific Language, DSL)**의 특성을 갖는다. 범용 프로그래밍 언어(C++, Python 등)로 행동 제어를 구현하는 대신, 행동 명세에 특화된 어휘(Sequence, Fallback, Condition, Action 등)와 구문(XML 태그 계층)을 사용하여 높은 수준의 추상화를 달성한다.
DSL로서의 행동 트리 XML은 다음과 같은 장점을 갖는다.
- 표현력의 집중: 행동 제어에 불필요한 범용 프로그래밍 개념(변수 선언, 메모리 관리, 스레드 제어 등)이 배제되어, 행동 논리에만 집중할 수 있다.
- 정적 분석 용이성: XML의 구조적 규칙성에 의하여, 트리의 구조적 속성(깊이, 폭, 노드 유형 분포 등)을 자동으로 분석할 수 있다.
- 도구 지원: XML 스키마 검증, Groot 등의 시각적 편집 도구, 자동 코드 생성 등 도구 체인(toolchain)의 지원이 용이하다.
6. 선언적 설계의 실용적 장점
6.1 실행 전 검증
선언적 명세의 핵심적 장점은, 실행 전에 명세의 구조적 속성을 검증할 수 있다는 것이다. XML 기반 행동 트리 정의에 대하여 다음과 같은 정적 검증이 가능하다.
- 구조적 유효성: 트리가 올바른 형태(유효한 부모-자식 관계, 빈 노드 없음 등)를 갖는지 검증한다.
- 포트 일관성: 노드가 요구하는 입력 포트가 모두 연결되어 있고, 타입이 일치하는지 검증한다.
- 도달 가능성: 트리 내의 모든 노드가 Tick에 의하여 도달 가능한지 검증한다.
BehaviorTree.CPP에서는 BehaviorTreeFactory::createTreeFromFile() 호출 시 이러한 정적 검증이 자동으로 수행되어, 구조적 오류가 실행 전에 감지된다.
6.2 동적 행동 변경
선언적으로 정의된 행동 트리는 **실행 시점(runtime)**에 동적으로 변경될 수 있다. XML 파일을 교체하거나, 트리 구조를 프로그래밍적으로 재구성함으로써, 로봇의 행동 논리를 재컴파일 없이 변경할 수 있다. 이 능력은 임무 조건에 따라 행동을 동적으로 전환하여야 하는 자율 시스템에서 특히 유용하다.
6.3 재현 가능한 행동 기록
선언적 행동 명세는 그 자체가 행동의 완전한 기록(record)이 된다. XML 파일을 버전 관리 시스템(Git 등)에 저장함으로써, 특정 시점의 로봇 행동을 정확히 재현할 수 있다. 절차적 코드에 흩어진 행동 논리에 비하여, 단일 XML 파일로 캡슐화된 행동 명세는 추적성(traceability)과 감사 가능성(auditability)이 탁월하다.
7. 선언적 설계의 한계
선언적 설계에도 한계가 존재한다. 행동 트리의 XML 명세는 제어 흐름의 “무엇을“에 대한 기술에는 적합하지만, 복잡한 연산 논리(수식 계산, 상태 변환 알고리즘 등)의 표현에는 적합하지 않다. 이러한 연산 논리는 여전히 절차적 코드(C++ 노드 구현)에 의하여 처리되어야 한다.
또한, 선언적 명세만으로 표현하기 어려운 동적 제어 패턴(예: 조건에 따른 서브트리의 동적 생성, 트리 구조 자체의 자기 수정 등)이 존재한다. 이러한 경우에는 선언적 명세와 절차적 코드의 결합이 불가피하며, 이 결합의 경계를 명확히 관리하는 것이 설계의 핵심 과제가 된다.
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/
- Iovino, M., Scukins, E., Styrud, J., Ögren, P., & Smith, C. (2022). “A Survey of Behavior Trees in Robotics and AI.” Robotics and Autonomous Systems, 154, 104096.
- Fowler, M. (2010). Domain-Specific Languages. Addison-Wesley.
버전: 2026-03-31