메인 콘텐츠로 건너뛰기
2026-09-10개발 로그AI Agent아키텍처

돌아가던 Agent를 뜯어내다: PureLab 기반 교체 한 달의 기록

7월, 제품 프로세스 내에서 1세대 어시스턴트를 완성했습니다. 8월에는 효과를 대조하기 위해 옛 엔진을 남기려다 서른 개가 넘는 단단한 결정을 적은 설계를 통째로 폐기했습니다. 다음 한 달은 옛 경로와의 호환도, 이력 이전도 없이 대화를 제품 프로세스에서 분리했습니다.

돌아가던 Agent를 뜯어내다: PureLab 기반 교체 한 달의 기록

8월 월간 보고서에 이런 문장을 적었습니다. 어시스턴트의 이번 버전은 당분간 개방하지 않습니다.

게으름을 피운 것이 아닙니다. 당시 1세대 Agent는 이미 정리 페이지 내에서 대화하고, 곡을 검색하고, 미리보기를 제공할 수 있었습니다. 진짜로 막힌 부분은 기반이었습니다. 그 위에 기능을 더 쌓게 되면 오케스트레이션, 세션, 키, 그리고 음악 쓰기 기능이 모두 같은 프로세스에 용접되듯 결합됩니다. 두 번째 제품을 만들 때도 같은 과정을 반복해야 합니다. 그래서 우리는 돌아가는 기존 시스템을 뜯어내고 임베딩 가능하며, 심사할 수 있고, 충돌을 격리할 수 있는 런타임으로 교체하기로 결정했습니다.

이 교체 작업은 채팅창을 처음부터 새로 만드는 것보다 훨씬 어려웠습니다.

🛠 1세대는 이미 돌아가고 있었다, 이것이 진정한 문제의 시작

7월에 만든 시스템은 프로토타입이 아니었습니다. PureLab 프로세스에 내장된 완전한 어시스턴트였습니다. 여러 턴의 스트리밍, 세션 데이터베이스 저장, 취소와 직렬 잠금, 사용자 제공 모델 키, 라이브러리 검색 및 태그 미리보기 기능까지 갖추고 있었습니다. 파일 쓰기 역시 여전히 제품 자체의 확인 게이트를 거쳤습니다. 영역 보안은 강력했습니다. 모델은 파일을 직접 수정할 수 없고 경로는 마스킹 처리되었으며, 대화를 통한다고 해서 요금제 제어를 우회할 수도 없었습니다.

문제는 '대화가 가능한가’가 아니라 형태에 있었습니다.

오케스트레이션, 이벤트 채널, 세션 테이블, 키 복호화, 도구 호출이 전부 제품 프로세스 안에 묶여 있었습니다. 인터페이스는 오직 이 하나의 이벤트 흐름만을 인식했습니다. 라이브러리를 바꾸거나 탭을 전환하거나 생성이 충돌할 경우, 상태 머신을 프론트엔드와 백엔드 양쪽에 다시 작성해야 했습니다. 더 번거로운 점은 다음 데스크톱 제품에도 어시스턴트가 필요하다면 Host 시스템을 그대로 복제해야 한다는 것이었습니다. 이는 단순한 임베딩이 아니라 각 앱이 자체적으로 Agent를 키우는 격이었습니다.

물론 ‘기존 시스템을 남겨두고 새 시스템을 연결하는’ 방법도 시도해 보았습니다.

🚧 더 험난한 우회로: 효과 비교를 위한 듀얼 엔진 유지, 하지만 4,000줄의 설계를 통째로 폐기하다

8월 초에는 더 안정적으로 보이는 길이 있었습니다. 우측 패널에 '클래식 AI’와 '스마트 어시스턴트’를 동시에 배치하는 것이었습니다. 처음에는 새 기반을 도입할 때 '효과 비교’를 위한 기준점을 두기 위해 예전 커널을 유지하려 했습니다. 새로운 격리 프로세스가 Windows 호환성, 패키징, 키 채널을 천천히 보완하는 동안 기존 엔진을 통해 모델 출력 품질을 검증하기를 원했습니다.

서류상으로는 이를 '안정적 전환’이라 부르지만, 설계에 반영되자 재앙으로 변했습니다.

이 '비교’를 유지하기 위해 두 가지 대화 명령은 섞일 수 없었고, 두 세션은 대조가 불가능했으며, 동일한 키를 프로세스 내 오케스트레이션과 격리 프로세스 양쪽에 동시에 공급해야 했습니다. 더 치명적인 것은 키를 환경 변수나 설정 파일에 기록할 수 없었다는 점입니다. 미리보기, 확인, 쓰기, 롤백은 제품 본연의 보안 체인을 계속 따라야 했고, 새로운 커널은 임의의 파일 접근 권한을 가져서는 안 되었습니다. 당시 Windows는 격리 프로세스를 명확히 차단하고 있었지만 진입점은 유지해야 했고, 문구는 자연스러워야 했으며 빈 화면이거나 충돌이 일어나서도 안 되었습니다.

