ROS 2에서 package.xml은 패키지의 신분증입니다.
노드가 실제로 어떻게 빌드되는지는 C++ 패키지에서는 CMakeLists.txt, Python 패키지에서는 setup.py가 담당합니다.
하지만 이 패키지가 어떤 이름을 가지는지, 어떤 의존성을 사용하는지, 어떤 빌드 방식을 쓰는지는 package.xml이 설명합니다.
1. package.xml이 하는 일
package.xml은 ROS 2 패키지의 메타데이터를 담는 파일입니다.
주요 역할은 다음과 같습니다.
| 패키지 이름 | ROS 2에서 이 패키지를 부르는 이름 |
| 버전 | 패키지 버전 |
| 설명 | 패키지가 하는 일 |
| 관리자 | 유지보수 담당자 |
| 라이선스 | 사용 조건 |
| 의존성 | 빌드, 실행, 테스트에 필요한 패키지 |
| 빌드 타입 | ament_cmake, ament_python 등 |
ROS 2 Humble에서 colcon build를 실행하면 colcon은 각 패키지의 package.xml을 읽고 패키지 의존 관계를 판단합니다.
즉, package.xml이 틀리면 패키지 빌드나 실행에서 바로 문제가 납니다.
2. package.xml 기본 구조
기본 구조는 다음과 같습니다.
<?xml version="1.0"?>
<package format="3">
<name>패키지_이름</name>
<version>0.0.0</version>
<description>패키지 설명</description>
<maintainer email="이메일">관리자 이름</maintainer>
<license>라이선스</license>
의존성 태그들...
<export>
<build_type>빌드_타입</build_type>
</export>
</package>
ROS 2 Humble에서는 보통 다음 형식을 사용합니다.
<package format="3">
format="3"은 package.xml 문법 버전입니다. 실습에서는 그냥 ROS 2 Humble에서 일반적으로 사용하는 package.xml 형식이라고 이해하면 됩니다.
format="3"은 package.xml 문법 버전입니다.
쉽게 말하면 다음과 같습니다.
format="3" = package.xml을 3번 형식 규칙으로 작성했다는 뜻
ROS에는 과거부터 여러 manifest 형식이 있었습니다.
형식 주 사용 시기/용도
| format 1 | 오래된 ROS 1 방식 |
| format 2 | 개선된 ROS 1/ROS 2 호환 방식 |
| format 3 | ROS 2에서 일반적으로 사용하는 방 |
3. C++ 패키지: my_cpp_package
my_cpp_package는 C++ 패키지입니다.
따라서 빌드 타입은 다음과 같습니다.
<build_type>ament_cmake</build_type>
C++ 패키지에서는 보통 rclcpp를 사용합니다.
예를 들어 C++ 코드에서 다음 헤더를 사용한다면,
#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/string.hpp"
package.xml에는 최소한 다음 의존성이 필요합니다.
<depend>rclcpp</depend>
<depend>std_msgs</depend>
my_cpp_package/package.xml 예제
<?xml version="1.0"?>
<package format="3">
<name>my_cpp_package</name>
<version>0.0.0</version>
<description>ROS 2 Humble C++ practice package</description>
<maintainer email="dragon@example.com">dragon</maintainer>
<license>Apache-2.0</license>
<buildtool_depend>ament_cmake</buildtool_depend>
<depend>rclcpp</depend>
<depend>std_msgs</depend>
<test_depend>ament_lint_auto</test_depend>
<test_depend>ament_lint_common</test_depend>
<export>
<build_type>ament_cmake</build_type>
</export>
</package>
C++ 패키지에서 중요한 부분
1) 패키지 이름
<name>my_cpp_package</name>
이 이름은 패키지 폴더 이름과 같아야 합니다.
~/ros2_study/src/my_cpp_package
즉, 폴더 이름과 package.xml의 <name> 값이 다르면 안 됩니다.
2) 빌드 도구 의존성
<buildtool_depend>ament_cmake</buildtool_depend>
C++ 패키지는 CMake 기반으로 빌드합니다.
그래서 ament_cmake가 필요합니다.
3) C++ 클라이언트 라이브러리 의존성
<depend>rclcpp</depend>
rclcpp는 ROS 2 C++ 노드를 만들 때 사용하는 기본 라이브러리입니다.
C++ 노드에서 다음 코드를 사용하면 반드시 필요합니다.
#include "rclcpp/rclcpp.hpp"
4) 메시지 패키지 의존성
<depend>std_msgs</depend>
std_msgs/msg/String 같은 기본 메시지를 사용할 때 필요합니다.
예를 들어 C++ 코드에서 다음을 사용하면,
#include "std_msgs/msg/string.hpp"
package.xml에 다음이 있어야 합니다.
<depend>std_msgs</depend>
5) 빌드 타입
<export>
<build_type>ament_cmake</build_type>
</export>
이 부분이 빠지면 ROS 2가 이 패키지를 어떤 방식으로 빌드해야 하는지 알 수 없습니다.
C++ 패키지는 반드시 다음 구조를 사용합니다.
<export>
<build_type>ament_cmake</build_type>
</export>
이건 실무에서도 자주 터지는 포인트입니다.
빌드가 이상하게 안 되면 package.xml의 <build_type>부터 확인하는 게 맞습니다.
4. Python 패키지: my_first_package
my_first_package는 Python 패키지입니다.
따라서 빌드 타입은 다음과 같습니다.
<build_type>ament_python</build_type>
Python 패키지에서는 보통 rclpy를 사용합니다.
예를 들어 Python 코드에서 다음을 사용한다면,
import rclpy
from std_msgs.msg import String
package.xml에는 다음 의존성이 필요합니다.
<exec_depend>rclpy</exec_depend>
<exec_depend>std_msgs</exec_depend>
my_first_package/package.xml 예제
<?xml version="1.0"?>
<package format="3">
<name>my_first_package</name>
<version>0.0.0</version>
<description>ROS 2 Humble Python practice package</description>
<maintainer email="dragon@example.com">dragon</maintainer>
<license>Apache-2.0</license>
<exec_depend>rclpy</exec_depend>
<exec_depend>std_msgs</exec_depend>
<test_depend>ament_copyright</test_depend>
<test_depend>ament_flake8</test_depend>
<test_depend>ament_pep257</test_depend>
<test_depend>python3-pytest</test_depend>
<export>
<build_type>ament_python</build_type>
</export>
</package>
Python 패키지에서 중요한 부분
1) 패키지 이름
<name>my_first_package</name>
이 이름은 다음 항목들과 맞아야 합니다.
~/ros2_study/src/my_first_package
그리고 setup.py 안의 package_name도 같아야 합니다.
package_name = 'my_first_package'
Python 패키지에서는 이름이 하나라도 어긋나면 ros2 run에서 실행 파일을 못 찾는 경우가 많습니다.
2) rclpy 실행 의존성
<exec_depend>rclpy</exec_depend>
rclpy는 ROS 2 Python 노드를 만들 때 사용하는 기본 라이브러리입니다.
Python 코드에서 다음을 사용하면 필요합니다.
import rclpy
Python 노드에서:
import rclpy
를 해도, 현재 환경에 이미 rclpy가 설치되어 있으면 실행됩니다.
예를 들어 Ubuntu에서 ROS 2를 설치하면 보통 다음 패키지가 이미 깔려 있습니다.
ros-${ROS_DISTRO}-rclpy
그래서 package.xml에 없어도 Python 인터프리터가 rclpy를 찾을 수 있습니다.
Python 코드에서 rclpy를 직접 사용한다면:
<exec_depend>rclpy</exec_depend>
를 넣는 게 맞습니다.
3) 메시지 패키지 실행 의존성
<exec_depend>std_msgs</exec_depend>
Python 코드에서 다음을 사용하면 필요합니다.
from std_msgs.msg import String
Python 패키지에서는 보통 실행 시점 의존성으로 작성합니다.
<exec_depend>std_msgs</exec_depend>
<exec_depend>rclpy</exec_depend>
<exec_depend>geometry_msgs</exec_depend>
<exec_depend>my_first_package_msgs</exec_depend>
<exec_depend>turtlesim</exec_depend>
4) 빌드 타입
<export>
<build_type>ament_python</build_type>
</export>
Python 패키지는 반드시 ament_python으로 지정해야 합니다.
C++ 패키지처럼 ament_cmake를 쓰면 안 됩니다.
5. C++ 패키지와 Python 패키지의 차이
핵심 차이는 빌드 타입입니다.
| 패키지 이름 | my_cpp_package | my_first_package |
| 빌드 타입 | ament_cmake | ament_python |
| 주요 파일 | CMakeLists.txt | setup.py, setup.cfg |
| ROS 클라이언트 라이브러리 | rclcpp | rclpy |
| 대표 의존성 태그 | <depend> | <exec_depend> |
| export build_type | ament_cmake | ament_python |
6. 인터페이스 패키지와 연결되는 경우
현재 실습환경에는 인터페이스 패키지도 있습니다.
my_first_package_msgs
이 패키지는 .msg, .srv, .action 파일을 정의하는 패키지입니다.
C++ 패키지나 Python 패키지에서 이 인터페이스를 사용한다면 각각의 package.xml에 의존성을 추가해야 합니다.
C++ 패키지에서 인터페이스 사용
my_cpp_packagesms의 C++ 코드에서 다음처럼 사용자 정의 메시지를 사용한다고 가정합니다.
#include "my_first_package_msgs/msg/my_message.hpp"
그러면 my_cpp_packagesms/package.xml에 다음을 추가합니다.
<depend>my_first_package_msgs</depend>
예:
<depend>rclcpp</depend>
<depend>std_msgs</depend>
<depend>my_first_package_msgs</depend>
Python 패키지에서 인터페이스 사용
my_first_package의 Python 코드에서 다음처럼 사용자 정의 메시지를 사용한다고 가정합니다.
from my_first_package_msgs.msg import MyMessage
그러면 my_first_package/package.xml에 다음을 추가합니다.
<exec_depend>my_first_package_msgs</exec_depend>
예:
<exec_depend>rclpy</exec_depend>
<exec_depend>std_msgs</exec_depend>
<exec_depend>my_first_package_msgs</exec_depend>
7. 의존성 태그 정리
package.xml에서 자주 사용하는 의존성 태그는 다음과 같습니다.
| <buildtool_depend> | 빌드 도구 의존성 |
| <build_depend> | 빌드할 때 필요한 의존성 |
| <exec_depend> | 실행할 때 필요한 의존성 |
| <depend> | 빌드와 실행 모두 필요한 의존성 |
| <test_depend> | 테스트할 때 필요한 의존성 |
실습에서는 이렇게 기억하면 됩니다.
C++ 패키지:
<buildtool_depend>ament_cmake</buildtool_depend>
<depend>rclcpp</depend>
<depend>std_msgs</depend>
Python 패키지:
<exec_depend>rclpy</exec_depend>
<exec_depend>std_msgs</exec_depend>
인터페이스 패키지를 사용할 때:
<depend>my_first_package_msgs</depend>
또는 Python에서는:
<exec_depend>my_first_package_msgs</exec_depend>
8. 실습환경에서 빌드 확인
workspace는 ros2_study입니다.
cd ~/ros2_study
colcon build
특정 패키지만 빌드하려면 다음처럼 합니다.
colcon build --packages-select my_cpp_packagesms
colcon build --packages-select my_first_package
빌드 후에는 반드시 환경 설정을 합니다.
source install/setup.bash
패키지가 인식되는지 확인합니다.
ros2 pkg list | grep my_cpp_packagesms
ros2 pkg list | grep my_first_package
ros2 pkg list | grep my_first_package_msgs

