기업백년 ANC는 현황판 표시의 34%가 거짓이던 날, 흩어진 정보를 anc.db 한 곳으로 모았습니다(ANC 내부 기록 기준). 핵심 설계는 DB-first — 기록의 원천(SoT, jsonl)을 데이터베이스로 단방향 동기화하고, 모든 현황을 거기서만 읽는 구조입니다. 5개 테이블·직원 44명·CHECK 제약·sync_from_sot 빌더로, 거짓의 원인이던 '측정 타이밍 불일치'를 구조로 제거했습니다.
현황판은 거짓말을 한 적이 없습니다. 다만 화면마다 다른 시점을 보고 있었을 뿐입니다. 어떤 카드는 어제의 기록을, 옆 카드는 방금 갱신된 값을 그렸습니다. 그래서 같은 사실이 화면에 따라 달라 보였습니다.
이 글은 그 어긋남을 DB-first 통합으로 끝낸 하루의 기술 케이스스터디입니다. 모든 수치는 ANC 내부 운영 기록 기준이며, 외부 패턴은 1차 출처로 표기했습니다.
결론부터 말하면, 답은 더 똑똑한 모델이 아니라 진실의 방향을 하나로 고정하는 구조였습니다.
1. 왜 현황판의 34%가 거짓이었나?
발단은 한 숫자였습니다. ANC 내부 감사 기준, 한 시점에 현황판 표시의 34%가 실제 상태와 어긋나 있었습니다. 처음엔 에이전트가 거짓 보고를 한 줄 알았지만, 추적해 보니 원인은 측정 타이밍 불일치였습니다.
흩어진 jsonl 기록들이 서로 다른 주기로 갱신되는데, 화면은 그 중 일부만 그 순간에 읽었습니다. 그러니 같은 직원, 같은 과제가 화면마다 다른 상태로 보였습니다. 이것이 우리가 전사 신뢰성 감사를 시작한 계기였습니다.
"보이지 않으면 없는 것이다."— 기업백년 대표
이 문장이 방향을 정했습니다. 흩어진 채로는 아무리 많은 데이터도 '보이지 않는 것'과 같습니다. 보이게 하려면 한 곳에 모아야 했습니다.
2. anc.db — 데이터 보관센터의 골조
그날 우리는 anc.db를 실물로 구축했습니다. 흩어진 현황을 모으는 단일 보관센터입니다. 골조는 단출합니다. 표 한 장으로 정리하면 이렇습니다(ANC 내부 기록 기준).
| 구성 | 값 | 역할/제약 |
|---|---|---|
| 테이블 수 | 5개 | 직원·측정·사실 등 도메인 분리 |
| employees 행 | 44명 | 조직 인원의 단일 기준 명부 |
| measurements 행 | 9건 | 측정값에 measured_at 시점 동반 |
| facts 행 | 18건 | CHECK 제약으로 정의 외 값 거부 |
| 현황판 거짓 비율(개선 전) | 34% | 원인=측정 타이밍 불일치 |
여기서 핵심은 measurements 테이블이 값만이 아니라 언제 쟀는가를 함께 적재한다는 점입니다. 측정 시점을 데이터에 박아 넣자, 화면은 더 이상 '아무 시점'을 그리지 않고 '같은 시점'을 그리게 됐습니다.
3. DB-first: 진실은 한 방향으로만 흐른다
설계 원칙은 DB-first입니다. 기록의 원천(SoT)인 jsonl 파일에서 데이터베이스로 단방향으로만 동기화합니다. 이 일을 하는 코드가 sync_from_sot 빌더입니다.
왜 굳이 한 방향이냐면, 양방향으로 덮어쓰는 순간 '어느 쪽이 진실인가'를 영원히 알 수 없게 되기 때문입니다. SoT에서 DB로만 흘려보내면 진실의 방향이 하나로 고정되고, 동기화는 몇 번을 다시 돌려도 같은 결과를 내는 멱등 연산이 됩니다.
그래서 ANC는 DB 담당을 사람 한 명에게 맡기지 않습니다.
"흩어두면 흔적, 모아야 자산."— 기업백년 대표
이 모토가 정확히 DB-first의 이유입니다. 흩어진 jsonl은 흔적이지만, 한 곳으로 모은 anc.db는 조직이 매일 읽는 자산이 됩니다. 담당은 코드입니다 — 빌더는 개발 팀장(Quinn)이, 정합성은 기획실장(Mako)이 보되, 별도 전담 운영자를 두지 않습니다.
4. CHECK 제약 — 기계가 거부권을 갖는 가장 낮은 층
모으기만 해서는 정합성이 보장되지 않습니다. 잘못된 값이 들어오면 보관센터도 오염됩니다. 그래서 facts를 비롯한 테이블에 CHECK 제약을 걸었습니다.
CHECK 제약은 데이터베이스가 정의되지 않은 값을 입력 단계에서 거부하는 규칙입니다. 상태 컬럼에 허용값을 못 박아 두면, 빌더가 엉뚱한 값을 넣으려 할 때 적재 자체가 실패합니다. 사람의 검토를 기다리지 않고 데이터베이스가 먼저 막는 것입니다.
이것이 ANC가 일관되게 적용하는 '기계는 거부권, 사람은 승인권' 원칙의 가장 낮은 층입니다. 결정론 규칙이 하한선을 지키고, 사람은 비가역 결정만 승인합니다.
실제로 anc.db 구축 당시 facts 18건에 건 CHECK가 작동해 정의 외 값을 거부하는 것을 확인했습니다.
5. 이 패턴은 ANC만의 발명이 아니다
단일 진실원과 구조화된 적재라는 발상은 멀티에이전트 시스템의 표준 처방과 맞닿아 있습니다. Anthropic은 에이전트 시스템을 만들 때 화려함보다 단순함과 명료한 구조를 먼저 두라고 권합니다.
"성공하는 구현은 복잡한 프레임워크가 아니라, 단순하고 조합 가능한 패턴 위에서 만들어진다."— Anthropic, Building Effective AI Agents
같은 회사의 멀티에이전트 리서치 시스템은 단일 에이전트 대비 내부 평가에서 90.2% 성능 향상을 보였는데, 그 전제 역시 각 워커의 산출을 정해진 구조로 받아 종합하는 것이었습니다. 데이터를 구조로 박는다는 점에서 DB-first와 같은 뿌리입니다. 또한 생성형 검색 최적화(GEO) 연구는 출처와 통계를 명시한 구조화 콘텐츠가 AI 검색 노출을 최대 40%까지 끌어올린다고 보고합니다(arXiv:2311.09735). 정합한 데이터는 운영만이 아니라 노출에도 자산이 됩니다.
자주 묻는 질문
Q. DB-first와 그냥 DB를 쓰는 것은 뭐가 다른가요?
DB를 쓴다고 다 DB-first는 아닙니다. DB-first는 기록의 원천을 jsonl로 따로 두고, DB는 그것을 단방향으로 받아 읽기 전용 통합 뷰 역할만 하게 하는 설계입니다. 진실의 방향이 한쪽으로 고정되어 있다는 점이 핵심입니다.
Q. 측정 타이밍 불일치는 어떻게 막았나요?
measurements 테이블이 값과 함께 measured_at 시점을 적재하도록 했습니다. 화면은 더 이상 '지금 읽히는 아무 시점'이 아니라 '같은 측정 시점'을 그리므로, 카드마다 다른 진실이 보이던 34% 거짓이 사라졌습니다.
Q. 담당자를 두지 않으면 데이터는 누가 지키나요?
코드가 지킵니다. 멱등한 sync_from_sot 빌더와 CHECK 제약이 사람의 의지력 대신 정합성을 강제합니다. 사람(Quinn·Mako)은 빌더와 제약 자체를 설계·검수하지, 매일 손으로 데이터를 맞추지 않습니다.
anc.db 한 곳으로 모으는 DB-first 통합과 sync_from_sot 빌더·CHECK 제약을 직접 설계했다. 텔레그램봇·Notion 동기화·일일 브리핑 크론·AML 스캐너 운영을 총괄한다. 이 글은 그가 현황판 34% 거짓을 추적해 데이터 보관센터를 세운 ANC 내부 운영 기록을 1차 자료로 썼다.- 참고 1차 출처
- Anthropic, Building Effective AI Agents — 단순·조합 가능한 패턴 우선
- Anthropic, How we built our multi-agent research system — 단일 대비 90.2% 향상
- Aggarwal et al., GEO: Generative Engine Optimization (KDD 2024, 최대 40% 향상)
- 업계 동향: Search Engine Land — What is GEO