'효과 비교’를 위해 만들어진 그 이중 진입점 설계는 30개가 넘는 엄격한 결정들로 채워졌고, 본문만 4,000줄을 넘어섰습니다. 구현을 시작하기도 전에 우리는 깨달았습니다. 이건 비교가 아니라 두 개의 어시스턴트, 두 개의 장부, 두 개의 장애 영역을 동시에 유지하는 일이라는 것을. '기존 세션을 호환하자’는 어떤 생각도 양쪽 모두를 교착 상태로 몰아넣을 것이 분명했습니다.

8월 13일, 해당 문서는 통째로 폐기되었습니다.

새로운 계약은 몇 문장 되지 않았지만 그 대가는 컸습니다. Kit는 전부 새로운 코드, 새로운 명령, 새로운 이벤트 채널로 작성되었습니다. 기존 경로와의 호환성, 이력 대조, 기록 이전, 테이블 공유는 모두 배제되었습니다. 기존 Agent의 '비교 임무’는 즉시 종료되었습니다. 제품의 이전 진입점만 삭제하고 새로운 계약은 수정하지 않았습니다.

이는 사용자 측에서 ‘이전 채팅 기록 불러오기’ 기능을 볼 수 없음을 의미합니다. 누락된 것이 아니라 의도된 것입니다. 옛 세션을 새 런타임으로 이전하는 것은 배려처럼 보일 수 있지만, 실제로는 두 생명주기를 영원히 묶어버리는 일입니다. 우리는 그 이자를 감당할 수 없었습니다.

⛰️ 기반 교체를 위해 함께 넘어야 할 산들

폐기는 단순한 허가에 불과했습니다. 진정한 난관은 '제품 내 채팅 기능’을 3계층으로 분리하고 이를 한 달 안에 PureLab에 적용하는 일이었습니다.

  • 📦 첫 번째 산은 프로세스: 모델 루프는 더 이상 정리 페이지, 쓰기 작업, 분석과 같은 충돌 영역을 공유해서는 안 됩니다. 대화는 격리된 프로세스에서 실행되어야 하며, 제품은 실행, 모니터링, 그리고 실패 시 복구만을 담당합니다. 격리 프로세스가 다운되더라도 음악 라이브러리와 태그 파이프라인은 유지되어야 합니다. 반대로 제품은 범용 터미널, 임의의 파일 시스템, 외부 도구를 모델에 넘겨서는 안 되며, 음악 라이브러리에 대한 쓰기 권한은 어시스턴트에게 주어지지 않습니다.
  • 🔌 두 번째 산은 프로토콜: 인터페이스는 하위 계층의 세션 프로토콜을 다루어서는 안 되며, 제품 내부에서도 ‘프롬프트 전송, 이벤트 수신, 히스토리 조합’ 과정을 수동으로 작성해서는 안 됩니다. 그 중간에는 전송, 중지, 세션 목록, 복구, 채널 구성 등의 안정적인 제품 프로토콜이 존재해야 합니다. 전송 방식은 데스크톱 명령일 수 있지만, 프로토콜 자체는 특정 앱에 종속되지 않습니다. 두 번째 제품이 해야 할 일은 패널을 띄우고, 현재 라이브러리의 아이덴티티를 부여하며, 도메인 기능을 등록하는 것이지 Host를 다시 구현하는 것이 아닙니다.
  • 🔑 세 번째 산은 키: 사용자의 모델 Key는 제품 내에 계속 봉인되어 있어야 합니다. 이 Key는 격리 프로세스의 디스크나 환경 변수 어디에도 나타나서는 안 됩니다. 요청이 격리 프로세스에서 로컬 루프백으로 반환되면, 제품 프로세스가 일시적으로 암호를 해독해 사용자가 지정한 인터페이스로 전달한 후 폐기합니다. 데이터베이스 파일을 복사하면 여전히 암호문을 복구할 수 있는 알려진 위험이 있지만, 이를 시스템 키체인으로 이미 해결했다고 가장하지 않았습니다.
  • 🛠 네 번째 산은 영역 도구: 어시스턴트는 현재 인증된 라이브러리를 검색하고, 트랙을 읽고, 이름 변경 및 태그 패치를 미리 보며 초안을 생성할 수 있습니다. 그러나 쓰기 시작, 이름 변경 시작, 파이프라인 실행, 분석 등의 작업은 불가능합니다. 비즈니스 프로세스는 다음과 같아야 합니다: 먼저 1~5곡에 대한 미리보기를 진행하고, 샘플이 정확할 경우 최대 50개의 초안을 생성합니다. 그 후 워크벤치에 쓰기 창이 나타나고 사용자가 Apply를 클릭해야만 파일이 수정됩니다. 모델은 경로를 스스로 생성하거나 사용자에게 라이브러리 내부 번호를 요구하거나, '이미 수정이 완료되었다’고 주장해서는 안 됩니다.
  • 🚀 다섯 번째 산은 크로스 플랫폼 패키징: 동일한 계약 내에서 macOS는 샌드박스 서명을 통과해야 했고, Windows는 한동안 사용할 수 없어 '현재 시스템에서는 사용 불가’라는 메시지만 표시했습니다. 9월이 되어서야 Windows는 격리 프로세스의 홈 디렉토리, 기능 스위치, 디버그/릴리스 디렉토리를 일치시켰습니다. 데스크톱 소프트웨어 Agent 작업의 절반은 대화 기능이 아니라 ‘설치되고, 실행되며, 메인 프로그램을 다운시키지 않도록’ 하는 데 있습니다.

