# rosdep와 종속성 관리

#### rosdep 개요

ROS2 패키지를 개발하면서 가장 번거로운 일 중 하나는 패키지가 필요로 하는 라이브러리나 툴을 일일이 설치하고 버전을 맞추는 과정이다. 이를 자동화하고 간단히 처리할 수 있도록 도와주는 도구가 바로 `rosdep`이다. ROS1 시절부터 사용되어 왔으며, ROS2에서도 동일하게 활용할 수 있다. `rosdep`은 시스템 의존성(System Dependency) 관리 도구로서, ROS 개발 환경에서 패키지를 빌드할 때 필요한 의존성을 자동으로 설치해 준다. 예를 들어, 특정 오픈소스 라이브러리를 사용해야 하는 노드나 패키지가 있을 때, 패키지 메타 정보(예: `package.xml`)에 의존성을 명시하고 `rosdep`을 통해 설치함으로써 빌드 환경을 간단히 세팅할 수 있다.

#### rosdep 설치와 설정

ROS2 Humble 버전이 설치된 환경에서 기본적으로 `rosdep`이 제공되지만, 만약 rosdep이 없는 환경이라면 우선 아래와 같이 설치해야 한다. Ubuntu를 기준으로 예시를 들면 다음과 같다.

```bash
sudo apt update
sudo apt install python3-rosdep
```

그다음 rosdep 데이터베이스를 업데이트해 준다.

```bash
sudo rosdep init
rosdep update
```

`rosdep init` 명령은 `/etc/ros/rosdep/` 경로에 데이터베이스 관련 설정 파일을 생성하고, `rosdep update` 명령은 각종 ROS 배포판에 맞는 의존성 정보를 최신 상태로 갱신해 준다.

#### package.xml과 rosdep

ROS2 패키지는 `package.xml` 파일을 통해 의존성과 관련된 메타 정보를 제공한다. 예를 들어 아래처럼 `<depend>` 또는 `<build_depend>` 등을 활용하여 ROS 환경에서의 의존성을 명시할 수 있다.

```xml
<package format="3">
  <name>my_ros2_pkg</name>
  <version>0.0.1</version>
  <description>Example package</description>
  <maintainer email="your_email@domain.com">Your Name</maintainer>
  <license>Apache-2.0</license>

  <build_depend>rclcpp</build_depend>
  <build_depend>sensor_msgs</build_depend>
  <exec_depend>sensor_msgs</exec_depend>

  <depend>opencv</depend>
</package>
```

위 예시에서 ROS2 빌드 및 실행에 필요한 패키지로 `rclcpp`, `sensor_msgs`, `opencv` 등을 명시하였다. 여기서 `rclcpp`나 `sensor_msgs`처럼 ROS 패키지로 제공되는 것은 `ament` 빌드 시스템에서 자동으로 처리 가능하지만, OpenCV 등과 같은 시스템 라이브러리는 OS에 따라 설치 방법이 다르다.

이를 시스템 독립적으로 설치하기 위해 `rosdep`을 사용하면, 예를 들어 Ubuntu에서는 apt를 통해, Fedora에서는 dnf를 통해 필요한 라이브러리를 자동으로 설치하게 된다.

#### rosdep에서 정의되는 키(키워드)

`rosdep`은 OS별, 배포판별로 다른 패키지 이름을 매핑해 주는 개념을 사용한다. 이때 사용되는 주요 키(Key)는 다음과 같다.

* **package name**: 예를 들어 `opencv`처럼, ROS 패키지 안에서 사용하는 일반 명칭
* **OS definition**: Ubuntu, Debian, Fedora, macOS 등 OS별 실제 패키지 이름을 `yaml` 파일 등에 매핑

ROS2에서는 `rosdistro` 리포지토리에서 이 매핑 정보를 관리하며, 로컬 시스템에 설치된 rosdep이 이를 불러와 해석하고, 알맞은 설치 명령을 실행하게 된다.

#### rosdep 예시: OpenCV

OpenCV 라이브러리에 대한 rosdep 의존성 키는 ROS2 공식 설정 파일에서 다음과 같이 정의되어 있다(실제 rosdistro의 yaml 파일 참조).

```yaml
opencv:
  ubuntu: [libopencv-dev]
  debian: [libopencv-dev]
  fedora: [opencv-devel]
  ...
```

이 정의를 통해 사용자의 OS가 Ubuntu라면 `sudo apt install libopencv-dev`를, Fedora라면 `sudo dnf install opencv-devel` 명령이 실행된다.

#### rosdep으로 의존성 자동 설치

