Skip to main content
Summary

하나의 모델이 아니라 하나의 시스템

이 책에서 만든 AI 로봇 에이전트는 거대한 모델 하나가 모든 것을 해결하는 구조가 아니다. 자연어를 이해하는 LLM, 세상을 보는 비전 모듈, 좌표를 바꾸는 캘리브레이션 모듈, 경로를 계획하는 MoveIt2와 Navigation, 실패를 감지하는 검증기, 그리고 안전 제어가 함께 움직이는 시스템이다.

핵심은 역할 분리다. LLM은 사용자의 말을 해석하고 작업을 나눈다. "빨간 컵을 오른쪽에 놓아줘"라는 문장에서 대상, 조건, 목표 위치를 뽑고, detect_object, pick, place, verify 같은 단계로 바꾼다. 그러나 LLM이 관절 속도나 모터 토크를 직접 정해서는 안 된다. 실제 움직임은 MoveIt2, Nav2, 그리퍼 제어기, 저수준 컨트롤러가 맡는다. 여러 LLM 로봇 시스템에서도 공통적으로 LLM은 고수준 계획과 작업 분해를 담당하고, 전통적인 로봇 모듈이 저수준 제어를 수행하는 구조가 사용된다1.

최종 구조는 다음처럼 정리할 수 있다.

사용자 명령
  ↓
LLM 계획자
  ↓
계획 검증기 / 안전 정책 / 스킬 디스패처
  ↓
로봇 스킬 서버
  ↓
비전 · 좌표 변환 · MoveIt2 · Nav2 · 그리퍼 · 제어기
  ↓
센서 피드백 · 실행 결과 · 실패 원인
  ↓
재계획 또는 종료

이 흐름은 단순하지만 강력하다. 자연어 명령은 항상 실행 가능한 스킬 호출로 바뀌어야 하며, 실행 결과는 다시 계획 계층으로 돌아와야 한다. 이것이 AI 로봇 에이전트의 기본 폐루프다.

나만의 AI 로봇 에이전트 완성하기AI 생성 이미지

프로젝트 구조를 먼저 고정하라

좋은 프로젝트는 파일 구조에서 이미 설계 의도가 보인다. 실험 코드가 여기저기 흩어져 있으면 하드웨어를 바꾸거나 LLM을 교체할 때 전체 시스템이 무너진다. 처음부터 책임별로 폴더를 나누는 것이 좋다.

ai_robot_agent/
├── agent/              # LLM 계획자, 프롬프트, 작업 상태 관리
├── dispatcher/         # 스킬 호출 검증, 안전 정책, 실행 순서 관리
├── perception/         # 객체 검출, 세그멘테이션, 깊이 처리
├── calibration/        # 카메라-로봇 좌표 변환, TF 설정
├── skills/             # detect, pick, place, navigate, stop 구현
├── control/            # MoveIt2, Nav2, 그리퍼, 저수준 제어 연결
├── learning/           # 모방학습, 강화학습 정책
├── configs/            # 로봇별 설정, LLM 설정, 안전 제한
├── logs/               # 실행 로그, 실패 로그, 영상, 리포트
├── demos/              # 데모 시나리오와 실행 스크립트
└── docs/               # README, API 문서, 재현 절차

로봇별 차이는 skills/, control/, configs/ 안에 가둔다. 예를 들어 같은 pick(object_id)라는 스킬이라도 로봇팔이 UR5인지, xArm인지, 소형 교육용 로봇인지에 따라 내부 구현은 달라진다. 하지만 LLM이 보는 인터페이스는 같아야 한다.

ROS-LLM 같은 ROS 기반 LLM 프레임워크도 비슷한 방향을 보여 준다. 새 로봇을 붙일 때 로봇별 함수 인터페이스를 담당하는 llm_robot과 설정을 담당하는 llm_config를 수정하도록 설계되어 있으며, LLM 상태를 /llm_state 토픽으로 노출한다2. 이 아이디어를 일반화하면, "로봇별 구현"과 "에이전트의 공통 계획 구조"를 분리하는 것이 중요하다는 결론을 얻을 수 있다.

스킬은 로봇의 API다