이 다섯 개의 산은 동시에 넘어야 했습니다. 대화를 먼저 구현한 뒤 보안을 보완하거나, 보안을 먼저 확보하고 Windows를 나중에 지원하게 되면 비교 기간 동안 이전 진입점을 다시 가져오게 됩니다. 우리는 그 이전 진입점을 가져올 자격조차 삭제해 버렸습니다.

⚙️ 진정으로 시간을 쏟은 이 한 달의 기록

8월 중순부터 9월 10일까지 캘린더에는 '접속(통합)'이라고 적혀 있었지만, 실제로는 끊임없는 엣지 케이스 처리의 연속이었습니다:

  • 채널과 상태 머신의 얽힘: 설정에는 사용자가 찾을 수 있는 ‘AI 어시스턴트’ 진입점이 반드시 있어야 합니다. 설정이 완료되지 않은 상태에서 패널이 준비된 것처럼 보여서는 안 됩니다. 대화 패널의 기본값은 영어 빈 상태(Empty State)여야 하며, 제품이 '설정으로 이동’을 주입해 사용자를 설정 페이지로 유도해야 합니다. 내부 오류 코드를 임의로 인터페이스에 노출해서도 안 됩니다. 인터페이스 주소를 변경할 때 한동안 Key를 다시 제출하도록 강제했으나, 이후에야 'Key는 유지한 채 주소나 모델만 변경’하는 실제 사용자 행동을 허용했습니다. 이는 단순한 문구 문제가 아니라, 채널 상태 머신과 키 해독 기능이 묶여 있었기 때문입니다.
  • 채팅창보다 훨씬 까다로운 세션 관리: 새 세션을 생성할 때 ‘가장 최근의 비어 있지 않은 세션 복구’ 기능에 덮어씌워져서는 안 됩니다. 다른 라이브러리로 전환하면 세션 목록도 꼬임 없이 함께 변경되어야 합니다. 오른쪽 패널을 닫았다가 열더라도 동일한 실행 내에서는 화면을 보완해야 하며, 대화를 타자기처럼 재현해서는 안 됩니다. 소프트웨어를 완전히 종료하고 다시 열 때만 콜드 복구가 이루어집니다. 전환 후 돌아올 때 기록이 유실되는 문제도 있었으나, 이후 세션별로 이미 투영된 이벤트를 기억하도록 수정했습니다. 세션을 삭제할 때는 기저 세션을 닫고 디스크 디렉토리를 정리해야 하며, 생성 중 실수로 삭제하지 못하도록 방지해야 합니다.
  • 매우 소모적인 쓰기 메커니즘: 이전 Agent의 확인 게이트 방식은 옳았습니다. 새로운 기반이 전송 방식을 바꿨다고 보안이 느슨해져서는 안 됩니다. 채팅 내에서 '이번 도구 사용 허용’을 다시 묻지 않습니다. 승인된 조회는 호스트가 통과시킵니다. 9월 초가 되어서야 ‘파라미터 입력 → 소규모 샘플 미리보기 → 초안 생성 → 사용자의 Apply 클릭’ 과정을 제품 이벤트로 통합했습니다. 파일 수정 확인은 채팅 팝업이 아닌 여전히 쓰기 창에서 이루어집니다. 파일명 변경에는 패치가 없어 경로 대조만 출력하며, 사용자가 작업 영역에서 확인 후 적용해야 합니다. 이 계약 체계에서는 '어시스턴트가 이미 파일을 수정해 두었다’는 문장 자체가 모두 버그로 취급됩니다.
  • 패널의 독립성과 임베딩의 타협: 패널 자체도 데모가 아닌 워크벤치처럼 보여야 합니다. Markdown은 제목과 목록만 지원하며 코드 하이라이팅은 없습니다. 스트리밍 출력, 실패, 취소는 모두 동일한 렌더링 시스템을 사용합니다. 패널 내부는 영어로 하드코딩되어 있으며, 제품 측에서 변경할 수 있는 것은 설정 진입점 문구 하나뿐입니다. 이는 3개 리포지토리 임베딩의 대가 중 하나입니다. 패널은 정리 페이지 오른쪽에 내장되어 있으며, 추출, 치환, 파이프라인 기능과 시선을 빼앗지 않도록 최근에서야 하단으로 이동했습니다.