개발 중인 패키지에 `package.xml`에서 의존성을 올바르게 명시했다면, 아래와 같은 명령어로 해당 패키지가 필요로 하는 시스템 의존성을 자동으로 설치할 수 있다.

```bash
rosdep install --from-paths src --ignore-src -y
```

* `--from-paths`: 설치해야 할 ROS 패키지들이 있는 소스 디렉터리를 지정한다.
* `--ignore-src`: 이미 패키지 내부에 있는 ROS 의존성은 무시하고, 시스템 레벨 의존성만 설치한다.
* `-y`: 사용자의 입력 없이 자동으로 진행한다.

이 명령을 실행하면, rosdep은 `src` 디렉터리 내 모든 ROS 패키지들의 의존성을 확인하고, 아직 설치되어 있지 않은 라이브러리나 툴을 OS 기반 패키지 관리자를 통해 자동으로 설치한다.

#### rosdep 개요

ROS2 패키지를 개발하면서 가장 번거로운 일 중 하나는 패키지가 필요로 하는 라이브러리나 툴을 일일이 설치하고 버전을 맞추는 과정이다. 이를 자동화하고 간단히 처리할 수 있도록 도와주는 도구가 바로 `rosdep`이다. ROS1 시절부터 사용되어 왔으며, ROS2에서도 동일하게 활용할 수 있다. `rosdep`은 시스템 의존성(System Dependency) 관리 도구로서, ROS 개발 환경에서 패키지를 빌드할 때 필요한 의존성을 자동으로 설치해 준다. 예를 들어, 특정 오픈소스 라이브러리를 사용해야 하는 노드나 패키지가 있을 때, 패키지 메타 정보(예: `package.xml`)에 의존성을 명시하고 `rosdep`을 통해 설치함으로써 빌드 환경을 간단히 세팅할 수 있다.

#### rosdep 설치와 설정

ROS2 Humble 버전이 설치된 환경에서 기본적으로 `rosdep`이 제공되지만, 만약 rosdep이 없는 환경이라면 우선 아래와 같이 설치해야 한다. Ubuntu를 기준으로 예시를 들면 다음과 같다.

```bash
sudo apt update
sudo apt install python3-rosdep
```

그다음 rosdep 데이터베이스를 업데이트해 준다.

```bash
sudo rosdep init
rosdep update
```

`rosdep init` 명령은 `/etc/ros/rosdep/` 경로에 데이터베이스 관련 설정 파일을 생성하고, `rosdep update` 명령은 각종 ROS 배포판에 맞는 의존성 정보를 최신 상태로 갱신해 준다.

#### package.xml과 rosdep

ROS2 패키지는 `package.xml` 파일을 통해 의존성과 관련된 메타 정보를 제공한다. 예를 들어 아래처럼 `<depend>` 또는 `<build_depend>` 등을 활용하여 ROS 환경에서의 의존성을 명시할 수 있다.

```xml
<package format="3">
  <name>my_ros2_pkg</name>
  <version>0.0.1</version>
  <description>Example package</description>
  <maintainer email="your_email@domain.com">Your Name</maintainer>
  <license>Apache-2.0</license>

  <build_depend>rclcpp</build_depend>
  <build_depend>sensor_msgs</build_depend>
  <exec_depend>sensor_msgs</exec_depend>

  <depend>opencv</depend>
</package>
```

위 예시에서 ROS2 빌드 및 실행에 필요한 패키지로 `rclcpp`, `sensor_msgs`, `opencv` 등을 명시하였다. 여기서 `rclcpp`나 `sensor_msgs`처럼 ROS 패키지로 제공되는 것은 `ament` 빌드 시스템에서 자동으로 처리 가능하지만, OpenCV 등과 같은 시스템 라이브러리는 OS에 따라 설치 방법이 다르다.

이를 시스템 독립적으로 설치하기 위해 `rosdep`을 사용하면, 예를 들어 Ubuntu에서는 apt를 통해, Fedora에서는 dnf를 통해 필요한 라이브러리를 자동으로 설치하게 된다.

#### rosdep에서 정의되는 키(키워드)

`rosdep`은 OS별, 배포판별로 다른 패키지 이름을 매핑해 주는 개념을 사용한다. 이때 사용되는 주요 키(Key)는 다음과 같다.

* **package name**: 예를 들어 `opencv`처럼, ROS 패키지 안에서 사용하는 일반 명칭
* **OS definition**: Ubuntu, Debian, Fedora, macOS 등 OS별 실제 패키지 이름을 `yaml` 파일 등에 매핑