LLM에게 제공할 것은 자유로운 제어 권한이 아니라 제한된 스킬 목록이다. 스킬은 로봇이 안전하게 수행할 수 있는 행동을 함수처럼 감싼 것이다.

대표 스킬은 다음과 같다.

detect_object(query, constraints) -> objects
pick(object_id, grasp_hint) -> result
place(object_id, target_pose_or_region) -> result
navigate_to(place_id) -> result
check_status() -> robot_state
stop(reason) -> result

각 스킬은 입력과 출력이 명확해야 한다. 특히 실패 반환이 중요하다.

{
  "ok": false,
  "skill": "pick",
  "stage": "grasp",
  "reason_code": "EMPTY_GRASP",
  "message": "그리퍼가 닫혔지만 물체 접촉이 확인되지 않았습니다.",
  "retryable": true,
  "suggested_recovery": ["redetect_object", "try_next_grasp"]
}

이런 반환값이 있어야 LLM이 다음 행동을 추측하지 않고 근거를 가지고 재계획할 수 있다. OBJECT_NOT_FOUND라면 다시 관찰한다. AMBIGUOUS_TARGET라면 사용자에게 묻는다. NO_IK_SOLUTION이라면 다른 접근 방향을 시도한다. SAFETY_VIOLATION이라면 즉시 중단한다.

스킬은 너무 작아도, 너무 커도 안 된다. set_joint_velocity처럼 낮은 수준이면 LLM이 위험한 제어를 하게 된다. 반대로 clean_room()처럼 너무 크면 실패 원인을 알기 어렵다. 좋은 스킬은 사람이 이해할 수 있는 작업 단위이면서, 내부적으로는 센서 확인과 안전 검사를 포함한다.

계획 검증기는 반드시 필요하다

LLM의 출력은 명령이 아니라 초안이다. 초안은 실행 전에 검증되어야 한다. 검증기는 다음 질문을 확인한다.

  • 이 스킬은 허용 목록에 있는가?

  • 인자의 타입과 범위가 맞는가?

  • 대상 객체가 실제로 감지되었는가?

  • 목표 위치가 작업 공간 안에 있는가?

  • 경로 계획이 가능한가?

  • 금지 구역이나 사람과 충돌할 위험은 없는가?

  • 이 작업은 사용자 확인이 필요한 고위험 작업인가?

이 계층은 물리 세계의 현실성을 판단하는 거부권을 가진다. PaLM-SayCan 계열의 구조에서도 언어 모델이 제안한 행동을 현재 상황에서 수행 가능한지 평가하는 affordance, 즉 실행 가능성 판단이 중요한 역할을 한다1. 우리 프로젝트에서는 이를 plan_validator 또는 skill_veto_layer로 구현하면 된다.

예를 들어 LLM이 다음 계획을 만들었다고 하자.

[
  {"skill": "detect_object", "args": {"query": "red cup"}},
  {"skill": "pick", "args": {"object_id": "cup_1"}},
  {"skill": "place", "args": {"region": "right side"}}
]

검증기는 cup_1이 실제 감지 결과에 있는지 확인한다. right side가 누구의 오른쪽인지 불분명하면 기준 객체를 요구한다. 놓을 공간이 비어 있지 않으면 실행을 거부한다. 컵 안에 액체가 있다고 판단되면 속도 제한이나 사용자 확인을 요구한다.

안전한 에이전트는 "무엇을 할 수 있는가"보다 "무엇을 하지 않을 것인가"가 더 명확하다.

로그는 다음 개선의 재료다

로봇 프로젝트는 한 번에 완성되지 않는다. 물체를 못 찾고, 깊이값이 흔들리고, 좌표 변환이 틀리고, 경로 계획이 실패하고, 그리퍼가 빈손으로 닫힌다. 이 실패를 감으로 고치면 오래가지 못한다. 로그로 남겨야 한다.

각 실행에는 최소한 다음 정보가 있어야 한다.

- 사용자 원문 명령
- LLM이 만든 구조화 계획
- 호출된 스킬 이름과 인자
- 센서 관측 요약
- ROS2 액션 상태와 피드백
- 성공 여부와 reason_code
- 재시도 횟수
- 재계획 내용
- 최종 성공 여부
- 사람 개입 또는 긴급 정지 여부

