React로 구축한 적대적 AI 위원회 (그리고 왜 AI가 당신과 논쟁하는가)
요약
사용자의 의견에 무조건 동의하는 AI의 한계를 극복하기 위해, 서로 다른 추론 편향을 가진 에이전트들이 토론하는 로컬 우선 SPA 'NoFlattery'를 소개합니다. React와 Zustand를 기반으로 구축되었으며, 사용자의 API 키를 직접 사용하여 보안과 개인정보를 보호합니다.
핵심 포인트
- 의도적으로 의견이 불일치하는 멀티 에이전트 토론 시스템 구축
- 로컬 우선(Local-first) 및 BYOK 방식으로 데이터 보안 강화
- React 19, Zustand, Dexie를 활용한 단일 파일 SPA 구조
- 결정론적 턴제 엔진을 통한 예측 가능한 에이전트 상호작용
여러 에이전트가 당신의 결정에 대해 토론하고 판결을 내려주는 로컬 우선(Local-first) 방식의 단일 파일 SPA입니다.
문제점: 내가 질문한 모든 AI가 그저 내 의견에 동의했다
이 프로젝트의 이름을 거의 잘못 지을 뻔했습니다.
강력해 보이는 이름을 골랐습니다. ChatGPT에게 물어보니 좋아했고, Claude에게 물어보니 고개를 끄덕였습니다. 상표권 충돌, 잘못된 검색 의도, 또는 BBC와 벌이게 될 SEO 전쟁에 대해 아무도 경고해주지 않았습니다.
그 순간 저는 문제가 이름이 아니라는 것을 깨달았습니다. 문제는 피드백 루프(Feedback loop)였습니다. 대부분의 AI 어시스턴트는 사용자를 기쁘게 하도록 튜닝되어 있어서, 당신의 사각지대를 보여주는 대신 숨겨버립니다. 중대한 결정을 내려야 할 때, "좋은 생각입니다"라는 말은 당신이 얻을 수 있는 가장 값비싼 답변입니다.
그래서 저는 그 반대의 것을 만들었습니다. 의도적으로 의견이 일치하지 않는 AI 에이전트들의 위원회입니다.
NoFlattery가 하는 일
NoFlattery는 2~4개의 에이전트를 한 방에 모으고, 그들에게 서로 다른 추론 편향(Reasoning biases)을 부여하여 당신의 결정에 대해 토론하게 만듭니다. 출력 결과는 단순한 채팅 기록이 아닙니다. 그것은 결정 기록(Decision Record)입니다. 즉, 명확한 판결, 그 뒤에 숨겨진 추론, 주요 리스크, 결정을 바꿀 수 있는 요소, 그리고 다음 단계가 포함됩니다.
제품 결정, 가격 책정, 기술 스택, 채용, 또는 하나의 관점만으로는 부족한 모든 결정에 사용하세요.
주요 제품 특징:
- 로컬 우선 (Local-first): 당신의 채팅 내용과 API 키는 브라우저에 그대로 머뭅니다.
- BYOK (Bring Your Own Key): 본인의 OpenAI, Anthropic, OpenRouter 또는 Ollama 키를 가져와 사용하세요.
- 일회성 결제: 구독 없음, 계정 없음, 데이터 수집 없음.
기술 스택
앱 전체는 다음을 사용하여 구축된 단일 파일 SPA입니다:
- React 19 + TypeScript
- 상태 관리를 위한 Zustand
- 로컬 우선 저장을 위한 IndexedDB 기반의 Dexie
- 단일
index.html배포를 위한 Vite +vite-plugin-singlefile - 사용자가 자신의 키를 연결할 수 있는 OpenAI 호환 프로바이더 런타임
왜 단일 파일인가요? 배포가 매우 단순해지기 때문입니다. HTML 파일 하나면 됩니다. 데이터를 위한 서버도 필요 없고, 빌드 오케스트레이션(Build orchestration)도 필요 없습니다. Cloudflare Pages에 앱을 배포하고 잊어버리면 됩니다.
전환 엔진: 마법이 아닌 결정론적 방식
NoFlattery의 핵심은 턴제 멀티 에이전트 엔진 (turn-based multi-agent engine)입니다. 사용자 메시지 하나가 한 라운드를 트리거합니다. 각 에이전트는 정의된 편향 (bias)을 가지고 순서대로 발언합니다. 다음에 누가 말할지를 결정하는 숨겨진 선택 모델 (selector models)은 없습니다. 정체성 계약 (identity contracts)을 깨뜨리는 조용한 폴백 (silent fallbacks)도 없습니다.
흐름은 다음과 같습니다:
- 사용자가 질문을 합니다.
- 각 에이전트는 자신의 역할과 지금까지의 대화 내용을 바탕으로 응답을 생성합니다.
- 에이전트들은 서로를
@mention하여 직접적인 응답을 강제할 수 있습니다. - 라운드가 끝나면 사용자는 답장을 하거나, 요약을 요청하거나, 새로운 결정을 시작할 수 있습니다.
토론 모드 (Discussion modes)는 별도의 상태 머신 (state machines)이 아니라 프롬프트 인젝션 (prompt injections)입니다. 적대적 모드 (Adversarial mode)는 에이전트들이 더 강력하게 도전하게 만듭니다. 감사 모드 (Audit mode)는 에이전트들이 결함을 찾도록 만듭니다. 투표 모드 (Vote mode)는 명확한 평결을 강제합니다. 이를 통해 런타임 (runtime)을 작고 예측 가능하게 유지합니다.
기본적으로 로컬 우선 (Local-first by default)
모든 대화, 모든 API 키, 모든 설정값은 Dexie를 통해 IndexedDB에 저장됩니다. 사용자가 자신의 키로 프로바이더 (provider)를 호출하기로 선택하지 않는 한, 아무것도 브라우저를 떠나지 않습니다.
이것은 타협이 아닙니다. 하나의 기능입니다. 정직한 결정에 관한 도구라면, 프라이버시 모델도 메시지와 일치해야 합니다: 당신의 데이터는 당신의 것입니다.
서버와 접촉하는 유일한 부분은 Pro 버전을 위한 라이선스 검증뿐입니다. 그마저도 단순한 키와 디바이스 해시 (device hash)일 뿐입니다. 채팅 기록도, 프롬프트도, 텔레메트리 (telemetry)도 없습니다.
배운 점들
1. 사용자는 또 다른 챗봇을 원하지 않습니다.
그들은 자신이 방어할 수 있는 결정을 원합니다. 대화 기록 (transcript)보다 평결 (verdict)이 더 중요합니다. 이것이 결정 기록 (Decision Record)이 채팅이 아닌 일급 객체 (first-class) 출력물인 이유입니다.
2. 단일 파일 배포는 많은 골칫거리를 제거합니다.
Docker도 필요 없고, DB 마이그레이션 (DB migrations)도 필요 없습니다. "내 컴퓨터에서는 되는데"라는 상황도 없습니다. npm run build를 실행하면 단 하나의 index.html이 생성됩니다. 인프라 복잡성이 거의 제로에 가깝게 떨어집니다.
3. 로컬 우선은 신뢰를 얻는 지름길입니다.
특히 당신을 모르는 초기 사용자들에게는 더욱 그렇습니다. "우리는 보지 않겠다고 약속합니다"라는 말보다 "당신의 데이터는 브라우저에 머뭅니다"라는 말이 믿기 더 쉽습니다.
4. 결정론 (Determinism)은 영리함보다 더 중요합니다.
저는 더 똑똑한 라우팅 (Routing), 숨겨진 선택자 (Hidden selectors), 모델 기반 오케스트레이션 (Model-based orchestration) 등을 시도해 보았습니다. 매번 시스템은 디버깅하기 더 어려워졌고 신뢰성은 떨어졌습니다. 에이전트당 한 번의 라운드, 한 번의 주문, 하나의 정체성. 그것이 제품을 신뢰할 수 있게 만드는 제약 조건입니다.
시도해 보세요
만약 위원회를 거쳐 결정하고 싶은 사항이 있다면:
댓글에 결정 사항을 남겨주세요. 서로 의견이 다른 에이전트들이 모인 방에서 그것에 대해 무엇이라고 말할지 궁금합니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기