MySQL, PHP, Bash를 사용하여 AI를 위한 운영체제를 구축했습니다
요약
AI 에이전트의 컨텍스트 관리 문제를 해결하기 위해 MySQL, PHP, Bash를 활용하여 직접 운영체제(OS) 구조의 시스템을 구축한 사례를 소개합니다. 단순한 문서화를 넘어 운영 그래프(Operational Graph)를 통해 작업과 리소스를 체계적으로 관리하는 엔지니어링 접근법을 다룹니다.
핵심 포인트
- AI 에이전트의 핵심 희소 자원은 지능이 아닌 컨텍스트임
- 기존의 노트 방식은 확장성이 낮고 모순이 발생하기 쉬움
- MySQL, PHP, Bash를 이용해 운영체제 개념의 시스템 구축
- 운영 그래프를 통해 작업(Job)과 리소스(Resource)를 구조화하여 관리
원문은 unviejoprogramador.com (스페인어 버전)에서 처음 게시되었습니다.
이전 글에서 저는 인공지능 (AI)이 제 프레임워크 안에서 매일 작동한다고 언급했습니다. 제가 말씀드리지 않은 것은, 저를 거의 포기하게 만들 뻔했던 문제, 혹은 제가 은퇴할 때 가장 자랑스러워할 엔지니어링 결과물이 된 해결책에 관한 이야기입니다.
문제는 이렇습니다. 제 AI는 천재적이면서도 건망증이 심합니다. 매일 아침은 마치 제가 만난 최고의 엔지니어를 고용하는 것 같았지만... 다른 행성에서 막 도착한 사람 같았습니다. 그 엔지니어는 우리가 어제 무엇을 했는지, 물건이 어디에 있는지, 이 집에서 각 작업이 어떻게 수행되는지, 혹은 — 가장 위험한 것은 — 무엇을 건드려서는 안 되는지를 기억하지 못했습니다. 아침에 설명한 모든 것이 해가 질 때쯤이면 증발해 버렸습니다. 기억력이 없는 천재 엔지니어는 엔지니어가 아닙니다. 그것은 키보드를 든 위험 요소일 뿐입니다.
초보자들은 AI가 매일 아침 다시 읽을 수 있도록 점점 길어지는 노트 파일로 이 문제를 해결하려 합니다. 저도 처음에는 그렇게 시작했습니다. 하지만 그것은 확장성 (scale)이 없습니다. 노트는 늘어나고, 서로 모순되며, 시간이 지나면 쓸모없어지는데 아무도 이를 정리하지 않습니다. 저는 이 질병을 40년 동안 알고 있었습니다. 그것은 문서화 (documentation)라고 불리며, 저는 그것이 어떻게 끝나는지도 알고 있습니다.
희소 자원은 지능이 아니다
모든 것을 바꾼 관찰은 AI가 아닌 시스템 엔지니어링 (systems engineering)에서 왔습니다. 에이전트 (agent)의 희소 자원은 지능이 아니라 컨텍스트 (context)입니다. 즉, 하나의 세션 내에서 그 머릿속에 담을 수 있는 양, 즉 작업 기억 (working memory)입니다.
그리고 희소 자원을 관리하는 것 — 무엇을 언제 로드할지, 누가 무엇을 건드릴 수 있는지, 무엇을 유지하고 무엇을 버릴지를 결정하는 것 — 은 60년대부터 하나의 이름으로 불려 왔습니다. 바로 **운영체제 (operating system)**입니다. 주변에 시스템이 없는 언어 모델 (language model)은 컴퓨터가 없는 훌륭한 CPU와 같습니다. 모든 것을 할 수 있지만, 아무것도 책임지지 않습니다.
그래서 저는 숙련된 프로그래머라면 누구나 할 줄 아는 방식을 택했습니다. 문제를 해결해 줄 유행하는 프레임워크를 찾는 것을 멈추고, 직접 컴퓨터를 구축한 것입니다. 평생을 다뤄온 도구들인 MySQL 데이터베이스, PHP, 그리고 bash를 사용하여 말이죠. 벡터(vectors), 임베딩(embeddings), 마법 같은 시맨틱 메모리(semantic memory)는 없습니다. SQL로 작성된 스키마(schema)를 가진 평범한 데이터베이스와 CLI(Command Line Interface)뿐입니다.
직조기 (The loom)
이 시스템의 핵심은 제가 '직조기(loom)'라고 부르는 것입니다. 이는 운영 그래프(operational graph)로, 비즈니스의 모든 운영 지식을 다섯 가지 노드(node) 유형으로 보유하는 데이터베이스입니다. 이 유형들을 나열하는 이유는 이 분류 자체가 설계의 절반을 차지하기 때문입니다.
작업 (Job) — 수행해야 할 무언가입니다. 생명 주기(대기 중(pending) → 오픈(open) → 차단됨(blocked) → 종료됨(closed))를 가지며, 날짜가 기록된 로그를 포함합니다: 할당, 실행 내용, 그 이유를 포함한 결정 사항, 그리고 종료 시 반드시 검증 가능한 결과가 있어야 합니다.
리소스 (Resource) — 존재하는 무언가입니다: 서버, 애플리케이션, 데이터베이스, 제어판 등입니다. 리소스 카드에는 접근 방법, 사용 방법, 그리고 현재 상태가 명시되어 있습니다.
절차 (Procedure) — 반복 가능한 작업이 수행되는 방식입니다. 런북(runbook): 적용 시점, 단계, 검증 방법, 실패 시 조치 사항을 포함합니다.
사람 (Person) — 누가 누구인지에 대한 정보입니다: 연락처, 역할, 운영하는 대상 등입니다. 실제 비즈니스를 운영하는 일의 절반은 누구에게 연락해야 할지 아는 것이기 때문입니다.
규칙 (Rule) — 횡단적 기준(cross-cutting criterion): 결과가 충족해야 하는 조건입니다. 단계별 과정을 다루는 절차(procedure)와는 다릅니다. 이 규칙들은 실제 발견의 핵심이었기에 아래에서 더 자세히 다루겠습니다.
이 노드들은 일곱 가지 관계 유형(사용함(uses), 따름(follows), 포함함(contains), 차단됨(blocked-by)...)으로 연결되며, 일관성 행렬(coherence matrix)을 통해 허용된 조합만을 가집니다. 이 행렬은 CLI를 통해 모든 연결을 검증하며, 무의미한 엣지(edge)를 거부합니다. 어휘(vocabulary)는 의도적으로 폐쇄적입니다. 만약 어떤 것이 이 일곱 가지 중 하나에 맞지 않는다면, 그것은 엣지가 될 가치가 거의 없기 때문입니다. 이것이 바로 저의 과도한 엔지니어링(over-engineering) 시간을 수개월이나 아껴준 또 다른 관례입니다: 새로운 관계를 발명하기 전에, 먼저 일반 텍스트로 상호 참조(cross-reference)를 작성하십시오. 이것은 스키마의 뒷문(back door)이 아니라, 스키마의 입학 정책입니다. 산문(prose)은 스키마보다 더 오래 지속됩니다.
서브시스템별 메커니즘
저는 운영체제(operating-system)라는 비유를 조심스럽게 유지합니다. 커널(kernel)은 존재하지 않으며, 만약 여러분이 이것을 안전벨트가 달린 티켓 시스템(ticket system)이라고 부르고 싶다면 그 명칭에 대해 논쟁하지 않겠습니다. 제가 옹호하는 것은 이것이 컨퍼런스의 허무맹랑한 이야기(conference smoke)가 아니라는 점입니다. 모든 고전적인 서브시스템(subsystem)이 이곳에 구체적인 대응물을 가지고 있습니다.
스케줄러 (The scheduler). 우선순위가 있는 작업 큐(job queue)입니다. 하나의 작업은 다른 작업에 의해 차단(blocked)될 수 있으며, 차단한 작업이 종료되면 차단되었던 작업은 **스스로를 해제(releases itself)**하여 큐로 돌아갑니다. 의존성(Dependencies)은 누군가의 기억이 아니라 시스템에 의해 관리됩니다.
페이징 (Paging). 단 하나의 명령어가 어떤 작업에 대해서든 AI의 시작 패키지를 단일 호출로 구성합니다: 할당(assignment), 마지막으로 수행된 작업, 액세스 세부 정보가 포함된 리소스, 절차의 단계 및 적용 가능한 규칙들입니다. 6번의 쿼리(queries) 대신 한 페이지의 컨텍스트(context)를 제공합니다. 출력에는 요약 모드(summary mode)가 있는데, 시스템이 덤프(dumps)에 태우지 않는 모든 토큰(token)은 AI가 사고하는 데 사용할 수 있는 토큰이 되기 때문입니다.
메모리 보호 (Memory protection). 가드(guard)는 컨텍스트 없이 누구도 작업하지 못하도록 거부합니다: 어떤 에이전트(agent)도 활성화된 작업, 연결된 리소스와 절차, 그리고 눈앞에 놓인 적용 가능한 규칙 없이는 코드, 서버 또는 데이터에 접근할 수 없습니다. 이는 전형적인 에이전트의 실패 모드, 즉 충분한 컨텍스트 없이 겉으로만 자신감 있게 행동하는 것에 대한 안전벨트입니다. 그리고 무엇이 어렵고 무엇이 어렵지 않은지에 대해 정확히 짚고 넘어갑시다: CLI의 거부는 강력합니다(hard) — 제안이 아니라 종료 코드(exit code)입니다 —; 컨텍스트에 로드된 규칙은 유연합니다(soft), 모델이 읽은 내용을 무시할 수 있기 때문입니다. 그 틈새를 메우기 위해 나머지 두 개의 레이어(layer)가 존재합니다: 고자질하는 로그(log)와 승인하는 인간입니다.
권한 (Permissions). 자격 증명 (Credentials)은 값마다 암호화되어 금고 (vault)에 저장됩니다. 키는 오직 저만이 알고 있는 PIN과, 데이터와 함께 절대 이동하지 않는 로컬 비밀 값 (local secret)을 결합하여 생성됩니다. 테이블 전체가 유출되더라도 그저 노이즈에 불과할 것입니다. AI는 사용되는 시점에, 그리고 제가 금고를 열어둔 동안에만 이름별로 각 자격 증명을 가져옵니다. 여기서 정확히 말씀드리겠습니다. 사람들이 과장하곤 하는 부분인데, 이 설계는 비밀 정보의 노출을 최소화 (minimises) 하는 것이지, 노출을 완전히 제거한다고 주장한다면 그것은 거짓말일 것입니다. 또한 운영 환경 (production)에서의 민감한 작업은 명시적인 인간의 승인을 필요로 하며, 이는 그룹화되어 정확한 대상을 명시해야 합니다. 한밤중에
지금쯤 한 명 이상의 독자가 그 비결을 찾으려 할 것입니다. 어딘가에서 대기 중인 데몬(daemon)이 있을까요? 데이터베이스에 연결된 모델이 있을까요? 둘 다 아닙니다. 상주하는 프로세스는 없습니다. 에이전트(agent)는 내 개발 머신에 셸(shell) 접근 권한을 가진 코딩 어시스턴트이며, loom은 MySQL을 통한 작은 CLI를 통해 읽고 쓰입니다. 세션은 내가 시작할 때 생성됩니다. 단 한 번의 명령으로 컨텍스트 패키지(context package)를 가져오고, 작업을 수행하며, 모든 동작을 엔트리(entries)로 기록한 뒤 종료됩니다. 지속되는 것은 프로세스가 아니라 데이터 계약(data contract)입니다.
진정으로 스케줄링된 작업은 평범한 구식 cron이며, 의도적으로 지루하게 설계되었습니다. 그룹 승인(grouped approval) 또한 어떤 정교한 비동기 큐(asynchronous queue)가 아닙니다. 그것은 대화입니다. 에이전트가 대상을 명시하며 배치(batch)를 제안하면, 나는 동일한 세션 내에서 예 또는 아니오라고 답합니다. 그리고 최후의 수단인 스케줄러는 여전히 나 자신입니다. 세션이 있을 때와 없을 때를 내가 결정합니다. 이것 또한 비용 제어(cost control)이며, 가장 오래된 방식입니다.
규칙: 헌법
뒤늦게 깨달은 사실은 한 종류의 지식이 누락되었다는 것이었습니다. 그것은 "무엇이 존재하는가"도, "어떻게 수행되는가"도 아닌, **"무엇이 반드시 지켜져야 하는가"**였습니다. 기준(criteria) 말입니다. 그 이면에 이유가 있는 강박(manias)들 말입니다. 숙련된 운영자는 알고 있지만 신입 사원은 모르는 것 — 즉, 그 지식을 보유한 사람이 은퇴할 때 모든 회사에서 사라져 버리는 지식입니다. 이 사례는 매우 현실적입니다.
그래서 어느 날 우리는 수년간 축적된 574개의 문서 파일과 AI 스스로가 기록해 온 개인적인 노트들을 훑어보았고, 그 모든 곳에 흩어져 있는 규칙들을 수확했습니다. 오늘날 그것들은 주제별로 그룹화된 약 260개의 개별 규칙이 되었으며, 각 규칙은 출처와 — 이 부분이 중요한데 — 검증(verification) 방법을 포함하고 있습니다. 우리 집의 모토는 다음과 같습니다. 검증이 없는 규칙은 소망일 뿐이다.
규칙은 그것을 사용하는 절차(procedures)와 연결되어 있으며, 가드(guard)는 AI가 실행하기 전에 규칙을 AI 앞에 배치합니다. 이것들은 읽힐 수도 있는 문서가 아니라, 로드되는 컨텍스트(context)입니다. 법이 존재하는 것과 사법부(judiciary)가 존재하는 것의 차이와 같습니다.
시스템의 건전성을 유지하는 원칙
두 가지 원칙이 이 시스템(the loom)이 모든 기업용 위키(corporate wiki)가 2년 안에 겪게 되는 전철을 밟지 않도록 방지합니다.
The loom은 데이터 평면 (data plane)이 아니라 제어 평면 (control plane)입니다. 이는 인덱스(index), 라이브 상태(live state), 그리고 포인터(pointers)를 보유합니다. 대량의 데이터(Bulk data)는 그 소스(source)에 존재하며 실시간으로 쿼리(query)됩니다. 보고서(Reports)는 문서가 아니라 쿼리입니다. 저장된 보고서는 생성되는 순간 이미 오래된 정보(stale)가 되며, 그 이후로는 영원히 낡은 상태로 남습니다.
명시적인 진실의 계층 구조 (explicit hierarchy of truth). 만약 the loom과 문서가 서로 충돌한다면, the loom이 승리합니다. 만약 the loom과 현실이 충돌한다면, 현실이 승리합니다. 그리고 the loom은 수행 중인 작업의 일부로서 즉시 수정됩니다. 모든 종료된 작업은 시스템이 이전보다 더 많은 것을 알게 된 상태로 남아야 합니다. 이러한 자기 개선(self-improvement)은 하나의 기능(feature)이 아니라, 시스템의 존재 목적 그 자체입니다.
두 씨뿌리꾼의 밤
그리고 설계에 없던 일이 발생했습니다.
어느 날 밤, 두 개의 인공지능 (AI)이 병렬로 작업하고 있었습니다. 한 창에는 강력한 모델이, 다른 창에는 저렴한 모델이 각자의 작업을 수행하고 있었습니다. 작업 할당의 우연으로 인해, 두 모델 모두 서로의 존재를 인지하지 못한 채 동시에 the loom에 규칙을 심기(sowing) 시작했습니다. 첫 번째 모델이 자신의 작업을 검증하러 갔을 때, 자신이 생성하지 않은 노드(nodes)들을 발견했습니다.
그다음에 일어난 일은 이 시스템이 무엇인지를 가장 잘 설명해 줍니다. 첫 번째 AI는 the loom을 참조함으로써 (by consulting the loom) 충돌을 감지했고, 상대방의 작업 내에 (in the other one's job) 조정 노트(
회의적인 엔지니어라면 이렇게 말할 것입니다: 그것은 레이스 컨디션 (race condition)이며, 수동으로 해결하고 기록한 것뿐이라고 말이죠. 맞습니다. 바로 그 점이 핵심입니다 — 공유 상태 (shared state)가 보이지 않던 충돌을 가시적이고 감사 가능한 (auditable) 사건으로 바꾸었으며, 문서화된 해결책을 남기게 했습니다. 시스템은 사고가 전혀 없는 것으로 측정되는 것이 아니라, 사고를 어떻게 기록하고 알리는가로 측정됩니다.
무엇이 변했는가 (그리고 무엇이 힘든가)
서론을 제외한 결과는 다음과 같습니다: 세션이 설명 대신 몇 분 만에 시작됩니다; 절차들이 첫 번째 시도에 성공하는데, 이는 지난번의 지식이 있어야 할 곳에 있기 때문입니다; 그리고 시스템은 내 기억 대신 실시간 쿼리 (live queries)를 통해 이번 달에 누구에게 송장을 발행해야 하는지, 어떤 고객이 연락이 끊겼으며 그 이유는 무엇인지와 같은 실제 비즈니스 질문에 답합니다.
누구도 속지 않도록 솔직히 말씀드리자면, 힘든 점도 있습니다: 매일의 규율을 요구합니다 (
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기