AI와 로봇 연구하기
들어가며 — AI의 답을 연구의 근거로 바꾸려면
AI는 큰 저장소에서 관련 파일을 찾고, 긴 로그에서 원인 후보를 좁히고, 논문의 방법을 prototype code로 옮기는 일을 빠르게 해낸다. 문제는 무엇을 보고 그런 판단을 했는지가 그만큼 잘 남지 않는다는 데 있다.
기록이 남지 않아도 당장은 불편하지 않다. 답은 매끄럽고 수정안까지 붙어 있으니, 그대로 고치고 다음으로 넘어가면 된다. 그러나 몇 달 뒤 심사 의견에 답하려고 결과를 다시 꺼내면, 그 숫자가 어떤 조건에서 나왔는지 아무도 알 수 없다.
그래서 이 책은 AI에게서 더 나은 답을 끌어내는 법을 다루지 않는다. 답을 받은 자리에서 무엇을 보았고 무엇을 실행했는지를 파일로 남기는 법을 다룬다.
비싼 모델도 서비스 조건까지 통제할 수는 없다
성능이 좋은 상용 모델에 비용을 더 들이면 도움이 될 수 있다. 다만 더 비싼 구독이 언제나 같은 품질을 보장하지는 않는다.
품질은 모델 성능뿐 아니라 사용자가 모두 통제할 수 없는 동작 조건에도 영향을 받기 때문이다. 상용 구독은 폐쇄형 서비스여서, 공급자는 실제 매개변수 수, 요청을 처리하는 backend, 앞에 붙는 system prompt를 제한적으로만 공개한다.
공개된 사례도 있다. Anthropic은 2026년 4월 Claude Code postmortem에서 그달에 보고된 품질 저하의 원인을 셋으로 나눴다. 한 요청의 추론량을 정하는 값을 바꾼 일, 추론 내용을 다음 요청으로 넘기는 캐시에 버그가 생긴 일, 답을 짧게 내도록 유도한 system prompt가 그것이다.
셋 모두 사용자 쪽에서는 손댈 수 없었다. 글을 쓰는 사람은 그날 답이 왜 달라졌는지도 알 방법이 없었다. 구독 등급을 올려도 이 성질은 바뀌지 않는다.
그러므로 모델 내부를 통제하려 하기보다 바깥의 작업 조건부터 붙잡아야 한다. 사용자가 통제할 수 있는 영역에 작업 조건을 마련하는 것이다.
다만 공급자가 바꾸는 조건 가운데 일부는 문서에 버전과 수치로 공개된다. 버전이 올라가면 그 수치도 함께 바뀌므로, 이런 값은 본문에 두지 않고 확인한 날짜와 함께 부록 G의 「Claude의 Adaptive thinking과 Prompt caching」에 모아 두었다.
자체 서버만으로 연구 환경이 완성되지는 않는다
성능이 좋은 모델을 자체 서버에 올리면 공급자의 routing이나 quota 변화에는 덜 흔들린다. 그렇다고 작업 조건 전체를 손에 넣는 것은 아니다.
상용 서비스의 품질은 모델 가중치 하나만으로 결정되지 않는다. 어떤 모델을 고르는지, system prompt에 무엇을 넣는지, 긴 대화를 어떻게 줄이는지, 무엇을 캐시에 남기는지, 어떤 도구를 부르는지, 어떤 자료를 찾아 붙이는지가 모두 답을 바꾼다. 가중치를 우리 서버에 올려도 이 항목들은 여전히 우리가 정해야 한다.
특히 외부 자료를 가져와 활용하는 방식은 하나의 단일 기능이 아니라 여러 구체적인 설계 선택으로 나뉜다. 외부 자료를 가져오는 방법만 보아도 그렇다. REALM은 자료 검색 과정을 사전 학습 단계부터 모델과 함께 학습시켰다. DPR의 경우 질문과 문서를 동일한 공간의 벡터로 매핑해 검색 효율을 높였다. 이어 RAG는 검색된 문서를 생성 모델의 생성 조건으로 결합했고, FiD는 여러 편의 문서를 동시에 입력받는 구조로 확장하는 데 집중한다. 나아가 RETRO는 외부 데이터베이스 규모를 대폭 확장했으며, Atlas는 소수 예시(few-shot) 조건에서도 검색 증강이 유효함을 입증했다.
이 연구들이 다룬 것은 모델 가중치뿐 아니라 자료를 찾고 읽히는 방식이다. 가중치를 손에 넣는 일과 작업 조건을 손에 넣는 일은 다르다.
모델이 바깥에서 끌어온 자료를 읽는 곳은 context window인데, 이곳에도 손댈 부분이 있다. 창에 넣는 토큰이 늘어날수록 그 안에서 필요한 내용을 정확히 되짚기 어려워질 수 있다. Anthropic의 Effective context engineering for AI agents는 이 현상을 context rot이라 불렀다.
이 현상은 모델이 문장을 읽는 방식과 관련이 있다. 일반적인 self-attention 구조에서는 각 토큰이 다른 토큰과의 관계를 계산한다. 토큰이 n개라면 계산할 관계는 n² 규모로 늘어난다. 창이 길어질수록 비교할 관계가 빠르게 늘어나고, 그만큼 필요한 정보를 골라 쓰기 어려워질 수 있다. 같은 글에서는 이를 attention budget이라 불렀다.
따라서 창을 채우는 것 자체를 목표로 삼아서는 안 된다. 원하는 결과를 내는 데 필요한 가장 작은 자료 묶음을 고르고, 그 안의 신호를 분명하게 만들어야 한다.
연구실 환경에서 핵심은 web-scale index 구축보다 다룰 자료의 경계를 명확히 획정하는 데 있다. 논문 PDF, code path, 실험 로그, dataset 규약, 심사 의견을 어떤 단위로 나눌지 정한 다음, 질문을 관련 자료와 연결한다.
자료의 경계를 정하는 일과 정해진 범위 안에서 직접 작업하는 일은 다르다. 사람과 에이전트의 역할도 여기에서 나뉜다. 실제 세션 40만 개를 살핀 Anthropic의 사용 분석에서도 같은 역할 구분이 나타났다. 그 자료는 1부에서 따로 읽는다.
이 역할 분담을 매번 즉석에서 다시 정하지 않으려면 에이전트가 따라갈 작업 지침이 필요하다. 이 책의 절차는 그 지침을 저장소의 AGENTS.md, project memory, 실험 기록, 주장·근거 표에 나누어 적는 방법이다.
연구용 AI 하네스의 여섯 요소
이 책이 만들려는 작업 구조를 한 단어로 부르면 하네스다. 등반 장비에서 온 말로, 매어 두는 줄과 거는 고리를 뜻한다.
2026년 연구는 에이전트를 기반 모델에 실행 하네스를 붙인 시스템으로 보고, 그 하네스를 여섯 요소로 나누었다. 무엇을 보여 줄지(관측), 그중 무엇을 이번 호출에 넣을지(문맥), 어떤 주기로 돌리고 언제 멈출지(제어), 무엇을 실행하게 할지(행동), 무엇을 남길지(상태와 산출물), 무엇으로 확인하고 무엇을 막을지(검증과 통치)다.
여섯 요소 가운데 네 요소는 연구 기록과 직접 맞닿아 있다. 관측 영역에는 로그·diff·스크린샷이 수집되며, 문맥 영역에서는 작업에 필요한 정보를 선별한다. 상태 영역에는 체크포인트와 추적 내역이 축적되고, 검증 영역에서는 테스트와 감사 기록으로 정합성을 확인한다. 이렇게 남겨 둔 기록이 하네스의 뼈대가 된다.
AutoExperiment의 논문 재현 실험에서는 핵심 함수 하나를 지운 과제를 GPT-4o로 풀게 했다. 과제에 딸린 모든 실험의 결과가 원래 코드의 결과와 상대 오차 5% 이내이면 성공으로 셌다. 정해진 세 걸음을 순서대로 밟는 방식의 성공률은 8.3%였고, 같은 모델이 환경의 응답을 보고 다음 행동을 정하는 방식에서는 35.3%였다. 모델은 그대로이고 하네스를 바꾼 비교다.
무엇을 늘렸을 때 효과가 나는지도 달랐다. 같은 연구의 별도 실험에서 추론 토큰 예산을 늘린 고정 상호작용 방식의 최고 성공률은 o1에서 22.2%, o3-mini에서 27.8%였다. GPT-4o가 환경과 주고받을 수 있는 횟수를 늘린 방식은 38.9% 근처까지 올랐다. 모델과 실행 방식이 함께 다른 비교이므로 증가분을 상호작용만의 효과로 볼 수는 없지만, 이 과제에서는 긴 추론뿐 아니라 실행 결과를 보고 고칠 기회도 중요했다.
이 책은 이 여섯 요소를 연구실의 작업에 적용한다. 대체로 1부는 상태와 문맥, 2부는 관측과 검증, 3부는 제어와 행동에 해당한다.
한 연구에서 AI가 낸 아이디어의 순위는 실행 뒤 뒤집혔다
이 책이 하네스를 만드는 이유는 AI를 믿지 못해서가 아니다. AI가 잘하는 단계와 근거가 마련되는 단계가 서로 엇갈리기 때문이다.
Si 등은 LLM이 새로운 연구 착상을 낼 수 있는지를 사람과 비교해 측정했다. 100명이 넘는 NLP 연구자에게 각자 착상을 내게 한 다음, 사람의 것과 모델의 것을 섞어 출처를 모르게 심사하게 했다. 새로움에서는 모델 쪽이 사람 전문가보다 높았다(p < 0.05). 실현 가능성은 조금 낮았다.
착상의 새로움 평가에서는 모델이 앞선 셈이다. 그러나 착상은 논문이 아니다.
같은 연구진은 그 착상들을 실제로 실행하는 후속 연구로 나아갔다. 전문 연구자 43명에게 착상을 무작위로 배정해 평균 103시간 동안 구현하게 했다. 연구자들은 결과를 4쪽 분량의 논문으로 작성했고, 다른 전문가들이 출처를 모른 채 심사했다. 실행 전후의 점수를 대조한 결과, 모델이 낸 착상은 네 항목(새로움·흥미·효과·종합) 모두에서 사람의 착상보다 큰 폭으로 하락했다(p < 0.05). 최종 평균은 사람의 착상이 높았지만, 착상 43개를 각각 독립 표본으로 본 비교에서 최종 점수 차이는 통계적으로 유의하지 않았다.
이 두 연구에서 모델의 강점은 근거가 서는 자리보다 앞쪽에 있었다. 착상 평가에서 높게 받은 점수가 사람이 구현한 뒤의 평가까지 이어지지는 않았다. 이는 모델이 직접 실험을 수행하는 능력을 측정한 결과는 아니다. 착상의 출처가 무엇이든 실제 조건에서 돌려 숫자를 얻고, 그 숫자로 말할 범위를 정해야 한다. 하네스는 이 실험과 검증 과정을 돕는 구조로 쓴다.
아이디어를 내는 일과 고르는 일은 다르다
모델은 하나의 질문에도 그럴듯한 착상 후보를 여럿 내놓을 수 있다. 그러나 그중 무엇이 해 볼 값어치가 있는지는 질문한 연구자가 정해야 한다.
앞선 착상 연구의 저자들도 자기 시스템이 스스로 출력을 평가하지 못하고 생성 결과도 다양하지 않다는 한계를 들었다. 착상을 많이 뽑을수록 새것은 늘지 않고, 앞서 낸 것을 말만 바꾼 것이 늘어난다.
논문 재현 과제에서도 생성 능력과 선택 능력의 격차가 수치로 확인된다. GPT-4o에게 동일한 문제를 5회 반복해 풀게 했을 때 적어도 한 번 이상 정답을 맞힌 비율은 48.2%에 달한 반면, 1회 단독 시도 시 정답률은 35.3%에 머물렀다. 그러나 자기가 생성한 다섯 개 답안 중 최적의 답을 고르게 하자 정답률은 37.6%에 그치는 결과를 보였다. 정답 후보가 이미 풀이 공간에 포함되어 있었음에도, 자체적인 선별 과정을 통해 얻은 개선 폭은 2.3%포인트에 불과했다.
스스로 고쳐 쓰게 한다고 반드시 나아지는 것도 아니다. 답을 낸 뒤 스스로 검토하고 다시 답하게 한 연구에서는 GSM8K 정확도가 75.9%에서 두 번 검토한 뒤 74.7%로 내려갔다. 바뀐 답을 나누어 보면, 맞던 것을 틀리게 바꾼 비율은 8.8%이고 틀리던 것을 맞게 바꾼 비율은 7.0%다.
같은 연구는 조건 하나만 바꾸어 다시 측정했다. 정답을 확인할 수 있는 외부 판정자가 답이 아직 틀렸다고 알려 줄 때만 다시 풀게 하자 75.9%가 84.3%로 올랐다. 절차는 그대로였고, 외부의 오류 신호 하나만 더해졌다.
모델은 답을 만들어 낸다. 그러나 만들어 놓은 것 가운데 무엇이 맞는지를 가리려면 외부의 판정 기준이 필요하다. 그 기준을 적용하려면 당시의 입력과 결과가 기록으로 남아 있어야 한다.
그래서 좁히는 일은 사람 쪽에 남는다. 이 책의 절차는 매번 어디까지 말할 수 있는가를 묻는다. 이 물음으로 많은 후보를 실행 가능한 범위까지 좁힌다. 뒤에 나오는 규칙은 모두 그 물음에 답할 재료를 남기는 방법이다.
재현 과제가 보여 준 AI의 실행 한계
재현 과제는 착상을 제외하고 모델의 실행 능력을 따로 측정한다. 이미 나온 논문을 주고 그 결과를 다시 만들게 하기 때문이다.
PaperBench는 ICML 2024 구두·스포트라이트 논문 20편의 결과를 재현하게 했다. 논문마다 재현 과정을 잘게 나누어 채점표를 만들자 개별 채점 항목은 8,316개가 됐다. 가장 높은 점수는 21.0%였고, 같은 과제 일부를 기계학습 박사들에게도 시켜 본 결과 모델은 아직 사람을 넘지 못했다.
분야를 넓혀도 비슷하다. CORE-Bench는 전산·사회과학·의학 논문 90편에서 과제 270개를 만들고 난이도를 셋으로 나눴다. 가장 어려운 층의 최고 성능은 21%였다.
코드만 떼어 놓은 과제에서도 같은 실행 한계가 드러난다. ResearchCodeBench는 2024~2025년 논문 20편에서 각 논문의 새로운 대목만 골라 과제 212개를 만들었다. 학습에 이미 들어갔을 가능성을 줄이기 위해 저장소 20개 가운데 13개를 모델 컷오프 이후 것으로 채웠다. 가장 잘한 모델은 37.3%였고, 40%를 넘긴 모델은 없었다.
난이도를 단계별로 바꾸어 측정한 사례도 있다. AutoExperiment는 재현이 이미 확인된 논문 넷의 저장소에서 핵심 함수를 지운 뒤 채워 넣게 했다. 하나를 지웠을 때는 35.3%였으나 둘을 지우자 8.5%로 떨어졌다. 다섯을 지우면 사실상 0이다.
지운 함수가 많아질수록 논문 본문을 읽게 한 쪽과 읽게 하지 않은 쪽의 차이는 벌어졌다. 하나를 지웠을 때는 35.3%와 34.1%로 거의 같았지만, 넷을 지우자 본문이 없는 쪽은 완전히 실패했다. 코드가 충분히 남아 있을 때는 코드가 절차를 보완하지만, 빠진 부분이 많아질수록 본문에 적어 둔 설명이 필요해진다.
이 재현 과제들이 보고한 실패 원인에는 공통점이 있다. 실행 시간이 부족하거나 의존성과 데이터 정렬에서 막힌다. 논문 본문만 보고 절차를 다시 세워야 할 때는 빠진 절차, 방법에서 벗어난 실행, 중간에 깨지는 환경이 실패 사유로 꼽힌다.
이 목록은 2부에서 만들 최소 기록의 항목과 거의 겹친다. 방법 자체의 난도에 더해, 그 방법을 돌리는 데 필요한 정보가 충분히 기록되지 않으면 재현은 더 어려워진다.
자동 연구가 낸 성과에도 사람의 검증은 필요했다
2025년 11월에 공개된 Kosmos는 한 번 실행할 때 에이전트 롤아웃을 200회 수행하고, 평균 42,000줄의 코드를 작성하며 논문 1,500편을 읽는다. 함께 일한 연구자들은 20주기로 이루어진 한 번의 실행을 자신의 기준으로 6개월치 작업으로 보았다. 독립 과학자들이 보고서의 문장을 하나씩 확인했을 때 79.4%가 정확한 것으로 판정됐다. 제시한 발견 일곱 건 가운데 셋은 아직 발표되지 않은 결과를 다시 찾아낸 것이고, 넷은 새로운 기여다.
심사를 통과한 사례도 있다. Intology의 Zochi가 작성한 논문은 ACL 본 학술대회 논문집에 실렸다. 다만 제출 전의 결과 검증과 심사자와의 의견 교환은 사람이 맡았다.
Sakana의 시스템은 논문 한 편을 처음부터 끝까지 만드는 데 15달러에서 25달러 정도가 든다고 보고했다. 이 시스템은 ICLR 2025 워크숍에 세 편을 제출했고, 그중 한 편은 평균 6.33점으로 채택됐다. 이는 사람이 낸 원고 가운데 55%보다 높은 점수다. 만든 쪽도 세 편 모두 본 트랙 기준에는 이르지 못한다고 적었고, 사전 합의에 따라 철회했다.
79.4%가 정확했다면 나머지는 정확하다고 확인되지 않았다는 뜻이다. 6개월치로 평가된 작업이 짧은 시간에 나오더라도, 남는 일은 어떤 문장이 확인을 통과하지 못했는지 찾는 것이다. 그러려면 각 문장이 무엇을 보고 만들어졌는지가 기록으로 남아 있어야 한다.
완전 자동화에도 실행과 검증의 빈틈은 남는다
워크숍 심사를 통과했다는 사실이 실행과 검증의 문제가 사라졌다는 뜻은 아니다. 문헌을 훑고, 착상을 내고, 코드를 작성하고, 실험과 집필과 자체 심사까지 이어 가는 동안 보고된 한계는 앞의 연구들이 지적한 약점과 겹쳤다. 호흡이 긴 추론 과정에서 오류가 누적되며, 도구 연동 실패나 디버깅·검증 고리의 단절도 빈번히 발생한다. 새로움 판정도 얕아 이미 있는 것을 새것이라고 부르거나, 진짜 새것을 놓친다.
과제를 통제해 측정하면 이 문제는 더 뚜렷해진다. ResearchGym은 ICML·ICLR·ACL 논문 5편을 바탕으로 제안 기법만 블라인드 처리하고 데이터와 베이스라인은 보존한 평가 환경을 구축했다. 39개 세부 과제에서 GPT-5의 완료율은 평균 26.5%에 머물렀으며, 15회의 전체 평가 중 베이스라인을 상회한 사례는 단 한 건에 그쳤다. 다만 그 한 번의 결과는 ICML 2025 Spotlight 해법의 수치를 앞섰다. 저자들은 주된 실패 원인으로 성급한 결론 도출, 시간·자원의 비효율적 배분, 미흡한 가설의 고수, 병렬 실험 조율 미숙, 문맥 길이 제약을 지적한다.
파일·명령·결과를 연구 기록으로 남긴다
실행의 일부를 모델과 도구에 맡기더라도, 연구자는 실행 조건을 정하고 결과를 검증할 책임을 맡는다. 그러려면 무엇을 보고 무엇을 실행했는지가 남아 있어야 한다. 이어지는 세 부는 그 기록을 하나씩 만드는 방법을 다룬다.
요청을 자세히 설명하고, 잘못을 지적하고, 빠진 맥락을 보충하면 답이 나아질 때가 있다. 그러나 이 방식에서는 사용자가 매번 상황을 기억하고 같은 설명을 반복해야 한다. 오래 이어지는 작업에는 버티지 못한다.
연구가 바로 그런 작업이다. 실험은 며칠씩 이어지고 원고는 여러 차례 바뀐다. 심사 의견에 답하려면 몇 달 전의 결과와 지금의 코드 상태를 함께 열어 봐야 한다. 이때 진정으로 힘을 발휘하는 요소는 현란한 프롬프트 대화보다 AI의 오류를 사후에 추적하고 재검증할 수 있도록 설계된 작업 구조다.
읽은 파일과 돌린 명령과 그 결과를 적어 둔다. 셋 모두 그날 손에 있던 것이므로 새로 만들 필요가 없다. 이것만 있으면 모델이 바뀌거나 세션이 끊겨도 같은 자리에서 이어 갈 수 있다.
적어 둘 자리도 미리 정한다. 부록의 first-day-workspace-checklist.md에는 이 기록을 어디에 둘지 정하는 표가 있다. project goal, code truth, dataset truth, experiment truth, manuscript truth 다섯 줄에 각각 Primary source와 Secondary source를 적는 표다. 어느 자료를 기준으로 삼을지 미리 정해 두면, 나중에 요약과 파일이 어긋나더라도 어느 쪽을 따를지 다시 정할 필요가 없다.
모델 성능에 따라 탐색 속도와 정리 품질은 달라지지만, 같은 파일과 로그를 보고 같은 절차를 따를 수 있다는 점은 변하지 않는다.
1부는 답 하나마다 남겨야 할 기록을, 2부는 실험 수치를 원고 문장으로 옮기는 표를, 3부는 그 둘을 에이전트가 따라갈 규칙으로 바꾸는 방법을 다룬다. 각 부에서 만든 산출물은 파일로 남고, 다음 연구를 시작할 때 사람과 에이전트가 함께 읽는다.
1부 검증 가능한 연구 기록
에러 로그를 붙여 넣으면 모델은 몇 초 안에 원인을 설명한다. 문장은 매끄럽고 수정안도 함께 나오니, 곧바로 고친 뒤 실험을 다시 돌리고 싶어진다.
그 설명이 맞는지는 문장의 모양만으로 판단할 수 없다. 파일을 열고 명령을 실제로 돌려 봐야 한다. 그래서 답을 실행에 옮기기 전에는 무엇을 확인했고 어떤 명령을 돌렸는지 남겨 둔다.
1장 AI와 사람이 나누어 맡을 일
AI는 넓게 찾아서 후보를 정리하는 일에 유용하다. 에러 로그에서 확인할 원인 후보를 찾고, 파일·함수·config의 위치를 짚고, 긴 로그와 심사 의견을 단계별로 나눌 수 있다. 반박문이나 README의 첫 문장을 제안하고, 여러 저장소와 실험 조건의 차이를 표로 정리할 수도 있다.
하지만 이 역할은 후보를 좁히는 데까지다. 실제 원인은 실험과 로그를 확인해야 정할 수 있다. AI가 후보를 내놓은 뒤 무엇을 확인할지는 사람이 정해야 한다.
목표와 범위는 사람이 정한다
Anthropic은 약 40만 개의 세션을 살펴 2026년 Claude Code 사용 분석을 냈다. 이 분석에서도 목표와 범위를 정하는 일과 구체적인 실행 방법을 고르는 일이 서로 나뉘었다.
목표와 범위를 정하는 결정의 약 70%를 사용자가 주도한 반면, 구체적인 파일 수정과 실행 명령 선택은 약 80%를 Claude가 담당했다. 사람이 작업의 방향성을 잡고 모델이 세부 실행을 보좌하는 분업 구도다.
저자들은 익숙함을 세 가지로 가늠했다. 지시가 얼마나 정확한지, 무엇을 검증해 달라고 하는지, 사용자가 Claude를 바로잡는지 아니면 그 반대인지다. 이 익숙함은 과제마다 따로 평가한 것이므로, 한 사람의 전반적인 실력을 뜻하지는 않는다.
셋 가운데 차이를 만든 것은 둘째였다. 무엇을 검증해 달라고 요청하는지가 익숙한 사람과 그렇지 않은 사람을 갈랐다.
모델이 제안한 검증 지점만으로는 충분하지 않다. 실제 파일과 대조할 항목과 통과 기준은 요청하는 사람이 정해야 한다. 더 좋은 답을 끌어내는 요령보다 어디를 검증할지 짚는 일에 힘을 써야 하는 까닭이다.
이를 짚으려면 세 가지를 분명히 해야 한다. 먼저 어느 dataset의 어느 split을 어떤 코드 경로와 metric으로 측정하는지 지목한다. 다음으로 실행 시점에 실제로 읽힌 config를 확인한다. 마지막으로 AI가 낸 원인 후보를 단계별로 대조해 맞지 않는 것을 걷어 낸다.
여기서 셋째 항목의 단계란 데이터를 읽어 들이는 일에서 정합과 최적화를 거쳐 평가에 이르는 구간을 말한다. 어디에서 틀어졌는지에 따라 고칠 곳도 달라진다. 이 구간에 이름을 붙이는 일은 2부에서 따로 다룬다.
세 가지 모두 지난번에 무엇을 확인했는지 알아야 정확히 지목할 수 있다. 같은 보고서에 따르면 숙련된 사용자는 단일 요청에 평균 약 12개의 작업을 담았으며 프롬프트 길이도 약 3,200단어에 달했다. 반면 덜 익숙한 사용자의 경우 약 5개 작업과 600단어 수준에 머물렀다. 단어 수 자체로 지시의 품질을 단정할 수는 없으나, 복합적인 작업을 위임한 집단일수록 맥락과 제약을 담은 상세한 요청을 작성했음은 분명하다.
보고서는 분석 자체의 한계도 명확히 짚었다. 세션에서 생성된 코드가 실제 소프트웨어에 반영되었는지는 해당 로그만으로 확인하기 어려우며, 세션 분류 역시 사람이 직접 검토하기보다 대화 기록을 읽은 모델에 위임한 결과다. 뒤에서 기록마다 검증 가능한 범위를 한정해 적어 두는 이유도 여기에 있다.
자동화할수록 사후 검증이 중요해진다
답이 나올 때마다 화면을 지켜보는 방식으로는 충분하지 않다. 자동화 연구는 그 이유를 이미 적어 두었다.
Bainbridge는 Ironies of Automation(1983)에서 화학 공장의 자동 제어 장치를 예로 들어 이 문제를 짚었다. 공장에 자동 장치를 들이는 이유는 그 장치가 사람보다 그 일을 잘하기 때문이다. 그러나 장치가 제대로 작동하는지 살피는 일은 다시 사람에게 남는다.
Bainbridge는 사람이 장치를 살피기 어려운 까닭도 이어서 설명했다. 무엇이 정상인지 규칙으로 모두 적어 낼 수 있다면, 그 규칙은 이미 장치 안에 들어가 있다. 사람이 같은 규칙을 머릿속으로 따라가며 장치보다 먼저 이상을 알아챌 수는 없다는 뜻이다.
결국 사람에게 남는 일은 계기판을 바라보는 일뿐이다. 변화가 드문 화면을 응시하며 30분 이상 높은 주의력을 유지하기란 어려우며, 수동 제어 감각을 오래 쓰지 않으면 정작 비상 상황에서 적시에 개입할 능숙함을 잃고 만다.
AI가 추론을 진행하는 동안 화면만 바라보는 사용자는 수동적인 감시자에 머문다. 모델의 내부 근거를 실시간으로 추적하기란 불가능하며, 화면을 오래 응시한다고 해서 숨은 결함이 저절로 드러나지도 않는다.
답이 나온 뒤에는 그 결과를 실제 상태와 대조해야 한다. 그러려면 대조할 기준을 먼저 마련해 두어야 한다.
객관적 기준이 부재하면 판단은 직관이나 기분에 휘둘리기 쉽다. Parasuraman과 Riley(1997)는 자동화 시스템에 대한 인간의 태도를 분석하면서, 과도한 맹신(overtrust)과 완전한 불신(distrust)이라는 양극단이 공존함을 보였다.
두 태도를 가르는 것은 도구의 실제 성능보다 최근의 경험이었다. 어제 오탐이 한 번 났다는 이유로 도구를 접었다가, 다음 주에는 근거 없이 다시 꺼내 쓰는 식이다. 기록이 쌓여 있으면 며칠간의 인상 대신 지난번에 실제로 나온 결과에 판단의 근거를 둘 수 있다.
연구 기록에서 경계해야 할 다섯 가지 오류
먼저 경계할 일은 실행 상태를 보지 않은 채 원인을 단정하는 것이다. 파일이 존재한다는 사실을 그 파일이 실제로 쓰였다는 뜻으로 받아들여서도 안 된다.
| 경계해야 할 오류 | 왜 문제가 되는가 |
|---|---|
| 보지 않은 현재 상태 확정 | 파일명, memory, 요약만으로 최신 repo나 runtime을 단정한다 |
| 코드 존재와 실행 사용 혼동 | 저장소에 있는 모듈을 지금 돌아가는 방법으로 착각한다 |
| 숫자를 주장으로 넓혀 잡기 | metric 하나를 방법 개선이나 generalization 주장으로 올린다 |
| 실패 단계 혼합 | data loading, matching, optimization, evaluation 실패를 한 원인으로 합친다 |
| 위험 비용 무시 | 요청에 적지 않은 시간과 계산 자원, 심사자 신뢰, 원고 주장 범위가 판단에서 빠질 수 있다 |
이 표는 오류의 빈도를 집계한 순위표가 아니다. 뒤에서 설명할 기록 절차가 무엇을 막는지 한눈에 볼 수 있도록 묶은 것이다. 원 파일과 실행 결과와 조건을 나누어 남기면, 적어도 추정이 확인한 사실로 둔갑하는 일은 피할 수 있다.
2장 대화 밖에 남겨야 할 기록
Thinking Machines는 동일한 프롬프트를 온도 0 설정으로 1,000회 반복 입력했다. 그 결과 무려 80개의 상이한 완성본이 생성되었다. 최빈출 완성본조차 1,000회 중 78회에 불과한 빈도를 보인다. 추론 경로의 분기점도 흥미롭다. 첫 102개 토큰까지는 1,000개 시도 모두 완벽히 일치했으나, 103번째 토큰에서 992개는 Queens, New York을 선택했고 나머지 8개는 New York City로 갈라졌다.
이 실험에서 출력 차이를 유발한 핵심 요인은 샘플링 온도가 아닌 서버 배치(batch) 크기였다. 서버는 여러 요청을 묶어 한 번에 돌리고, 그 묶음의 크기는 그때그때 부하에 따라 달라진다. 커널은 묶음 크기에 따라 덧셈 순서를 바꾸므로 같은 입력에서도 다른 수가 나온다. 같은 묶음에 실린 다른 요청이 결과를 바꾼다.
같은 글에는 커널을 고친 결과도 실려 있다. 묶음 크기와 상관없이 같은 순서로 더하는 커널로 바꾸자 1,000개가 모두 같아졌다. 대신 26초가 55초로 늘었고, 커널을 다듬어 42초까지 낮췄다.
온도 0만으로는 재현을 보장할 수 없다. 이 실험에서는 재현성을 확보하려고 추론 스택 안쪽의 커널을 바꿨고, 최적화한 뒤에도 처리 시간은 약 1.6배였다. 외부 API를 사용하는 쪽에서는 이 커널을 바꿀 수 없다.
모델이 낸 문자열은 그 자리에서 저장한다. 같은 프롬프트를 적어 두고 나중에 다시 부르면 된다고 생각하지 않는다. 다시 불러도 같은 결과가 온다고 가정할 수 없다.
실행 상태는 대화 밖에서도 바뀐다
Suchman은 Plans and Situated Actions(1987)에서 계획이 행동을 세부까지 결정한다는 가정을 비판했다. 계획은 참고 자료일 뿐이며, 실제 일은 그때그때 형편을 보며 해 나간다는 것이다.
AI가 내놓는 설명과 수정안도 그런 뜻에서 계획이다. 남겨야 할 것은 그 자리에서 실제로 무슨 일이 있었는지다.
그런데 Docker container, ROS2 topic, CUDA process, dataset split, calibration file, metric script, TeX table 같은 실행 상태는 대화 밖에서 바뀔 수 있다. 이런 변화는 저절로 대화창에 들어오지 않는다.
Hutchins는 Cognition in the Wild(1995)에서 현재 상태를 한 사람이 모두 파악하고 있지 않다는 점을 보였다. 큰 군함이 항구로 들어갈 때 항해사 한 사람이 머릿속으로 항로를 짜는 것이 아니다. 해도와 계기와 서로 주고받는 절차가 함께 항로를 만든다.
연구실도 같은 구조다. 다만 배에서는 해도와 계기가 현재 상태를 계속 보여 주지만, 연구실에서는 container나 dataset이 바뀌어도 그 사실이 저절로 드러나지 않는다. 사람과 AI가 나중에 다시 열어 확인할 수 있는 상태는 파일에 남겨야 한다. 그 파일을 열지 않으면 확인할 근거도 없는 셈이다.
AI의 설명과 확인한 사실을 나누어 적는다
그래서 받은 답 아래에는 세 가지를 차례로 적는다. 먼저 모델의 설명을 요약하지 말고 그대로 옮긴다.
요약하는 순간 그것이 내 문장이 되어 버려 나중에는 어디까지가 모델의 말이었는지 알 수 없다. 옮긴 설명 아래에 실제로 연 파일과 실행한 명령을 적고, 명령이 내놓은 결과를 붙여 넣는다.
끝에는 붙여 넣은 결과로 말할 수 있는 범위를 적는다. 이 말할 수 있는 범위 칸이 가장 어렵다. 앞서 본 40만 세션 분석도 결론과 함께 알 수 없는 것을 적어 두었다. 여기에서도 결과에서 직접 확인되는 선을 넘지 않게 범위를 적는다.
모델의 생성문과 관측 사실을 한데 섞어 적으면 동일한 실수를 되풀이하기 쉽다. 그럴듯한 가설이 검증된 근본 원인인 양 오독되고, 저장소에 방치된 코드가 실제 실행 경로로 둔갑하여 원고에 반영될 위험이 있다. 서로 다른 조건에서 나온 수치가 과장된 일반 성능으로 부풀려지며, 정작 필수 실험은 건너뛴 채 반박문 문장만 다듬는 오류로 이어진다. 인계 메모나 memory 파일마저 원본 검증 자료 행세를 하게 되는 셈이다.
모델의 말과 눈으로 본 것을 다른 줄에 적는다. 모델의 설명은 요약하지 말고 그대로 옮기고, 그 아래에 실제로 연 파일과 돌린 명령과 나온 결과를 적는다. 한참 뒤에 다시 열어 봐도 어디까지가 모델의 말이고 어디부터가 확인한 사실인지 갈린다.
다시 열어 보려면 이 기록이 파일로 있어야 한다. 모델에 그 파일을 쓰게 할 수도 있다. Anthropic의 맥락 다루기 cookbook은 이때 쓰는 도구를 memory_20250818이라는 이름으로 제시한다. 다만 실제로 파일을 만지는 쪽은 모델이 아니다.
Claude가 파일을 열거나 고치겠다는 요청을 내면, 그 요청을 받아 실행하는 것은 우리 쪽에서 돌리는 도구다. 요청할 수 있는 것은 view·create·str_replace·insert·delete·rename 여섯이고, 그 여섯이 닿는 자리는 우리 디스크다.
기록은 작성 주체와 무관하게 동일한 파일 시스템에 저장되므로 이전 작업 내역을 언제든 투명하게 열람할 수 있다. 이 파일은 맥락 창 밖에 있으므로 세션이 바뀌어도 남는다.
지난 기록은 현재 상태가 아니다
다만 기록에 남는 것은 적을 당시의 상태다. 며칠 뒤 열어 보면 경로도 명령도 그때 나온 숫자도 적어 둔 그대로지만, 그사이 기계 쪽은 계속 움직였다.
ROS2를 예로 들면 이렇다. 토픽마다 QoS profile이 붙는데, 이는 메시지를 반드시 보낼지 아니면 놓쳐도 넘어갈지를 정하는 설정이다. 보내는 쪽과 받는 쪽의 설정이 맞아야 메시지가 건너간다.
ROS2의 기본 통신 설정은 신뢰성 보장(RELIABLE)인 데 반해, 상당수 카메라나 LiDAR 드라이버는 전송 손실을 감수하고 속도를 우선하는 방식(BEST_EFFORT)을 채택한다. 보내는 쪽이 BEST_EFFORT인데 받는 쪽이 RELIABLE이면 메시지가 안 온다.
지난주에 토픽이 들어오는 것을 보고 잘 맞아 있다고 적어 두었어도, 그동안 누가 받는 쪽을 기본값으로 돌려놓았다면 그 줄은 이제 틀렸다. 읽어서 틀린 티가 나지는 않는다. 그래서 적어 둔 파일을 열고 적어 둔 명령을 그대로 다시 돌린다.
답 하나마다 붙는 기록이 있듯, 작업 공간 전체를 놓고 같은 일을 하는 메모도 하나 있다. 여기에는 프로젝트의 목표가 무엇인지, 지금 기준으로 삼는 코드 경로가 어디인지, 어느 dataset과 split을 쓰고 있는지, 실험과 원고가 어디까지 왔는지, 심사에서 걸릴 만한 곳이 어디인지를 적는다.
메모 끝에는 다음 작업에도 적용할 교정 사항을 둔다. 부록 B의 빠른 시작 문서는 이런 메모를 실제로 채운 예다. 같은 것을 두 번 바로잡았다면 이 메모에 올려 두고, 다음에 이 파일을 여는 사람이 그 사실을 알고 시작하게 한다.
이 메모를 어디에 둘지도 함께 정한다. 채우다 보면 심사 의견 원문과 미공개 숫자가 같이 들어오는데, 이런 줄을 둘 곳은 공개 저장소와 다르다.
반복되는 실패 유형과 운영 규칙과 공개용 template은 공개 저장소에 둔다. 개인 대화 원문과 개인 경로와 심사 의견 원문과 미공개 숫자와 인증 정보는 로컬 기록에 남긴다. 부록 D에서도 이 경계를 다시 시작할 때 확인할 항목으로 꼽는다.
읽어서 되짚을 수 있는 것은 여기까지다. 메모는 지난번에 눈으로 보고 적은 값이므로 지금도 그런지는 돌려 봐야 안다.
메모를 읽고 끝내지 않는다. 메모에 적힌 명령을 그대로 다시 돌려 현재 상태와 대조한다. 코드가 그대로여도 container나 split이 바뀌었으면 같은 조건이 아니다.
돌려 봐야 아는 현재 상태는 여섯 군데에 흩어져 있다. 저장소에서는 branch·commit과 수정된 파일 내역을 살피고, 실행 환경에서는 동작 중인 process·container·device 상태를 점검한다. 데이터에서는 dataset의 version과 split과 calibration을, 지표에서는 metric 출력과 plot과 실패한 실행을 확인한다. 원고에서는 TeX diff와 figure 원본과 table을 열고, 마지막으로 project memory와 인계 메모에서 지난 작업의 방향을 찾는다.
마지막 항목이 과거의 작업 맥락을 기술하는 기록이라면, 앞선 다섯 항목은 현재 시점에서 직접 열거나 재실행해 검증해야 할 실체다. 메모를 누가 썼든 어느 하나로도 다른 항목의 상태를 대신 확인할 수는 없다. 저장소가 깨끗해도 container는 그때 그대로일 수도, 아닐 수도 있다. metric 출력이 남아 있어도 지금 코드에서 나온 값인지는 데이터 쪽을 따로 봐야 안다.
실행 쪽을 여는 방법은 부록 F의 로봇 실험 문제 해결 안내서에 모아 두었다. 환경을 갈아엎기 전에 pip show와 dpkg -l | grep과 apt policy로 지금 무엇이 깔려 있는지 적는다.
새 terminal에서 package를 못 찾으면 echo $AMENT_PREFIX_PATH로 지금 걸린 workspace를 읽는다. 토픽이 안 들어올 때 ros2 topic list와 ros2 node list를 함께 찍으면 노드가 안 뜬 것인지 이름이 다른 데 붙은 것인지가 갈린다. 적어 둔 줄에는 그 갈래가 남지 않는다.
모델이 읽어 둔 정보도 같은 방식으로 낡는다. 우리가 파일을 열고 명령을 돌리는 동안 그 결과가 모델의 맥락 창에도 그대로 쌓이기 때문이다.
앞의 cookbook은 아무 관리도 하지 않은 실행 하나에서 창을 무엇이 채우는지 측정했다. 최대 335,279 토큰까지 갔고, 그중 96.3%는 파일을 읽어 들인 내용이었다. 도구 호출 기록은 1.9%, 모델의 추론은 1.7%였다.
창에 든 것의 거의 전부는 어느 시점에 읽힌 파일의 사본이다. 그 파일이 그 뒤에 바뀌면 모델은 옛것을 들고 답한다. 우리 메모와 같은 이유로 낡지만, 창 안에는 낡았다는 표시가 생기지 않는다.
낡는 것을 막을 수는 없으니 다시 읽을 자리를 창 밖에 둔다. 같은 실험에서는 세션을 두 번 이어 돌려 이 차이를 쟀다. 첫 세션의 탐색 결과를 파일로 빼 둔 경우 둘째 세션을 5K 토큰이라는 가벼운 상태로 시작한 반면, 기록을 남기지 않은 조건에서는 문서 8개를 다시 불러오느라 332K 토큰까지 치솟았다.
여기서 말하는 창 밖은 우리 디스크다. 모델이 앞에서 든 여섯 가지 파일 작업 가운데 하나를 요청하면 우리 쪽 도구가 그것을 로컬에서 실행하므로, 모델이 쓴 것도 우리가 적은 기록과 같은 파일 시스템에 놓인다.
긴 작업은 단계마다 기록을 남긴다
긴 작업을 한 세션에 맡기기 어려운 이유는 과제 길이를 달리한 측정에서도 드러난다. METR이 재는 방식은 이렇다. 과제별로 숙련자가 완료하는 데 소요되는 시간을 매겨 둔 뒤, 모델의 완료 성공률이 50%에 도달하는 과제 소요 시간을 해당 모델의 역량 지표로 평가한다. 2026년 1월 기준 가장 앞선 값은 320분이다. 이는 가장 앞선 모델이 숙련자 기준 320분짜리 과제를 절반의 확률로 끝냈다는 뜻이다.
이 값은 빠르게 오른다. 두 배가 되는 데 걸린 기간은 전체 구간에서 196.5일, 2023년 이후에는 130.8일, 2024년 이후에는 88.6일이었다. 다만 측정에는 한계가 있다. 8시간 넘는 과제 31개 가운데 사람 시간이 실제로 측정된 것은 5개뿐이고 나머지는 추정이며, 신뢰구간도 아직 넓다.
과제 길이에 따라 성공률이 떨어지는 양상은 모형으로도 설명된다. 사람에게 걸리는 시간이 1분 늘 때마다 일정한 확률로 실패한다고 놓으면 관측된 곡선이 대체로 맞는다는 모형이 있다. 그렇게 놓으면 과제가 길어질수록 성공률은 지수 함수 꼴로 떨어진다. 길이를 두 배로 늘리면 성공률은 제곱이 된다. 긴 일에는 하위 단계가 여럿 있고 그중 하나만 어긋나도 전체가 어긋나기 때문이다.
모델 열 종으로 에피소드 23,392건을 돌린 조사에서 pass@1 평균은 짧은 과제 76.3%에서 아주 긴 과제 52.1%로 내려갔다. 분산은 커졌다. 긴 과제의 결과 분산이 짧은 과제의 두 배를 넘는 모델이 있었고, 잘하는 모델일수록 그랬다.
창에 남은 정보를 모델이 실제로 쓰는지도 측정했다. 프런티어 모델 18종을 놓고 입력 길이만 늘려 가며 잰 2025년 조사에서, 시험한 모든 구간에서 성능이 떨어졌다. 창이 다 차기 한참 전부터 그랬다.
창의 불필요한 맥락을 제때 비워 주면 과제 성능이 개선되기도 한다. Anthropic의 내부 평가에서는 agentic search의 성능이 기본 설정 대비 맥락 정리만으로 29%, 외부 기억 도구까지 함께 썼을 때 39% 향상됐다. 이는 성공률의 퍼센트포인트 차이가 아니라 기준 대비 상대 향상이다. 별도로 제시한 100턴 웹 검색 실험에서는 맥락 정리를 쓴 경우 토큰 소비가 84% 줄었다. 성능 향상 수치와 토큰 절감 수치는 각각의 평가 조건과 함께 읽어야 한다.
긴 작업을 한 세션에 밀어 넣지 않는다. 사람 기준 몇 시간을 넘길 일은 걸음마다 기록을 남겨 끊어 간다. 창에 정보가 남아 있다는 것과 모델이 그것을 쓴다는 것은 다르다.
연구 작업은 며칠에서 몇 달이어서 320분 선을 넘기는 경우가 많다. 한 세션에 전부 맡기기보다 단계마다 기록을 파일로 남기고, 다음 세션에서 그 기록을 읽어 이어 가야 한다.
모델이 쓴 요약은 원자료가 아니다
지금까지 다룬 기록은 확인한 파일과 명령 결과를 함께 남긴 것이다. 그런데 작업 공간에는 모델이 줄여 쓴 글도 함께 쌓인다. 대화 끝에 붙는 압축본, 다음 세션에 넘기려고 써 둔 인계 메모, project memory에 적힌 몇 줄이 그것이다. 이 셋은 확인 기록과 나란히 놓이지만 같은 무게로 쓰면 안 된다.
대화 끝에 붙는 압축본은 compaction이 만든다. 우리가 시켜서 도는 것이 아니다. 창이 일정 크기에 닿으면 저절로 걸린다. 앞의 cookbook은 이 연산이 창 전체에 걸린다고 적었다. 사용자가 한 말, 모델이 한 말, 도구 호출, 도구 결과, 앞서 한 압축의 결과까지 모두가 요약 하나로 뭉뚱그려진다.
뭉뚱그려진다는 말은 여기서 되돌릴 수 없다는 뜻이다. cookbook이 돌린 실행에서 압축 한 번은 180K 토큰짜리 앞 대화를 약 2,783 토큰으로 줄였다. 줄어든 자리에 무엇이 있었는지는 그 요약만으로 되살릴 수 없다.
같은 cookbook은 clearing이라는 다른 방식을 제시했다. 이 방식은 다시 불러올 수 있는 지난 결과를 창에서 덜어내면서 그 호출이 있었다는 기록은 남긴다. 호출 기록은 결과를 다시 확인할 길을 남기지만, 명령어만 같다고 같은 출력이 보장되지는 않는다. 입력 파일과 실행 환경이 달라지거나 외부 서비스가 갱신될 수 있으므로, 필요한 결과와 당시 조건은 앞서 제시한 원칙대로 명령과 구분해 기록한다.
clearing은 되돌릴 길을 남기지만 compaction은 남기지 않는다. 그래서 compaction이 지나간 뒤의 요약은 그 자체로 확인할 방법이 없는 글이 된다. 되돌릴 길을 창 밖에 두려면 exclude_tools에 memory를 적어 그 결과만은 덜어내지 않게 한다.
인계 메모와 project memory도 마찬가지다. compaction이 지나가지 않아도 모델이 줄여 쓴 글이라, 그 글만 놓고는 어느 대목이 어디서 왔는지 갈리지 않는다. 갈리려면 원문을 옆에 놓아야 한다.
요약을 확인할 때 원문이 필요한 까닭을 다룬 연구가 있다. Maynez 등은 뉴스 기사와 요약문을 나란히 놓고 판정자들에게 기사에 없는 내용이 요약에 들어간 구간을 표시하게 했다.
이 과제에서 판정자들은 기사를 함께 읽었다. 기사에 없는 내용이 들어간 요약문은 전체의 70%를 넘었다. 뉴스를 한 문장으로 요약하는 과제에서 2020년 요약 모델을 평가해 얻은 값이다.
인계 메모를 읽을 때도 같은 조건이 필요하다. 옆에 파일을 놓고 줄마다 맞춰 본다.
메모만 읽어서 걸러 낼 수 있는 것은 앞뒤가 맞지 않는 문장뿐이다. 그러나 사실과 어긋난 문장도 앞뒤는 맞게 읽힐 수 있다. "calibration을 다시 맞춘 뒤 성능이 올랐다"는 줄에는 틀린 데가 없다. 언제 만졌는지가 적혀 있지 않아, 그 줄만 놓고는 참인지 거짓인지 가릴 길이 없다.
Ji 등의 환각 조사가 이런 출력에 이름을 붙여 두었다. 원문을 아무리 뒤져도 참인지 거짓인지 가릴 근거가 없는 쪽을 extrinsic hallucination이라 부른다. 같은 조사는 읽는 쪽에서 왜 안 걸리는지도 적었다.
Hallucinated text gives the impression of being fluent and natural despite being unfaithful and nonsensical.
요약을 원 자료로 쓰지 않는다. 인계 메모나 압축본을 읽을 때는 옆에 원문 파일을 놓고 줄마다 맞춘다. 앞뒤가 맞는 채로 틀린 문장은 메모만 읽어서는 안 걸린다.
문장의 겉모습으로는 참과 거짓이 갈리지 않으니, 가르는 기준을 세션 첫머리에 미리 박아 둔다. 부록 B에는 상태 메모와 함께 첫 세션에 넣을 프롬프트도 있는데, 거기 이 한 줄이 들어 있다.
Do not infer project truth from summaries when source files or artifacts are
available.
작업을 다시 시작하면 현재 상태부터 확인한다
옆에 파일을 놓고 맞춰 보면 될 일이다. 그런데 며칠 만에 앉으면 파일 대신 요약을 읽게 된다. 자리를 비운 며칠 사이 기계가 무엇을 했는지 알려면 돌아와서 남은 것을 읽는 수밖에 없기 때문이다.
며칠 자리를 비운 뒤 요약만 읽는 사람도 자동 장치를 손대지 않고 지켜본 사람과 같은 처지에 놓인다.
Endsley는 상황을 안다는 것을 셋으로 갈라 놓았다. 지금 무엇이 있는지 알아채는 일, 그것이 무슨 뜻인지 잡는 일, 곧 어떻게 될지 내다보는 일이다.
Endsley와 Kiris는 1995년 내비게이션 실험에서 수동 주행과 자동 주행 환경의 상황 인식을 대조했다. 자동화 주행 환경의 참가자들은 단순 정보 지각 수준은 유지했으나, 상황의 의미를 종합적으로 이해하는 능력 면에서는 유의미한 저하를 보였다. 해당 실험은 지각과 이해 단계만 측정했으므로 향후 예측력까지 단정할 수는 없다.
Endsley가 그 실험을 자기 글에서 다시 정리하며 지켜보는 사람의 처지를 적었다.
When acting as monitor of an automated system, people are frequently slow in detecting that a problem has occurred necessitating their intervention.
자동 장치를 지켜보는 사람은 개입이 필요한 문제가 생겼다는 사실을 자주 늦게 알아챈다는 말이다. 알아챈 다음에도 일이 남는다.
Once detected, additional time is also needed to determine the state of the system and sufficiently understand what is happening in order to be able to act.
알아챈 뒤에도 지금 상태가 어떤지 파악하고 무슨 일인지 충분히 이해해야 손을 댈 수 있는데, 거기에 시간이 또 든다는 말이다.
이 실험을 연구실 작업에 그대로 옮길 수는 없다. 다만 요약을 읽고 "여기까지 했지"라고 떠올리는 일도 먼저 무엇이 남아 있는지 알아채는 데서 시작한다. 어디에 무엇이 있었는지는 요약으로 찾을 수 있다. 그것이 지금도 같은 상태인지는 명령을 돌려 봐야 알 수 있다.
3장 점수와 판정의 근거를 확인한다
점수는 객관적인 지표처럼 보이지만, 단발성 수치와 자동 채점기의 판정에는 각기 다른 검증 절차가 필요하다. 실행값을 비교할 때는 반복 측정을 통해 변동 범위를 확인해야 하며, 자동 채점기 판정 역시 샘플을 추출해 원자료와 대조하는 확인을 거친다. 실제로 벤치마크 네 종의 과제 496개를 전문가가 다시 검토한 감사에서는 채점기 판정과 사람 판정이 92건 달랐다. 18.5%에 해당한다. 상태 대조가 지나치게 엄격해 맞은 답을 틀렸다고 판정한 경우, 정답 자체가 잘못된 경우, 문자열이 포함됐는지만 보고 통과시킨 경우가 있었다.
점수는 반복 횟수와 함께 적는다. 한 번 실행한 값만으로 비교를 확정하지 않는다. 비용이 허락하는 한 동일 조건에서 3회 이상 반복 실행하여 최솟값과 최댓값을 포괄하는 범위를 함께 남긴다.
그러나 반복과 불확실성을 함께 기록하는 관행은 아직 널리 자리 잡지 않았다. 기계학습·자연어처리 학회 여섯 곳의 2018~2024년 논문 46,114편을 살펴 벤치마크 논문 445편을 추린 조사에서는, 결과를 비교할 때 불확실성이나 통계 검정을 사용한 논문이 16%였다. 나머지는 수 하나와 다른 수 하나를 나란히 두고 더 크다고 썼다.
널리 쓰이는 벤치마크 60종을 검토한 연구에서는 29종이 이미 포화 상태였다. 모델들이 상위 구간에 몰려 서로를 구별하기 어려운 상태다.
모델의 자기평가만으로 답의 진위를 가릴 수 없을 뿐더러, 외부 기준으로 삼는 벤치마크 점수조차 채점기 오류나 성능 포화 현상의 영향을 받기 마련이다. 따라서 점수 하나를 그대로 판정 기준으로 삼지 말고, 반복 횟수와 실행 조건을 함께 기록해야 한다. 한 번 실행해 나온 수만 표에 적어 다음 결정을 내리면 그 결정도 그 수의 흔들림을 벗어나지 못한다.
자기 평가는 확인 근거가 되지 않는다
모델에게 자신이 낸 답을 다시 채점하게 해도 실제 파일이나 실행 결과가 새로 생기지는 않는다. 판정 문장은 하나 더 붙지만, 그 답을 확인할 근거는 그대로다.
그래서 이 책은 모델의 자기평가만으로 무엇이 맞는지 결정하지 않는다. 무엇을 보았고 무엇을 실행했는지는 적게 하되, 맞는지는 사람이 파일을 열어 판단한다.
근거에 따라 말할 수 있는 범위가 달라진다
명령이 낸 결과를 바탕으로 어디까지 말할 수 있는지는 무엇을 함께 확인했는지에 따라 달라진다.
| 자료 | 예 | 말할 수 있는 범위 |
|---|---|---|
| 원 파일 | 소스 코드, config, TeX, CSV, log | 파일 안에서 직접 확인한 내용 |
| 실행 결과 | command output, generated figure, metric result | 해당 실행에서 나온 결과 |
| 조건을 확인한 결과 | dataset, split, metric, baseline을 확인한 숫자 | 같은 조건 안의 비교 |
| 요약 | handoff, compact summary, memory note | 다음에 확인할 위치 |
| AI 추정 | 원인 추정, 구조 해석, 요약 판단 | 확인해야 할 설명 |
이 표는 옳고 그름을 가르는 기준표가 아니라, 각 자료가 실제로 증명할 수 있는 한계와 유효 범위를 오른쪽 칸에 명시한 것이다.
원 파일에서는 파일 안에 적힌 것만 확인할 수 있다. 코드가 저장소에 있다는 사실과 그 코드가 실행됐다는 사실은 다르므로, 파일을 열어서는 후자를 알 수 없다.
실행 결과로는 한 걸음 더 나아갈 수 있다. 그 실행에서 실제로 나온 값이므로 실행됐다는 사실까지 말할 수 있다. 다만 결과 파일에 조건이 함께 기록되지 않았다면, 그것만으로는 다른 실행과 비교할 수 없다.
조건까지 확인하면 그 결과를 비교할 수 있다. dataset과 split과 metric과 baseline을 대조했으므로 같은 조건 안에서는 두 수치를 나란히 놓을 수 있다. 조건 밖으로 벗어나는 순간에는 다시 그렇게 할 수 없다.
요약만으로는 원래 상태를 확인할 수 없다. 모델이 줄여 쓴 글이므로, 그 안의 어느 대목이 참인지 가리려면 원 자료가 필요하다. 따라서 요약문은 사실을 확정하는 최종 근거보다 검토할 원본 위치를 안내하는 색인으로 활용해야 마땅하다.
AI 추정도 내용을 확정하는 근거가 아니다. 어떤 파일이나 실행 결과를 바탕으로 했는지 드러나지 않는 설명이라면, 확인할 거리로만 사용한다.
앞의 기록은 이 표의 여러 줄에 대응한다. 모델이 만든 설명은 AI 추정에, 실제로 확인한 파일은 원 파일에, 실행한 명령과 나온 결과는 실행 결과에 해당한다. 각 기록에는 실제로 확인한 자료에 맞는 범위를 적는다.
가령 final_results.csv를 열어 숫자를 확인했다면, 우선 그 파일 안의 내용을 읽었다고 말할 수 있다. 그 숫자를 만든 명령과 config까지 찾으면 해당 실행에서 나온 결과인지 확인할 수 있다. 다른 결과와 비교하려면 dataset과 split과 metric과 baseline도 대조해야 한다.
같은 실험 숫자를 다시 볼 때 먼저 물을 내용은 정해져 있다. 어느 dataset의 어느 split인지, 그 지표는 값이 큰 쪽이 좋은지 작은 쪽이 좋은지, 어느 metric script와 어느 baseline인지, 실제로 읽은 출력이 무엇인지다.
이 항목을 채우면 그 숫자가 어느 조건에서 나온 값인지 정해지고, 같은 조건의 baseline과 비교할 수 있다. final_results라는 이름만으로는 그 조건을 하나도 알 수 없다.
## 4장 연구를 다시 시작할 때
작업을 재개할 때는 열어 볼 대상의 우선순위를 미리 정해 두어야 한다. 정해 둔 순서가 없으면 손에 잡히기 쉬운 요약문부터 읽게 되며, 요약의 오류는 읽는 동안 쉽게 드러나지 않는다.
- 현재 repo와 공개/비공개 경계 확인.
- project memory나 handoff 문서를 통해 진행 방향 파악.
- 관련 소스 및 설정 원본 파일 탐색.
- 실행 결과가 필요한 경우 command와 output path를 대조한다.
- 원고 작업 시 table, figure, paragraph 일치 여부 확인.
- summary와 원본 파일이 충돌하면 원본 파일을 최우선한다.
- 다음 구체적 실행 행동 하나만을 확정한다.
처음에 경계를 확인하는 까닭은, 뒤이어 하는 모든 일이 결국 무언가를 적는 일이기 때문이다. 지금 열어 둔 저장소가 공개 영역인지 로컬 영역인지 확인하지 않고 쓰기 시작하면 심사 의견 원문이나 미공개 수치가 공개 저장소에 들어갈 수 있다.
1단계부터 3단계까지가 근거 자료를 탐색·열람하는 구간이라면, 4단계 이후는 구체적인 명령과 실행 결과를 검증하는 과정이다. 요약의 역할은 셋째까지다. 무엇을 열지 안내할 수는 있어도, 무엇이 사실인지는 판단하지 못한다.
그래서 작업을 시작할 때는 요약 전체를 넣기보다 먼저 열어 볼 이름만 넘긴다. Anthropic은 경로·질의·링크만 남겨 두었다가 필요할 때 불러오는 방식을 just in time이라 부르며, 자료를 미리 벡터로 바꿔 넣는 방식과 구분했다. 미리 넣는 자료가 많아질수록 창 안의 토큰도 늘고, 토큰이 늘면 앞에서 살핀 context rot이 생긴다.
셋째와 넷째 단계에서는 파일과 실행 조건이 서로 맞는지 확인한다. 코드가 같아도 split이 달라졌다면 같은 조건이 아니기 때문이다. 원본 파일을 확인할 때는 config, split, calibration file을 함께 열어 대조하며, 명령과 출력 경로를 확인할 때도 실행 당시의 container와 환경 변수를 면밀히 살핀다.
원고 작업에는 다섯째 단계가 더 필요하다. 문단에서 인용한 수치가 방금 확인한 실행 결과에서 나온 값인지 대조하는 일이다. 이 대조를 하려면 TeX diff, figure 원본, table을 함께 열어야 한다.
열어 본 원 파일이 요약과 다르면 여섯째 단계로 간다. 기존 요약을 덮어쓰지 말고, 어긋난 지점과 현재 확인한 값을 새 기록에 남긴다. 그래야 다음에 무엇이 어긋났는지 비교할 원본이 사라지지 않는다. 같은 항목에서 두 번 어긋났을 때에는 상태 메모의 교정 사항으로 올린다.
한 번에 하나만 바꾼다. branch와 config와 script와 원고 문단을 한꺼번에 손대지 않는다. 하나만 바꿔 두면 다음번에 수치가 달라졌을 때 확인할 변경점이 줄어든다. 반복 실행의 변동과 환경 변화도 함께 확인한다.
여러 곳을 한꺼번에 고치면 수치가 달라졌을 때 변경점을 하나씩 되짚으며 원인을 찾아야 한다.
다음 행동 하나를 정한 뒤 멈추는 편을 택할 때도 있다. 더 물어도 답이 나오지 않아서가 아니다. 답은 계속 나오지만 근거가 더 늘지 않을 때 멈춘다. 부록 D는 이를 다섯 경우로 나눈다. 같은 단계에서 근거가 그대로인 경우, 도구 실패와 방법 실패가 섞인 경우, 실험 조건은 바뀌었는데 숫자를 비교하려는 경우, 심사 위험은 남아 있는데 문장 다듬기만 반복하는 경우, 비공개 자료가 공개 문서에 섞일 위험이 있는 경우다. 이 다섯 자리에서 AI는 계속 답할 수 있다. 멈출지는 사람이 정한다.
멈추든 계속하든, 그날 실행한 일을 기록에 남긴다. 다음에 다시 앉는 사람이 어디부터 열지 그 기록에서 알 수 있기 때문이다.
실행 전에 작업 범위와 근거를 정한다
다시 시작해 이어 가는 작업에서는 요청 하나가 쉽게 커진다. 로그 분석으로 시작한 일이 코드 수정으로 번지고, 마침내 실험 해석과 원고 문장까지 따라오는 일도 있다.
이렇게 번진 요청은 여러 곳을 함께 바꾸므로, 결과가 달라졌을 때 원인 후보도 함께 늘어난다. 기록해 둔 작업을 다시 실행할 때 그사이 바뀐 곳이 하나라면 그 변경의 영향을 먼저 확인할 수 있다. 결과 차이의 원인인지 확정하려면 다른 조건과 실행의 변동도 대조해야 한다.
요청의 번짐은 하나의 요청이 실행되는 동안 일어난다. 그 과정에서 언제 도구를 부를지 정하는 절차는 연구에서 먼저 제안됐다.
ReAct는 모델이 생각을 한 줄 적고 행동을 한 번 하는 일을 번갈아 하도록 했다. 행동으로 지식 베이스나 환경에서 새 정보를 얻고, 그 정보를 바탕으로 계획을 고친다. Toolformer는 계산기, 질의응답, 검색, 번역, 달력 API를 언제 부를지와 어떤 값을 넘길지를 모델이 스스로 정하도록 학습시켰다.
두 연구에서 모델은 능동적으로 외부 도구를 호출하여 그 반환값을 다음 의사결정의 입력으로 삼았다. 연구 현장에서는 연구자가 그 도구 출력을 사후에 재검토한다. 원고 문장의 근거로 제시하고 심사 의견에 답할 때도 활용한다.
도구 출력은 모델의 설명과 함께 작업 기록에 들어온다. 따라서 도구를 불렀다는 사실과 그 출력으로 어디까지 말할 수 있는지는 나누어 봐야 한다. git diff, ros2 출력, metric CSV, PDF 빌드 결과마다 각각 무엇까지 근거로 삼을 수 있는지 짚어 둔다.
도구를 부르는 일을 여러 에이전트에 나눌 수도 있다. Anthropic의 multi-agent research system은 하나가 조율하고 나머지가 일을 나눠 수행하는 구조를 설명한다. 앞의 하나는 lead agent, 뒤의 여러 개는 subagent라 부른다.
Anthropic은 Opus 4 하나가 lead를 맡고 Sonnet 4 여럿이 subagent로 붙은 구성을, Opus 4 하나만 쓴 구성과 자체 평가에서 비교했다. multi-agent 구성의 점수는 단일 에이전트 구성보다 90.2% 높았다. 다만 문서에는 무엇을 재는 평가였는지 적혀 있지 않다.
병렬로 도구를 호출한 쪽은 순서대로 하나씩 호출한 쪽보다 복잡한 질의에 걸리는 시간을 최대 90%까지 줄였다.
문서는 그 성과에 든 비용도 적었다. 에이전트 하나는 일반 대화보다 약 4배의 토큰을 쓰고, 여러 에이전트를 병렬로 세우면 약 15배까지 늘어난다. 문서는 같은 평가에서 token usage by itself explains 80% of the variance라고 썼다. 사용한 토큰의 양이 결과 차이 대부분을 설명했다는 뜻이다.
반대로 여러 에이전트가 맞지 않는 경우도 문서에 적혀 있다. 서로 같은 맥락을 계속 공유해야 하거나, 한 에이전트의 결과에 다음 에이전트가 깊게 의존하는 일이다. 대부분의 코딩 작업과 실시간 조율도 여기에 들어간다.
연구실에서 코드를 고치고 그 결과를 실험 해석과 원고 문장에 연결하려면 맥락을 많이 공유해야 하고 단계 사이의 의존도도 높다. 여러 에이전트가 단일 dataset과 config를 실시간 공유해야 하는 데다, 후속 추론이 선행 단계의 정밀한 출력에 직결되기 때문이다.
에이전트를 하나만 두더라도 돌아온 결과를 확인하는 일은 사람의 몫이다. 앞에서 살핀 자동화의 역설이 여기에도 적용된다. 사람이 실시간으로 따라가며 볼 수 없으므로, 작업이 끝난 뒤 남은 기록을 살핀다.
한 번에 바뀐 곳이 여러 곳이면 그 모두를 확인해야 한다. 확인할 지점을 하나로 제한하려면 한 번의 AI 작업이 바꿀 수 있는 범위도 좁게 정해야 한다.
앞서 말한 기록은 답을 받은 뒤에 남긴다. 이와 달리 변경 허용 범위는 모델의 답변을 열람하기 전에 사전에 확정해 두어야 한다. 매끄러운 답을 받으면 거기서 제안한 수정까지 따라가기 쉬워져, 작업 범위를 모델의 제안에 맡기게 된다.
그래서 요청을 보내기 전에 부록의 experiment-contract.md를 연다. 계약 양식에는 실험 조건과 명령어를 명시하는 항목들이 나열되어 있으며, 그중 핵심은 Evidence Gate라 불리는 검증 관문이다. 이 실행으로 말해도 되는 것, 말하면 안 되는 것, 그 선을 넘으려면 무엇이 더 필요한지를 적는 세 줄이다.
이 세 줄은 실행 전에 쓴다. 결과를 보고 난 뒤에 쓰면 나온 수치에 맞춰 기준을 바꾸게 된다. 좋은 값이 나온 뒤에는 주장을 넓히기 쉬우므로, 범위를 사후 판단에 맡기지 않고 미리 정한다.
연구 작업의 종류부터 정한다
바꾸려는 대상은 지금 하는 일이 어느 갈래에 속하는지에 따라 달라진다. 갈래마다 근거로 삼는 것이 다르기 때문이다. 구현 디버깅에서는 실행 출력이 근거지만, 원고 주장을 고칠 때는 실험 조건이 근거다. 둘을 한 요청에 섞으면 어떤 근거로 무엇을 결정했는지 남지 않는다.
증상이 어느 단계에서 발생했는지도 먼저 가른다. 부록의 stage-local-debugging.md는 단계별로 범위에 넣을지를 묻고, 넣었다면 근거를 옆 칸에 쓰게 한다. 근거 칸이 비어 있는 단계는 아직 짐작일 뿐이다. 짐작한 단계를 범위에 넣어 고치기 시작하면, 고친 뒤에도 그것이 원인이었는지 알 수 없다.
연구 작업은 성격에 따라 대략 여덟 갈래로 분류할 수 있다. 이전 세션을 이어받는 작업은 상태 복원 범주에 들고, 코드·Docker·ROS2 이슈 해결은 구현 디버깅에 해당한다. 새로운 실험 조건을 설정하는 단계는 실험 설계이며, 도출된 수치와 표를 분석하는 작업은 결과 해석으로 구분할 수 있다. 논문에서는 실험을 주장에 연결하거나, 원고 주장의 근거를 고치거나, 심사 의견에 답한다. 새로움과 비교 위치를 정하는 일은 관련 연구 정리에 속한다. 지금 하는 일에 이 가운데 한 이름을 붙일 수 없다면 요청이 번졌다는 신호다.
에이전트의 실행 권한을 먼저 정한다
갈래를 정한 다음에는 그 안에서 AI가 어디까지 할 수 있는지도 먼저 정한다. 읽기와 실행 사이에 선을 긋지 않으면 요청한 일과 실제로 일어난 일이 달라질 수 있기 때문에, 권한 범위를 따로 살펴야 한다. 파일만 보자고 했는데 파일을 고쳐 돌아오면 나중에 무엇이 바뀌었는지 다시 추적해야 한다.
권한은 대략 다섯 단계로 나뉘며, 뒤로 갈수록 되돌리기 어렵다. 읽기와 분석만 맡기거나 구조와 계획만 제안받는 단계에서는 파일이 바뀌지 않는다. 명령 실행을 허용하되 파일 수정은 따로 확인하는 단계부터 상태가 달라질 수 있다. 명령은 파일을 고치지 않아도 프로세스, 캐시, 결과 디렉터리를 남기기 때문이다. 수정까지 맡기면 저장소가 바뀌고, 실행과 결과 확인까지 요구하면 그 결과가 다음 판단의 근거가 된다.
따라서 고를 때 묻는 것은 어디까지 맡길 수 있느냐가 아니다. 어긋났을 때 되돌릴 수 있느냐다. 파일을 읽기만 해야 한다면 읽기만을 요청하고, 실행 결과가 있어야 다음 판단을 할 수 있다면 실행 요청을 적는다.
적어 둔 권한을 지키는 것은 사람의 몫이다. 기계에도 그 권한을 지키는 조건을 걸어 둘 수 있다. Claude Code의 hook은 정해진 지점에 셸 명령, HTTP 요청, 모델 프롬프트를 하나 걸어 두는 장치다.
지점은 세 주기로 나뉜다. 세션당 한 번 실행되는 것(SessionStart·SessionEnd), 요청당 한 번 실행되는 것(UserPromptSubmit·Stop), 도구를 부를 때마다 실행되는 것(PreToolUse·PostToolUse)이다.
이 가운데 PreToolUse에 걸어 둔 명령이 종료 코드 2를 내면 해당 도구 호출은 막힌다. 무엇을 막을지는 그 자리에 연결한 스크립트가 정한다.
이번 작업에 읽기만이라고 적었다면 편집 도구가 호출될 때 2가 나오도록 설정한다. 그러면 호출은 그 자리에서 멈춘다. 종료 코드 대신 JSON으로 {"decision": "block", "reason": ...}를 내보내면, 막은 이유도 기록에 함께 남는다.
완료 보고에는 다시 확인할 근거를 남긴다
막은 이유든 실행 결과든, 작업이 끝나면 파일에 적힌 흔적으로 남는다. Anthropic의 Claude Code 사용 분석은 성공을 두 가지로 나누어 셌다.
하나는 모델이 대화를 읽고 성공이라고 판단한 경우이고, 다른 하나는 나중에 다시 열어 볼 수 있는 흔적이 남은 경우다. 뒤의 기준으로 세려면 통과한 테스트, 실제로 들어간 commit, 목표에 맞는 명령 출력, 사용자가 분명히 밝힌 확인 가운데 하나가 필요했다.
작업을 마치고 작성하는 완료 보고에도 동일한 검증 요건이 부과된다. 미래에 그 보고서를 열람할 주체는 본인 자신이며, 당시에 의존할 수 있는 유일한 단서는 보고서에 명기된 실물 파일과 명령어 흔적뿐이다.
에이전트를 여러 개 두는 경우에도 이 조건은 같다. Anthropic이 긴 작업의 맥락을 다루는 방법으로 제시한 것은 compaction, 구조화된 메모 남기기, 그리고 sub-agent였다.
sub-agent는 각자 좁은 일을 맡고 1,000~2,000 토큰짜리 요약만 돌려준다. sub-agent가 무엇을 읽었든 lead agent가 받는 것은 그 요약뿐이다. 그래서 그 문서는 맥락을 잘 다루는 일을 "finding the smallest possible set of high-signal tokens that maximize the likelihood of some desired outcome"이라고 설명했다.
완료 보고도 같다. 어떤 단어로 기록하느냐에 따라 다음에 그 파일을 여는 사람이 손에 쥐는 정보가 달라진다.
| 넓은 보고 | 더 나은 보고 |
|---|---|
| 시스템을 고쳤다 | command X 실행 뒤 warning signature Y가 사라졌다 |
| 성능이 좋아졌다 | 같은 조건 P에서 metric M이 baseline B에 비해 어떻게 달라졌는지 적었다 |
| 논문 답변이 준비됐다 | Table 2 조건과 답변 범위를 맞췄다 |
| repo를 이해했다 | 파일 A/B/C와 남은 질문 D를 확인했다 |
완료 보고에 다시 열어 볼 이름을 적는다.
시스템을 고쳤다대신 어느 명령 뒤에 어떤 신호가 사라졌는지,성능이 좋아졌다대신 어느 조건에서 어느 지표가 어느 baseline과 견줘 어떻게 됐는지를 적는다.
오른쪽 칸의 command X, 조건 P, Table 2, 파일 A/B/C는 다음에 다시 열어 확인할 수 있는 이름이다. command X를 재실행하고 조건 P를 다시 맞추면 보고의 내용과 실제가 어긋난 지점이 드러난다.
이런 보고가 쌓이면 같은 어긋남이 두 번째로 나타난 지점도 이름으로 확인할 수 있다. 후속 작업은 완전히 새로운 세션 환경에서 출발하므로, 다음 세션에서 다시 열 수 있도록 기록과 산출물을 파일 시스템에 남겨 두어야 한다. 텍스트뿐 아니라 그림과 데이터도 그 근거에 포함된다.
그래서 두 번 나타난 어긋남은 다음 세션을 시작할 때 확인할 규칙 한 줄로 옮긴다. SessionStart는 세션당 한 번 실행되므로, 그 줄을 읽어 오는 일을 여기에 걸어 둘 수 있다.
규칙의 내용은 당면한 오류 유형에 따라 차별화된다. 원본 대신 요약문만을 토대로 답변을 작성한 전력이 있다면 원본 파일 직접 열람을 첫 작업으로 강제한다. 저장소에 존재하는 소스코드를 런타임 활성 코드로 오인한 경우라면, 모듈 이름과 실제 런타임 콜스택 대조를 선행 조건으로 지정할 수 있다. 2부의 표는 이러한 유형별 오류에 붙일 표준 라벨을 체계화해 둔다. 나아가 심사 의견을 단순 문장 다듬기로 무마하려 했던 기록이 포착되면, 다음 세션은 주장·근거 대조표 작성부터 착수하도록 유도한다.
논문 문장, 공개 코드, 실행 결과를 근거로 어디까지 말할 수 있는지는 2부에서 하나씩 가른다.
2부 실험 결과에서 논문의 주장까지
논문에 적힌 방법, 저장소에 공개된 코드, 실제 실행 기록은 서로 다른 근거다. 논문의 방법 설명은 저자의 주장이다. 공개 코드는 현재 저장소에 어떤 구현이 들어 있는지를 보여 주지만, 그 코드가 해당 실험에 쓰였다는 사실까지 증명하지는 않는다. 실행 기록은 그 코드가 현재 환경에서 어떤 경로를 지나 어떤 결과를 냈는지 남긴다.
논문과 저장소를 함께 살펴 다시 실행하려면 먼저 세 근거를 나누어 기록한다. 저장소에 파일이 있다는 사실만으로 그 파일이 실험에 쓰였다고 볼 수 없기 때문이다.
다시 돌려 본다는 말의 뜻은 NeurIPS 2019 Reproducibility Program 보고서에 적혀 있다. 같은 코드와, 구할 수 있다면 같은 데이터로 논문이나 발표에 실린 결과와 비슷한 결과를 얻는 일이다. 이 보고서는 연구 결과를 믿어도 되는지 확인하려면 이 단계를 거쳐야 한다고 보았다.
이 프로그램의 점검표는 다섯 절로 나뉘며, 그 가운데 이론적 주장, 공개한 코드, 보고한 실험 결과를 각각 별도 절로 다룬다. 무엇을 주장했는지, 무엇을 공개했는지, 무엇을 실행해 얻었는지를 섞지 않는 구분이다.
논문에 적힌 구성요소를 저장소에서 찾았다면 두 가지를 더 확인해야 한다. 해당 구성요소가 config를 거쳐 실제로 호출되는지, 그리고 실행 결과에 직접 영향을 미치는지 여부다.
논문 초록과 저장소 README에도 구성요소의 이름과 역할이 적혀 있을 수 있다. 다만 둘 다 축약된 요약본에 불과하므로, 실제 구현 상태를 판단할 때는 소스 파일과 실행 경로를 직접 검증한 기록을 남겨야 마땅하다.
## 5장 논문·코드·실행은 서로 다른 근거다
기록할 자리는 표 형태로 체계화한다. 부록의 paper-code-experiment-map.md가 이에 해당하며, 논문 한 편마다 하나의 표를 작성해 관리한다. 이때 재실행의 출발점은 대상 코드와 데이터를 명확히 가르는 일이다. 저장소에서 탐색한 파일이 실제 런타임 경로에 온전히 포함되는지 살피고, 데이터 역시 기록에 남은 dataset과 split 정보를 기준으로 특정한다.
표에 넣을 항목은 2부의 양식을 따른다. 논문 주장, 코드 경로, 실제 호출 경로, 명령과 metric script, 원고에서 말할 수 있는 범위 다섯 줄이다.
| 항목 | 적을 내용 | 채우는 시점 |
|---|---|---|
| 논문 주장 | 논문 표·그림의 숫자와 주장 문장 | 실행 전 |
| 코드 경로 | 저장소에서 찾아낸 파일 경로 | 실행 전 |
| 실제 호출 경로 | 돌려 봤을 때 실제로 지나간 경로 | 돌려 본 뒤 |
| 명령과 metric script | 다시 돌려 보는 데 쓴 것 | 돌려 본 뒤 |
| 말할 수 있는 범위 | 앞의 네 항목으로 원고에 쓸 수 있는 범위 | 앞이 다 찬 뒤 |
표에는 위에서 아래로 이어지는 순서가 있다. 먼저 논문 주장을 옮긴다. 어느 표와 그림의 문장인지까지 적어 두면, 다음에는 그 표와 그림을 바로 찾아갈 수 있다.
이어 저장소에서 이름으로 탐색한 코드 경로를 명시한다. 실제 호출 경로는 런타임 검증을 거쳐야 확인되므로 바로 아래 칸에 배치하기 마련이다. 두 경로의 일치 여부는 있는 그대로 기재하며, 이 차이가 뒤에서 라벨을 구분 짓는 기준이 된다.
넷째 줄에는 재실행에 사용한 구체적 명령과 metric script를 기록한다. 마지막 줄은 앞선 항목들이 모두 채워진 뒤 결론 문장으로 작성하되, 원고 서술 시에도 해당 줄에 확정된 범위만을 인용한다.
이 표는 필요한 파일을 한꺼번에 펼치지 않고, 다음에 열 대상을 경로로 남겨 두는 역할도 한다. 논문 전문과 저장소 전체를 한꺼번에 모델에 넣으면 맥락이 길어지고, 1부에서 본 context rot 때문에 필요한 대목을 정확히 되짚기 어려워진다.
Anthropic은 파일 경로나 질의, 링크처럼 가벼운 이름만 들고 있다가 실행 시점에 그 자리에서 불러오는 방식을 just in time이라고 설명했다. 표의 둘째 줄에 참조 식별자를 적어 두고, 이를 열어 실행해 얻은 결과는 셋째 줄에 수록한다.
논문과 코드에서 확인할 여섯 항목
표를 채울 때는 다음 질문으로 논문과 저장소를 살핀다. 실행 전에는 문서와 코드의 위치를 확인하고, 실제 호출 경로와 config 사용 여부는 실행 뒤의 기록으로 확인한다.
- 논문 주장이 어느 절·표·그림에 있는가
- 공개 코드에서 그 모듈이 어디 있는가
- 그 모듈이 실제 예제에서 호출되는가
- config key가 실행 시점에 읽히는가
- 논문 표의 숫자를 만든 script가 지금 저장소에 공개되어 있는가
- 논문 시점과 지금 branch 사이에 규약이 바뀌었는가
첫 질문은 원고에서 주장할 수 있는 범위를 정한다. 이어 모듈 경로를 찾아야 실제 호출 여부와 config 사용 여부를 확인할 수 있다. 마지막 두 질문은 논문을 쓰던 시점의 실행 규약과 현재 저장소의 규약이 같은지를 묻는다.
필요한 대목만 차례로 여는 구조는 에이전트가 자료를 읽는 방식에도 쓰인다. Anthropic의 Agent Skills는 지시와 script와 자료가 든 폴더를 에이전트가 찾아 필요할 때 불러 쓰게 하며, 그 폴더를 여는 단계를 셋으로 나눴다.
각 폴더에는 SKILL.md 한 장이 있고, 그 안에는 이름과 사용 시점이 적혀 있다. 1층에서는 이 두 줄만 모델에 미리 보여 준다. 2층에서는 관련 있다고 판단되면 SKILL.md 본문을 읽고, 3층에서는 같은 폴더의 다른 파일을 필요할 때 연다.
Anthropic은 이 구조를 잘 정리된 매뉴얼에 비유했다. 목차에서 시작해 장을 거쳐 자세한 부록으로 가되, 필요한 만큼만 불러온다. 앞 절에서 세운 질문도 답이 나온 지점에서 다음 단계로 내려간다.
구현 상태는 증거로 분류한다
답이 모이면 모듈의 상태를 한 단어로 부를 수 있다. 실제로 구현되어 있는지와 실행을 확인했는지에 따라 다음 가운데 하나를 붙인다.
| 라벨 | 의미 |
|---|---|
| active | runtime에서 호출되고 결과에 영향을 준다 |
| disabled | 구현되어 있으나 꺼져 있다 |
| configured-unused | config에는 있으나 실행 경로 밖에 있다 |
| planned-only | 문서나 issue에만 있다 |
| tested-failed | 시도했으나 실패 기록이 있다 |
| dead | 남아 있으나 현재 경로 밖에 있다 |
| unknown | 확인 전 |
라벨은 확인한 근거와 함께 붙인다. 문서나 issue에만 계획이 남아 있다면 planned-only, flag로 꺼져 있다면 disabled로 적는다. 실제 호출과 결과 영향을 따지는 active, configured-unused, dead는 실행 경로를 확인해야 구분할 수 있다. tested-failed에는 시도한 명령과 실패 기록이 필요하다.
unknown은 질문은 정했지만 아직 답을 얻지 못했다는 표시다. 실행한 뒤 근거가 생기면 알맞은 라벨로 바꾼다. 빈칸은 질문하지 않은 것인지 해당 사항이 없는 것인지 알 수 없으므로, 확인할 항목에는 빈칸 대신 unknown을 쓴다.
이렇게 하면 파일을 읽어 답할 수 있는 일과, 현재 branch와 config로 실행한 출력이 있어야 답할 수 있는 일이 나뉜다. AI에 맡길 일도 이 경계에 맞춰 정한다.
AI는 논문에서 방법의 구성요소를 뽑고, 저장소에서 관련 function과 class와 config를 찾고, issue thread와 README에 적힌 규약 변화를 모은다. 위 질문 가운데 5와 6의 답은 코드 본문 밖에 있으므로 AI가 YAML, launch command, issue comment, 실패한 sequence, 표 caption까지 확인하도록 한다.
실행 결과를 봐야 알 수 있는 항목은 사람이 확인한다. 실제 호출 여부, config 값이 실행 경로에 도달했는지, dataset과 metric 조건이 같은지, 그 근거로 원고에서 어디까지 말할 수 있는지가 여기에 해당한다.
AI가 추출할 항목은 구성요소 이름, function, config key, 규약 변화로 구성되며, 추출된 답을 수납할 칸 역시 사전에 규격화해 둔다. 따라서 칸의 이름과 형식을 먼저 지정하고 그 형식에 맞는 답만 받게 할 수 있다.
Claude API의 structured outputs가 이를 위한 장치다. 답의 형식을 스키마로 정하면 모델이 그 형식을 벗어난 답을 아예 낼 수 없게 한다고 설명한다. 칸 이름을 스키마로 걸어 두면 돌아온 답은 그대로 표의 한 줄이 된다.
다만 스키마가 보장하는 범위는 알고 써야 한다. 칸 이름과 종류를 정하고, 반드시 있어야 할 칸을 지정하는 데까지는 가능하다. 값이 정규식에 맞는지, 길이가 얼마 이하인지 같은 조건은 스키마 밖이므로 따로 확인해야 한다.
따라서 스키마는 필요한 칸과 값의 형식을 고정할 뿐, 그 값이 사실인지까지 확인하지 않는다. 칸에 적힌 경로를 실제 실행에서 거쳤는지는 앞의 라벨과 실행 기록으로 판단한다.
논문이 말한 위치와 실행 경로의 라벨이 어긋나면 1부의 방식처럼 한 번에 하나씩 바꾸며 범위를 좁힌다. 좁히는 동안 다시 확인하는 대상은 라벨을 붙인 근거다.
active로 적은 줄에는 그 라벨의 근거가 된 명령과 config를 함께 남긴다. 다음에 그 줄을 열면 같은 명령을 다시 실행해 라벨이 그대로인지 확인한다. 그리고 그 명령이 내놓는 숫자에는 조건이 붙어야 한다.
6장 실험 결과가 원고의 수치가 되기까지
로보틱스 metric에는 여러 조건이 함께 붙는다. dataset과 split, sensor와 frame, calibration과 alignment, metric script, 실패 처리 방식, baseline 중 하나라도 달라지면, 같은 이름의 metric이라도 서로 다른 조건을 측정한 값이 된다. 따라서 두 수치를 나란히 비교하려면 이 조건들이 같아야 한다.
그 일치 여부는 수치를 낸 쪽이 무엇을 함께 공개했는지에 달려 있다. benchmark가 수치와 함께 평가 script, dataset 규약, 실패 처리 방식을 내놓는 까닭도 여기에 있다. 다른 사람이 같은 수를 다시 얻으려면 그 정보가 필요하다.
앞서 본 재현성 보고서에는 코드와 데이터가 들어갔다. 로보틱스에서는 sensor 입력, frame, calibration, alignment까지 더 적어야 한다. 오차가 낮거나 성공률이 높거나 지연이 짧다고 원고에 쓰려면, 그 수치가 나온 조건도 함께 밝혀야 한다.
실행 환경의 조건을 수치로 명시한 사례도 있다. Anthropic의 code execution tool 문서는 Claude가 명령을 실행하고 파일을 다루는 sandbox의 경계를 설명한다. 해당 규격에 따르면 메모리와 디스크 할당량은 각각 5 GiB, CPU는 단일 코어로 제한되며 셀 단위 코드 실행은 90초의 제한 시간을 둔다.
이 sandbox에서 얻은 수치라면 그 경계값 역시 수치의 조건이 된다. 연구실 기계에서 측정한 값이라면 그 기계의 경계값도 조건으로 붙는다.
수치가 어느 기계와 dataset에서 측정됐는지 되짚으려면, 실행 전에 확인할 항목을 정해 둔다. 어느 dataset의 어느 split인지, 지표는 큰 값이 좋은지 작은 값이 좋은지, 어느 metric script와 baseline을 썼는지, 실제로 읽은 출력은 무엇인지 적는다. 이런 조건을 확인할 수 있는 수치만 원고의 근거로 쓴다.
이 내용은 실행을 시작할 때 적어 두어야 한다. 나중에 맞추려 하면 명령 이력, config 파일, 결과 디렉터리를 따로 열어야 한다. 셋은 서로 다른 시점의 상태를 담고 있을 수 있으므로, 어느 것이 해당 실행 당시의 것인지 분명하지 않을 수 있다.
먼저 수치의 조건을 적는다. 어느 dataset의 어느 split과 sequence인지, 어느 sensor로 무엇을 받아 무엇을 내는지, 정답 좌표계와 alignment는 무엇인지, metric과 기준값과 baseline은 무엇인지 남긴다.
로보틱스에서는 특히 좌표계와 alignment가 자주 어긋난다. 같은 궤적도 어느 좌표계에서 오차를 재는지에 따라 다른 양이 나오며, 추정 궤적을 정답에 맞추는 방식을 바꾸면 같은 실행에서도 다른 오차가 나온다. 기준값도 마찬가지다. 값을 조금만 옮겨도 같은 실행의 성공률이 달라진다.
조건 다음에는 같은 명령을 다시 실행하는 데 필요한 정보를 적는다. 명령과 config, 결과가 저장될 경로, 제한 시간, 실패 구간을 처리한 방식이다.
실패 구간을 어떻게 처리했는지 빠뜨리면 숫자가 실제보다 좋아 보일 수 있다. 추적을 놓친 구간을 평균에서 제외하면 남은 구간만으로 평균이 계산되기 때문이다. 결과 파일이 나오면 결과 경로도 채운다. 여기까지가 실행 하나를 위한 최소 기록이다.
숫자보다 결과물의 완전성을 먼저 확인한다
실행이 끝난 뒤에는 metric 값을 읽기 전에 결과물부터 확인한다. 최소 기록은 실행을 걸 때 정한 조건일 뿐, 실제로 그 조건대로 실행됐는지는 나온 파일을 열어 봐야 알 수 있다. 설정과 다르게 실행돼도 metric은 숫자를 내놓으므로, 숫자부터 보면 잘못 실행된 결과를 성능으로 읽게 된다.
아래 일곱 항목은 결과 디렉터리를 처음 연 사람이 하나씩 확인할 내용이다. 실행 하나만 열어도 답할 수 있는 항목이어서 이 표에 모았다.
| 항목 | 확인 내용 |
|---|---|
| coverage | 입력 구간과 출력 구간이 서로 맞는가 |
| output count | 예상 출력 수와 실제 출력 수가 맞는가 |
| timestamp span | 시작/종료 시간이 맞는가 |
| frame/calibration | frame convention과 calibration이 같은가 |
| preprocessing | resize, crop, filtering, normalization 조건이 같은가 |
| cache/checkpoint | 현재 model과 config에서 나온 결과물인가 |
| failure policy | 실패 구간을 평균이나 집계에서 어떻게 처리했는가 |
첫 세 항목은 실행이 끝까지 진행됐는지를 확인한다. 출력 구간이 입력 구간보다 짧다면 일부 구간만 평가됐을 수 있다. 출력 수가 부족하면 중간에 누락된 부분이 있는지 살피고, 시작과 종료 시각이 예상과 다르면 실행 구간부터 다시 확인한다. 이런 차이는 metric 값만 보아서는 드러나지 않을 수 있다.
가운데 두 항목은 조건이 그대로 유지됐는지를 확인한다. frame convention이나 calibration이 이전과 달라지면 그럴듯한 숫자가 나와도 다른 양을 측정한 셈이다. resize, crop, normalization이 달라지면 모델이 받은 입력과 그 해석도 달라진다.
cache/checkpoint 항목은 실행 환경이 요청 사이에 상태를 유지할 때 중요하다. 앞의 code execution tool 문서에는 두 종류의 상태 유지가 적혀 있다. 하나는 컨테이너다. 약 5분 동안 사용하지 않으면 현재 상태가 저장되었다가 같은 컨테이너로 복원되며, 30일이 지나면 만료된다. 다른 하나는 변수다. 도구 버전을 code_execution_20260120 이후로 올리면 변수에 담긴 값도 요청 사이에 남는다.
상태가 이어지면 앞 요청에서 만든 변수나 파일을 이번 요청이 다시 참조할 수 있다. 이때 지금 config를 바꿨어도 결과물에 이전 상태가 반영됐을 수 있다. 그래서 결과물을 열어 그것이 현재 model과 config에서 나온 것인지 확인한다.
마지막 항목은 앞에서 본 실패 처리다. 실패 구간을 제외하거나 다르게 집계하면 숫자가 좋아 보일 수 있으므로, 수치와 함께 처리 방식을 확인한다.
숫자를 읽기 전에 결과물부터 연다. 설정과 다르게 실행돼도 metric은 숫자를 내놓는다. 입력 구간과 출력 구간이 맞는지, 출력 수가 예상과 같은지 먼저 확인한 뒤 값을 읽는다.
하나라도 어긋나면 그 수치는 보류한다. 어긋난 항목을 최소 기록에 남겨 두면 다음에 같은 실행을 확인할 때 어디부터 열어야 할지도 정해진다.
두 실험을 비교할 조건부터 맞춘다
결과물이 맞는 것을 확인한 뒤에야 수치를 baseline이나 지난번 수치 옆에 놓는다. 그 전에 두 실행이 같은 것을 측정했는지 아래 항목으로 확인한다.
아래 항목은 두 수치를 한 표에 넣기 전에 서로 맞대어 확인한다. output path는 실행마다 따로 확인하는 값이지만, 엉뚱한 결과 파일을 읽으면 나머지 조건을 모두 맞춰도 비교가 무효가 되므로 같은 표에 둔다.
| 항목 | 확인 내용 |
|---|---|
| task input/output | 어떤 입력에서 어떤 출력을 평가하는가 |
| ground truth | 정답 파일, 좌표계, 시간 범위가 같은가 |
| threshold | success/failure를 가르는 기준이 같은가 |
| baseline | 같은 조건의 baseline인가 |
| metric script | 지난번과 같은 script인지 |
| output path | 실제로 읽은 결과 파일이 맞는지 |
여섯 항목은 각기 다른 방식으로 두 수치를 갈라놓는다. task input/output에서는 처음부터 다른 문제를 풀었는지 확인한다. metric 이름이 같아도 무엇을 넣고 무엇을 평가했는지가 다르면 비교할 수 있는 값이 아니다.
ground truth와 threshold가 다르면 같은 실행에서도 숫자가 달라진다. 정답 파일, 좌표계, 시간 범위가 달라지면 다른 양을 측정하게 된다. 성공과 실패를 가르는 기준값을 조금 옮기기만 해도 방법을 하나도 고치지 않고 성공률이 달라진다.
baseline에서는 비교 대상이 같은지 확인한다. 다른 조건에서 측정한 baseline 옆에 우리 수치를 놓으면, 무엇과 비교해 올랐다는 것인지가 사라진다.
metric script는 이름이 같아도 내부가 다를 수 있다. script가 바뀌면 같은 입력에서도 다른 값이 나올 수 있고, 바꾼 사람이 우리가 아니라면 바뀐 사실조차 알기 어렵다.
앞의 다섯 조건을 모두 맞췄더라도 마지막으로 output path가 맞는지 확인한다. 조건을 아무리 맞춰도 지금 읽는 파일이 그 실행의 결과가 아니면 소용없다.
이 가운데 metric script, baseline, 결과 경로는 실행을 걸 때 최소 기록에 이미 적어 둔 항목이다. 그때 적은 값과 지금 읽는 값이 같을 때 두 수치를 한 표에 넣는다.
metric script 항목에는 script 이름뿐 아니라 실행에 사용한 라이브러리 버전도 포함한다. 앞서 본 code execution tool의 sandbox처럼 실행 중 패키지를 새로 받을 수 없고 사전 설치된 패키지를 쓰는 환경에서도, 문서의 패키지 목록만으로는 실제 설치 버전까지 알 수 없다. 같은 script라도 의존성 버전이 달라지면 결과가 달라질 수 있으므로, sandbox든 연구실 기계든 실행 환경에서 확인한 버전을 함께 적는다.
원고의 수치에는 조건을 붙인다
두 표를 확인하고 나면 그 수치로 어디까지 말할 수 있는지가 정해진다. 원고에는 비교 조건이 드러나는 문장을 쓴다.
같은 dataset, 같은 sensor 입력, 같은 metric script를 쓴 baseline보다 main metric이 개선되었다.
성능이 향상되었다처럼 조건이 없는 문장은 보류한다. 오차가 낮거나 성공률이 높다고 쓸 때는 어느 dataset과 sensor 입력에서, 어느 metric script로 계산한 baseline과 비교했는지를 함께 밝힌다.
표 caption에도 같은 규칙을 적용한다. metric 표에는 수치와 비교 조건이 함께 있어야 한다. caption에 무엇을 쓸지는 그 표가 무엇을 측정했는지에 따라 달라진다.
로보틱스 원고에는 metric 표 외에도 실행 중 일어난 사건의 횟수를 센 표가 들어간다. 이런 표에는 센 횟수만 직접 드러난다. 그 결과가 다음 단계의 입력으로 쓰여 영향을 미쳤다고 적으려면 추가 근거가 필요하다. 표 아래 설명도 표가 뒷받침하는 범위를 넘지 않는다.
실패한 실행도 결과로 기록한다
결과 파일이 나온 실행에는 결과 경로와 metric을 채울 수 있다. 중간에 멈춘 실행도 버리지 않고, 어디까지 진행됐으며 무엇 때문에 멈췄는지 남긴다.
제한 시간 초과, 메모리 부족, sensor dropout, 추적 실패, 빠진 sequence, metric script 실패, 잘못된 정답 파일은 다음 실험의 조건을 정하는 자료가 된다. 최소 기록의 실패 처리 항목에는 집계 시 실패 구간을 처리한 방식을 명시하며, 중간에 멈춘 실행에 대해서도 최종 진행 단계와 중단 지점을 꼼꼼히 남겨 둔다.
실패가 어느 지점에서 일어났는지에 따라 다음에 확인할 곳이 달라진다. 따라서 원인을 추측하기 전에 신호가 끊긴 단계를 먼저 구분한다.
AI에 증상을 물으면 QoS, calibration, cache, normalization 같은 원인 후보를 빠르게 얻을 수 있다. 그러나 후보를 받자마자 수정하면 현재 실행 경로를 확인하기 전에 원인을 단정하게 된다. 어느 단계에서 신호가 끊겼는지 먼저 육안으로 확인한 뒤 제시된 후보와 대조한다.
1부에서 인간공학 연구자 Endsley가 상황을 안다는 일을 셋으로 나눈 것을 보았다. 지금 무엇이 있는지 지각하는 일, 그 의미를 이해하는 일, 가까운 미래를 예측하는 일이다.
실패 기록에도 이 구분을 적용한다. 눈으로 확인한 신호, 그 신호가 끊긴 단계, 아직 검증하지 않은 원인 후보를 서로 다른 칸에 적는다. 한 칸에 섞어 쓰면 관측한 사실과 추측을 구분하기 어렵다.
7장 실패 원인을 단계별로 좁힌다
복잡한 로보틱스 pipeline에서는 단계마다 증상이 다르게 나타난다. 어디에서 흐름이 끊겼는지에 따라 확인할 대상도 달라지므로, 먼저 각 단계에 이름을 붙인다.
input
preprocessing
representation
matching
geometry
optimization
evaluation
아래의 두 목록은 이 일곱 이름을 그대로 사용한다. 어떤 목록을 볼지는 지금 나타난 증상에 따라 정한다. 첫 번째 목록은 문제가 특정 단계에 국한될 때 빠르게 원인을 좁히는 데 쓰이며, 두 번째 목록은 일곱 단계를 처음부터 차례로 짚어가며 점검할 때 쓴다.
입력 신호가 없을 때 확인할 순서
받는 쪽 callback이 비어 있다면 신호는 input에서 멈춘 상태다. 그 뒤의 여섯 단계는 아직 입력을 받지 못했으므로, 이때 확인할 단계는 input 하나뿐이다. 수정하기 전에 다음 순서로 살핀다.
ros2 topic list로 topic 존재 확인ros2 topic info --verbose로 QoS 확인- publisher/subscriber namespace 확인
use_sim_time과/clock확인- container device, network, volume 확인
- 이어서 코드 또는 launch 수정
각 항목을 확인할 때마다 현재 단계, 관측한 신호, 다음에 볼 항목을 기록한다. 1부터 5까지는 모두 input 단계 안의 확인이다. 예를 들어 topic 이름은 목록에 보이는데 callback이 비어 있다면, 다음에는 같은 단계에서 QoS profile을 확인한다.
1부에서 본 것처럼 ROS2 기본값은 반드시 보내는 RELIABLE이고 sensor data profile은 놓쳐도 넘어가는 BEST_EFFORT다. driver와 받는 쪽이 서로 다르면 메시지가 오지 않을 수 있으며, 2는 바로 이 어긋남을 확인하는 단계다.
topic이 실제로 들어오는 것을 확인한 뒤에야 다음 단계로 preprocessing을 적는다. container device, network, volume처럼 실행 환경에서 나타나는 증상은 부록 F의 로봇 실험 문제 해결 안내서에서 확인 경로를 찾을 수 있다.
1의 ros2 topic list를 AI가 대신 실행하고 결과를 옮겨 준다면 한 가지를 더 확인해야 한다. 도구가 돌려주는 응답에는 길이 제한이 있을 수 있다.
Anthropic의 도구 작성 지침은 도구가 신호가 분명한 정보만 에이전트에 돌려주어야 한다고 설명한다. 긴 응답은 페이지로 나누고 범위를 좁히거나 필요한 항목만 걸러 내도록 권한다.
Claude Code는 도구 응답을 기본 25,000 토큰으로 제한하며, 제한에 걸리면 응답 뒤쪽이 잘린다. 따라서 예상보다 짧은 목록을 받았다면 실제로 빈 목록인지, 길이 제한 때문에 잘린 것인지 먼저 구분한다. 잘린 목록이라면 topic 이름을 좁혀 다시 실행한다.
성능 저하는 입력 단계부터 추적한다
성능 수치 하나가 떨어졌다면 그 값은 일곱 단계를 모두 거쳐 나왔다. 앞 절에서는 비어 있는 callback 하나로 끊긴 지점을 input으로 좁힐 수 있었다. 그러나 모든 단계를 지난 값에서는 일곱 단계가 모두 후보로 남는다.
뒤 단계는 앞 단계의 출력을 받아 동작하므로, 앞이 어긋나면 뒤도 함께 어긋난 것처럼 보인다. 어느 단계에서 문제가 생겼는지는 위에서부터 하나씩 확인한다. 수정하기 전에 다음을 본다.
- dataset, split, sensor input 범위 확인
- timestamp, frame, calibration 확인
- preprocessing과 normalization 확인
- cache, checkpoint, intermediate output 확인
- matching, geometry, optimization의 입력과 출력 확인
- metric script와 failure policy 확인
- 이후 model architecture, training 설정, control parameter 수정
일곱 이름은 데이터가 흐르는 순서다. input으로 들어온 데이터를 preprocessing이 손질하고, representation이 다루기 좋은 형태로 바꾼다. 이어 matching이 짝을 찾고, geometry가 위치를 잡고, optimization이 전체를 맞춘다. 마지막으로 evaluation이 결과를 숫자로 잰다.
위 목록의 번호도 이 순서를 따른다. 1과 2에서는 input과 그 조건을 확인한다. 3에서는 preprocessing에 속한 normalization을 보고, 4에서는 representation이 남긴 cache, checkpoint, intermediate output을 확인한다.
5에서는 matching, geometry, optimization의 입력과 출력을 한 줄에서 확인한다. 6에서는 evaluation에 사용하는 metric script와 failure policy를 점검한다. 앞 절에서 숫자마다 dataset과 split과 metric script를 적어 두었다면, 1과 6에서는 그 기록을 그대로 대조할 수 있다. 7에서는 일곱 이름을 모두 확인한 뒤 비로소 model architecture, training 설정, control parameter 수정에 들어간다.
확인 결과는 같은 형식으로 적는다
앞의 두 목록에서는 각 항목이 하나의 확인이 된다. 다음 세션에서도 같은 지점을 다시 열려면, 이 확인들이 한 파일에 같은 형식으로 쌓여 있어야 한다. 부록의 stage-local-debugging.md가 그 형식이다.
양식에는 성공 신호와 실패 신호를 실행 전에 적는다. 무엇이 나오면 성공으로 볼지 정하지 않은 채 실행하면, 나온 출력에 맞춰 기준이 바뀐다. 기준은 실행 전에 적을 때만 고정된다.
실행이 끝난 뒤 채우는 칸에는 이 확인으로 말할 수 있는 것과 말할 수 없는 것을 적는다. ros2 topic list를 실행해 본 확인이라면 허용되는 주장도 input 단계까지다.
눈으로 확인한 신호를 적는 칸에는 하나만 적는다. 앞 절에서 언급한 도구 작성 지침은 오류 메시지를 다음에 무엇을 해야 하는지 알려 주는 말로 쓰라고 권한다. traceback을 통째로 붙여 넣은 확인과, input에서 어느 topic이 비어 있었는지를 적은 확인은 여기서 구분된다.
이 확인을 한 파일에 쌓아 두면 같은 점검을 반복하고 있는지 살필 수 있다. 옮겨 갈 단계를 적는 칸에 같은 이름이 두 번 연속 나오면, 그사이 새로 확인한 신호가 있는지 본다. 같은 단계에 머물렀더라도 새 근거를 얻었다면 점검은 진전된 것이다.
실행 실패와 방법 실패를 나누어 본다
같은 단계에서 새 근거 없이 점검을 반복했다면 그 단계 안을 한 번 더 나눈다. 같은 단계에 적힌 실패라도 종류에 따라 다음에 할 일이 달라진다. 아래 표의 앞 세 줄은 눈으로 확인한 신호에 따라 구분한다.
| 실패 종류 | 예 |
|---|---|
| 실행 환경 실패 | pip install, CUDA driver, Docker volume, dataset path |
| runtime 실패 | callback 없음, tf lookup 실패, node crash |
| 평가 실패 | wrong frame, wrong split, wrong metric script |
| 방법 실패 | 조건을 맞춰 확인한 뒤에도 성능이 낮음 |
실행 환경 실패는 여러 원인으로 나뉜다. 빌드가 성공했다는 사실은 소스코드가 정상 컴파일되었음을 입증하지만 패키지 의존성, CUDA driver, Docker volume, dataset path의 정상 동작까지 보증하지는 않는다.
같은 명령을 code execution tool 안에서 실행했다면 환경 조건도 달라진다. 앞서 본 것처럼 그 컨테이너는 인터넷이 막혀 있어 실행 중 패키지를 받을 수 없으므로, 필요한 패키지가 미리 설치되어 있는지 확인해야 한다.
컨테이너 복원과 변수 값 유지도 확인한다. 앞 실행의 상태가 이번 실행에 영향을 줄 수 있기 때문이다. 환경을 확인한 뒤에는 callback이나 tf lookup 같은 runtime 신호와 metric script 같은 평가 조건을 각각의 기록에서 대조한다. 출력 파일은 확인 기록의 결과 경로를 직접 열어 현재 실행의 산출물인지 확인한다.
방법 실패는 마지막에 적는다. 실행 환경·runtime·평가라는 앞의 세 가능성을 모두 지운 뒤에야 넷째 줄이 남는다. 도구 실패를 방법 실패로 적으면, 아직 확인하지 않은 지점이 사라진 것처럼 기록된다.
실행 환경, runtime, 평가 조건을 확인하지 않은 실패는 방법 실패로 올리지 않는다. 도구 실패와 방법 실패가 한 기록에 섞이면 어느 조건에서 성능이 낮았는지 알 수 없으므로, 부록 D의 중지 조건에 따라 원인을 다시 분리한다.
evaluation까지 확인을 마친 기록이라야 비로소 성능 수치에 관한 주장을 뒷받침할 수 있다. 반면 input 단계에서 멈춘 기록이라면 그 지점까지 육안으로 검증된 사실에 한해 서술을 뒷받침하는 데 그친다. 이처럼 기록에 남은 단계와 실패 유형에 따라 원고에 허용되는 문장의 범위가 달라지기 마련이다. 이렇게 도출된 문장은 주장과 근거의 쌍으로 정리하여 claim-evidence-map.md에 체계적으로 수록한다.
8장 심사 의견을 주장과 근거로 푼다
심사 의견은 제출 당시 원고를 대상으로 한다. 심사를 기다리는 동안 문장을 다듬었다면, 현재 원고와 심사자가 읽은 문장이 달라질 수 있다. 답변을 준비할 때는 먼저 심사 의견이 겨냥한 원문과 그때의 근거를 다시 찾는다.
의견 하나를 받으면 먼저 원고의 무엇을 겨냥했는지 가른다. 어조를 지적한 의견은 문장을 고쳐 답할 수 있다. 실험 조건을 묻는 의견은 기존 기록으로 답할 수 있는지 확인하고, 근거가 없다면 실험을 더 해야 한다. 주장 범위를 지적한 의견에는 근거에 맞게 범위를 줄여 답한다.
의견이 겨냥한 대상을 가르려면 주장과 근거가 만나는 곳에 이름이 붙어 있어야 한다. Toulmin은 The Uses of Argument에서 실제 논쟁에서 주장이 서는 방식을 나누어 설명했다.
논증에서 내세우는 명제는 claim이라 했다(p.12). “무엇을 근거로 하는가”에 답하는 것은 data다(p.97). 둘 사이에는 다리 하나가 더 필요하다. Toulmin은 그 자리에 놓이는 것을 "general, hypothetical statements, which can act as bridges, and authorise the sort of step to which our argument commits us"(p.98)라고 적었다. 일반적이고 가정적인 진술이 근거에서 주장으로 나아가는 논리를 정당화하는 다리 역할을 한다는 뜻이다.
이 다리가 warrant다. 다리는 그 근거가 왜 그 주장을 받치는지를 말한다. Toulmin은 이 다리가 잘 드러나지 않는다고도 적었다. "data are appealed to explicitly, warrants implicitly"(p.100)라고 했는데, 근거는 드러내 놓고 제시하지만 다리는 적지 않은 채 넘어간다는 뜻이다.
원고에서도 data는 표와 그림으로 드러나지만, 그 숫자가 왜 주장을 뒷받침하는지는 생략되기 쉽다. 이 다리를 문장으로 밝혀 두면 심사 의견이 근거 자체를 묻는지, 근거에서 주장으로 넘어가는 논리를 묻는지 구분할 수 있다.
주장의 범위는 다리와 별도의 자리에 적는다. Toulmin이 qualifier로 따로 둔 자리다. probably, generally, presumably처럼 주장의 세기를 낮추는 말이 여기에 온다. 이 말을 지우면 근거는 그대로여도 주장만 커진다.
의견 하나를 주장·근거 표에 옮긴다
부록 D는 원고 문장에서 시작할 때 claim-evidence-map.md를 쓰라고 적었다. 의견 하나를 이 표의 한 줄로 옮기면, 다음 행동이 어느 칸에서 나오는지 보인다.
| 항목 | 내용 |
|---|---|
| 심사 의견 | 원문 또는 요약 |
| 문제가 된 주장 | reviewer가 겨냥한 문장 |
| 현재 근거 | figure, table, experiment, citation |
| 부족한 근거 | 새로 필요한 실험 또는 계산 |
| 원고 수정 위치 | 고칠 section, table, caption, paragraph |
| 답변 범위 | 답변서에서 말할 수 있는 범위 |
| 남는 한계 | 인정해야 할 한계 |
warrant를 위한 칸은 따로 두지 않고 현재 근거 칸에 함께 적는다. 다리는 그 근거가 무엇을 받치는지 말하는 것이므로, 근거에서 떼어 놓으면 읽을 수 없다.
figure와 table 이름을 적을 때에는 그 숫자가 주장을 어떻게 받치는지도 한 줄로 덧붙인다. 읽는 쪽이 채워 넣던 논리가 표 안으로 들어온다. 심사 의견이 그 연결을 문제 삼는다면 기존 근거로 설명할 수 있는지 확인하고, 부족한 부분은 부족한 근거 칸에 적는다.
답변 범위에 쓸 말은 현재 근거 칸에서 나와야 한다. 그 칸 밖에서 나온 말은 남는 한계로 내려간다.
주장·근거 표는 세션 밖에 보관한다
표를 채우는 동안에는 심사 의견 원문, 겨냥된 문장, 표의 숫자, 새로 실행한 결과가 한 세션에 쌓인다. 1부에서 본 compaction은 이 표에 특히 크게 작용한다. 칸에 적어 둔 것이 대부분 figure와 table 이름 같은 짧은 이름이어서, 요약으로 접히면 그 이름이 무엇을 가리켰는지도 함께 사라지기 때문이다. Anthropic의 context engineering 문서는 무엇이 요약 하나로 뭉뚱그려지는지 이렇게 적었다.
user messages, assistant messages, tool calls, tool results, even prior compaction blocks are all flattened into the summary
사용자가 한 말, 모델이 한 말, 도구 호출과 그 결과, 앞서 접어 둔 요약까지 모두 새 요약 하나에 들어간다는 뜻이다. 요약이 한 번 지나간 뒤에도 현재 근거 칸이 가리키던 이름을 다시 찾으려면, 그 이름은 창 밖의 파일에 적혀 있어야 한다.
이처럼 정보를 맥락 창 밖에 두어 다음 세션까지 남기는 방식을 memory라고 한다. 문서는 이를 "structured note-taking"이라 부른다. 같은 비교에서 memory를 쓴 둘째 세션은 5K 토큰으로 시작했지만, 쓰지 않은 둘째 세션은 문서 여덟 개를 다시 읽어 332K까지 갔다. claim-evidence-map.md를 파일로 두면 필요한 근거만 다시 불러올 수 있다.
파일에 옮겨 적는 일은 압축이 걸리기 전에 마쳐야 한다. 압축이 걸리는 시점은 설정으로 정한다. 손대지 않으면 150K 토큰에서 걸리고, 앞당겨도 50K 아래로는 내릴 수 없다.
Claude Code의 hooks 문서에는 압축 전후에 할 일을 정하는 자리가 있다. 표의 한 줄을 파일로 빼 두는 일을 압축 직전 자리에 걸어 두면, 세션이 압축을 지나도 같은 칸에서 다음 행동을 꺼낼 수 있다.
근거가 갖춰진 뒤에 답변을 쓴다
표를 채우면 의견이 겨냥한 주장, 현재 근거, 부족한 근거가 한 줄에서 나뉜다. 이제 그 근거로 답변서를 쓸 수 있는지 판단한다.
부록 D는 멈춰야 하는 조건 하나로 “심사 위험이 남았는데 문장 다듬기만 반복한다”를 적었다. 답변 문장을 언제 써도 되는지는 아래 세 번째 줄에서 갈린다.
- reviewer comment에서 공격받은 주장을 추출한다.
- 해당 주장이 기대는 table, figure, experiment, citation 탐색.
- 근거가 충분하면 답변 문장 작성.
- 근거가 부족하면 실험, 재계산, 주장 줄이기 중 하나를 선택한다.
- 원고를 고칠 자리를 답변서에 명시한다.
무엇이 지적됐는지 정하기 전에 답을 쓰기 시작하면 엉뚱한 곳을 고치고 정작 필요한 근거는 그대로 둘 수 있다. 근거가 충분한지 먼저 판단해야, 문장 수정으로 답할지 실험·재계산·주장 축소로 답할지가 정해진다.
원고에서 고칠 위치는 이 판단 뒤에 정한다. 위치부터 정하면 그 자리에 맞는 근거만 찾게 되어 순서가 뒤집힌다.
reviewer가 겨냥한 문장이 표의 숫자를 가리킨다면 그 표와 문장을 함께 확인한다. 숫자가 잘못됐는지, 설명이나 주장의 범위가 잘못됐는지에 따라 고칠 자리가 달라진다. 표를 고칠 때에도 이 다섯 단계를 그대로 밟는다. 뽑아 둔 주장이 표 하나를 근거로 삼는다면, 둘째 단계에서는 그 표에 담긴 칸을 확인한다.
어떤 칸을 확인할지는 표의 내용에 따라 달라진다. metric 표는 낮은 오차나 높은 성공률뿐 아니라, 그 수치가 어느 조건에서 나왔는지도 적혀 있어야 비교할 수 있다.
이 책의 표 양식에서는 dataset, sensor, frame, 실패 처리를 표의 칸에 두고, split, calibration, alignment, metric script, baseline은 caption이나 본문에서 보완한다. 다른 양식에서는 배치가 달라질 수 있지만, 어디에 두든 독자가 비교 조건을 빠짐없이 확인할 수 있어야 한다. 빈 조건이 있다면 기존 실행 기록에서 채울 수 있는지, 실험을 다시 돌려야 하는지 가른다.
사건을 센 표는 같은 다섯 단계 안에서도 metric 표와 확인할 항목이 다르다. 표에는 센 횟수만 직접 드러난다. 그 횟수가 다음 단계에 미친 영향까지 말하려면 세 가지를 따로 확인해야 한다. 사건을 제대로 세었는지, 잘못 감지한 사건을 걸러 냈는지, 그 처리가 다음 단계에서 요구하는 시간 안에 끝났는지다.
이 정보는 횟수 표만으로는 알 수 없다. 기존 로그나 분석으로 확인할 수 없다면 추가 실험이 필요하다. caption과 본문은 확보한 근거의 범위까지만 쓰고, 고친 위치를 답변서에 적는다.
근거 없이 문장만 고치면 답변이 약해진다
이 순서를 건너뛰어도 답변서는 완성된다. 다만 완성된 답변서가 원고에 무엇을 남기는지는 달라진다.
| 실패 | 결과 |
|---|---|
| comment를 어조 문제로만 처리 | 비교 조건이나 실험 공백이 남는다 |
robust, general, significant를 추가 |
근거가 받치지 못하는 주장으로 커진다 |
| citation만 추가 | reviewer가 지적한 실험 조건 확인이 빠진다 |
| 공손한 문장부터 작성 | Table, Figure, Section 수정이 빠진다 |
첫째 줄은 의견을 가르는 단계에서 생긴다. 비교 조건을 묻는 comment를 어조 문제로 받으면, 문장이 정중해진 뒤에도 그 조건은 표의 빈칸으로 남는다.
둘째 줄은 근거를 그대로 둔 채 주장만 더 강하게 만드는 손질이다. 셋째 줄의 citation은 다른 연구의 근거이므로, reviewer가 물은 이 원고의 실험 조건을 대신 채워 주지 못한다. 필요한 조건은 이쪽 기록에서 찾거나 실험을 다시 실행해 확인해야 한다.
답변에는 예의가 필요하지만 정중한 표현이 근거를 대신하지는 않는다. 실험 조건을 지적한 의견은 기존 기록에서 조건을 확인해 답하고, 기록이 부족하면 실험을 다시 실행한 뒤 답한다.
그 실행이 앞의 숫자와 같은 조건에서 나왔는지 reviewer가 확인할 근거도 답변서에 있어야 한다.
숫자를 다시 마주했을 때 물으라고 부록 D가 둔 물음에는 split, metric script, baseline 셋이 들어 있다. 그 물음은 어느 dataset의 어느 split인지부터 묻고, 거기에 적힌 dataset이 답변 문장의 범위를 정한다. 여러 dataset에 두루 통한다는 주장을 받치는 근거가 한 dataset에서 나왔다면 답변 문장도 그 dataset에 맞춰 쓴다. 줄인 주장 부분은 남는 한계 칸으로 옮겨 적는다.
9장 심사와 투고에 필요한 검증
심사 의견이 어떤 방식으로 작성됐든, 답변서는 표면적인 어조보다 의견이 지적한 실질적 근거에 초점을 맞추어 답해야 한다. Pangram의 ICLR 2026 심사평 분석은 약 7만 건 가운데 15,899건(21%)을 전부 모델이 쓴 것으로 분류했다. 이 수치는 심사자의 자기 보고가 아닌 검사기의 기계적 판정 결과이며, 개별 심사평의 작성 주체를 단정하지는 않는다. 같은 분석에서는 그렇게 분류된 심사평이 더 길고 점수를 더 후하게 주는 경향도 보고했지만, 이 연관만으로 개별 심사평의 타당성을 판단할 수는 없다.
실무에서 필요한 판단은 앞 장과 같다. 의견이 어조를 짚는지, 비교 조건을 묻는지, 근거가 받치는 주장 범위를 묻는지 먼저 가른다. 조건을 묻는 의견에 문장만 다듬어 답하면 근거의 빈칸은 남는다.
답변서에는 다시 돌려 볼 수 있는 이름을 적는다. baseline을 같은 조건에서 다시 맞췄다면 split, metric script, baseline 이름을 그대로 쓴다. 심사자가 실행 조건을 짚어 볼 수 있어야 한다.
참고문헌이 실제로 존재하는지 확인한다
참고문헌은 형식이 그럴듯하다는 이유만으로 실제 문헌이라고 볼 수 없다. 제목, 저자, 연도, 학회·저널명이 서로 맞는지 원문이나 출판사 페이지에서 대조한다. 원고에 남은 자리표시자나 작성 과정의 메타 코멘트도 투고 전에 별도로 확인한다.
이 문제는 원고를 문장 단위로 다시 읽는 것만으로 놓치기 쉽다. 인용 목록을 DOI나 제목으로 조회하고, 자리표시자와 메타 문구는 별도 항목으로 점검한다.
투고 전에 참고문헌을 하나씩 조회한다. DOI나 제목으로 원문이나 출판사 기록을 확인한다. 링크가 열리지 않으면 서지 오류인지 접근 문제인지 다른 경로로 대조한다. 실재성과 인용 내용을 확인할 수 없는 항목은 확인 전까지 투고용 참고문헌으로 확정하지 않는다.
코드 중심 심사에는 재실행 근거가 필요하다
원고 대신 실행 가능한 산출물을 먼저 내자는 제안이 있다. 저자는 주장마다 이를 뒷받침하는 코드의 위치와 데이터의 위치를 적은 목록을 함께 낸다. 학회 쪽 시스템이 그 환경을 세우고 실험을 돌린 뒤, 주장과 근거를 대조한 보고서를 만들면 사람 심사자는 그 보고서를 읽는다.
이 방식이 자리를 잡든 그렇지 않든 준비물은 이미 정해져 있다. 주장 하나에 근거 하나를 붙인 목록과, 그 근거를 다시 돌릴 수 있는 환경이다. 이 부에서 만든 표가 그대로 그 목록이 된다.
주장·근거 표를 원고와 같은 저장소에 둔다. 원고 문장 하나, 그 문장을 받치는 실행 하나, 그 실행을 다시 돌리는 명령 하나를 한 줄에 적는다.
3부 연구 절차를 에이전트 규칙으로
공개된 agent 저장소에는 연구 작업에도 적용할 만한 습관이 담겨 있다. 작은 단위로 고치기, 가정 밝히기, 실패 보고, 역할 나누기, 도구 호출 기록이 여기에 속한다.
다만 이런 규칙은 대체로 코드를 고치고 도구를 호출하는 절차에 초점을 둔다. 로봇 실험 수치를 다루려면 dataset, calibration, frame, metric, 실패 처리, 심사 위험까지 함께 적어야 한다. 외부 규칙을 가져올 때 이 항목들을 연구 환경에 맞게 보완해야 한다.
에이전트가 도구를 언제, 어떻게 부를지 정하는 방법은 연구에서도 다뤄져 왔다. Yao 등의 ReAct는 모델이 생각을 한 줄 적고 행동을 한 번 하는 과정을 번갈아 내놓게 했다. 적어 둔 생각은 계획을 세우고 진행 중에 고치는 데 쓰인다. 한편 행동은 지식 베이스나 환경에서 정보를 더 얻는 통로 역할을 한다. 이 방식을 집안일 지시를 따르는 과제와 온라인 쇼핑 과제에서 측정했을 때, 앞선 방법보다 성공률이 각각 34%p와 10%p 높았다.
ReAct는 추론과 행동을 번갈아 생성하는 예시를 프롬프트에 주고, 모델이 다음 행동을 고르게 했다. Schick 등의 Toolformer는 API 호출을 포함한 자료로 모델을 학습시켰다. 모델이 어떤 API를 언제 부를지, 어떤 값을 넘길지, 돌아온 결과를 다음 문장 예측에 어떻게 쓸지 배우도록 했다.
두 연구 모두 도구를 호출하고 결과를 다시 추론에 넣는 절차를 썼다. 그러나 어느 dataset의 어느 split을 쓸지, 어느 metric script로 측정할지는 연구자가 정해야 한다. 이 조건이 빠지면 서로 다른 실험을 같은 결과처럼 비교할 수 있으므로 외부 규칙을 그대로 옮겨서는 안 된다.
무엇을 어디에 적을지는 작업이 돌아가는 구조를 보면 정할 수 있다. Anthropic의 Managed Agents는 에이전트가 작동하는 구조를 셋으로 나눴다. session은 일어난 일을 지우지 않고 순서대로 쌓는 기록이다. harness는 모델을 호출하며, 모델이 요청한 도구를 실제 환경에 넘겨 실행하는 loop 구조다. sandbox는 코드가 실제로 돌고 파일이 고쳐지는 실행 환경이다.
연구 workspace에도 이 구분을 적용할 수 있다. 어느 파일을 먼저 읽고 어떤 결과에서 멈출지를 정한 규칙은 harness에 해당한다. 다음 작업에서 다시 읽을 기록은 session에, 실제 파일과 command와 dataset이 놓인 실행 경계는 sandbox에 해당한다.
외부 저장소의 규칙을 가져올 때는 먼저 각 문장이 session, harness, sandbox 가운데 어디에 속하는지 가른다.
10장 외부 에이전트 규칙을 연구에 맞춘다
저장소의 star 수만 보고 규칙을 고르지 않는다. star는 관심의 크기만 나타낼 뿐, 규칙이 지금도 지켜지는지와 연구 작업에 옮길 만한지는 드러내지 않는다.
선택 기준은 유형이다. skill 모음에서는 유용한 습관 문장을 가져올 수 있다. framework 문서의 경우 역할 분리와 도구 넘김의 틀을 참고하기 좋다. 네 가지 유형과 각각에서 살필 항목을 표에 적었다.
| 유형 | 예 | 볼 것 |
|---|---|---|
| coding-agent skill repo | multica-ai/andrej-karpathy-skills |
작은 수정, 가정 명시, 범위 제한, 실패 보고 |
| agent 개념 입문 repo | datawhalechina/hello-agents |
agent, memory, tool use, evaluation 항목 |
| framework 문서 | LangGraph, CrewAI, AutoGen, OpenAI Agents SDK | workflow, role 분리, tool handoff, tracing |
| local research agent repo | alexjunholee/robotics-research-agent |
user reaction prior, 연구 증거 확인 규칙 |
첫 줄의 skill repo는 작업 습관을 다시 쓸 수 있는 단위로 묶어 둔 저장소다. Anthropic은 Agent Skills를 지시, 스크립트, 자료를 한 폴더에 담아 에이전트가 필요할 때 불러 쓰는 방식이라고 설명했다.
폴더마다 SKILL.md 한 장이 들어간다. 파일 맨 위에는 이름과 함께 언제 쓰는지가 한 줄로 적혀 있다. 에이전트는 이 요약 한 줄을 읽고 폴더를 열지 결정한다. 이 설명까지는 skill 제공자가 작성하는 영역이다. 작성된 스킬을 연구 작업의 어느 지점에서 불러올지는 규칙을 가져오는 사람이 판단한다.
표의 볼 것 칸에 적힌 항목도 session, harness, sandbox로 나눈다.
작은 수정, 가정 밝히기, 실패 보고, 역할 나누기, 도구 넘기기는 에이전트가 걸음마다 따를 문장이므로 harness로 간다. 도구 호출을 나중에 되짚을 수 있게 남긴 기록(tracing)과 사용자가 이전에 무엇을 반려했는지 적은 기록(user-reaction-prior.md)은 다음 작업에서 다시 읽어야 하므로 session으로 간다. 실제 저장소와 데이터셋과 명령은 sandbox로 간다.
모든 내용을 규칙으로 옮길 필요는 없다. 입문 저장소의 memory나 evaluation 같은 개념은 분류를 이해하는 데 참고하되, 실제 행동을 바꾸는 문장이 아니라면 규칙 파일에 넣지 않는다.
이 기준에 따라 코딩 규칙은 AGENTS.md로 옮기고, 교육용 저장소에서는 학습 자료의 구성만 참고한다. 도구 목록은 필요한 기능을 찾는 용도로 쓴다. 로보틱스 연구 규칙에는 데이터셋, 지표, 출력, 주장, 심사 위험 항목을 보탠다.
일반 코딩 규칙에는 로봇 실험 정보가 빠져 있다
이 유형에 속한 규칙은 코드와 도구에 집중한다. 로봇 실험 수치를 두고 말하려면 아래 항목이 더 필요하다.
- dataset, split, sequence
- task input/output
- ground-truth frame
- metric script
- failure policy
- implementation status
- result provenance
- 원고에서 말할 수 있는 범위
1부와 2부에서 다룬 이 항목 가운데 앞의 다섯은 실행을 시작할 때 채우는 최소 기록이며, sandbox 안의 파일과 script를 가리킨다.
뒤의 셋은 실행 결과를 해석하는 항목이다. implementation status는 논문 주장과 실제 실행 경로를 대조해 지정한다. result provenance에는 해당 수치가 도출된 실행 맥락을 기록한다. 마지막에는 이 근거로 원고에서 어디까지 말할 수 있는지 범위를 밝힌다.
외부 저장소에서 가져온 문구 옆에는 이 항목들을 따로 붙인다. 빠뜨리면 조건이 다른 수치를 같은 실험처럼 비교할 수 있다. 부록 D(PATH.md)는 실험 조건이 바뀌었는데 숫자를 비교하려 한다를 멈춰야 하는 조건 하나로 적어 두었다.
이런 실수에도 실행 오류가 나지 않을 수 있다. 조건이 바뀐 뒤에도 앞 조건에서 만든 cache를 그대로 읽거나, 이름만 같은 metric script 둘을 한 표에 올리면 숫자는 나오지만 비교 근거는 무너진다. 실행 조건과 provenance를 함께 적어야 이 어긋남이 보인다.
원고에서 말할 수 있는 범위는 뒤에서 claim-evidence-map.md의 주장과 근거로 나누어 적는다.
외부 규칙은 기능별로 나누어 가져온다
외부 규칙을 가져오려면 먼저 기능별로 나눈다. 한 prompt 안에는 도구를 부르는 법, 다음 세션에 남길 상태, 계속 적용할 행동 규칙이 한꺼번에 들어 있을 수 있다. 이를 통째로 옮기면 나중에 한 기능만 고치거나 교체하기 어렵다.
각 문장이 무슨 기능을 하는지부터 묻는다. Model Context Protocol에서는 AI 애플리케이션에 기능을 붙이는 프로그램을 server라고 부른다. 여기서는 server가 제공하는 요소를 셋으로 분류한다. tool은 호출해 동작을 시키는 함수, resource는 읽어서 맥락으로 쓰는 자료, prompt는 대화를 구성할 때 다시 쓰는 틀이다.
가져올 줄에도 같은 질문을 한다. 이 줄은 실행되는 것인가, 읽히는 자료인가, 다시 채워 쓰는 틀인가.
- 외부 repo의 규칙을 기능별로 분류한다.
- Claude, Cursor, Codex 같은 특정 도구에 묶인 호출법 분리
- 다음 작업에도 남겨야 할 상태는
project-memory.json, ledger, replay case로 이관 - 남는 행동 규칙은
AGENTS.md나 template에 정리한다. - 실제 실행 경계 설정 (repo, dataset, artifact, command)
- dataset, metric, 결과물, reviewer risk 항목 추가
- 사용자가 반복해서 반려한 패턴을 문서 앞쪽에 배치
첫째 단계에서는 문구를 기능별로 나눈 뒤, 둘째 단계에서 특정 도구 이름에 묶인 호출법을 떼어 낸다. 이렇게 나누어 두면 필요한 기능만 다시 조합할 수 있다. Anthropic의 도구 작성 지침도 여러 동작을 한 도구로 묶거나, 관련 도구에 같은 이름 앞머리를 붙여 범위를 드러낼 수 있다고 설명한다.
가져온 규칙도 기능별 이름으로 묶는다. dataset 규칙과 원고 규칙을 구분해 두면 다음 요청에서 어느 부분을 읽어야 하는지 분명해진다.
tool·resource·prompt로 문장의 기능을 나눈 뒤에는 session·harness·sandbox에 실제 자리를 정한다. 다음 작업에서 다시 읽을 기록은 session으로, 작업마다 따를 행동 규칙은 harness로, 규칙이 다루는 저장소·dataset·결과물·명령은 sandbox로 간다. 특정 도구의 호출법은 그 도구가 속한 저장소에 남긴다.
다섯째 단계의 실행 경계에는 로봇을 돌릴 때 요소가 하나 더 추가된다. 로봇은 코드가 도는 기계 바깥에서 물리적으로 동작하기 때문이다. 장치, 시계, 네트워크의 현재 상태 역시 이 경계에 포함된다. 이 상태를 구체적으로 기록하는 방법은 다음 절에서 살펴본다.
여섯째 단계에서는 앞에서 정리한 실험 항목을 더한다. 이를 생략하면 규칙을 옮겨도 로봇 실험의 조건과 수치를 추적할 수 없다.
일곱째 단계에서는 사용자가 반복해서 반려한 패턴을 규칙 앞쪽에 둔다. 작업을 시작할 때 먼저 읽게 해야 같은 실수를 되풀이하지 않는다.
일곱 단계를 마치면 규칙은 AGENTS.md와 template 안에 놓이고, 다음 요청부터 에이전트가 읽는다.
반복된 오류는 다음 규칙으로 남긴다
규칙이 지켜졌는지는 산출물에서 확인한다. 따라서 답을 내놓기 직전에 점검할 항목도 규칙 안에 둔다. 부록 B의 첫 요청에는 원문이나 산출물이 있을 때 요약만 보고 현재 상태를 단정하지 말라는 문장이 들어 있다. 작업 전에 읽은 규칙을 마지막에 다시 확인하기 위한 장치다.
답을 내놓기 직전에 스스로 짚을 것을 규칙에 넣어 둔다. 읽지 않은 파일을 읽은 것처럼 말하지 않았는지, 근거 범위를 넘는 주장을 쓰지 않았는지, 실행해야 할 때 계획만 말하지 않았는지를 그 자리에서 본다.
가져온 규칙에도 마지막 점검을 둔다. 위 상자의 세 항목에 더해, 사용자가 반려한 문체나 구조를 반복하지 않았는지와 공개 문서에 내부 작업 기록을 남기지 않았는지를 확인한다.
문제가 발견되면 먼저 산출물을 고친다. 같은 항목이 두 번째로 걸리면 AGENTS.md의 규칙 한 줄이나 replay case로 남긴다. 이 기록을 보면 어떤 규칙이 실제 오류를 줄였는지도 확인할 수 있다.
가져온 규칙을 계속 쓸지는 metric 혼동, cache 실수, 반복되는 reviewer comment가 실제로 줄었는지로 판단한다. 이를 확인하려면 규칙을 적용한 로봇 환경의 상태와 결과를 함께 기록해야 한다.
11장 로봇 실험의 조건을 기록한다
앞 절의 다섯째 단계에서는 실행 경계를 나누라고 했다. 로봇에서는 그 경계가 코드 바깥까지 이어진다. 하드웨어, OS, 네트워크, 실시간 조건이 함께 맞물려 움직이기 때문이다.
에이전트는 질문이나 연결된 도구로 전달받은 관측값만 알 수 있다. 장치와 실행 상태를 알려 주지 않으면 에이전트는 현재 로봇의 조건에 맞게 답을 좁히지 못한다.
그러므로 질문을 만들기 전에 토픽, 장치, 시계, 네트워크, 권한, 시스템 구조의 현재 상태를 먼저 적는다. 이런 관측값이 있어야 답이 그 자리에서 실행할 확인 절차로 좁아진다.
에이전트가 코드를 직접 실행하는 sandbox에서는 문서가 조건을 미리 알려 준다. Anthropic의 code execution tool 문서는 메모리와 디스크가 각각 5 GiB이고 CPU가 하나이며 인터넷이 막혀 있다고 명시한다. 할 수 있는 일과 할 수 없는 일이 숫자로 먼저 주어진다는 뜻이다.
로봇을 돌리는 현장에는 그런 문서가 없다. 같은 항목을 지금 이 기계에서 직접 확인해야 한다. 어떤 장치가 연결되어 있는지, 시계가 맞는지, 네트워크가 어디까지 닿는지는 현장에서 직접 확인해야 알 수 있다.
시행 횟수와 불확실성을 함께 본다
장치와 시계, 네트워크를 확인한 뒤에는 시행 횟수와 비교 방법을 실행 전에 정한다. 시행 횟수는 관행 대신 구별하려는 차이와 허용할 불확실성에 맞추어 정한다. 성공률만 적으면 표본 규모가 드러나지 않는다. 17/20과 14/20은 각각 85%와 70%지만, 백분율만 제시하면 두 값의 불확실성을 판단할 수 없다.
성공률 옆에 시행 횟수와 불확실성을 같이 적는다.
17/20처럼 분자와 분모를 남기고, 두 정책을 비교할 때는 같은 방법으로 계산한 구간이나 검정 결과를 함께 제시한다.
성공 횟수만 세는 대신 비교 설계를 바꿀 수도 있다. RoboArena는 학술기관 일곱 곳에서 DROID 로봇으로 정책 일곱 종을 이중맹검 짝비교로 600회 넘게 실행했다. 평가자들은 과제와 환경을 각자 골랐지만, 두 정책을 나란히 두고 어느 쪽이 더 나은지만 답했다. 이렇게 얻은 순위는 연구에서 시험한 전체 과제와 정책을 빠짐없이 평가해 만든 기준 순위에, 한곳의 표준 과제로 얻은 순위보다 더 가까웠다. 여기서의 정확성은 그 기준 순위와의 일치 정도를 뜻한다.
다른 하나는 시뮬레이션을 섞는 방법이다. 시뮬레이션을 많이 돌리고 실기를 적게 진행한 뒤 둘 사이의 어긋남을 보정해 실기 성능의 구간을 내는 방법은 같은 보장을 얻는 데 드는 하드웨어 작업량을 20~25% 줄였다.
두 방법 모두 기록이 있어야 성립한다. 짝비교에서는 두 정책을 어떤 환경에서 비교했는지 명시해야 한다. 시뮬레이션 보정의 경우 같은 조건을 양쪽에서 실행했다는 사실을 남겨 둔다.
자동 실험의 판정은 원자료를 다시 열어 검증한다
자동 실험에서는 모델이 다음 실험을 제안하고, 장비가 데이터를 만들고, 채점 결과가 다시 다음 선택으로 들어간다. 이 고리가 계속 작동했다는 사실만으로 채점이 옳았다고 볼 수는 없다. 생성과 검증에 같은 판정 절차를 쓰면 그 절차의 오류가 다음 실험에도 이어진다.
버클리의 A-Lab 사례에서 이 차이가 드러난다. 합성 과정과 X선 회절 무늬의 판정은 자동 고리 안에서 진행됐지만, 뒤에 판정 품질이 문제로 지적되자 같은 회절 원자료를 사람이 다시 맞춰 결과를 재검토했다. 자동 고리가 계속 돈 사실과 고리 안의 성공 판정이 옳다는 사실은 별개였다.
검증 절차는 크게 네 단계로 구분할 수 있다. 먼저 실행 조건과 성공 기준을 고정한 뒤 실행 중 원자료와 실패 기록을 보존한다. 이어서 자동 판정이 읽은 입력과 적용 규칙을 남기고, 마지막으로 고리 밖에서 원자료를 열어 판정을 재확인한다. 무엇을 변수로 두었는지, 어디까지를 성공으로 셌는지, 실패한 실행을 집계에서 어떻게 다뤘는지도 같은 기록을 통해 대조할 수 있어야 한다.
로봇 실험에서는 장치 연결, 시계, 네트워크 상태에 따라 같은 명령의 결과가 달라질 수 있다. 실험 규칙은 자동 고리를 대신하지 않고, 고리의 실행 조건, 원 데이터, 판정 절차를 다시 확인할 자리를 정한다.
증상에 맞는 첫 확인 명령을 찾는다
토픽이 오지 않거나, 컨테이너에서 장치가 보이지 않거나, 드라이버가 아무 반응도 하지 않는 증상에는 각각 먼저 실행해 볼 명령이 있다. 그 명령들을 증상별로 부록 F의 로봇 실험 문제 해결 안내서에 모아 두었다.
첫 항목은 QoS다. ROS2의 기본 publisher·subscription profile은 RELIABLE이고 sensor data profile은 BEST_EFFORT다. 예를 들어 카메라나 LiDAR driver가 BEST_EFFORT로 보내는데 subscriber가 RELIABLE을 요구하면 호환되지 않아 메시지가 오지 않는다. 참조표는 먼저 ros2 topic info /camera/image_raw --verbose를 실행한 뒤 출력의 Reliability와 Durability 줄을 보라고 안내한다. 이 증상을 토픽이나 driver 탓으로 돌리기 전에 그곳부터 확인한다.
나머지 항목도 같은 형식이다. 증상마다 먼저 실행할 명령 하나와 그 출력에서 확인할 줄이 붙어 있다. 어떤 증상이든 질문을 만들기 전에 그 명령으로 현재 상태를 적고, 적은 내용을 에이전트에게 준다.
12장 에이전트에게 맡길 일과 사람이 잴 일
에이전트의 답은 질문에 담긴 환경 정보와 관측 자료를 바탕으로 나온다. 따라서 같은 증상이라도 무엇을 함께 알려 주느냐에 따라 답이 달라진다.
"카메라가 안 돼요"라고만 물으면 지금 쓰는 기계에 맞춰 좁히지 않은 원인 목록이 돌아온다. 그러나 같은 증상이라도 다음과 같이 구체적으로 적으면 답의 범위가 달라진다.
Ubuntu 22.04, ROS2 Humble, Intel RealSense D435를 쓴다.
rs-enumerate-devices에서는 보이지만ros2 launch realsense2_camera rs_launch.py를 실행하면Could not open device오류가 난다. Docker 안에서 실행 중이고,--device=/dev/video0은 매핑했다.
둘째 질문에는 장치가 한 도구에서는 보이지만 다른 실행 환경에서는 열리지 않는다는 관측이 들어 있다. 이 정보가 있으면 드라이버 자체뿐 아니라 컨테이너의 장치 접근 조건부터 확인할 수 있다.
그래서 물을 때마다 다음 일곱 가지를 함께 적는다.
- OS 버전, ROS 버전
- 하드웨어 플랫폼 (x86 vs ARM/Jetson)
- 센서 모델명
- 오류 메시지 전문
ros2 topic list,ros2 node list출력- Docker 사용 여부와 실행 옵션 (
docker run명령 전체) - 네트워크 구성 (유선/무선, IP 대역)
일곱 항목 가운데 오류 메시지는 줄이지 말고 원문 그대로 옮긴다. Could not open device 같은 문자열은 그 자체로 찾아볼 수 있지만, 이를 "카메라가 안 열린다"라고 요약하면 찾을 수 없어진다.
docker run 명령도 통째로 복사한다. 장치, 네트워크, 볼륨을 어떤 방식으로 넘겼는지가 모두 담겨 있으므로 다시 옮겨 적으면 정보가 빠질 수 있다.
오류 메시지와
docker run명령은 통째로 옮긴다. 오류 문자열은 그 자체가 검색 키워드가 되므로 임의로 요약해서는 안 된다.docker run명령줄 역시 장치·네트워크·볼륨 매핑 정보가 온전히 담겨 있다.
나머지 다섯 항목은 답을 현재 기계와 구성에 맞게 좁히는 정보다. OS와 ROS 버전은 패키지 이름과 기본값을 결정한다. 하드웨어 플랫폼은 특정 패키지의 지원 여부를 가르는 기준이다. 센서 모델명은 확인할 드라이버를 정한다. ros2 topic list와 ros2 node list 출력은 노드가 뜨지 않았는지 다른 이름으로 실행되었는지 파악하게 해 준다. 네트워크 구성 정보는 여러 장치가 연결된 환경 맥락을 설명한다.
제안을 실행하기 전에 현재 환경과 맞는지 확인한다
돌아온 답에는 실행해 볼 명령이나 바꿀 설정이 들어 있다. 명령을 실행하거나 설정을 바꾸기 전에는 제안의 종류에 맞춰 확인해야 할 항목이 달라진다.
패키지를 설치하라는 제안이라면 먼저 그 패키지가 현재 쓰는 ROS와 Ubuntu 버전을 지원하는지 확인한다. 이때 apt search ros-humble-PACKAGE_NAME 같은 명령을 쓴다.
설정을 바꾸라는 제안이라면 현재 설정부터 백업하고, 그 제안이 어떤 관측 결과를 설명하려는지 살핀다. 설명하는 관측 결과가 없으면 바꾼 뒤에도 무엇이 나아졌는지 알 수 없다.
환경을 다시 설치하라는 제안이라면 그 전에 현재 상태를 기록해 둔다. pip show와 dpkg -l | grep, apt policy로 설치된 항목과 충돌 범위를 남긴 다음 손댄다. 다시 설치한 뒤에는 그 기록이 유일한 이전 상태가 된다.
코드를 받았다면 다른 사람의 기계에서만 동작하는 요소가 섞여 있는지 확인한다. 하드코딩된 경로(/home/user/...), IP(192.168.1.100), x86 전용 패키지(amd64 wheel)가 이에 해당한다.
초안은 맡겨도 현장 상태는 직접 측정한다
| 에이전트로 초안을 만들기 좋은 일 | 현장에서 측정값을 확보해야 하는 일 |
|---|---|
| 알고리즘 구현 (SLAM, detection 등) | 하드웨어 디버깅 |
| ROS2 노드/서비스 코드 작성 | QoS/DDS 설정의 실제 성능 확인 |
| Python/C++ 코드 리팩토링 | USB/시리얼 장치 상태 확인 |
| 논문 읽기/요약 | LiDAR 연결과 네트워크 패킷 확인 |
| CMakeLists.txt 작성 | 실시간 주기와 지터 측정 |
| 데이터 전처리 파이프라인 | Docker 안팎의 장치 접근 확인 |
| 시각화 코드 (matplotlib, Open3D) | 센서 간 시간 동기화 확인 |
| 일반적인 오류 메시지의 해석 | dmesg와 커널 로그를 현장 증상과 대조하는 일 |
왼쪽 칸은 문서와 코드만으로도 초안을 만들 수 있는 일이다. 오른쪽 칸은 하드웨어와 소프트웨어가 맞닿는 자리이므로, 장치 상태와 타이밍, 패킷처럼 지금 이 기계에서 얻은 관측 자료가 있어야 답이 선다. 먼저 직접 측정한 뒤 그 결과를 분석 입력으로 준다.
13장 연구 단계의 역할을 나누고 하네스를 점검한다
에이전트의 산출물은 확인 전까지 초안이다. 논문 읽기, 코드 작성, 실험 설계, 원고 작성은 서로 다른 자료로 초안을 검증해야 한다. 작업마다 오류가 드러나는 지점이 다르기 때문이다.
논문은 원문을 먼저 읽는다
중요한 논문은 세 차례에 걸쳐 읽는다. 에이전트의 요약은 원문을 직접 확인한 뒤에 보조 자료로 곁에 둔다. 요약부터 읽으면 요약이 고른 내용에 주의가 쏠려, 원문에서 확인할 범위까지 좁아질 수 있다.
읽으면서 채우는 칸은 부록의 paper-reading-note.md에 마련되어 있다. 특히 방법의 가정을 따로 적는다. 관측 모델을 어떻게 두었는지, 데이터에 무엇을 전제했는지는 원문에서 확인해야 한다. 원문에서 채운 내용과 요약이 다르면 해당 대목을 다시 읽는다. 이 읽기 방식은 「연구노트」의 논문을 세 번에 나누어 읽기와 마음가짐에서 다룬다.
코드는 실행 조건을 함께 준다
프로토타입을 요청할 때는 실행 조건과 기준값을 명시한다. 어떤 데이터셋에서 어떤 특징점을 추출하고 어떻게 매칭할지, 어느 라이브러리를 쓰며 기준값을 얼마로 둘지 적는다. 조건을 비워 두면 받은 코드가 어떤 기본값을 택했는지 다시 확인해야 한다.
디버깅할 때는 오류 메시지와 관련 코드를 함께 제공하고, 가능한 원인과 확인할 순서를 묻는다. 순서까지 받아 두어야 어디까지 점검했는지도 남는다. 구조를 바꾸는 작업은 변경 전후의 동작을 테스트로 검증할 수 있으므로 맡기기 수월하다.
하드웨어가 맞닿는 자리는 직접 잰다. 장치 상태, 타이밍, 패킷은 지금 이 기계에서 관찰하고 측정해야 한다.
직접 확인할 항목은 앞의 표 오른쪽 칸에 있다. ROS의 QoS, 하드웨어 권한, 네트워크 설정, 실시간 타이밍이다.
실험은 빠진 비교 축을 찾는다
실험을 설계할 때는 baseline 비교 표를 건네고, 놓친 비교 축의 후보를 묻는다. 제안받은 축은 연구 질문과 자원에 맞는지 사람이 다시 고른다. 필요한 비교를 설계 단계에서 찾으면 심사 뒤에 실험을 다시 돌리는 비용을 줄일 수 있다. 실험 설계와 ablation, 결과 해석에 에이전트를 활용하는 방법은 「연구노트」의 Revision/Rebuttal과 Figures에서 다룬다.
원고 초안은 문장과 서지를 다시 확인한다
초고 단계에서는 핵심 아이디어와 실험 결과를 주고 Introduction의 논리 구조를 제안받을 수 있다. 영어 문장은 문법과 문맥을 함께 살펴 달라고 요청한다. 받은 문장은 근거와 문맥을 확인한 뒤 원고의 목소리에 맞춘다. 한 논문 안에서 문단마다 어조가 갈리면 논리보다 표현의 차이가 먼저 눈에 띌 수 있다.
특히 서지 항목은 주의해야 한다. 모델이 제시하는 연도와 학회명은 그럴듯한 형식을 갖추어, 읽기만 해서는 오류가 드러나지 않을 수 있다. 잘못된 인용은 원고의 신뢰를 무너뜨리므로, 초안을 받은 뒤 논문 원문이나 출판사 페이지에서 연도, 학회·저널명, 권·호를 하나씩 확인한다.
작업이 바뀔 때마다 초안과 확인된 사실을 나눈다
이 네 작업은 하루 동안 번갈아 이어진다. 아침에 논문 요약을 확인하고 낮에 코드를 수정한 뒤 저녁에 관련 연구 표를 정리하는 식이다. 갈래가 바뀌어도 앞서 살핀 내용이 손에 남아 있어, 하나의 요청이 다른 갈래까지 번지기 쉽다.
부록의 weekly-research-ledger.md는 이렇게 여러 갈래로 퍼진 작업을 주 단위로 정리한다. 그 주에 나온 수치를 한 줄씩 기록하고, 각 줄에 원고에 쓸 수 있는지 표시한다. 표시하지 않은 수치는 그 주에 나왔더라도 아직 원고에 쓰지 않는다.
연구를 진전시킨 일과 환경을 구축한 일을 따로 적도록 한 이유도 같다. 도구를 연결하고 데이터를 옮긴 하루는 바빴더라도, 새 주장이 하나도 늘지 않았을 수 있다. 두 칸을 나누어 적어야 이를 알 수 있다.
갈래를 바꿀 때마다 무엇이 초안이고 무엇이 확인된 사실인지 구분해 둔다. 에이전트가 만든 비교 표에서 두 논문의 방법이 뒤바뀌었는지는 원문을 열어야 알 수 있다. 이 확인 작업은 결과물을 검토하는 사람이 맡는다. 1부의 기록으로 확인된 근거를 보존하고, 2부의 표로 그 근거를 주장에 연결하며, 3부의 규칙을 통해 연구 갈래가 바뀌어도 근거와 주장이 뒤섞이지 않도록 통제한다.
여섯 요소로 연구 하네스를 점검한다
서문에서는 하네스를 여섯 자리로 나누었다. 이제 세 부에서 그 여섯 자리가 무엇으로 채워졌는지 정리한다.
- 관측은 무엇을 보여 줄지다. 1부의 기록 형식과 2부의 결과물 먼저 보기가 여기 들어간다.
- 문맥은 그중 무엇을 이번 호출에 넣을지다. 세션을 끊어 가는 규칙과 밖에 적어 두는 습관이 여기다.
- 제어는 어떤 주기로 돌리고 언제 멈출지다. 이 부의 갈래 판단과 읽기만 시킬지 실행까지 시킬지가 여기다.
- 행동은 무엇을 실행하게 할지다. 참조표와 권한 규칙이 여기다.
- 상태는 무엇을 남길지다. 실험 기록과 주장·근거 표가 여기다.
- 검증은 무엇으로 확인할지다. 반복 횟수와 시행 수, 참고문헌 대조가 여기다.
마지막 요소는 검증이다. 모델의 산출물만으로는 무엇이 맞는지 판정할 수 없으므로 바깥의 기준이나 자료와 대조해야 한다. 나머지 다섯 요소는 이때 필요한 자료와 실행 경로를 남긴다. 제어도 미리 적어 둔 중지 조건과 다음 행동을 읽어 결정한다. 따라서 연구 하네스를 구성하는 작업은 모델을 고르는 일보다 무엇을 보여 주고, 남기고, 대조할지 결정하는 데서 시작한다.
부록 A — AI 연구의 용어·근거·작업 구조
AI 도구를 연구에 쓰다 보면 역할이 다른 모델, 도구, 에이전트, 기억 기록을 한데 묶어 생각하기 쉽다. 이 경계가 흐려지면 실험 수치와 원고의 주장도 함께 흔들린다. 아래 표는 각 용어가 가리키는 대상과 근거로 삼을 수 있는 범위를 정리한다.
AI 연구의 기본 용어
| 용어 | 뜻 | 조심할 점 |
|---|---|---|
| 모델 | 텍스트, 코드, 이미지, 표를 생성하거나 판단하는 기반 모델 | 모델의 답변은 현재 작업 공간을 다시 확인할 출발점일 뿐, 그 상태를 확정하는 근거는 아니다 |
| 도구 | 파일 읽기, 명령 실행, 검색, 이미지 생성처럼 모델 밖에서 행동을 수행하는 기능 | 도구 결과는 해당 명령이나 API의 범위 안에서만 근거가 된다 |
| 에이전트 | 모델과 도구를 결합해 여러 단계를 수행하는 실행자 | 에이전트의 행동만으로 연구 주장이 성립하지 않으며, 실행 결과가 주장을 뒷받침해야 한다 |
| 스킬 | 정해진 상황에서 에이전트가 따르는 절차와 판단 기준 | 작업자는 스킬을 사용할 조건을 확인한다 |
| 하네스 | 상태, 근거, 행동, 확인, 주장을 잇는 운영 구조 | 한 번의 AI 작업 결과로 주장할 수 있는 범위를 제한한다 |
| AGENTS.md | 에이전트가 작업 전에 읽는 저장소 규칙 | 한 번의 요청이 끝난 뒤에도 프로젝트 규칙으로 남는다 |
| 기억 기록 | 현재 상태, 반복 위험, 계속 적용할 사용자 교정 사항을 보관하는 기록 | 근거를 다시 확인할 위치를 알려 주는 자료다 |
| 변경 이력 | 실험, 주장, 교정 사항, 반복 확인이 어떻게 바뀌었는지 남긴 기록 | 다음 행동의 범위를 정할 때 사용한다 |
| 반복 확인 | 같은 실패가 다시 발생하는지 확인하는 작은 시험 | 다음 작업 전에 반복 실수를 찾는 데 사용한다 |
| 실험 조건 | dataset, split, metric, baseline, output path 등 수치를 비교할 때 함께 확인하는 항목 | 수치는 이 조건 안에서만 비교한다 |
| 결과물 | 파일, 로그, 표, 그림, 체크포인트, 명령 출력 | 출처와 함께 읽어야 한다 |
| 주장 | 원고, 답변서, README, 발표에서 독자에게 제시하는 판단이나 결론 | 근거 범위를 넘어서면 안 된다 |
근거 단계와 주장 범위
| 단계 | 예 | 말할 수 있는 범위 |
|---|---|---|
| 방향 잡기 | 이전 요약, 기억 기록, 인계 메모 | 어디를 다시 볼지 정한다 |
| 확인 대상 | 파일명, 이슈 제목, 검색 결과 | 원인이나 다음 확인 대상을 제안한다 |
| 관찰 | 원본 파일 일부, 로그 일부, 설정 일부 | 직접 본 범위 안의 사실을 말한다 |
| 실행 결과 | 명령 실행 결과, 생성된 파일 | 그 실행의 결과를 말한다 |
| 실험 조건 확인 | dataset, split, metric, baseline, output path를 확인한 숫자 | 같은 조건 안에서 비교한다 |
| 원고 주장 | 그림, 표, 인용, 심사 위험을 함께 확인한 문장 | 원고와 답변서에 쓴다 |
AI는 이 단계를 건너뛴 답을 내놓을 수 있다. 요약을 근거처럼 쓰거나, 한 번의 실행 결과를 방법이 나아졌다는 증거로 내세우기도 한다. 로그 일부만 보고 전체 실행의 원인을 단정할 때도 있다.
도구별 역할과 확인 항목
| 도구 | 좋은 용도 | 확인할 항목 |
|---|---|---|
| 대화 모델 | 개념 정리, 논문 질문, 주장 분리 | 답변이 원본 파일 확인에 근거하는지 살핀다 |
| 코딩 에이전트 | 저장소 읽기, 작은 수정, 스크립트 실행 | 원본 파일, 명령 출력, 변경 내용을 남긴다 |
| IDE 보조 도구 | 한 파일 안의 짧은 편집과 이름 변경 | 변경 범위와 포매터·테스트를 확인한다 |
| 브라우저·검색 도구 | 외부 저장소, 논문, 문서 발견 | 링크, 확인일, 주장 범위를 남긴다 |
| 터미널·스크립트 | 빌드, 지표 산출, 체크섬 확인 | 실행 명령과 출력 경로를 남긴다 |
| 프로젝트 기억 기록 | 계속 적용할 교정 사항과 현재 상태 보관 | 기억 기록은 증거 위치를 찾는 단서로 사용한다 |
도구가 바뀌면 근거의 무게도 다시 따져 본다. 검색 결과는 아직 후보일 뿐이다. 터미널 명령을 실제로 실행한 기록이 있어야 실행 결과로 볼 수 있다. 수치는 dataset, split, metric script를 확인한 뒤 원고에 쓴다.
MCP의 tool·resource·prompt
새 도구를 붙일 때도 실행할 기능, 읽을 자료, 다시 사용할 틀을 구분한다. Model Context Protocol에서 host는 server마다 client를 하나씩 만들어 전용 연결을 유지하고, 서버는 세 가지를 함께 제공한다. 실행하는 기능은 tool, 맥락으로 읽는 자료는 resource, 다시 사용하는 틀은 prompt다. 서버를 연결할 때는 이 셋 가운데 무엇을 어떤 역할로 쓸지 구분해 둔다. 클라이언트 쪽에는 sampling과 elicitation, logging이 있다. 이 가운데 elicitation은 서버가 사용자에게 추가 정보나 확인을 요청하는 통로이므로, 사람의 확인이 필요한 일은 이 통로로 요청한다.
세션·하네스·샌드박스
Anthropic의 Managed Agents는 세션(session)을 사건의 append-only log로, 하네스(harness)를 모델을 부르고 도구 호출을 넘기는 loop로, 샌드박스(sandbox)를 실행 환경으로 정의한다. 부록 B의 첫 연구 작업 공간 만들기는 이 세 역할을 작은 연구 작업 공간에 대응시킨다. 세션에서 확인한 내용은 project-memory.json과 기록 장부에 남긴다. 하네스 규칙은 AGENTS.md와 프롬프트 템플릿에 담고, 저장소·데이터셋·결과물과 명령 실행은 샌드박스에서 다룬다. 첫 AI 세션에서는 이 세 경계를 먼저 밝히고 행동 하나만 선택한다.
Claude 규칙을 Codex로 옮기는 기준
Claude용 규칙에서는 행동 규칙과 확인 기준만 Codex로 옮긴다.
| Claude 중심 자료 | 옮길 것 | 그대로 두면 안 되는 것 |
|---|---|---|
CLAUDE.md |
행동 규칙, 확인 기준, 프로젝트 경계 | Claude 전용 명령 |
.claude/skills |
절차 지식, 분기 규칙 | 파일 경로와 UI 전제 |
| 슬래시 명령 | 반복 가능한 목적과 입력 형식 | 특정 도구의 호출 문법 |
| Cursor 규칙 | 편집 원칙, 문체 점검 | 편집기 내부 설정을 전체 규칙처럼 사용하는 것 |
Codex가 저장소에서 계속 적용할 규칙은 AGENTS.md에 둔다. 템플릿과 프로젝트 기억 기록은 그 규칙을 언제 읽을지 가리킨다. 규칙을 옮긴 뒤에는 새 AGENTS.md를 다시 읽고 확인 항목이 빠지지 않았는지 살핀다.
작업 절차를 skill로 구성하는 기준
한 가지 작업에만 쓰는 절차는 폴더 하나로 분리해 AGENTS.md 옆에 둔다. Anthropic의 Agent Skills는 skill을 정해진 작업을 더 잘 수행하도록 에이전트가 찾아내 필요할 때 불러 쓰는 지시·스크립트·자료를 담은 폴더로 정의한다. SKILL.md는 YAML frontmatter로 시작하며, name과 언제 쓰는지를 적는 description은 필수다. description에는 부록 B에서 파일마다 정한 "이 파일을 언제 여는가"라는 질문의 답을 적는다. 단계적 공개는 세 층으로 나뉜다. 1층에서는 이름과 description만 system prompt에 올리고, 2층에서는 관련 있다고 판단하면 SKILL.md 본문을 읽으며, 3층에서는 같은 폴더의 다른 파일을 필요할 때 읽는다. 폴더가 여러 개여도 1층에 올라가는 것은 이름과 description뿐이다.
부록 B — 첫 연구 작업 공간 만들기
본문에서 AI가 잘하는 일과 틀리는 일, 사람이 감당할 위험, 하네스가 확인할 경계를 먼저 읽는다. 그런 다음 이 부록에 모아 둔 파일을 새 연구 작업 공간으로 옮긴다.
도구의 역할부터 나눈다
처음에는 연구의 현재 상태와 도구의 역할을 함께 정한다. 모델명은 그다음에 다룰 문제다. 역할을 먼저 정해 두면 그 역할을 맡을 제품은 나중에 바꿔 끼울 수 있다.
| 연구 장면 | 먼저 열 도구 | 첫 확인 |
|---|---|---|
| 저장소를 읽고 작은 수정을 한다 | 코딩 에이전트 | AGENTS.md와 원본 파일을 먼저 읽었는가 |
| 논문 주장을 코드와 실험에 연결한다 | 대화 모델 또는 코딩 에이전트 | 논문-코드-실험 표가 남는가 |
| ROS2, Docker, CUDA, 데이터셋 오류를 좁힌다 | 코딩 에이전트와 터미널 | 단계별 명령 출력이 있는가 |
| 외부 저장소나 논문을 찾는다 | 브라우저·검색 도구 | 출처 URL과 주장 범위가 분리됐는가 |
| 원고와 답변서를 고친다 | 원고 담당 역할 | 쓸 문장과 보류할 문장이 분리됐는가 |
| 반복 실패를 막는다 | 하네스 담당 역할 | 실패를 변경 기록이나 반복 확인 사례로 남겼는가 |
같은 AI 제품이 여러 역할을 맡을 수 있다. 한 요청 안에서 역할이 바뀌면 확인 기준도 다시 적는다.
tool·resource·prompt와 sampling·elicitation·logging의 구분은 부록 A의 「MCP의 tool·resource·prompt」에서 확인한다.
작업 공간을 만들고 파일을 설치한다
역할과 확인 기준은 파일로 남겨야 다음 세션이 이어받을 수 있다. 루트에는 AI가 먼저 읽을 파일을 두고, 나머지는 용도별 폴더로 나눈다.
workspace/
├── AGENTS.md
├── README.md
├── project-memory.json
├── repos/
├── datasets/
├── artifacts/
├── notes/
└── templates/
이 폴더들은 서로 다른 디스크에 둘 수 있다. 동기화 폴더, 외장 디스크, 원격 서버를 쓴다면 Git 메타데이터와 데이터셋을 어디에 저장할지 먼저 정한다. 코드 이력, 원시 데이터, 실험 결과물, 비공개 메모는 처음부터 나누어 둔다.
이 책의 공개 가이드 묶음에서는 templates/의 시작 파일을 정해진 자리로 옮긴다.
workspace-readme.md를 README.md로,
AGENTS.template.md를 AGENTS.md로, project-memory.template.json을
project-memory.json으로 복사하고, 첫 요청에 쓸 first-ai-session-prompt.md를
notes/에 둔다. 주장과 근거를 적을 claim-evidence-map.md는 원고 작업을 시작할 때
가져온다. README.md는 복사한 서식의 빈칸만 짧게 채우고, 상태 메모는 복사한
project-memory.json의 항목에 맞춰 쓴다. 이 공간에 무엇을 두는지, 공개·비공개 경계를 어디에 두는지만 밝히면 된다.
번들을 내려받아 풀었다면 다음과 같이 시작한다. 아래 명령은 첫날 점검과 논문·실험
기록에 필요한 파일까지 한 번에 설치한다. GUIDE는 가이드 묶음의 루트이고,
WORKSPACE는 새 연구 작업 공간의 위치다.
GUIDE="$PWD"
WORKSPACE="$HOME/robotics-ai-workspace"
mkdir -p "$WORKSPACE"/repos "$WORKSPACE"/datasets "$WORKSPACE"/artifacts \
"$WORKSPACE"/notes "$WORKSPACE"/templates
cp "$GUIDE/templates/workspace-readme.md" "$WORKSPACE/README.md"
cp "$GUIDE/templates/AGENTS.template.md" "$WORKSPACE/AGENTS.md"
cp "$GUIDE/templates/project-memory.template.json" "$WORKSPACE/project-memory.json"
cp "$GUIDE"/templates/*.md "$WORKSPACE/templates/"
cp "$GUIDE/templates/first-day-workspace-checklist.md" "$WORKSPACE/notes/"
cp "$GUIDE/templates/first-ai-session-prompt.md" "$WORKSPACE/notes/"
cp "$GUIDE/templates/paper-code-experiment-map.md" "$WORKSPACE/notes/"
cp "$GUIDE/templates/experiment-contract.md" "$WORKSPACE/notes/"
cp "$GUIDE/templates/weekly-research-ledger.md" "$WORKSPACE/notes/"
Windows PowerShell에서는 같은 구성을 다음과 같이 만든다.
$Guide = (Get-Location).Path
$Workspace = "$HOME\robotics-ai-workspace"
New-Item -ItemType Directory -Force -Path `
"$Workspace\repos", "$Workspace\datasets", "$Workspace\artifacts", `
"$Workspace\notes", "$Workspace\templates" | Out-Null
Copy-Item "$Guide\templates\workspace-readme.md" "$Workspace\README.md"
Copy-Item "$Guide\templates\AGENTS.template.md" "$Workspace\AGENTS.md"
Copy-Item "$Guide\templates\project-memory.template.json" "$Workspace\project-memory.json"
Copy-Item "$Guide\templates\*.md" "$Workspace\templates\"
Copy-Item "$Guide\templates\first-day-workspace-checklist.md" "$Workspace\notes\"
Copy-Item "$Guide\templates\first-ai-session-prompt.md" "$Workspace\notes\"
Copy-Item "$Guide\templates\paper-code-experiment-map.md" "$Workspace\notes\"
Copy-Item "$Guide\templates\experiment-contract.md" "$Workspace\notes\"
Copy-Item "$Guide\templates\weekly-research-ledger.md" "$Workspace\notes\"
복사가 끝나면 작업 공간 루트에서 파일이 제자리에 있는지 확인한다. POSIX 셸에서는 다음 확인을 모두 통과한 뒤 첫 AI 세션을 연다.
(
set -eu
cd "$WORKSPACE"
for path in \
AGENTS.md \
README.md \
project-memory.json \
notes/first-day-workspace-checklist.md \
notes/first-ai-session-prompt.md \
notes/paper-code-experiment-map.md \
notes/experiment-contract.md
do
if [ ! -f "$path" ]; then
printf 'missing %s\n' "$PWD/$path" >&2
exit 1
fi
done
python3 -m json.tool project-memory.json >/dev/null
mkdir -p artifacts
)
Windows PowerShell에서는 같은 확인을 이렇게 한다.
Set-Location $Workspace
@(
"AGENTS.md",
"README.md",
"project-memory.json",
"notes\first-day-workspace-checklist.md",
"notes\first-ai-session-prompt.md",
"notes\paper-code-experiment-map.md",
"notes\experiment-contract.md"
) | ForEach-Object {
if (-not (Test-Path $_)) { throw "missing $_" }
}
Get-Content .\project-memory.json | ConvertFrom-Json | Out-Null
New-Item -ItemType Directory -Force -Path .\artifacts | Out-Null
복사만 마친 파일에는 아직 빈칸이 남아 있다. project-memory.json에서는 먼저 다섯
묶음을 채운다. source_of_truth에는 AI가 다시 읽을 파일을, tool_surface_map에는
연구 장면별 도구 역할을 적는다. 지금 쓸 수 있는 말과 보류할 말은
current_evidence에서 가른다. 처음 시작할 연구 루프 하나는
first_research_loop에 고정하고, 다음 세션의 첫 행동은
next_smallest_actions에 남긴다.
session·harness·sandbox의 뜻과 파일 대응은 부록 A의 「세션·하네스·샌드박스」에서 확인한다.
notes/first-ai-session-prompt.md의 Prompt To Send 블록에 이 세 경계를 적는다.
빈칸을 모두 채운 뒤 artifacts/first-ai-session-message.txt에 저장하고, 첫 AI
세션에는 이 파일의 내용을 그대로 입력한다.
AGENTS.md에 프로젝트 규칙을 적는다
루트의 README.md와 AGENTS.md에도 같은 빈칸이 남아 있다. README.md에는
프로젝트 이름과 저장소, 데이터셋, 결과물 위치만 직접 적는다. 그다음 루트의 AGENTS.md에서
다음 항목만 먼저 채운다. 원 서식은
templates/AGENTS.template.md에서 확인할 수 있다.
- project truth
- public/private boundary
- managed agent boundary
- work modes
- evidence gate
- durable corrections
이미 CLAUDE.md, .claude/, Cursor 규칙이 있다면 옮길 규칙과 버릴 명령을
나눈다. 따라 할 절차는 templates/codex-porting-checklist.md에 있다. 파일 이름과
플러그인 명령은 도구마다 형식이 다르므로 규칙의 의미부터 본다. "가정을 드러내라", "작게
고쳐라", "성공 기준을 검증 가능하게 만들어라" 같은 규칙은 Codex에서도 그대로 쓴다.
한 작업에서만 쓰는 절차를 skill 폴더로 떼는 기준은 부록 A의 「작업 절차를 skill로 구성하는 기준」에서 확인한다.
현재 상태를 먼저 기록한다
AGENTS.md의 project truth와 durable corrections에 채울 내용은 여기에서 나온다.
프로젝트의 목표, 현재 정본으로 삼는 코드 경로와 dataset, 실험과 원고가 어디까지
왔는지, 심사에서 문제가 될 만한 부분, 계속 적용할 교정 사항을 원본 파일과 실행 결과로
확인해 상태 메모에 적는다.
첫 AI 요청은 한 작업으로 좁힌다
첫 요청에는 적어도 다음 다섯 항목을 넣는다. 답변 전 전체 점검은 부록 C의 아홉
항목으로 따로 한다. 첫 요청은
templates/first-ai-session-prompt.md를
채워 보낸다. 가장 작은 형태는 이렇다.
Read AGENTS.md and the first-day workspace checklist.
Before answering, state:
- object under truth control
- current evidence permits
- current evidence forbids
- smallest next action
- verification
Do not infer project truth from summaries when source files or artifacts are
available.
AI의 답변을 연구 작업에 반영하기 전에 근거 상태부터 확인한다.
첫 메시지는 artifacts/first-ai-session-message.txt처럼 파일로 남겨 두고,
다음 세션도 같은 읽기 순서로 시작한다.
첫 연구 루프는 하나만 고른다
project-memory.json의 first_research_loop에 고정할 루프를 여기에서 고른다.
| 상황 | 시작 템플릿 |
|---|---|
| 논문 한 편을 읽는다 | paper-code-experiment-map.md |
| 데이터셋 상태가 불명확하다 | dataset-archaeology-sheet.md |
| 실험 숫자를 해석한다 | experiment-contract.md |
| 오류를 좁힌다 | stage-local-debugging.md |
| 원고 문장을 고친다 | claim-evidence-map.md |
한 번에 여러 루프를 열면 요청이 다시 넓어지므로 첫 요청의 성공 기준은 하나만 둔다. 표의 첫 줄을 골랐다면 이렇게 요청한다. "이 논문의 핵심 주장, 실제로 호출되는 코드 경로를 확인할 대상, 실험 절차의 빈칸을 분리하라."
세션을 닫기 전에 결과를 기록한다
작업이 끝나면 project-memory.json이나 weekly-research-ledger.md에 현재 확인한
사실, 아직 말하면 안 되는 주장, 다음 행동 하나를 적는다. 이 세 줄을 어느 기록에 이어 적을지는
부록 D에서 다룬다.
AI가 잘못된 가정을 세웠다면 그 사례를 notes에 적어 두고, 같은 가정이 반복되면
AGENTS.md의 규칙 한 줄로 올린다. 다음 세션은 이렇게 남긴 기록을 읽고 시작한다.
세 줄 가운데 아직 말하면 안 되는 주장은 claim_boundaries에 옮긴다.
첫 세션이 끝난 뒤 project-memory.json의 current_evidence,
first_research_loop, claim_boundaries, next_smallest_actions를 함께 고친다.
이 기록을 갱신하면 다음 AI 세션이 같은 근거 범위를 이어받는다.
부록 C — 예시 작업 공간
examples/first-robotics-workspace/는 빠른 시작 절차를 따라 구성한 작은 공개 예시다. 공개해도 되는 파일과 기록 단위만 담았으므로, 처음 사용하는 사람은 자신의 작업 공간에 맞춰 이름과 경로를 바꾸면 된다. 이 예시는 다음 세션에서도 연구 상태를 다시 확인할 수 있도록 그 상태를 파일에 남기고, 세션·하네스·샌드박스의 경계도 나누어 둔다.
예시 작업 공간의 파일 구조
examples/first-robotics-workspace/
├── AGENTS.md
├── README.md
├── project-memory.json
└── notes/
├── codex-porting-checklist.md
├── experiment-contract.md
├── first-ai-session-message.txt
├── first-ai-session-prompt.md
├── first-day-workspace-checklist.md
├── paper-code-experiment-map.md
├── stage-local-debugging.md
└── weekly-research-ledger.md
각 파일이 맡는 일
| 파일 | 역할 |
|---|---|
AGENTS.md |
AI가 가장 먼저 읽는 프로젝트 작업 규칙 |
README.md |
예시 폴더만 열었을 때 따를 시작 순서 |
project-memory.json |
현재 확인한 사실, 원본 파일, 근거 범위, 연구 루프, 다음 행동 |
first-ai-session-message.txt |
AI 세션에 바로 입력하는 메시지 |
codex-porting-checklist.md |
Claude/Cursor 중심 규칙을 Codex 중심 규칙으로 옮기는 방법 |
first-ai-session-prompt.md |
AI 세션에서 지킬 읽기 순서와 확인 기준 |
first-day-workspace-checklist.md |
원본 파일과 작은 행동이 다루는 범위 |
paper-code-experiment-map.md |
논문 읽기를 코드 경로와 실험 절차에 연결 |
experiment-contract.md |
숫자를 주장에 쓰기 전에 확인할 실험 절차 |
stage-local-debugging.md |
ROS2 토픽 문제를 단계별 점검으로 좁혀 가는 방법 |
weekly-research-ledger.md |
한 주 동안의 주장, 실험 절차, 위험, 다음 행동 |
답변 전 점검과 세션 종료 기록
예시에는 AI가 첫 답변을 하기 전에 확인할 아홉 가지 항목이 들어 있다.
session record to update:
harness rule that controls this action:
sandbox action allowed now:
sandbox action not allowed now:
object under truth control:
current evidence permits:
current evidence forbids:
smallest next action:
verification:
이 아홉 항목은 AI의 일반적인 조언을 현재 연구 상태에 맞는 행동으로 좁힌다. 세션을 마칠 때에는 현재 확인한 사실, 아직 말해서는 안 되는 주장, 다음 행동 하나를 기록한다.
부록 D — 다음 세션으로 이어지는 연구 기록
AI와 연구할 때에는 다음 세션이 앞서 확인한 근거 범위 안에서 작업을 이어 가는 데 필요한 기록을 남긴다. 파일과 명령, 숫자, 원고 문장이 어디에서 나왔는지도 함께 적는다.
다시 시작할 때 필요한 기록
AGENTS.md- 현재 상태와 계속 적용할 사용자 교정 사항을 적은 프로젝트 기억 기록
- 공개/비공개 경계
- 지금 이어 갈 작업 하나
- 다음 AI 요청에서 확인해야 할 항목
작업 공간을 다시 열었을 때에는 다음 세 가지 상태만 확인했다고 말한다.
workspace can be resumed
first research loop is selected
next small action is known
반대로, 아직 말해서는 안 되는 내용도 기록한다.
method works
experiment improved
reviewer risk is resolved
작업에 맞는 결과물을 남긴다
한 번의 작업에서는 중심 결과물 하나를 정한다. 논문을 읽었다면 그 결과물은 주장, 코드 경로, 실험 조건 표가 된다. 시작점이 달라지면 남겨야 할 파일과 확인할 항목도 달라진다.
| 시작점 | 남길 것 | 확인할 항목 |
|---|---|---|
| 논문 한 편 | paper-code-experiment-map.md |
주장, 코드 경로, 실험 조건 |
| 데이터셋 확인 | dataset-archaeology-sheet.md |
split, count, frame, convention |
| 실험 숫자 | experiment-contract.md, result-provenance-tuple.md |
비교할 수 있는 조건 |
| 실행 중 문제 | stage-local-debugging.md |
도구/실행 환경/데이터/방법 실패 구분 |
| 원고 문장 | claim-evidence-map.md |
쓸 수 있는 문장과 보류할 문장 |
다음 AI 세션에서 같은 실험 숫자를 다시 검토한다면, 먼저 어느 dataset의 어느 split인지, query와 database의 방향이 무엇인지, 어느 metric script와 어느 baseline인지, 실제로 읽은 output이 무엇인지 묻는다.
반복 실패는 다음 규칙으로 남긴다
같은 문제를 두 번 이상 바로잡았다면 프로젝트 기억 기록, 주간 기록, 실험 조건 목록, 결과 출처 기록, 주장·근거 표, 반복 확인 사례(replay-case.md) 가운데 하나에 남긴다.
세션을 닫을 때 남길 세 줄
세션을 닫기 전에는 세 가지를 적는다. 현재 확인한 사실, 아직 말하면 안 되는 주장, 다음 행동 하나다.
다음 세션은 이 세 줄을 읽고, 확인한 사실을 바탕으로 작업을 이어 간다. 세 줄이 비어 있다면 연구 상태를 다시 세우는 일부터 시작한다.
작업을 멈추고 범위를 줄일 때
AI가 계속 답할 수 있어도 현재 작업을 멈춰야 할 때가 있다.
- 같은 단계에서 근거가 그대로다.
- 도구 실패와 방법 실패가 섞여 있다.
- 실험 조건이 바뀌었는데 숫자를 비교하려 한다.
- 심사 위험이 남았는데 문장 다듬기만 반복한다.
- 비공개 자료가 공개 문서에 섞일 위험이 있다.
이때는 새 결론을 내리려 하지 말고, 다음 행동을 근거 하나를 확인하거나 서로 섞인 원인 가운데 한 층을 분리하는 데까지 좁힌다.
부록 E — 공개 출처와 참고 자료
기존 목록 확인일: 2026-06-18 로보틱스 실행 환경 자료 확인일: 2026-07-17 Ch.2 자료 확인일: 2026-07-26 맥락 관리·에이전트 운영 자료 확인일: 2026-07-26
이 목록에는 공개 가이드에서 언급한 외부 저장소와 이론 자료의 공개 링크를 모았다. 각 링크에서는 접근 가능 여부와 제목·저자·저장소의 역할, 본문에서 인용한 최소 주장만 확인했다.
외부 에이전트와 스킬 저장소
multica-ai/andrej-karpathy-skillsdatawhalechina/hello-agentse2b-dev/awesome-ai-agentskaushikb11/awesome-llm-agentslangchain-ai/langgraphcrewAIInc/crewAImicrosoft/autogen- OpenAI Agents SDK
alexjunholee/robotics-research-agent
인간과 AI의 행동 이론
- Bainbridge, Ironies of Automation
- Parasuraman & Riley, Humans and Automation: Use, Misuse, Disuse, Abuse
- Endsley, Toward a Theory of Situation Awareness in Dynamic Systems
- Endsley, Automation and Situation Awareness (Endsley & Kiris 1995 실험을 저자가 정리한 장)
- Suchman, Plans and Situated Actions / Lancaster profile
- Hutchins, Cognition in the Wild
LLM 에이전트와 검색·근거 검증
- Yao et al., ReAct: Synergizing Reasoning and Acting in Language Models
- Schick et al., Toolformer: Language Models Can Teach Themselves to Use Tools
- Anthropic, Agentic coding and persistent returns to expertise
- Anthropic, Appendix to Agentic Coding and Persistent Returns to Expertise
- Anthropic, Scaling Managed Agents: Decoupling the brain from the hands
- Ji et al., Survey of Hallucination in Natural Language Generation
- Maynez et al., On Faithfulness and Factuality in Abstractive Summarization
- Guu et al., REALM: Retrieval-Augmented Language Model Pre-Training
- Karpukhin et al., Dense Passage Retrieval for Open-Domain Question Answering
- Lewis et al., Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks
- Izacard & Grave, Leveraging Passage Retrieval with Generative Models for Open Domain Question Answering
- Borgeaud et al., Improving language models by retrieving from trillions of tokens
- Izacard et al., Atlas: Few-shot Learning with Retrieval Augmented Language Models
모델 버전·품질과 서비스 조건
- Anthropic, Models overview
- Anthropic, Model IDs and versioning
- Anthropic, Effort
- Anthropic, An update on recent Claude Code quality reports
- GitHub issue,
anthropics/claude-code#42796 - Business Insider, Anthropic says Claude Code did get worse
- Business Insider, Meet the people who pay $2,400 a year for Anthropic's top-of-the-line Claude plan
- The Times / Wall Street Journal, Anthropic Sued Over Limits on Its $200-a-Month AI Plans
평가와 재현성
- Pineau et al., Improving Reproducibility in Machine Learning Research
- Thinking Machines Lab, Defeating Nondeterminism in LLM Inference
- Benchmarking the Benchmarks: A Validity Audit of Tool-Calling Evaluation
- Beyond pass@1: A Reliability Science Framework for Long-Horizon LLM Agents
연구 하네스와 자동 연구
확인일: 2026-08-09
- From Question Answering to Task Completion: A Survey on Agent System and Harness Design — 실행 하네스의 여섯 자리
- Si et al., Can LLMs Generate Novel Research Ideas?
- Si et al., The Ideation-Execution Gap (ICLR 2026)
- PaperBench
- CORE-Bench
- ResearchCodeBench
- ResearchGym
- Kosmos: An AI Scientist for Autonomous Discovery
- AI for Auto-Research: Roadmap & User Guide
- METR, Time Horizon 1.1
- Ord, Is there a half-life for the success rates of AI agents?
- Huang et al., Large Language Models Cannot Self-Correct Reasoning Yet (ICLR 2024) — 오라클 신호가 있을 때와 없을 때
- Kim et al., From Reproduction to Replication: Evaluating Research Agents with Progressive Code Masking — pass@1 대 pass@5, 고정 하네스 대 동적 하네스
- Bean et al., Measuring what Matters: Construct Validity in Large Language Model Benchmarks
- When AI Benchmarks Plateau: A Systematic Study of Benchmark Saturation
- LLMs Gaming Verifiers: RLVR can Lead to Reward Hacking
심사와 출판
확인일: 2026-08-09
- Pangram Labs, 21% of ICLR 2026 reviews are AI-generated
- NeurIPS, AI-Generated Papers in the NeurIPS 2026 Position Paper Track
- Fabricated citations: an audit across 2·5 million biomedical papers, The Lancet, 2026-05-07
- Review the Code, Not the Story: A Vision and Protocol for Code-First Peer Review
로봇 정책 평가
확인일: 2026-08-09
- RoboArena: Distributed Real-World Evaluation of Generalist Robot Policies
- Reliable and Scalable Robot Policy Evaluation with Imperfect Simulators
- Toyota Research Institute, Statistical Thinking for Robot Policy Evaluation
자율 실험실
확인일: 2026-08-09
- Szymanski et al., An autonomous laboratory for the accelerated synthesis of novel materials, Nature 2023
- Chemistry World, New analysis raises doubts over autonomous lab's materials discoveries
- MatDiffract, 자동 상 동정·Rietveld refinement 정확도
연구 하네스와 자동 연구, 심사와 출판, 로봇 정책 평가, 자율 실험실 자료의 수치는
2026-08-09에 원문에서 확인했다. 본문에 제시한 수치는 각 원문이 보고한 값이며,
이 책이 직접 측정한 값이 아니다. 확인할 수 없었던 수치는 본문에서 제외했다.
로보틱스 실행 환경
- ROS 2 Humble, Quality of Service settings
- Docker, Running containers
- Docker, Host network driver
- NVIDIA, JetPack release notes
맥락 관리와 에이전트 운영
- Anthropic, Effective context engineering for AI agents
- Anthropic, Context engineering: memory, compaction, and tool clearing
- Anthropic, Equipping agents for the real world with Agent Skills
- Anthropic, How we built our multi-agent research system
- Anthropic, Writing tools for agents
- Anthropic, Code execution tool
- Anthropic, Extended thinking
- Anthropic, Prompt caching
- Anthropic, Structured outputs
- Claude Code, Hooks
- Model Context Protocol, Architecture
이 묶음에서는 본문이 인용한 정의와 수치를 원문으로 확인했다. cookbook 문서의 측정값 (최대 맥락 335,279 토큰, 파일 읽기 결과 96.3%, 메모리 사용 세션 5K 대 미사용 332K)은 해당 문서의 실행에서 나온 값이며, 이 책이 측정한 값이 아니다.
주장과 근거의 논증 구조
로컬 근거 자료, 대화 로그, 내부 작업 경로는 공개하지 않고 로컬 기록에만 보관한다.
부록 F — 로봇 실험 문제 해결 안내서
증상마다 가장 먼저 확인할 명령을 모아 두었다. 본문 3부의 「증상에 맞는 첫 확인 명령을 찾는다」 절에서는 이 안내서를 언제 쓰는지 다룬다.
ROS 2에서 자주 막히는 문제
QoS 불일치로 토픽이 오지 않을 때
ROS2의 기본 publisher·subscription profile은 RELIABLE이고, sensor data profile은 BEST_EFFORT다. 카메라와 LiDAR driver는 sensor data profile을 쓰는데 subscriber가 기본 profile을 쓰면 reliability가 맞지 않아 메시지가 오지 않는다. 토픽이나 driver를 의심하기 전에 실제 QoS부터 확인한다.
# 토픽의 QoS 프로파일 확인
ros2 topic info /camera/image_raw --verbose
출력에서 Reliability: BEST_EFFORT, Durability: VOLATILE 같은 줄을 확인한 뒤 subscriber의 QoS를 맞춘다.
from rclpy.qos import QoSProfile, ReliabilityPolicy, DurabilityPolicy
qos = QoSProfile(
reliability=ReliabilityPolicy.BEST_EFFORT,
durability=DurabilityPolicy.VOLATILE,
depth=10
)
self.subscription = self.create_subscription(Image, '/camera/image_raw', self.callback, qos)
코드를 요청할 때는 "이 토픽의 QoS는 BEST_EFFORT / SENSOR_DATA다"처럼 직접 확인한 profile을 함께 적는다. 코드를 받은 뒤에도 그 값이 들어갔는지 다시 확인한다.
use_sim_time과 tf2의 시간 불일치
rosbag을 재생할 때는 use_sim_time:=true도 함께 켜야 tf lookup이 그 시각을 찾는다. tf2 lookup failed가 나타나면 static_transform_publisher를 붙이기 전에 clock 설정부터 확인한다.
시뮬레이션 clock과 시스템 clock이 서로 맞지 않기 때문이다. Bag 파일의 timestamp는 기록 시점을 가리키지만 노드는 현재 시스템 시간으로 tf를 찾으므로, 두 쪽의 기준 시각이 서로 다르다. 두 시계를 bag 쪽으로 맞춘 뒤 실제로 맞았는지 확인한다.
# bag clock을 publish하는 재생 예
ros2 bag play my_bag --clock
# 노드 실행 시 sim_time 활성화
ros2 launch my_package my_launch.py use_sim_time:=true
# 실제 노드에 적용됐는지 확인
ros2 param get /my_node use_sim_time
tf2 lookup 코드를 받은 뒤에는 timeout과 예외 처리가 포함됐는지 확인한다.
from rclpy.duration import Duration
try:
transform = tf_buffer.lookup_transform(
'base_link', 'camera_link',
rclpy.time.Time(),
timeout=Duration(seconds=1.0)
)
except tf2_ros.LookupException as e:
self.get_logger().warn(f'TF lookup failed: {e}')
ROS 2 작업 공간 소싱 순서
ROS2 workspace에서는 /opt/ros/humble/setup.bash를 먼저 source한 다음 ~/ros2_ws/install/setup.bash를 source한다. 실행 절차를 받으면 그 안에 base와 overlay workspace가 모두 있는지, 불러오는 순서가 맞는지 확인한다.
# base를 먼저, overlay를 나중에 source
source /opt/ros/humble/setup.bash
source ~/ros2_ws/install/setup.bash
.bashrc에 경로를 넣었는데 새 terminal에서 package를 찾지 못한다면 다시 설치하기 전에 source 상태부터 살핀다. echo $AMENT_PREFIX_PATH는 현재 적용된 workspace를 보여 준다.
커스텀 메시지 빌드와 반영
.msg 파일을 만들 때는 CMakeLists.txt와 package.xml의 dependency도 함께 수정한다. 변경안을 받은 뒤에는 두 파일이 모두 포함됐는지 확인한다.
rosidl_generate_interfaces 설정이 빠지면 build는 통과하지만 Python import에서 막힌다. 이때는 package 설치를 살피기보다 interface 생성 설정을 먼저 확인한다.
# CMakeLists.txt에 반드시 추가
find_package(rosidl_default_generators REQUIRED)
find_package(std_msgs REQUIRED)
find_package(geometry_msgs REQUIRED)
rosidl_generate_interfaces(${PROJECT_NAME}
"msg/MyCustomMsg.msg"
DEPENDENCIES std_msgs geometry_msgs
)
<!-- package.xml에 반드시 추가 -->
<buildtool_depend>rosidl_default_generators</buildtool_depend>
<exec_depend>rosidl_default_runtime</exec_depend>
<depend>std_msgs</depend>
<depend>geometry_msgs</depend>
<member_of_group>rosidl_interface_packages</member_of_group>
--symlink-install을 붙여 build해야 Python 코드 수정이 바로 반영된다. 고친 코드가 반영되지 않으면 build option을 먼저 확인하고 cache는 그다음에 살핀다.
# Python 패키지 수정이 바로 반영되려면
colcon build --symlink-install
네임스페이스와 리매핑
ros2 topic echo /camera/image_raw에 아무것도 나타나지 않으면 namespace가 붙어 실제 topic이 /robot1/camera/image_raw가 됐는지부터 확인한다. driver를 살피기 전에 이름을 맞춘다.
# 토픽 목록부터 확인하라
ros2 topic list
# 특정 패턴으로 필터링
ros2 topic list | grep camera
디버깅을 요청할 때는 ros2 topic list와 ros2 node list 출력을 함께 보낸다. 두 출력이 있어야 namespace 문제와 node 문제를 구분할 수 있다.
ROS 2 launch 파일
생성된 ROS2 Python launch 파일에서는 다음 네 가지를 확인한다.
- ROS1 XML 문법과 ROS2 Python 문법의 혼용
- 노드 의존성을 놓친
LaunchDescriptionaction 순서 ComposableNode와 일반Node의 혼동- multi-robot 구성에서
PushRosNamespace누락
마지막 항목인 PushRosNamespace 누락은 다음 예처럼 피한다.
# multi-robot launch 파일에서 네임스페이스 적용
from launch.actions import GroupAction
from launch_ros.actions import Node, PushRosNamespace
robot1_group = GroupAction([
PushRosNamespace('robot1'),
Node(package='my_pkg', executable='my_node', name='sensor_node'),
])
에이전트에게 Launch 파일을 요청할 때는 ROS2 Python 형식인지, multi-robot namespace가 필요한지, ComposableNode를 쓸지를 적어 준다.
Docker에서 자주 빠지는 설정
Docker GUI와 디스플레이 권한
Docker 안에서 RViz나 Gazebo 같은 GUI 도구를 띄울 때 X11이나 XWayland를 쓰려면 display socket과 인증을 넘겨야 한다. xhost +local:docker는 local X server를 모든 로컬 사용자에게 열어 주므로, 필요한 socket만 골라 넘긴다.
다음은 X11 socket을 넘기는 최소 예다. X server 인증 정보는 host 설정에 맞춰 따로 넘긴다. 접근 제어는 켠 상태로 둔다.
docker run -it \
--env DISPLAY=$DISPLAY \
--env QT_X11_NO_MITSHM=1 \
-v /tmp/.X11-unix:/tmp/.X11-unix:rw \
my_image
각 옵션의 역할은 다음과 같다.
QT_X11_NO_MITSHM=1— Docker 안에서 MIT-SHM(공유 메모리) 확장 때문에 RViz가 죽으면 이 확장을 끈다.--ipc=host가 있어야 도는 프로그램도 있지만, 이 옵션은 host의 IPC namespace를 공유한다. 오류를 재현해 확인한 뒤에만 붙인다.- Wayland session에서는 X11 socket mount만으로 충분하지 않을 수 있다. 로그인할 때 Xorg session을 고르거나 host의 XWayland·Wayland 권한 설정에 맞춘다.
XDG_SESSION_TYPE환경 변수만 바꿔서는 현재 실행 중인 display server가 바뀌지 않는다.
USB 장치 연결
카메라, LiDAR, IMU 같은 USB 장치를 Docker 안에서 쓰려면 device를 하나씩 지정해 매핑해야 한다. 드라이버를 다시 설치하기 전에 container 안에 device가 보이는지 확인한다.
# 필요한 디바이스만 매핑
docker run -it --device=/dev/ttyUSB0 --device=/dev/video0 my_image
# 모든 디바이스 접근 허용 (보안상 비추, 디버깅용으로만)
docker run -it --privileged my_image
Docker 문서에 따르면 --privileged는 모든 host device 접근과 확장된 capability를 컨테이너에 부여한다. 상시 운용에서는 필요한 device만 --device로 매핑한다.
container를 띄운 뒤 USB 장치를 꽂으면 기존 device mapping에는 잡히지 않는다. 이때는 container를 다시 띄우거나, 디버깅할 때만 --privileged와 -v /dev:/dev 조합을 사용한다.
Docker의 ROS 네트워크
Docker 컨테이너 간 ROS2 통신에서 --network=host는 설정이 단순하지만 host의 network namespace를 공유해 network isolation을 없앤다. 포트 충돌 여부와 네트워크가 열리는 범위를 함께 확인한다.
ROS2 노드들이 bridge network에서 서로를 찾지 못하면 DDS(Data Distribution Service) discovery에 쓰이는 multicast가 container 경계를 넘는지 확인한다. Docker bridge 설정에 따라 discovery packet이 밖으로 나가지 않을 수 있다.
# 가장 간단한 방법 (개발 환경에서)
docker run -it --network=host my_ros2_image
# ROS_DOMAIN_ID로 다른 사람과 충돌 방지
docker run -it --network=host -e ROS_DOMAIN_ID=42 my_ros2_image
같은 네트워크에서 ROS_DOMAIN_ID가 겹치면 다른 시스템의 ROS2 graph와 연결된다. 연구실에서 여러 명이 동시에 ROS2를 쓰면 서로의 토픽이 보인다.
DDS를 더 세밀하게 조정해야 할 때는 Cyclone DDS config XML에서 사용할 네트워크 인터페이스를 하나로 지정한다.
<!-- cyclone_dds.xml -->
<CycloneDDS>
<Domain>
<General>
<NetworkInterfaceAddress>eth0</NetworkInterfaceAddress>
</General>
</Domain>
</CycloneDDS>
사용할 config 파일은 환경 변수로 지정한다.
export CYCLONEDDS_URI=file:///path/to/cyclone_dds.xml
Docker 안팎의 파일 소유권
root 사용자로 실행한 Docker 컨테이너에서 만든 파일은 host에서 root 소유로 남아 고치거나 지우려면 sudo를 써야 한다. 호스트 사용자의 uid·gid로 container를 띄우면 소유권이 그대로 따라온다.
# 호스트 사용자 권한으로 실행
docker run -it --user $(id -u):$(id -g) my_image
--user 옵션으로 호스트 사용자 권한을 적용해도 장치나 directory 권한 때문에 ROS package가 동작하지 않을 수 있다. 이때는 chmod 777로 모두 열기보다 Dockerfile에 non-root user를 만들고 필요한 group과 directory 권한만 부여한다.
# Dockerfile에서 non-root 유저 설정
RUN useradd -m -s /bin/bash rosuser && \
usermod -aG dialout rosuser
USER rosuser
센서·하드웨어·실시간 조건
시리얼 포트 권한
/dev/ttyUSB0에 연결할 때 Permission denied가 나타나면 sudo chmod 666 /dev/ttyUSB0으로 일시적으로 접근할 수 있다. 다만 이 권한은 재부팅하거나 장치를 다시 연결하면 사라진다.
다시 연결해도 남는 설정은 udev rule로 만든다.
# 벤더/프로덕트 ID 확인
udevadm info -a -n /dev/ttyUSB0 | grep -E 'idVendor|idProduct'
# /etc/udev/rules.d/99-sensors.rules
SUBSYSTEM=="tty", ATTRS{idVendor}=="1546", ATTRS{idProduct}=="01a9", GROUP="dialout", MODE="0660", SYMLINK+="gps"
# udev rule 적용
sudo udevadm control --reload-rules && sudo udevadm trigger
sudo usermod -aG dialout "$USER" # 다시 로그인한 뒤 group 적용
이렇게 하면 해당 USB 장치는 /dev/gps라는 고정 이름으로 연결되고 권한도 함께 적용된다. 같은 모델을 여러 개 쓸 때는 시리얼 번호를 규칙에 넣어 서로 구분한다.
USB 대역폭
USB3 카메라 여러 대를 같은 허브에 연결했을 때 프레임이 끊기면 driver와 함께 USB 컨트롤러의 대역폭도 확인한다.
# 어떤 카메라가 어떤 USB 컨트롤러에 붙어있는지 확인
lsusb -t
컨트롤러 대역폭이 원인이라면 설정보다 배선을 바꾼다. lsusb -t의 Bus 번호를 보고 카메라를 서로 다른 USB 컨트롤러에 나누어 연결한다. 데스크톱 PC에서는 앞면과 뒷면 포트가 서로 다른 컨트롤러에 연결돼 있기도 하다.
LiDAR의 IP와 UDP 연결
Velodyne이나 Ouster LiDAR에서 데이터가 들어오지 않을 때는 드라이버를 다시 설치하기 전에 네트워크 설정부터 확인한다. 고정 IP와 subnet이 맞지 않아도 같은 증상이 난다.
많은 Ethernet LiDAR는 고정 IP나 지정된 subnet 설정을 사용한다. 장치가 예를 들어 192.168.1.201/24라면 host interface도 겹치지 않는 192.168.1.x/24 주소로 맞춘다. 실제 주소와 UDP port는 장치 설정과 제조사 문서를 따른다.
# 1단계: LiDAR에 ping이 되는지 확인
ping 192.168.1.201
# 2단계: 호스트 이더넷 인터페이스 IP 설정
sudo ip addr add 192.168.1.100/24 dev eth0
sudo ip link set eth0 up
# 3단계: UDP 패킷이 오는지 Wireshark로 확인
sudo tcpdump -i eth0 udp port 2368 -c 10
장치가 ICMP에 응답한다면 ping으로 연결을 확인하고, 응답하지 않더라도 Wireshark나 tcpdump로 지정된 UDP port에 패킷이 들어오는지 살핀다. 패킷은 들어오는데 ROS 토픽에 나타나지 않으면 드라이버와 ROS 설정으로 확인 범위를 좁힌다.
카메라 드라이버와 v4l2
간단한 예제는 cv2.VideoCapture(0)만 보여 준다. 그러나 USB 카메라 하나가 영상과 메타데이터용으로 /dev/video0, /dev/video1을 함께 만들기도 하므로 장치 번호를 먼저 확인해야 한다.
# 카메라 디바이스 매핑 확인
v4l2-ctl --list-devices
# 지원하는 포맷과 해상도 확인
v4l2-ctl -d /dev/video0 --list-formats-ext
# 이 장치가 지원하는 control 확인
v4l2-ctl -d /dev/video0 --list-ctrls
자동 노출(auto exposure)과 자동 화이트밸런스가 frame 사이의 밝기를 크게 바꾸면 특징점 추출과 추적이 흔들린다. 지원하는 control 이름과 값의 허용 범위는 driver마다 다르므로 먼저 확인한다.
# 수동 노출 설정 (SLAM용)
v4l2-ctl -d /dev/video0 --set-ctrl=exposure_auto=1
v4l2-ctl -d /dev/video0 --set-ctrl=exposure_absolute=100
# 화이트밸런스 고정
v4l2-ctl -d /dev/video0 --set-ctrl=white_balance_automatic=0
SLAM이 흔들리면 알고리즘 매개변수를 만지기 전에 자동 노출과 화이트밸런스를 고정해 본다. 그 상태에서 영상 밝기와 특징점 추출이 안정되는지 함께 확인한다.
Jetson의 ARM·JetPack 환경
코드나 Docker 설정을 생성하면 x86을 전제로 한 의존성이 섞일 수 있다. NVIDIA Jetson에서는 ARM64와 JetPack의 버전 제약을 함께 확인한다.
주의할 점:
- package와 version의 조합에 따라 ARM64 wheel이 없을 수 있다. 이때는 source build로 가기 전에 JetPack package, NVIDIA container, 배포판 package 가운데 맞는 배포물이 있는지 찾아본다.
- JetPack 버전은 CUDA, cuDNN, TensorRT의 호환 범위를 정한다. 개별 패키지를 최신 버전으로 올리기 전에 JetPack 호환표를 읽는다.
- Docker image는 장치의 L4T·JetPack release와 호환되는 ARM64 image를 고른다. NVIDIA JetPack release notes에서 현재 조합을 먼저 확인한다.
장치에 설치된 조합은 이렇게 확인한다.
# JetPack 버전 확인
cat /etc/nv_tegra_release
# NVIDIA 문서의 r36.3 예시. 실제 장치에서는 확인한 L4T와 맞는 tag를 선택
docker pull nvcr.io/nvidia/l4t-jetpack:r36.3.0
코드를 요청할 때는 "Jetson Orin, JetPack 5.1.2, CUDA 11.4 환경이다"처럼 장치에서 직접 확인한 조합을 적는다. 이 숫자는 적는 형식을 보이기 위해 든 예다.
실시간 제어 주기
time.sleep(0.01)은 최소 대기 시간만 줄 뿐이며, 루프가 다시 도는 시점은 계산 시간과 운영체제 스케줄링이 정한다. 100 Hz는 코드에 적은 목표 숫자다.
# 주기 검증이 필요한 단순한 구현
import time
while True:
do_control()
time.sleep(0.01) # 실제 주기는 계산 시간과 시스템 부하에 따라 달라진다
Python의 GIL(Global Interpreter Lock)과 운영체제 스케줄링도 멀티스레드의 실행 시점에 영향을 준다. 엄격한 실시간성이 필요하다면 C++과 RT(Real-Time) 커널(PREEMPT_RT) 같은 구성을 살펴본다.
# 실제 퍼블리시 주파수 확인
ros2 topic hz /cmd_vel
코드에 적은 주파수는 목표다. ros2 topic hz가 출력하는 숫자는 관측된 수신 주파수다. 두 숫자가 벌어지면 계산 시간, 스케줄링, 통신 지연을 차례로 확인한다.
반복 실패의 원인을 좁히는 법
시뮬레이션에서만 동작하는 경우
Gazebo에서 동작한 코드가 실제 로봇에서 실패한다면 시뮬레이션과 현실이 다른 지점을 확인한다.
- 센서 노이즈: 시뮬레이터에 넣은 노이즈 모델이 실제 센서의 분포와 어긋난다
- 통신 지연: 시뮬레이션과 실제 시스템의 transport·queue·network 지연이 다르다
- 타이밍 불일치: 시뮬레이터의 clock·timestamp 조건과 실제 센서 간 동기화 오차가 다르다
- 좌표계 불일치: URDF와 실제 로봇의 센서 위치/각도가 미세하게 다르면 tf가 틀어진다
에이전트에게 질문할 때도 "시뮬레이션에서는 되지만 실제 로봇에서는 실패한다. 센서 노이즈 수준은 X이고, 통신 지연은 Y ms이며, 좌표계는 Z 방법으로 보정했다"처럼 측정한 차이를 숫자로 적어 준다.
소프트웨어를 고치기 전에 하드웨어부터 확인한다
케이블 불량, 접촉 불량, 전원 부족은 로그와 장치 상태를 직접 확인해야 구분할 수 있다. 센서 데이터가 간헐적으로 끊길 때는 버퍼 크기, 타임아웃, QoS와 함께 케이블과 USB 허브의 전원도 확인한다.
# 커널 로그에서 하드웨어 문제 단서 찾기
dmesg | tail -20
# USB 연결 해제/재연결 이벤트 확인
dmesg | grep -i usb | tail -20
dmesg에 USB disconnect, device descriptor read/64, error -71 같은 줄이 보이면 연결 상태와 전원부터 확인한다. 케이블을 바꾸고, 유전원 USB 허브를 연결하고, 다른 포트에 꽂아 증상이 달라지는지 비교한다.
OpenCV 재설치 전 패키지·ABI 충돌 확인
라이브러리 버전이 충돌한다면 환경 전체를 다시 설치하기 전에 pip show package_name으로 버전을 확인하고, 어느 패키지끼리 충돌하는지부터 좁힌다.
OpenCV에서는 다음 패키지가 한 환경에 섞이면 충돌할 수 있다.
opencv-python(기본)opencv-python-headless(GUI 없는 서버용)opencv-contrib-python(추가 모듈이 든 것)cv_bridge(ROS 패키지, 자체 OpenCV를 참조)
세 PyPI package는 같은 cv2 namespace를 차지하므로 한 환경에는 하나만 둔다. cv_bridge는 system OpenCV와 연결될 수 있어 pip OpenCV를 섞으면 version·ABI 충돌이 생길 수 있다. 현재 적용된 ROS package와 Python import 경로를 확인한 뒤 한 배포 경로를 고른다.
# 현재 설치된 OpenCV 확인
pip show opencv-python opencv-python-headless opencv-contrib-python
# ROS Humble system package 상태와 실제 import 경로 확인
apt policy ros-humble-cv-bridge
python3 -c 'import cv2; print(cv2.__version__, cv2.__file__)'
ROS Humble의 system OpenCV와 ros-humble-cv-bridge를 쓰기로 했다면 import 경로가 그쪽을 먼저 가리키게 둔다. package를 지우기 전에는 그 package에 의존하는 프로젝트가 있는지 확인한다.
반복 처방을 멈추고 원인을 추적한다
같은 처방을 되풀이해도 증상이 그대로라면 한 층 아래에서 원인을 관측한다. 시스템 로그를 확인하고, strace로 호출을 따라가며, 필요하면 패킷을 잡는다.
에이전트에게 물을 때는 에러 메시지뿐 아니라 다음과 같은 저수준 정보도 함께 제공한다.
# 시스템 로그
dmesg | tail -30
journalctl -u my_service --since "5 minutes ago"
# 프로세스 추적
strace -f -e trace=open,read,write ros2 run my_pkg my_node 2>&1 | head -100
# 네트워크 패킷 캡처
sudo tcpdump -i eth0 -w capture.pcap
이 정보를 함께 주면 어디에나 적용되는 재설치 처방을 반복하지 않고 현재 시스템에서 얻은 증거로 원인을 좁힐 수 있다.
부록 G — Claude의 Adaptive thinking과 Prompt caching (2026년 9월)
Claude 문서에 나온 버전과 수치를 정리해 둔다. 아래 항목의 확인 날짜는 2026년 9월 7일이다. 모델과 제공 플랫폼에 따라 지원 범위와 요금이 달라질 수 있으므로, 코드를 바꿀 때에는 링크한 문서의 해당 모델 항목을 다시 확인한다.
Adaptive thinking
이전에는 답변 전에 모델이 사용할 thinking 분량을 budget_tokens로 직접 지정했다. Claude 4.7 이상에서는 이 방식이 400 오류로 거부된다.
이제는 thinking: {"type": "adaptive"}를 사용한다. 모델은 요청마다 thinking을 쓸지, 쓴다면 얼마나 쓸지 스스로 정한다. 실제 사용량은 응답의 output_tokens_details.thinking_tokens에서 확인할 수 있다.
생각한 내용을 다음 턴까지 이어 가는 방식은 모델에 따라 다르다. extended thinking 문서에 따르면 Claude Opus 4.5와 Claude 4.6 이상 모델은 이전 턴의 thinking block을 보존하며, 그 토큰은 입력 토큰으로 청구된다. 여기서 4.6 이상에는 Opus뿐 아니라 Sonnet도 포함된다. Sonnet 4.5와 Haiku 4.5 및 그 이전 모델은 이전 턴의 thinking block을 지운다.
따라서 호출 코드가 같아도 어떤 모델을 고르느냐에 따라 두 가지가 달라진다. 모델이 이어받는 이전 맥락과 입력 토큰으로 청구되는 양이다.
Prompt caching
호출할 모델을 고정해도 요청의 어느 부분을 바꾸는지에 따라 비용은 달라진다. prompt caching 문서에 따르면 요청의 앞부분이 같으면 캐시에 저장된 부분을 다시 계산하지 않고 사용한다.
캐시는 tools, system, messages 순서로 쌓인다. 앞쪽이 바뀌면 뒤쪽 전체를 다시 쌓아야 한다. 예를 들어 도구 정의 하나를 고치면 캐시 전체가 처음부터 새로 저장된다.
저장 요금과 읽기 요금도 다르다. 5분 동안 저장할 때는 기본 입력 요금의 1.25배가 적용되고, "ttl": "1h"로 한 시간까지 늘리면 2배가 된다. 캐시에서 읽어 올 때는 대체로 0.1배이며, Claude Fable 5.1과 Claude Mythos 5.1은 0.025배다. 무효화된 구간을 다시 캐시에 저장하면 읽기 요금이 아니라 저장 요금이 붙는다.
캐시가 적용되는 최소 토큰 수 역시 모델별로 다르다. Opus 5는 512, Sonnet 5는 1,024, Haiku 4.5는 4,096이다. 이보다 짧은 앞부분은 저장되지 않으므로 매번 다시 계산된다.