AI Briefing

Shadow Workspace: 백그라운드에서 코드를 반복 개선하기

·2024.06.08 09:00

Cursor는 AI가 사용자 작업을 방해하지 않도록 숨은 워크스페이스를 둔다.

AI가 코드를 잘 고치려면 단순히 파일 조각을 읽는 수준을 넘어, 개발 환경 안에서 직접 반복할 수 있어야 한다. 하지만 사용자 파일을 그대로 건드리면 편집 충돌, lint 오류, 실행 불일치가 생기므로 Cursor는 이를 분리한 shadow workspace를 설계했다.

우선 목표는 LSP-usability다. AI가 자신의 수정 결과에 대해 lint를 보고, 정의로 이동하고, 언어 서버 프로토콜 전반을 활용할 수 있어야 한다. 반면 요구사항은 명확하다.

  • Independence: 사용자의 코딩 경험은 바뀌면 안 된다.
  • Privacy: 코드는 로컬에만 있어야 한다.
  • Concurrency: 여러 AI가 동시에 작업할 수 있어야 한다.
  • Universality: 모든 언어와 워크스페이스에서 동작해야 한다.
  • Maintainability: 가능한 한 적고 분리된 코드로 구현해야 한다.
  • Speed: 수분 단위 지연이 없어야 하고, 많은 브랜치도 처리해야 한다.

가장 단순한 방법은 원본 TextModel을 복사해 AI에게만 보여주는 것이다. 유지보수성은 좋지만, 같은 language server에 복사본이 알려지면서 참조 결과가 섞이고, Go처럼 전역 네임스페이스를 쓰는 언어에서는 중복 선언 문제가 생기며, Rust처럼 디스크 기반 import에 의존하는 언어에서는 기대한 lint가 아예 나오지 않는다. 결국 독립성을 해치면 사용자가 기능을 쓰지 않게 된다는 판단이 핵심이었다.

현재 구현은 숨은 Electron window를 하나 더 띄우는 방식이다. AI가 lint를 보고 싶을 때 메인 창과 분리된 숨은 창에 같은 작업공간을 띄우고, 그 안에서 수정과 lint 확인을 반복한다. 렌더러 프로세스 간 직접 통신은 피하고, 기존 VS Code의 message port 경로와 별도 IPC를 조합했으며, 내부 통신에는 gRPCbuf를 사용해 JSON 직렬화의 취약성을 피했다.

이 방식은 다음을 만족한다.

  • 사용자 창과 완전히 분리된 독립성
  • 로컬 환경 안에서만 동작하는 privacy
  • 창을 재사용하고, 15분 비활성 시 자동 종료해 메모리 부담을 완화하는 운영 방식
  • 여러 AI 요청을 하나의 shadow window에 interleave해 처리하는 concurrency

다만 완전하지는 않다. 특히 rust-analyzer는 파일 시스템에 실제로 기록된 코드에 의존해 lint를 내기 때문에, 현재 방식으로는 Rust의 LSP-usability를 충분히 제공하지 못한다. 예외적으로 deprecated된 RLS를 쓰는 경우는 가능하다.

다음 단계인 runnability는 더 어렵다. 코드를 실행하려면 디스크에 저장해야 하고, 빌드 캐시와 로그 같은 부수 효과도 분리해야 하므로 같은 폴더를 공유할 수 없다. 가장 단순한 cp -r 방식은 node_modules, venv, target 같은 거대한 디렉터리 때문에 너무 느려서, 이후에는 더 나은 복제 방식과 파일 시스템 수준의 격리가 필요해진다.

이 요약은 원문 이해를 돕기 위한 큐레이션입니다. 저작권은 원저작자에게 있으며, 정확한 내용과 맥락은 원문을 확인하세요.

요약 오류, 출처 표기 문제, 삭제 요청은 문의 · 건의로 알려주세요.