ROS2에서는 `rosdistro` 리포지토리에서 이 매핑 정보를 관리하며, 로컬 시스템에 설치된 rosdep이 이를 불러와 해석하고, 알맞은 설치 명령을 실행하게 된다.

#### rosdep 예시: OpenCV

OpenCV 라이브러리에 대한 rosdep 의존성 키는 ROS2 공식 설정 파일에서 다음과 같이 정의되어 있다(실제 rosdistro의 yaml 파일 참조).

```yaml
opencv:
  ubuntu: [libopencv-dev]
  debian: [libopencv-dev]
  fedora: [opencv-devel]
  ...
```

이 정의를 통해 사용자의 OS가 Ubuntu라면 `sudo apt install libopencv-dev`를, Fedora라면 `sudo dnf install opencv-devel` 명령이 실행된다.

#### rosdep으로 의존성 자동 설치

개발 중인 패키지에 `package.xml`에서 의존성을 올바르게 명시했다면, 아래와 같은 명령어로 해당 패키지가 필요로 하는 시스템 의존성을 자동으로 설치할 수 있다.

```bash
rosdep install --from-paths src --ignore-src -y
```

* `--from-paths`: 설치해야 할 ROS 패키지들이 있는 소스 디렉터리를 지정한다.
* `--ignore-src`: 이미 패키지 내부에 있는 ROS 의존성은 무시하고, 시스템 레벨 의존성만 설치한다.
* `-y`: 사용자의 입력 없이 자동으로 진행한다.

이 명령을 실행하면, rosdep은 `src` 디렉터리 내 모든 ROS 패키지들의 의존성을 확인하고, 아직 설치되어 있지 않은 라이브러리나 툴을 OS 기반 패키지 관리자를 통해 자동으로 설치한다.

#### 로컬에 사용자 정의 rosdep key 추가하기

ROS2를 사용하다 보면, 공식 `rosdistro`에서 제공하지 않는 라이브러리나 툴을 추가로 사용해야 하는 경우가 있다. 예를 들어, 특정 오픈소스를 사용하려 하는데 그것이 아직 rosdep 키로 등록되어 있지 않다면, 로컬에서 직접 rosdep 키를 정의하고 활용할 수 있다.

**rosdep 정의 파일 작성**: 로컬에서 사용할 rosdep 정의(예: `my_rosdep_keys.yaml`)를 생성하고, 아래와 같이 OS별로 실제 설치되어야 할 패키지를 매핑한다.

```yaml
# my_rosdep_keys.yaml
custom_lib:
  ubuntu: [libcustom-dev]
  debian: [libcustom-dev]
  fedora: [custom-devel]
  macos: [custom-lib]
  # ...
```

위 예시에서는 `custom_lib`라는 rosdep 키에 대해 Ubuntu/Fedora/macOS 등 다양한 OS 환경에서 설치해야 할 실제 패키지명을 지정하였다.

**로컬 정의 파일 등록**: rosdep은 기본적으로 `/etc/ros/rosdep/` 하위 또는 `$ROS_ETC_DIR/rosdep/` 하위의 yaml 파일을 참고한다. 하지만 시스템 전역이 아닌 사용자의 로컬 환경에서만 사용하는 정의를 등록하려면, 아래처럼 환경 변수를 설정하여 rosdep이 로컬 yaml 파일을 인식하도록 한다.

```bash
export ROSDEP_YAML_PATHS="$HOME/my_rosdep_keys.yaml"
rosdep update
```

이렇게 하면 `rosdep update` 시 로컬 yaml 파일에 기재된 `custom_lib` 정보를 읽어들여, 해당 키가 rosdep에서 유효하게 작동한다.

**package.xml에 적용**: 이제 내 패키지에서 해당 라이브러리를 사용해야 한다면, `package.xml`에 다음처럼 명시해 줄 수 있다.

```xml
<package format="3">
  ...
  <depend>custom_lib</depend>
  ...
</package>
```

이후 `rosdep install --from-paths src --ignore-src -y`를 실행하면, 등록한 rosdep 키에 따라 시스템 환경에 맞게 라이브러리가 설치된다.

#### rosdep check

`rosdep`에는 의존성 설치뿐 아니라, 현재 환경이 패키지 의존성을 만족하는지 확인하는 명령어도 있다.

```bash
rosdep check <package_name>
```

이 명령을 통해 특정 패키지가 필요로 하는 의존성이 모두 제대로 설치되어 있는지 점검할 수 있다. 만약 누락된 의존성이 있으면, 어떤 패키지를 설치해야 하는지 안내를 받을 수 있다.

#### 도커(Docker) 환경에서의 rosdep

