OpenAI가 실제로 발표한 내용
먼저 Habitat이 무엇이고 누가 여기서 데이터를 읽어오는지부터 시작하겠습니다. OpenAI는 이를 "OpenAI 제품이 필요한 정보에 빠르고 안정적으로 액세스할 수 있도록 구축한 온라인 스토리지 플랫폼"이라고 설명하며, 이 플랫폼이 처리하는 요청의 종류를 언급하며 시작합니다. "모든 OpenAI 제품은 로그인하거나, Codex 설정을 확인하거나, ChatGPT에서 새 대화를 시작할 때 등 데이터에 대한 빠르고 안정적인 액세스에 의존합니다. 이러한 각 작업은 제품이 응답하기 전에 여러 개의 개별 데이터 조회를 필요로 할 수 있습니다."
규모는 명확하게 제시되어 있습니다. Habitat은 "현재 초당 7,000만 개 이상의 요청을 처리하며, 거의 40개 지역에 걸쳐 매주 10억 명 이상의 사람들이 사용하는 제품을 지원"하고 있으며, "오늘날에는 500페타바이트 이상의 데이터를 제공하는 복잡한 분산 시스템"입니다.
그다음 여기서 중요한 설계 결정이 나오는데, OpenAI는 이를 한계가 아닌 결정으로 규정합니다.
"클라이언트가 대규모 테이블 스캔이나 여러 테이블 간의 조인(join)을 유발할 수 있는 임의의 SQL 쿼리를 구성하도록 허용하는 대신, Habitat은 단순한 NoSQL API를 노출합니다. 강력한 API의 부재는 Habitat 설계에서의 명시적인 트레이드오프입니다."
그 이유는 예측 가능성 때문입니다. "우리는 단순하고 예측 가능하며 일정한 작업량(constant-work)을 갖는 요청에 최적화하는 것을 목표로 합니다. 우리의 경험상 이러한 시스템은 확장하기가 훨씬 쉽고, 잘못 사용하거나 오용하기 어렵습니다. 예측할 수 없는 팬아웃(fanout)을 가진 요청은 운영상 위험합니다. 격리와 로드 밸런싱을 복잡하게 만들고, 서비스와 클라이언트 모두가 확장하기 어려운 레이턴시 절벽(latency cliff)을 유발합니다."
데이터 모델도 이에 따릅니다. "Habitat은 TAO에서 영감을 받아 클라이언트가 정의한 객체(object) 및 에지(edge) 유형을 중심으로 모델링된 NoSQL API를 노출합니다. 클라이언트는 객체와 에지, 그리고 이들이 서로 어떻게 연관되는지 미리 정의하지만, 각 유형의 콘텐츠는 정의하지 않습니다." OpenAI가 여기서 영감을 받은 대상을 언급한 점은 주목할 만합니다. 이는 임시방편으로 급조된 것이 아니라 이미 널리 검증된 패턴입니다.
그리고 언론 보도에서 생략된 문장이 나옵니다.
"우리는 각 객체와 그에 해당하는 에지가 스토리지 수준의 파티션에 함께 배치(colocate)되도록 이 그래프를 분할하지만, 객체와 그 에지가 가리키는 원격 객체를 함께 배치하기 위한 데이터베이스 수준의 공동 노력은 기울이지 않습니다. 그 결과 모델은 수평적 확장성을 위해 쉽게 분할되지만, 객체 간의 특정 홉(hop)이 서로 다른 지역에 저장된 완전히 다른 두 개의 Azure Cosmos DB 계정에서 가져와야 할 수 있으므로 그래프 탐색(graph traversal)은 비효율적입니다."
이 부분을 두 번 읽어보세요. 객체와 그 직접적인 에지는 함께 있습니다. 하지만 그 에지들이 가리키는 대상은 지구 반대편에 있을 수도 있습니다. OpenAI는 다음과 같이 명확하게 한계를 둡니다. "결과적인 관계는 그래프와 유사하지만, Habitat 자체는 특정 객체의 직접적인 에지를 쿼리하는 것 외에는 일반적인 그래프 탐색 쿼리를 지원하지 않습니다."
더 복잡한 작업은 실시간 경로(live path)에서 완전히 제외됩니다. "더 복잡한 쿼리 요구사항이 있는 클라이언트를 위해, 우리는 Rockset을 통해 노출되는 Habitat의 오프라인 보조 뷰(secondary view)를 제공합니다." 변경 사항은 CDC(change data capture)를 통해 스트리밍되며, 각 팀은 자체 인스턴스를 운영합니다. OpenAI는 그 이유를 명확히 밝힙니다. "이 설계는 온라인 스토리지를 읽기 집약적인 분석 및 검색 워크로드로부터 격리합니다."
이것이 바꾸는 것과 바꾸지 않는 것
이것은 오늘날 ChatGPT가 작동하는 방식을 바꾸지 않습니다. 이는 인프라 레이어에 대한 엔지니어링 게시물일 뿐 제품 발표가 아니며, OpenAI도 그렇게 주장하지 않습니다.
또한 특정 기능의 데이터가 어디에 저장되는지 알려주지도 않습니다. 이 게시물은 ChatGPT, API, Codex 및 내부 서비스를 Habitat의 클라이언트로 언급하고, "ChatGPT에서 새 대화 시작하기"를 요청의 예로 들고 있습니다. 어떤 제품 기능의 스키마도 공개하지 않았으며, 이 글에서 임의로 만들어내지도 않을 것입니다.
바뀌는 것은 우리가 할 수 있는 추측의 품질입니다. 이 게시물이 나오기 전에는 "왜 내 어시스턴트는 개별 사실은 기억하면서 그것들을 서로 연결하지는 못할까?"라는 의문이 그저 추측에 불과했습니다. 이제는 그것들을 연결하는 것이 스토리지 레이어에서 왜 비용이 많이 드는 작업인지에 대한 문서화된 아키텍처적 이유가 생겼으며, 이는 시스템을 구축한 사람들이 직접 밝힌 사실입니다. 즉, 직접적인 에지를 가진 단일 객체 조회는 저렴하고 일정한 작업량이 드는 케이스인 반면, 객체 간의 홉은 리전을 넘나들 수 있는 케이스이기 때문입니다.
이는 "AI의 메모리가 나쁘다"는 주장과는 다르며, 훨씬 더 유용한 관점입니다. why long context isn't memory에서 설명한 격차는 대개 모델의 문제로 프레임이 짜여집니다. 여기서는 한 단계 아래인 스토리지 계층에서 동일한 형태의 문제가 나타나고 있으며, 이는 벤더가 자체 시스템에 대해 직접 공개한 내용입니다.
가슴에 새겨둘 만한 문장이 하나 더 있습니다. 전체 설계 철학을 단 몇 마디로 설명해주기 때문입니다. "평균적인 사용자 요청이 수백 개의 데이터베이스 호출을 유발할 때, 사용자가 체감하는 것은 가장 느린 데이터베이스 호출이다."
사람들이 이 글에서 오해하기 쉬운 것들
OpenAI가 스토리지에서 임시방편을 썼다는 오해. 이 게시물은 그 반대임을 여러 이유를 들어 상세히 논증합니다. API를 제한하는 것이야말로 이 정도 규모의 시스템을 예측 가능하게 만드는 비결입니다. OpenAI는 제한이 없는 쿼리를 "운영상 위험하다"고 부르며 비용 불균형을 직접 설명합니다. "실행하기는 비싸고 어렵지만 작성하기는 저렴하고 쉬운 것이 SQL 쿼리입니다." 제품 팀이 10억 명의 사용자를 위한 데이터베이스를 다운시킬 수 있는 쿼리를 작성하지 못하도록 막는 플랫폼이야말로 제 역할을 다하고 있는 플랫폼입니다.
이것이 OpenAI에만 해당된다는 오해. 그렇지 않습니다. OpenAI는 영감을 준 대상으로 TAO를 언급했는데, 이는 다른 규모의 다른 회사에서 발표한 설계입니다. 그리고 이 설계가 담고 있는 트레이드오프(객체를 에지와 함께 배치하고, 원격 홉의 비용이 많이 든다는 점을 수용하는 것)는 그래프 형태의 저장소를 수평적으로 분할하는 표준적인 방법입니다. 매우 큰 규모의 온라인 데이터 저장소를 운영하는 사람이라면 누구나 동일한 셈법에 직면하게 됩니다.
오프라인 복사본이 문제를 해결해 줄 것이라는 오해. Habitat의 탈출구는 실재하며, OpenAI는 여기에 비용이 든다는 점을 솔직하게 인정합니다. "이 Rockset 프로비저닝은 클라이언트에게 추가적인 마찰을 유발합니다." 그리고 각 팀은 "자신의 Rockset 인스턴스를 확장할 책임이 있습니다." 이는 담당자와 예산이 배정된 내부 엔지니어링 옵션일 뿐입니다. 사용자를 위한 기능이 아니며, 게시물의 그 어떤 내용도 이를 암시하지 않습니다.
해결책이 더 긴 컨텍스트 창(context window)이라는 오해. 탐색 비용과 컨텍스트 길이는 서로 다른 문제입니다. 더 큰 창은 단일 요청에서 모델에 보여줄 수 있는 양을 바꿀 뿐, 스토리지 레이어가 어떤 조회를 저렴하게 처리할지 바꾸지는 못합니다. 이러한 혼동의 검색(retrieval) 버전은 why RAG isn't memory에서 다루고 있습니다. 문서를 찾는 것과 결론을 유지하는 것은 다릅니다.
해결책: 연결만을 전문으로 처리하는 곳에 연결을 보관하기
단일 객체 조회가 어디서나 저렴한 케이스라면, 지속 가능한 조치는 필요할 때마다 연결이 실시간으로 도출되기를 기대하는 것을 멈추고, 연결 자체를 하나의 객체로 기록하기 시작하는 것입니다.
1단계: 사실과 사실 사이의 관계를 분리하기
어시스턴트가 알고 있기를 실제로 기대하는 정보들을 살펴보고 두 개의 더미로 분류해 보세요.
첫 번째 더미는 사실(facts)입니다. "우리는 일 단위로 청구한다." "스테이징 데이터베이스는 프랑크푸르트에 있다." "Priya가 결제 연동을 담당한다." 이들은 각각 독립적이며, 어떤 시스템이든 저렴하게 가져올 수 있는 정보들입니다.
두 번째 더미는 관계(relationships)이며, 바로 여기에 가치가 숨어 있습니다. "재무 시스템이 일부 일수 청구를 거부하기 때문에 우리는 일 단위로 청구한다." "2025년 계약의 데이터 거주지 조항 때문에 스테이징은 프랑크푸르트에 있다." "조직 개편 이후 Priya가 결제를 담당하고 있으며, 이것이 이전 런북에 다른 사람의 이름이 적혀 있는 이유이다."
두 번째 더미는 아무도 기록하지 않는 더미입니다. 당시에는 각각의 절반이 너무 당연하게 느껴지기 때문입니다. 또한 재구성하는 데 가장 많은 비용이 드는 더미이기도 하며, 일정한 작업량의 단일 조회에 최적화된 저장소가 여러분을 위해 다시 조립하는 데 가장 취약한 부분이기도 합니다.
2단계: 관계를 두 개의 항목과 막연한 기대가 아닌, 하나의 문장으로 기록하기
한 문장으로 작성된 관계는 단일 객체입니다. 두 항목 사이에 암묵적으로 남겨진 관계는 탐색(traversal)이 되며, 여러분은 방금 벤더가 설명한 '탐색이 왜 비용이 많이 드는 경로인가'에 대한 글을 읽으셨습니다.
따라서 무언가가 대신 조인해 주기를 기대하며 위치 레코드와 계약 레코드를 따로 만드는 대신, "2025년 거주지 조항 때문에 프랑크푸르트"와 같이 하나의 레코드로 작성하세요. 이는 큰 보상으로 돌아오는 작은 규율이며, 좋은 커밋 메시지를 작성하는 것과 같은 직관입니다. 즉, diff는 사실이고 메시지는 관계입니다.
두 레코드가 실제로 충돌하는 경우, 모순이 나중에 발견되도록 방치하지 말고 레코드 자체에 이를 명시하세요. 아무도 그렇게 하지 않을 때 발생하는 실패 모드는 memory conflict detection에서 다루고 있습니다.
3단계: 모든 어시스턴트가 접근할 수 있는 단일 주소를 해당 레이어에 부여하기
한 제품의 메모리에 기록한 관계는 다음 제품이 볼 수 없습니다. 도구를 이동하거나 동시에 세 개를 사용하더라도 관계를 처음부터 다시 작성할 필요가 없도록, 이 레이어를 특정 벤더의 저장소 외부에 유지하세요. 이 문제의 실질적인 해결 과정은 one memory across ChatGPT, Claude and Gemini에서 자세히 다루고 있습니다.
MemoryLake에서 설정하기
MemoryLake는 두 번째 더미를 위해 구축되었습니다. 결정과 그 뒤에 숨겨진 이유를 여러분의 언어로 직접 기록하면, 연결된 모든 어시스턴트가 동일한 세트를 읽습니다. 어떤 벤더의 저장소에서도 데이터를 강제로 끌어오지 않으며, 이 레이어는 여러분이 넣은 내용만을 보관합니다.
1단계: API 키 생성하기
로그인하고 워크스페이스 설정을 연 다음 API 키를 생성합니다. 이는 어시스턴트가 동일한 레이어를 읽기 위해 사용하는 자격 증명이므로, 한 번 생성한 후 작업하는 모든 도구에서 접근할 수 있도록 유지하세요.