10. 최종 정리
ROS 2 Humble에서 package.xml은 패키지의 기본 정보를 담는 핵심 파일입니다.
C++ 패키지 my_cpp_package는 다음이 핵심입니다.
<buildtool_depend>ament_cmake</buildtool_depend>
<depend>rclcpp</depend>
<export>
<build_type>ament_cmake</build_type>
</export>
Python 패키지 my_first_package는 다음이 핵심입니다.
<exec_depend>rclpy</exec_depend>
<export>
<build_type>ament_python</build_type>
</export>
인터페이스 패키지 my_first_package_msgs를 C++ 또는 Python에서 사용한다면 각 패키지의 package.xml에 의존성을 추가해야 합니다.
C++ 패키지:
<depend>my_first_package_msgs</depend>
Python 패키지:
<exec_depend>my_first_package_msgs</exec_depend>
'강좌 > ROS2' 카테고리의 다른 글
| ROS 2 에서 CMakeLists.txt 이해하기 (0) | 2026.05.24 |
|---|---|
| ROS 2 Python 패키지의 setup.py 이해하기 (0) | 2026.05.24 |
| C++ ROS 2 패키지 생성하기 (0) | 2026.05.24 |
| ROS 2 개발자를 위한 C/C++ 기초강의 #2 (0) | 2026.05.24 |
| VS Code 원격 개발 환경 (0) | 2026.05.24 |