ROSA 같은 ROS 기반 에이전트 구조도 사용자의 요청, 사용 가능한 도구, 도구 호출 결과, 관측값을 반복적으로 주고받는 ReAct 흐름을 사용하며, 로그 파일·센서 읽기·이미지 캡처 같은 도구를 작업 공간의 일부로 다룬다3. 우리 프로젝트에서도 도구 호출 기록은 단순 디버깅 자료가 아니라 에이전트의 기억이자 개선 데이터다.

로그를 보면 개선 우선순위가 보인다. 실패의 60%가 OBJECT_NOT_FOUND라면 프롬프트보다 비전 임계값과 조명 조건을 먼저 봐야 한다. NO_IK_SOLUTION이 많다면 grasp 후보와 접근 방향을 고쳐야 한다. PATH_BLOCKED가 많다면 Navigation의 costmap, 대체 목표 pose, 재계획 규칙을 점검해야 한다.

좋은 개선 루프는 다음과 같다.

실행 → 실패 기록 → 원인 분류 → 가장 큰 병목 선택
→ 스킬/프롬프트/임계값/정책 수정 → 같은 시나리오 재실험

성공률만 보지 말고 단계별 성공률을 보자. 검출 성공률, grasp 성공률, place 정확도, 재시도 후 회복률, 사용자 개입 횟수, 안전 정지 횟수를 따로 봐야 어떤 부분이 약한지 알 수 있다.

데모는 짧고 재현 가능해야 한다

최종 프로젝트의 데모는 화려할 필요가 없다. 중요한 것은 전체 흐름이 보이는 것이다. 가장 좋은 데모는 하나의 자연어 명령이 인식, 계획, 실행, 검증, 재계획까지 통과하는 장면이다.

예를 들어 다음 시나리오를 준비할 수 있다.

명령: "빨간 컵을 노트북 오른쪽에 놓아줘."
1. 음성 또는 텍스트 명령 입력
2. LLM이 대상, 기준 객체, 목표 관계를 추출
3. 카메라가 빨간 컵과 노트북을 검출
4. 깊이와 TF로 3D 위치 계산
5. pick/place 스킬 계획 생성
6. 디스패처가 안전 검사 수행
7. MoveIt2가 로봇팔 경로 계획 및 실행
8. place 후 카메라로 결과 검증
9. 실패하면 재검출 또는 다른 grasp 후보로 재시도
10. 최종 결과를 사용자에게 보고

README에는 실행 명령만 적지 말고 구조를 설명해야 한다.

  • 필요한 하드웨어와 센서

  • ROS2 배포판과 주요 패키지

  • 카메라 캘리브레이션 방법

  • 설정 파일 위치

  • 사용 가능한 스킬 목록과 입력 형식

  • 예제 자연어 명령

  • 실패 코드 목록

  • 로그 저장 위치

  • 데모 재현 절차

  • 알려진 한계

데모 영상에는 화면 녹화와 실제 로봇 영상을 함께 넣으면 좋다. 왼쪽에는 자연어 명령과 LLM 계획, 오른쪽에는 RViz와 실제 로봇을 보여 준다. 실패가 있다면 숨기지 말고 짧게 보여 주자. 실패를 감지하고 안전하게 회복하는 장면은 이 프로젝트가 단순한 장난감이 아니라 로봇 시스템임을 보여 준다.

다음 단계: 여러 로봇과 범용 에이전트

하나의 로봇팔 프로젝트가 완성되면 다음은 확장이다. 첫 번째 방향은 멀티에이전트 작업 계획이다. 이동 로봇이 물체 근처로 가고, 로봇팔이 집고, 다른 로봇이 운반하는 식이다. SMART-LLM은 자연어 명령을 하위 작업으로 나누고, 각 작업에 필요한 스킬을 기준으로 여러 로봇 팀을 구성한 뒤 작업을 할당하는 흐름을 제안한다4. 이를 프로젝트에 적용하면 robot_skills.yaml에 로봇별 능력을 적고, 계획자가 어떤 로봇이 어떤 하위 작업을 맡을지 결정하게 만들 수 있다.