2단계: 첫 번째 메모리 업로드하기
사실이 아닌 관계부터 시작하세요. 이번 분기에 두 번 이상 설명했던 다섯 가지를 골라 규칙과 이유가 모두 포함된 단일 문장으로 각각 작성해 보세요. 다시 발견하려면 비용이 많이 들지만 기록해 두기에는 저렴한 제약 조건들을 추가하세요.

3단계: AI 및 에이전트 연결하기
ChatGPT를 비롯해 사용하는 다른 도구들을 연결하세요. 동일한 추론이 각각에 전달되므로, 새 대화는 처음부터가 아니라 이미 결론을 내린 내용에서부터 시작됩니다.

실제 업무에서 바뀌는 점
첫 번째 차이점은 엉뚱한 것에 짜증을 내지 않게 된다는 것입니다. 내가 사는 도시는 기억하면서 왜 그곳으로 이사했는지는 기억하지 못하는 어시스턴트는 부주의한 것이 아닙니다. 단일 객체와 그 직접적인 에지를 가져오는 데 매우 뛰어난 레이어의 지원을 받고 있을 뿐입니다. 이를 알게 되면 막연한 불만이 구체적인 습관으로 바뀝니다.
두 번째는 노트가 더 짧아지고 유용해진다는 점입니다. 자체적인 이유를 담고 있는 레코드는 이해하기 위해 두 번째 레코드가 필요하지 않으므로, 단독으로 읽혀도 살아남습니다. 이는 바로 이러한 시스템들이 최적화되어 있는 액세스 패턴입니다.
세 번째는 상황이 변할 때 나타납니다. 이유가 기록되어 있으면 나중에 다시 돌아와 그것이 여전히 유효한지 확인할 수 있습니다. 이는 사실 목록을 다시 읽으며 어떤 것이 오래되었는지 고민하는 것과는 완전히 다른 활동입니다. 이러한 검토 습관은 auditing what your AI remembers에서 다루고 있습니다.
네 번째는 세션 간의 연속성입니다. when ChatGPT loses context between sessions에서 설명한 답답한 기분은 대부분 어디에도 기록되지 않은 관계들을 매번 직접 수작업으로 다시 도출해야 하는 비용 때문에 발생합니다.
조회 형태의 메모리를 다루는 모범 사례
결정당 하나의 레코드를 작성하고, 그 안에 이유를 포함시키세요. 함께 있어야만 의미가 통하는 두 개의 레코드는 실패를 기다리는 탐색(traversal)일 뿐입니다.
구조화된 것보다 구체적인 것을 선호하세요. 평이한 문장으로 작성된 글이 유지 관리하지 못할 영리한 스키마보다 낫습니다. 데이터를 가져오는 시스템은 저장된 내용을 반환하는 데는 뛰어나지만, 여러분이 연결하고자 했던 의도를 추론하는 데는 서툽니다.
단순히 사실인 것뿐만 아니라 무엇이 변경되었는지 기록하세요. "우리는 3월에 공유 계정에서 이전했다"가 "우리는 자체 계정을 가지고 있다"보다 더 유용합니다. 독자에게 어떤 오래된 자료를 신뢰하지 말아야 할지 알려주기 때문입니다.
가장 오래된 항목들을 분기별로 한 번씩 다시 읽어보세요. 사실은 조용히 썩어갑니다. 반면 이유는 요란하게 썩어가므로 잘못된 부분을 발견하기가 더 쉽습니다.
레이어를 특정 제품 외부에 유지하세요. 벤더들은 아키텍처를 재구성합니다. OpenAI는 방금 라이브러리에서 서비스로, 그리고 다시 재작성으로 이어진 서비스를 설명하는 게시물을 발표했으며 스토리지 계층에 대한 두 번째 파트를 약속했습니다. 여러분의 추론 과정이 이를 신경 쓸 필요는 없어야 합니다.
엔지니어링 게시물을 제품 사양서로 취급하지 마세요. 이 글은 플랫폼과 그 트레이드오프를 설명할 뿐입니다. 특정 기능의 데이터 모델을 문서화한 것이 아니며, 그렇게 해석하는 것은 추측에 불과합니다.
결론
Habitat 게시물은 훌륭한 엔지니어링 글이며, 기억할 만한 가치가 있는 부분은 재작성 스토리가 아닙니다. 벤더가 요청받지 않았음에도 자사의 온라인 스토리지가 단순하고 예측 가능하며 일정한 작업량이 드는 조회에 맞게 의도적으로 설계되었고, 객체 간의 관계가 서로 다른 리전에 위치할 수 있으며, 실제 탐색이 필요한 모든 작업은 자체 담당자가 있는 오프라인 복사본으로 이동한다는 점을 스스로 밝혔다는 사실입니다.
이를 액면 그대로 받아들이면, 우리에게 남은 결론은 평범하면서도 해방감을 줍니다. 내가 말한 두 가지 사이의 연결이 필요할 때마다 다시 발견되기를 기다리지 마세요. 사용하는 모든 도구가 읽을 수 있는 곳에 그 연결을 평이한 문장으로 한 번만 기록해 두세요. 그렇게 하면 비용이 많이 드는 작업이 저렴한 작업으로 바뀝니다. 이는 한 단계 위 레이어에서 OpenAI의 플랫폼 팀이 사용한 것과 동일한 요령입니다.