ROS2 시뮬레이션 가상 환경 혼자 구축하기 | Docker + Gazebo 완벽 설정
이 글의 핵심
실물 로봇이나 GPU 워크스테이션 없이도 ROS2 + Gazebo 시뮬레이션 환경을 Docker 컨테이너로 구축해 혼자 연습할 수 있습니다. 이 글은 운영체제별(Linux/macOS/Windows WSL2) GUI 포워딩 설정과 docker-compose 구성, 그리고 실제로 자주 막히는 X11/그래픽 문제를 해결하는 방법을 정리합니다.
들어가며
ROS2와 Gazebo를 처음 설치해보려는 사람이 가장 먼저 마주치는 건 알고리즘이 아니라 설치 지옥입니다. 특정 Ubuntu 버전에 맞는 ROS2 배포판을 골라야 하고, 시스템에 이미 깔려 있는 다른 패키지와 충돌이 나기도 하고, macOS나 Windows를 쓰고 있다면 애초에 네이티브 설치 자체가 공식 지원 대상이 아닌 경우도 많습니다. 그리고 이 모든 걸 어렵게 설치한 뒤에 문제가 생기면, “처음부터 다시 깨끗하게 설치”하는 것 외에는 되돌릴 방법이 마땅치 않습니다.
이 글은 이 문제를 Docker로 우회하는 방법을 정리합니다. 컨테이너 안에 ROS2와 Gazebo를 격리해두면, 호스트 운영체제가 무엇이든 상관없이 동일한 환경을 재현할 수 있고, 문제가 생기면 컨테이너만 지우고 다시 만들면 됩니다. 자율주행 로봇을 독학하는 전체적인 학습 순서는 자율주행 로봇 개발 독학 로드맵에서 다뤘으므로, 이 글은 그중 “3단계: 시뮬레이터 환경 구축” 부분을 실제로 손에 잡히게 실습하는 데 집중합니다.
1. 기본 구성: ROS2 + Gazebo Docker 이미지
가장 기본이 되는 Dockerfile은 다음과 같습니다.
FROM osrf/ros:humble-desktop-full
RUN apt-get update && apt-get install -y \
ros-humble-turtlebot3* \
ros-humble-turtlebot3-simulations \
&& rm -rf /var/lib/apt/lists/*
ENV TURTLEBOT3_MODEL=burger
WORKDIR /root/ros2_ws
osrf/ros:humble-desktop-full 이미지는 OSRF(Open Source Robotics Foundation)에서 공식으로 배포하는 이미지로, ROS2와 Gazebo가 이미 함께 설치되어 있어 처음부터 직접 조합할 필요가 없습니다. TurtleBot3 시뮬레이션 패키지를 추가하면 별도의 로봇 모델(URDF)을 만들지 않고도 바로 실습을 시작할 수 있습니다.
2. Linux 호스트: X11 포워딩으로 GUI 띄우기
호스트가 Linux(Ubuntu 등)라면 X11을 그대로 포워딩하는 방식이 가장 간단하고 지연도 적습니다.
# 호스트에서 한 번 실행 (컨테이너의 X11 접근 허용)
xhost +local:docker
docker run -it --rm \
--env="DISPLAY=$DISPLAY" \
--env="QT_X11_NO_MITSHM=1" \
--volume="/tmp/.X11-unix:/tmp/.X11-unix:rw" \
--volume="$(pwd)/ros2_ws:/root/ros2_ws" \
--name ros2-sim \
my-ros2-gazebo bash
이 설정에서 가장 자주 빠뜨리는 부분이 xhost +local:docker입니다. 이 명령 없이 컨테이너를 실행하면 Gazebo 프로세스는 정상적으로 뜨는데 창만 나타나지 않는, 원인을 짐작하기 어려운 증상이 나타납니다. 반대로 매번 xhost +(모든 접근 허용)를 쓰는 것은 보안상 권장하지 않습니다 — +local:docker처럼 로컬 Docker 소켓으로 범위를 좁혀두는 것이 안전합니다.
3. macOS 호스트: XQuartz 대신 noVNC를 권하는 이유
macOS에서는 X11 서버가 기본 내장되어 있지 않아 XQuartz를 별도로 설치해야 하는데, 실제로 써보면 렌더링 성능 문제나 권한 설정 이슈로 삽질하는 시간이 꽤 깁니다. 특히 Apple Silicon(M 시리즈)에서는 x86_64 전용 이미지를 돌릴 경우 Rosetta 에뮬레이션 오버헤드까지 겹쳐 체감 성능이 크게 떨어집니다.
대안으로 noVNC 기반 컨테이너를 권합니다. 컨테이너 안에 가상 디스플레이(Xvfb)와 VNC 서버를 함께 띄우고, 호스트에서는 웹 브라우저로 접속해 화면을 보는 방식입니다.
FROM osrf/ros:humble-desktop-full
RUN apt-get update && apt-get install -y \
xvfb x11vnc novnc websockify \
ros-humble-turtlebot3-simulations \
&& rm -rf /var/lib/apt/lists/*
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
EXPOSE 6080
ENTRYPOINT ["/entrypoint.sh"]
#!/bin/bash
# entrypoint.sh
Xvfb :1 -screen 0 1280x800x24 &
export DISPLAY=:1
x11vnc -display :1 -forever -nopw &
websockify --web=/usr/share/novnc 6080 localhost:5900 &
exec "$@"
이렇게 구성하면 브라우저에서 http://localhost:6080/vnc.html로 접속해 Gazebo 화면을 그대로 볼 수 있습니다. 아키텍처(ARM64/x86_64)와 무관하게 동작 방식이 동일하다는 점도 장점입니다 — 호스트가 무엇이든 브라우저만 있으면 됩니다. 다만 VNC 특성상 X11 직접 포워딩보다는 약간의 렌더링 지연이 있으므로, 정밀한 조작이 필요한 실습보다는 관찰 위주의 시뮬레이션에 더 적합합니다.
4. Windows 호스트: WSL2 + WSLg
Windows 11의 WSL2에는 WSLg가 기본 통합되어 있어, 별도의 X 서버 설치 없이도 Linux GUI 애플리케이션을 바로 띄울 수 있습니다.
# WSL2 안에서 Ubuntu 셸 진입 후
wsl --install -d Ubuntu-22.04
WSL2 안에서는 Linux 호스트와 거의 동일하게 docker run에 DISPLAY 환경변수만 넘기면 되고, 별도의 X11 소켓 마운트도 WSLg가 처리해줍니다. 다만 USB 장치(실물 LiDAR나 아두이노 등)를 나중에 연결하려면 usbipd-win으로 USB 장치를 WSL2로 전달하는 별도 설정이 필요하다는 점은 미리 알아두는 것이 좋습니다 — 시뮬레이션 단계에서는 필요 없지만, 6단계(저가 실물 플랫폼 검증)로 넘어갈 때 처음 겪으면 당황하기 쉬운 부분입니다.
5. docker-compose로 반복 설정 없애기
매번 긴 docker run 명령을 치는 대신 docker-compose.yml로 고정해두면 실수를 줄일 수 있습니다.
services:
ros2-sim:
build: .
environment:
- DISPLAY=${DISPLAY}
- QT_X11_NO_MITSHM=1
volumes:
- /tmp/.X11-unix:/tmp/.X11-unix:rw
- ./ros2_ws:/root/ros2_ws
network_mode: host
stdin_open: true
tty: true
network_mode: host는 ROS2의 DDS 디스커버리가 멀티캐스트에 의존하기 때문에 필요합니다. 브리지 네트워크를 쓰면 컨테이너 안의 노드끼리는 통신이 되지만, 호스트에서 실행한 ros2 topic list 같은 명령이 컨테이너 안의 노드를 찾지 못하는 문제가 생깁니다. DDS 디스커버리 자체의 동작 원리는 ROS2와 Fast DDS 완벽 가이드에서 더 자세히 다뤘습니다.
6. 첫 실습: TurtleBot3를 빈 맵에서 움직여보기
환경이 준비되었다면, 컨테이너 안에서 다음을 실행해 첫 시뮬레이션을 띄웁니다.
# 컨테이너 안에서
ros2 launch turtlebot3_gazebo empty_world.launch.py
다른 터미널(같은 컨테이너에 docker exec로 접속)에서 키보드 조종 노드를 띄우면 로봇을 직접 움직여볼 수 있습니다.
ros2 run turtlebot3_teleop teleop_keyboard
이 시점에서 화면에 로봇이 뜨고 키보드로 움직인다면 환경 구축은 끝난 것입니다. 이후 SLAM(slam_toolbox)과 Nav2를 추가로 실행해보는 것이 다음 실습 단계이며, 이 부분은 로드맵 글의 4단계에서 이어서 다룹니다.
정리
- Linux: X11 직접 포워딩이 가장 간단하고 성능도 좋음
- macOS: XQuartz보다 noVNC 기반 컨테이너가 아키텍처 걱정 없이 안정적
- Windows: WSL2 + WSLg로 별도 X 서버 설치 없이 바로 사용 가능
- 워크스페이스는 항상 볼륨으로 마운트해 컨테이너를 휘발성으로 유지
network_mode: host를 빠뜨리면 DDS 디스커버리가 깨져 노드 간 통신이 안 되는 것처럼 보임
실물 로봇이 없다는 이유로 시작을 미루기보다, 이 정도 환경만 갖추면 SLAM과 Nav2를 직접 손으로 만져보며 배우는 데는 전혀 지장이 없습니다.