도커 컨테이너 안에서 ROS2를 설치하여 개발·실행하는 경우도 많은데, 이때 `rosdep`을 활용하면 컨테이너를 새로 빌드할 때마다 자동으로 의존성을 설치할 수 있어 편리한다. 예를 들어, Dockerfile에서 아래와 같이 명령을 작성할 수 있다.

```dockerfile
FROM ubuntu:22.04

# ROS2 Humble 설치, 기본 설정 등...
RUN apt-get update && apt-get install -y ros-humble-desktop python3-rosdep

# rosdep 초기화
RUN rosdep init && rosdep update

# 패키지 복사
COPY src /home/ws/src

# rosdep 설치
WORKDIR /home/ws
RUN rosdep install --from-paths src --ignore-src -y
```

이렇게 Dockerfile을 구성하면, 이미지 빌드시 자동으로 시스템 의존성이 설치되므로, 컨테이너를 실행하는 즉시 ROS 패키지 빌드가 가능한 환경을 얻을 수 있다.

#### rosdep 사용 시 주의할 점

* **OS 및 ROS2 배포판에 맞는 버전 확인** 같은 라이브러리라도 Ubuntu 20.04, 22.04 등 OS 버전에 따라 패키지 명이나 버전이 다를 수 있으므로, `rosdep update`로 최신 매핑 정보를 유지해야 한다.
* **중복 설치 문제** 이미 수동 설치한 라이브러리와 rosdep이 설치하는 라이브러리가 충돌할 수도 있다. 이 경우 패키지 매니저(apt, dnf 등)에서 버전 충돌 문제를 확인하고, 필요하면 수동으로 조정해야 한다.
* **ROS 패키지명 vs 시스템 패키지명** ROS2 내부 패키지 의존성과 시스템 라이브러리 의존성을 혼동하지 않도록, `package.xml`에서 `<build_depend>`와 `<depend>` 등을 구분해 사용하는 것이 좋다.

#### 오프라인 환경에서의 rosdep 활용

일부 네트워크 접근이 제한된 환경(예: 방화벽으로 외부 접속이 차단된 기업 내부망, 무선 연결이 어려운 로봇 현장 환경 등)에서는 rosdep이 OS별 패키지 저장소에 연결할 수 없거나 rosdistro 정보를 업데이트할 수 없는 경우가 있다. 이때 오프라인 환경에서도 rosdep을 활용하기 위한 일반적인 접근 방법은 다음과 같다.

1. 온라인 환경에서 미리 rosdep 데이터 다운로드
   * 온라인이 가능한 PC(로컬 또는 서버)에서 먼저 `rosdep update`를 실행해 최신 데이터를 가져온다.
   * `$HOME/.ros/rosdep/sources.cache`와 `/etc/ros/rosdep/sources.list.d/*`, `/etc/ros/rosdep/rosdep.yaml` 등의 파일을 백업해 둔다.
2. 오프라인 환경에 파일 복사
   * 위에서 백업한 rosdep 관련 파일들을 오프라인 환경으로 복사한다.
   * 동일한 디렉터리 구조로 맞추고, `rosdep update`를 생략한다(이미 최신 데이터가 준비되어 있다는 전제).
3. 오프라인 저장소(미러) 구성
   * 배포판별 OS 패키지 저장소(예: apt 미러, dnf 미러 등)를 사내망 또는 로컬 서버에 구성하고, `/etc/apt/sources.list` 등에 해당 미러 주소를 설정한다.
   * 이렇게 하면, rosdep이 OS 패키지를 설치할 때 외부로 나가지 않고 내부 미러에서 설치를 시도한다.

#### rosdep와 함께 사용하는 환경 변수

rosdep을 사용할 때, 특정 라이브러리나 패키지 버전이 유독 필요한 경우 환경 변수 세팅을 통해 요구하는 버전을 지정할 수도 있다. 다만 일반적인 rosdep 키 정의 파일은 ‘패키지 명칭’을 기준으로 매핑하기 때문에, 세부 버전까지 제어가 필요한 경우에는 다음과 같은 별도 전략이 필요하다.

* **CMake 옵션 활용**: package.xml 내부에서 rosdep으로 설치된 라이브러리 버전을 추적하기보다는, CMakeLists.txt에서 `$ENV{SOME_ENV_VAR}` 등을 활용해 빌드 시점에 버전 검사 로직을 둔다.
* **로컬 키 재정의**: 특정 버전의 패키지만 설치하도록 로컬 rosdep 키를 오버라이드하거나, deb 패키지 등으로 별도 제공받는 리포지토리를 사용할 수 있다. 예를 들어, `libopencv-dev` 대신 `libopencv4.5-dev` 등 명확히 버전이 적힌 패키지를 지정한다.