👀 지금 워크벤치에서 당신이 보게 될 것

제품은 이미 6.0으로 업데이트되었습니다. 정리 페이지 맨 우측, 활동 표시줄 하단에 AI 진입점이 고정되어 있습니다. 열어보면 다중 세션 지원, 복구 가능, 언제든 중지 가능한 완전한 대화형 워크벤치가 나타납니다. 8월 5.0 월간 보고서와 비교하면 진입점이 상주하게 되었습니다. 단, 스토어 출시 여부는 이 글에 포함하지 않습니다.

  • 유연한 설정: 먼저 설정에서 본인의 인터페이스, 모델, 키를 입력하세요. 우리는 대화 기능을 특정 클라우드에 종속시키지 않으며, 설정이 없을 때 몰래 내장 모델로 전환하지도 않습니다.
  • 절제된 영역 기능: 설정이 완료되면 현재 열려 있는 라이브러리를 대상으로 명령을 내릴 수 있습니다. 예를 들어 아티스트와 앨범별로 파일명 변경을 미리 보거나, 소규모 태그 초안을 먼저 확인할 수 있습니다. 어시스턴트는 검색, 미리보기, 초안 생성이 가능합니다. 하지만 실제 파일 변경 여부는 여전히 쓰기 창이나 파일명 변경 대조창에서 당신이 결정합니다. 8월에 출시된 태그 파이프라인은 유지되며, 어시스턴트가 당신을 대신해 '시작’을 누르지 않습니다.
  • 견고한 경계: 분석, 커버 아트, 가사, 네트워크 메타데이터 보완 기능은 이번 릴리스에서도 부여하지 않았습니다. 기술적 한계가 아니라 경계를 확고히 한 후에 기능을 확장하기 위함입니다.

💡 우리가 기꺼이 지불한 비용, 그리고 아직 갚지 못한 빚

기반 교체에서 가장 값비싼 대가는 새로운 코드를 작성하는 것이 아니었습니다. 1세대가 이미 구동 가능했고, 효과 비교를 위해 유지하려 했던 듀얼 엔진이 꽤 안정적으로 보였음에도 불구하고 이를 과감히 전체 폐기하기로 결정한 것이었습니다. 히스토리를 이전하지 않는 것은 예전 대화에 무책임한 일이고, 히스토리를 이전하는 것은 새로운 계약에 무책임한 일입니다. 우리는 후자를 선택했고, 제품에서 예전 진입점을 말끔히 삭제하여 두 세트의 어시스턴트가 영원히 대조되는 상황을 방지했습니다.

아직 해결하지 못한 과제들도 명확히 밝혀야 합니다. 자체 중계기로 채널 전환, 데이터베이스 암호문을 시스템 키체인으로 대체, Windows 출시 형태를 macOS처럼 안정적으로 만드는 작업 등은 여전히 진행 중입니다. 현재 어시스턴트는 워크벤치 내의 시범 프로젝트일 뿐, '스마트 어시스턴트 정식 출시’라는 광고 문구와는 거리가 멉니다.

8월에는 태그 정리를 하나의 파이프라인으로 묶었습니다. 단순 반복 작업을 수동 탭 전환으로 해결해서는 안 되기 때문입니다. 이번 달에는 대화, 키, 그리고 쓰기 작업이 동일한 장애 영역을 공유하지 않도록 어시스턴트를 제품 프로세스에서 분리했습니다. 이 두 가지 작업의 본질은 같습니다: 로컬 라이브러리 워크스테이션이 자동화를 과감하게 지원하면서도, 파일을 수정하기 전에는 확실하게 멈출 수 있도록 만드는 것입니다.

기반 교체가 완료되어야만 진정으로 정리를 도울 수 있습니다.