두 번째 방향은 Vision-Language-Action 모델이다. VLA 모델은 시각 입력, 자연어, 행동 생성을 하나의 구조에서 함께 처리하려는 접근이다. 카메라 장면을 보고, 명령을 이해하고, 실행 가능한 행동을 출력하는 방향으로 발전하고 있다5. 다만 실시간 추론, 안전 보장, 데이터 편향, 낯선 환경 일반화는 여전히 큰 과제다. 따라서 당장 모든 모듈을 VLA 하나로 대체하기보다, 특정 스킬이나 후보 행동 생성기에 먼저 적용하는 편이 안전하다.

세 번째 방향은 로봇 파운데이션 모델이다. 여러 로봇, 여러 환경, 여러 작업의 데이터를 모아 더 넓은 일반화를 노리는 흐름이다. 이때도 프로젝트의 기본 원칙은 변하지 않는다. 모델은 강력해질 수 있지만, 안전 검증, 실행 계층, 실패 로그, 사람 개입 구조는 계속 필요하다.

완성의 기준

나만의 AI 로봇 에이전트를 완성했다는 것은 모든 상황에서 실패하지 않는 로봇을 만들었다는 뜻이 아니다. 그런 로봇은 쉽게 만들 수 없다. 대신 다음 기준을 만족하면 좋은 출발점에 도달한 것이다.

  • 자연어 명령을 구조화된 계획으로 바꿀 수 있다.

  • LLM이 허용된 스킬만 호출한다.

  • 비전 결과가 로봇 좌표와 연결된다.

  • MoveIt2 또는 Navigation이 실제 실행을 담당한다.

  • 실패 원인을 표준 코드로 반환한다.

  • 재시도와 재계획이 제한된 규칙 안에서 동작한다.

  • 위험하거나 불명확한 명령은 거부하거나 질문한다.

  • 실행 로그와 데모 문서로 실험을 재현할 수 있다.

이 책의 목표는 로봇에게 모든 지능을 한 번에 넣는 것이 아니었다. 자연어, 비전, 조작, 학습, 제어, 안전을 연결해 물리 세계에서 행동하는 AI 시스템의 뼈대를 세우는 것이었다.

이제 여러분의 로봇은 문장을 듣고, 장면을 보고, 계획을 세우고, 움직이고, 실패를 확인하고, 다시 시도할 수 있다. 여기서부터가 진짜 시작이다. 더 좋은 센서, 더 많은 스킬, 더 똑똑한 정책, 더 안전한 검증기를 하나씩 붙여 가면 된다. 중요한 것은 끝까지 같은 원칙을 지키는 것이다.

LLM은 계획한다. 로봇 스킬은 실행한다. 센서는 결과를 확인한다. 안전 계층은 멈출 권한을 가진다. 로그는 다음 개선을 이끈다. 이 다섯 가지가 유지되는 한, 여러분의 AI 로봇 에이전트는 계속 성장할 수 있다.

참고

1Agentic LLM-based robotic systems for real-world applications: a review on their agenticness and ethics

2GitHub - Auromix/ROS-LLM: ROS-LLM is a framework designed for embodied intelligence applications in ROS

3Enabling Novel Mission Operations and Interactions with ROSA: The Robot Operating System Agent

4SMART-LLM: Smart Multi-Agent Robot Task Planning using Large Language Models

5Vision-Language-Action Models: Concepts, Progress, Applications and Challenges

책 목록

AI 로봇 에이전트 만들기: 비전·로봇팔·학습·LLM으로 자연어 명령을 실행하는 로봇

전체 목차 보기

이 노트는 보도·비평·교육·연구 목적으로 작성되었습니다. 저작권 문의가 있으시면 에서 알려주세요.

틸노트는 사용자가 AI를 활용해 노트를 쉽게 작성하거나 편집할 수 있는 서비스입니다.

AI 스퀘어 단톡방에 함께해요

AI 활용과 틸노트 사용 팁을 나누는 오픈채팅방입니다. 입장 비밀번호는 tilnote입니다.

참여하기