#### Cross Compile 환경에서 rosdep

로봇 개발 과정에서 ARM 보드나 임베디드 환경에서 ROS2를 구동하기 위해 크로스 컴파일(Cross Compile)을 수행할 때, 종속성 관리가 더욱 복잡해질 수 있다. rosdep은 호스트 시스템에 맞춘 패키지 관리자를 사용하므로, 크로스 컴파일 대상 시스템(타겟 아키텍처)와 호스트 시스템의 패키지 설치 방식이 다를 수 있다.

이를 해결하기 위해 다음과 같은 방식을 시도한다.

1. chroot 기반 빌드 환경 구성
   * QEMU 등을 이용해 타겟 아키텍처용 루트 파일 시스템(chroot 환경)을 구성하고, 해당 환경 안에서 apt, dnf 등을 실행할 수 있도록 한다.
   * 그다음 `rosdep`을 chroot 환경 내에서 실행하면, 실제 타겟 OS 패키지를 설치할 수 있다.
2. sysroot 디렉터리 구성
   * 타겟 아키텍처용 패키지(.deb 또는 .rpm)를 호스트에서 다운로드한 뒤, sysroot 디렉터리에 설치(압축 해제)하여 의존 라이브러리를 준비한다.
   * 빌드 시 CMake나 ament의 `--sysroot` 옵션 등을 활용해, 해당 디렉터리를 참조하도록 설정한다.
3. yocto 빌드 등 특정 툴체인 활용
   * rosdep보다는 Yocto 프로젝트 등 임베디드 전용 빌드 시스템에서 ROS2 패키지를 레시피로 관리하기도 한다.
   * 이 경우 각종 의존성 라이브러리를 Yocto에서 통합 관리하므로, rosdep 키 대신 Yocto 레시피 파일을 통해 설정한다.

#### rosdep 데이터 캐싱과 커스텀 URL

기본적으로 rosdep은 `https://raw.githubusercontent.com/ros/rosdistro`에서 OS별 키 매핑 정보를 가져온다. 보안 정책 등으로 GitHub 접근이 어려울 경우, 사내 Git 서버나 웹 서버 등에 rosdistro를 미러링한 뒤, 아래처럼 환경 변수로 커스텀 URL을 지정할 수 있다.

```bash
export ROSDISTRO_INDEX_URL="http://my.internal.server/rosdistro/index-v4.yaml"
rosdep update
```

이렇게 하면 rosdep이 공식 GitHub URL이 아닌 내부 서버에서 데이터를 받아온다.

#### rosdep 으로 패키지 설치 후 확인

rosdep이 설치한 라이브러리가 제대로 동작하는지 확인하려면 아래와 같은 과정을 거친다.

OS 패키지 관리자 확인:

```bash
dpkg -l | grep libcustom-dev  # Ubuntu/Debian 계열
rpm -qa | grep custom-devel   # Fedora/RedHat 계열
```

등으로 실제 설치된 버전 및 파일을 확인한다.

**CMake 또는 ament 빌드 시 정상 링크 여부 확인**: CMakeLists.txt에서 `find_package(custom_lib REQUIRED)` 등을 호출해 링크 에러가 없는지 확인한다.

**런타임 테스트**: 빌드된 노드를 실행하여, 의존 라이브러리로부터의 함수 호출이나 객체 생성이 정상 수행되는지 테스트한다.

#### rosdep와 CI(Continuous Integration)

CI/CD 파이프라인에서 ROS2 패키지 빌드 및 테스트가 자동화되려면, 빌드 이전 단계에서 시스템 의존성을 설치해 주어야 한다. 이를 간단히 처리하기 위해 `rosdep`이 유용하다.

* GitHub Actions 예시

  ```yaml
  name: Build and Test

  on: [push, pull_request]

  jobs:
    build_and_test:
      runs-on: ubuntu-latest
      steps:
      - name: Check out repo
        uses: actions/checkout@v2

      - name: Set up ROS2
        run: |
          sudo apt update
          sudo apt install -y ros-humble-desktop python3-rosdep
          sudo rosdep init
          rosdep update

      - name: Install dependencies
        run: |
          rosdep install --from-paths src --ignore-src -y

      - name: Build
        run: |
          colcon build

      - name: Run Tests
        run: |
          colcon test
          colcon test-result --verbose
  ```

  위 예시에선 GitHub Actions 환경에서 rosdep을 이용해 의존성을 설치한 뒤 빌드를 진행한다.
