ArbiterOS는 완성된 제품이 아니라, 40대 직장인이 집의 Mac mini에서 만들어 가는 개인 AI 시스템입니다. 이 글은 2026년 9월 4일 확인한 구성과 개발 기록을 기준으로, 작동한 기능과 아직 검증하지 못한 부분을 나눠 정리했습니다.
9월 추가 개발 기록: n8n 정규식 오류를 Python 생성기에서 고친 과정
2026년 9월 14일, 기한 질문 처리 경로에서 답변을 정리하는 Code 노드가 Invalid regular expression flags로 멈췄습니다. 모델 답변을 다듬기 전에 JavaScript 문법을 해석하는 단계에서 실패했습니다.
Python이 JavaScript를 문자열로 만들고 JSON으로 저장하는 구조에서 역슬래시를 과하게 이스케이프했습니다. JSON 표기에 보이는 역슬래시 수보다, JSON을 파싱한 뒤 실제 jsCode 값을 확인하는 것이 핵심이었습니다.
최소 재현 코드
아래 코드를 regex-repro.cjs로 저장하고 node regex-repro.cjs로 실행합니다. 실제 서비스나 인증정보 없이 동작합니다. new Function에는 이 예제의 고정 코드만 전달하며 외부 입력을 실행하지 않습니다.
const assert = require("node:assert/strict");
const before = String.raw`return raw.replace(/<think>[\\s\\S]*?<\\/think>/gi, '');`;
const after = String.raw`return raw.replace(/<think>[\s\S]*?<\/think>/gi, '');`;
try {
new Function("raw", before);
throw new Error("Expected a syntax error");
} catch (error) {
assert(error instanceof SyntaxError);
console.log("BEFORE:", error.name + ": " + error.message);
}
const clean = new Function("raw", after);
const sample = "<think>line 1\nline 2</think>{\"items\":[]}";
assert.equal(clean(sample), '{"items":[]}');
console.log("AFTER:", clean(sample));
assert.equal(JSON.parse(JSON.stringify({jsCode: after})).jsCode, after);
console.log("JSON round-trip: PASS");
왜 실패했나
수정 전에는 닫는 태그 앞의 역슬래시 두 개가 서로 묶여 그 뒤 슬래시가 정규식의 끝으로 해석됩니다. 뒤따르는 think가 플래그처럼 읽혀 구문 오류가 납니다. 수정 후에는 슬래시 하나를 이스케이프하는 의도가 그대로 전달됩니다.
실제 개발 기록에서 확인한 범위
생성기와 두 Code 노드를 함께 수정했습니다. 9월 14일 기록에는 정상 인용, 원문에 없는 인용의 거부, 잘못된 JSON, 빈 질문, 임베딩 오류, 검색 결과 없음, 낮은 검색 관련도에 대한 검사가 남아 있습니다. 위 최소 예제는 그 전체 검사를 대신하지 않습니다.
9월 22일에는 당시 보관한 수정 전후 코드로 별도의 로컬 재현 파일을 실행했습니다. 수정 전 SyntaxError: Invalid regular expression flags, 수정 후 {“items”:[]}, JSON 왕복 보존 PASS를 확인했습니다.
| 환경 | macOS, Node.js v26.5.0 |
|---|---|
| 실행 횟수 | 1회 |
| 전체 소요시간 | 35.2ms |
Python 단조 증가 타이머로 Node 프로세스 시작 직전부터 종료까지 측정했습니다. Node 시작 비용을 포함하며 모델·검색·n8n·Telegram 전송 시간은 포함하지 않습니다. 운영 응답 속도나 성능 개선 수치가 아닙니다.
같은 오류를 만나면 생성기 원본 → JSON에서 꺼낸 코드 → 실제 게시된 노드 순서로 비교하면 됩니다. 실행 성공과 답변의 내용 정확도는 별개입니다. 인용이 원문에 있어도 질문 관련성과 적용 조건은 따로 확인해야 합니다.
사례 기준일 2026-09-14, 로컬 재현일 2026-09-22. 작성자의 개발 기록을 바탕으로 AI 편집 도움을 받아 정리했습니다. 실제 서비스 식별자와 업무 자료는 포함하지 않았습니다.
왜 질문에 답하는 챗봇을 넘어 만들기 시작했나
저는 업무에서 법령과 문서의 논리를 검토할 때 ChatGPT와 Claude를 자주 사용합니다. 그런데 답변을 받는 것과 근거를 확인하는 것은 별개의 일이었습니다. 과거 법령을 현행 규정처럼 제시하거나 맞지 않는 정보를 주는 경우가 있어, 출처를 요청하고 실제 조문을 직접 읽는 습관을 들였습니다.
ArbiterOS는 그 확인 과정을 제 작업 환경에 연결해 보는 프로젝트입니다. 집에 둔 Mac mini에서 모델과 도구를 실행하고, 텔레그램으로 요청을 보내 필요한 기록과 근거를 찾아오는 것이 기본 방향입니다. 이름에 OS가 붙어 있지만 macOS를 대체하는 운영체제는 아닙니다. 여러 도구를 연결한 개인용 AI 에이전트 시스템에 가깝습니다.
목표는 AI에게 판단을 모두 넘기는 것이 아닙니다. 검토 후보를 찾는 작업과 최종 판단을 분리하려는 것입니다. 이 원칙은 AI 시대 직장인의 실전 습관: 법령 검토부터 바이브코딩까지에서도 정리했습니다.
현재 구성: Mac mini, 로컬 모델, 검색 가능한 기록
현재 장비는 Apple M4 Pro, 14코어 CPU, 메모리 24GB의 Mac mini입니다. Ollama에서 Qwen3 14B를 사용하고, n8n이 요청과 도구 실행을 연결합니다. Qdrant는 법령·노트·기한 자료를 의미 기반으로 찾는 검색 저장소 역할을 합니다.
- 텔레그램: 요청을 보내고 결과를 받는 창구입니다.
- n8n과 로컬 모델: 요청의 종류를 분류하고 해당 처리 경로로 보냅니다.
- Qdrant와 마크다운 문서: 검색용 벡터와 읽을 수 있는 원문을 나눠 보관합니다.
- 대화 기록: 현재는 n8n 데이터테이블을 사용합니다. 초기 Redis 기반 기억 구조를 현재 구성처럼 설명하지 않도록 구분했습니다.
- Docker와 로컬 중계기: 컨테이너 서비스와 Mac 본체의 기능을 연결합니다.
여기서 말하는 로컬은 모델 실행과 주요 검색·저장 경로의 위치입니다. 텔레그램과 Dynalist 같은 외부 서비스도 사용하므로, 시스템 전체가 오프라인이거나 아무 데이터도 외부로 나가지 않는다는 뜻은 아닙니다. 회사 자료와 개인 기록을 어디에 입력하고 무엇을 전송할지 따로 판단해야 합니다.
요청이 처리되는 흐름
별도 입력 경로: 검토함 폴더·예약 실행
Mac mini의 주요 처리·저장 영역
- n8n이 실행 흐름을 연결합니다.
- 자연어 요청은 로컬 모델이 작업 종류를 분류합니다.
- 법령·계약검토·기한·노트 검색 또는 일반 대화로 분기합니다.
- 검색이 필요한 경로는 Qdrant와 원문을 참조합니다.
- 법령 답변 등의 인용 검증 경로에서 원문과 인용을 대조합니다.
근거 확인이 안 되면 → 답변을 제한하고 후보·추가 확인으로 돌립니다.
중요한 해석과 최종 판단은 사람이 확인합니다.
기록의 별도 유입: Dynalist → Obsidian의 마크다운 → 노트 검색 인덱스. 단방향 가져오기이며, 메신저를 포함한 외부 서비스 연결은 로컬 영역 밖입니다.
이 그림은 모든 기능이 같은 순서로 실행된다는 뜻은 아닙니다. 일반 대화와 문서 검토는 다른 경로를 사용하며, 인용 대조가 답변 전체의 진실성이나 법률 해석의 타당성을 보증하지도 않습니다.
무엇을 확인했고, 무엇은 아직 모르는가
아래 수치는 2026년 9월 4일 운영 점검에서 확인한 스냅샷입니다. 9월 5일에는 이 점검 기록과 공개 본문을 대조해 검증 상태를 보강했습니다. 새로 성능 시험을 한 것은 아닙니다. 자료가 늘거나 재색인하면 수치가 달라질 수 있으며, 개수는 구축 범위이지 정확도 점수가 아닙니다.
- 작동함 — 확인한 실행·산출물 범위: 계약문서 두 건의 처리 완주와 출력 실패 0건, Dynalist 기록 1,037개를 가져온 산출물, 백업 파일 생성을 확인했습니다. 반복 실행의 안정성이나 내용의 정확도까지 뜻하지는 않습니다.
- 부분 검증: 요청 분류는 시험 문장의 경로 선택을, 법령 인용 대조는 원문과의 일치를 확인했습니다. 답변의 해석, 계약 판정, 기한의 의무 주체가 맞는지는 별도 문제입니다.
- 미검증: 계약검토의 누락·오탐, 일부 예약 작업의 지속적인 성공, 백업의 실제 복원, 동일 조건의 응답 속도 비교는 확인을 마치지 못했습니다.
- 다음 실험: 사람의 기준과 결과를 대조하고, 예약 시각·실행 기록·산출물을 함께 확인하며, 분리된 환경에서 복원 후 대표 기능이 다시 작동하는지 시험할 계획입니다.
| 항목 | 확인된 상태 | 남은 한계 |
|---|---|---|
| 법령 검색 | 조문 카드 2,845개와 검색 벡터 2,845개 수량 일치 | 개수 일치는 조문 최신성·완전성·답변 품질의 보증이 아님 |
| 계약문서 검토 | 입찰안내서 두 건의 처리 완주 및 출력 실패 0건 확인 | 판정의 정오·누락·오탐을 사람이 대조하는 검증은 미완료 |
| 노트 가져오기 | 마크다운 1,037개, 전부 출처 태그 확인 | 자동 주제 분류의 품질은 별도 평가 필요 |
| 검색 저장소 | 법령 2,845·노트 1,273·기한 1,738 벡터 확인 | 파일 수와 검색 단위 수는 다른 지표 |
| 백업 | 일일 백업 산출물 7세트 확인 | 의도한 실행 시각과 실제 시각의 불일치 점검 필요. 복원 성공은 별도 검증 |
| 예약 자동화 | 검토함 감시·브리핑·시스템 감시 등의 설정 존재 | 일부 성공 기록이 저장되지 않아 실제 주기 실행 확인에 한계 |
계약검토의 조항 수는 추출 방식을 바꾼 뒤 집계가 달라졌습니다. 그래서 여기서는 오래된 조항 수나 뒷받침 로그를 찾지 못한 처리시간을 성능 수치로 내세우지 않습니다. 끝까지 실행됐다는 것과 올바르게 판단했다는 것은 다릅니다. 원문에서 빠진 조항이 없는지 확인하는 일도 별도의 과제입니다.
시행착오 1: 프롬프트를 줄였더니 다른 일을 했다
8월 말 자연어 라우터를 손보며 프롬프트를 2,895자에서 2,269자로 줄였습니다. 짧게 정리했지만, 요청 종류의 경계를 설명하던 규칙까지 빠졌습니다. “오늘 작업 내용 정리해줘”라는 요청이 요약이 아니라 과거 노트 검색으로 보내졌습니다.
같은 38개 문장에 대한 분류 테스트는 개편 직후 33개 통과에서 요약·도움말 경계 규칙 복원 후 37개 통과로 바뀌었습니다. 마지막에는 “목록을 확인해 달라”는 요청이 웹 검색으로 가는 문제를 발견했습니다. 화면을 ‘열거나 조작하는 일’만 정의하고 ‘조회하는 일’을 빠뜨렸던 것입니다.
실패한 문장을 그대로 예시에 추가하면 점수만 좋아질 수 있습니다. 실제로 앞선 측정에서 예시와 시험 문장이 겹치는 문제가 있었습니다. 이후에는 규칙을 고치고, 프롬프트에 넣지 않은 새 문장 5개도 따로 시험했습니다. 그 다섯 문장은 모두 의도한 경로로 분류됐습니다.
다만 표본이 작고 개발 중 반복 사용한 문장도 있으므로, 이 결과를 일반적인 성공률로 확대하지 않습니다. 이것은 어느 도구로 보낼지를 맞힌 결과이지, 그 도구가 만든 답변의 정확도가 아닙니다. 다음에는 기존 시험과 겹치지 않는 요청을 더 모아 비교해야 합니다.
시행착오 2: 백업은 성공했는데 범위가 빠져 있었다
검색 저장소가 법령 하나에서 법령·노트·기한 세 종류로 늘어났는데, 백업 스크립트는 예전 범위에 머물러 있었습니다. 기존 백업 세트에는 법령만 포함되어 있었습니다. 기능을 추가할 때 복구 대상도 함께 추가해야 한다는 점을 놓친 것입니다.
남아 있는 백업 폴더를 비교하면 8월 29~30일 세트는 항목이 8개, 8월 31일 이후에는 10개입니다. 점검 기록에서 추가된 두 종류의 컬렉션이 포함된 것을 확인했습니다. 단순히 폴더의 개수가 늘었다는 사실만으로 백업이 올바르다고 판단하지는 않습니다.
이번 확인에서는 예약 시간대 문제도 남아 있었습니다. 백업 파일이 만들어지고 있더라도 의도한 시각에 실행되는지, 필요한 자료가 모두 들어 있는지, 실제 복원이 되는지는 각각 확인해야 합니다. 아직 복원 시험 결과까지 확인했다고 쓸 수는 없습니다.
시행착오 3: 모델보다 데이터 칸을 먼저 고쳐야 했다
법령에서 기한을 추출하는 과정에서는 ‘언제까지’라는 칸에 조건과 행위까지 섞이는 문제가 있었습니다. 시간을 담을 칸과 조건을 담을 칸을 분리하자, 운영 문서에 기록된 근거 확인 실패율은 31.9%에서 7.3%로 낮아졌습니다.
이 수치는 해당 추출·근거 확인 작업의 전후 결과입니다. 법률 판단 정확도가 올라갔다는 뜻은 아닙니다. 의무를 이행할 주체를 분류하는 문제는 별도로 남아 있습니다. 인용 문구가 원문에 존재해도, 그 문구를 누구에게 적용할지 틀릴 수 있기 때문입니다.
이 사례에서 다음 점검 순서는 모델 교체보다 입력과 출력 구조였습니다. 한 칸에 서로 다른 정보를 섞어 넣게 만들고, 결과가 모호하다고 모델만 탓하지 않도록 기록해 두었습니다.
Dynalist에서 Obsidian으로: 이제 기록을 가져와 찾을 수 있다
이전 초안에서는 Dynalist와 Obsidian 연결을 진행 중인 계획으로 적었습니다. 9월 4일 확인에서는 가져온 마크다운 1,037개와 폴더 97개가 존재했고, 모든 문서에 출처 태그가 붙어 있었습니다. 노트 검색용 인덱스도 연결되어 있습니다.
중요한 제한은 단방향 가져오기라는 점입니다. Dynalist의 기록을 Obsidian으로 가져오지만, Obsidian에서 수정한 내용을 Dynalist에 되돌려 보내는 양방향 동기화는 아닙니다. 가져온 산출물이 있다는 사실과 예약 동기화가 매번 정상 실행된다는 증거도 구분해야 합니다.
이 기록을 블로그 재료로 활용하는 것은 다음 단계입니다. 개인 메모를 곧바로 공개하는 흐름이 아니라, 사람이 공개할 기록을 고르고 민감한 내용을 제거한 뒤 초안을 만드는 방식을 생각하고 있습니다. 기록에 남지 않은 성과나 감정을 AI가 채워 넣지 않게 하는 것이 핵심입니다.
실제 노트의 내용과 폴더명에는 개인·업무 정보가 섞일 수 있어 이 글에는 원본 화면을 싣지 않았습니다. 기록을 근거로 다시 확인하는 학습 방식은 40대 직장인의 검증 중심 학습법과도 이어집니다.
Mac mini를 바꿀까? 아직은 측정할 것이 남았다
더 빠른 장비로 바꾸고 싶은 고민은 있습니다. 하지만 지금 보관된 자료에는 제 작업의 응답 속도와 처리량을 같은 조건으로 비교할 충분한 측정 기록이 없습니다. 따라서 특정 신제품의 성능 배수를 제 시스템의 개선 폭처럼 쓰거나, 구매할 모델을 확정하지 않겠습니다.
다음 비교에서는 같은 모델·같은 요청·같은 동시 실행 조건을 유지하고, 첫 응답까지 걸린 시간, 전체 처리시간, 메모리 압박과 스왑을 함께 기록하려고 합니다. 느린 원인이 검색인지 모델인지 문서 추출인지부터 구분해야 장비 교체의 필요성도 판단할 수 있습니다.
앞으로 확인할 네 가지
- 계약검토의 내용: 사람이 정리한 기준과 비교해 누락·오탐·근거 적합성을 각각 기록합니다. 처리 완주 여부와 판정 결과를 따로 집계할 계획입니다.
- 예약 작업의 실행: 예정 시각·시간대·실제 실행 기록·산출물을 한 실행 단위로 대조할 계획입니다. 기록이 없으면 성공으로 집계하지 않고 확인 불가로 남깁니다.
- 백업의 복구 가능성: 운영과 분리된 환경에서 백업을 복원하고, 대상 데이터와 대표 검색 결과를 대조할 계획입니다. 파일 생성과 기능 복구의 성공 여부를 따로 남깁니다.
- 기록의 공개 경계: 공개용 기록에는 확인 날짜·대상·검사 방법·결과·남은 한계를 함께 남깁니다. 일기·업무 원문과 인증정보를 제외하고 필요한 사실만 옮깁니다.
로컬에서 실행하더라도 비밀 키나 내부 자료가 화면·파일·링크에 남을 수 있습니다. 공개 전에는 원문 캡처보다 필요한 정보만 다시 작성한 도식을 사용합니다. 입력 자료와 계정을 다루는 기본 원칙은 AI에 업무 자료를 넣기 전 확인할 것에 따로 정리했습니다.
ArbiterOS의 개발일지는 ‘AI가 다 해준다’는 성공담보다, 무엇을 연결했고 어느 부분에서 틀렸으며 무엇을 아직 확인하지 못했는지 남기는 기록으로 이어가려 합니다.
개발 이력과 이 글의 변경 기록
초기 구축 순서는 운영 문서에 남아 있지만, 날짜를 독립적으로 확인할 수 없는 구간은 특정 날짜로 단정하지 않았습니다. 아래는 변경 기록이 남아 있는 최근 구간입니다.
- 초기 구축: 로컬 모델 → 메신저 연결 → 작업 흐름과 대화 기억 → 법령 검색과 계약검토 순으로 확장했습니다.
- 2026-08-25: Git 저장소와 변경 절차를 정리했습니다.
- 2026-08-29~30: Dynalist 가져오기, 노트 검색, 자연어 라우팅을 보강했습니다.
- 2026-08-31: 기한 검색을 연결하고 백업 대상을 확대했습니다.
- 2026-09-03: 법령 후속질문과 답변 근거 검증을 보강했습니다.
- 2026-09-04 글 교정: 현재 저장 구조와 노트 연동 상태를 반영하고, 처리 완주와 판단 품질을 구분했습니다. 시스템 개념도와 검증 한계를 추가했습니다.
2026-09-05 글 보강: 9월 4일 근거 자료에 맞춰 작동함·부분 검증·미검증·다음 실험을 구분하고, 다음 검증에서 남길 증거를 구체화했습니다. 새 성능 측정이나 복원 성공을 추가한 변경은 아닙니다.
작성 방식: 작성자의 사용 경험과 비공개 개발·검증 기록을 바탕으로 AI의 편집 도움을 받아 정리했습니다. 원문에는 개인·업무 정보가 있어 공개하지 않았습니다. 위 수치는 내부 점검 결과이며 독립적인 성능 인증이나 법률 자문을 의미하지 않습니다.