하루스페이스 랩
AI 작업이 멈춰도 다시 시작하려면 무엇을 남겨야 할까
의존성 승인, 연결 끊김과 문맥 소진을 겪으며 긴 대화 대신 의도·변경물·승인·실행 범위를 따로 보존하는 작업 연속성을 만든 일주일의 기록입니다.

Summary
한눈에 보기
- 의존성 승인 뒤에도 원 작업 전용 문맥과 격리된 변경물을 찾아 이어가도록 복구 기준을 분리했습니다.
- 검증된 잠금파일 캐시와 작업공간 내부 의존성 구조로 반복 설치 시간과 권한 충돌을 줄였습니다.
- 장기 문맥은 무조건 이어 붙이지 않고 예약 실행은 새 문맥에서 시작하며 필요한 사실은 저장소 기록으로 넘겼습니다.
이 글은 2026년 8월 3–9일의 설계 문서, Git 기록과 장애 이슈를 바탕으로 다시 쓴 Haru Space 개발 회고다. 비공개 대화, 작업·스레드 식별자, 로컬 경로, 내부 실행 구조와 인증 정보는 담지 않았다.
AI 작업이 중간에 멈추면 “다시 실행” 버튼을 누르면 될 것 같았다. 실제 코드 작업에서는 그렇게 단순하지 않았다.
멈추기 전에 파일을 바꿨는가. 외부 의존성 승인을 기다리고 있었는가. 승인 뒤 돌아갈 대화 문맥은 이 작업의 것인가. 저장소 기준 브랜치는 그사이 바뀌지 않았는가. 같은 요청을 새로 실행하면 변경이 중복되지 않는가.
우리는 처음에 연속성을 대화를 오래 기억하는 능력으로 생각했다. 일주일 동안 여러 실패를 겪고 나서는 정반대로 정의하게 됐다.
연속성은 가장 긴 대화를 붙드는 능력이 아니었다. 의도와 변경물, 승인과 실행 범위를 서로 다른 장부에 보존하고, 더는 도움이 되지 않는 문맥은 안전하게 끊는 설계였다.
의존성을 승인했더니 다른 작업으로 돌아갔다
첫 문제는 외부 패키지 승인이 필요한 작업에서 나타났다.
AI가 구현을 진행하다가 저장소에 없는 패키지가 필요하다고 요청하면 작업은 멈췄다. 사람이 정확한 이름과 버전을 확인하고 승인하면 제한된 설치기가 같은 격리 작업공간에 패키지를 준비한 뒤 원 작업을 이어 가야 했다.
그런데 초기 재개 흐름은 “이 방에서 이 펫이 마지막으로 사용한 대화”를 찾았다. 승인 대기 중 같은 방에서 다른 작업이 실행되면 마지막 대화 포인터가 바뀔 수 있었다. 원래 게시물을 작성하던 작업이 다른 작업의 문맥에서 재개되거나, 의존성 확인만 한 것처럼 끝날 가능성이 생겼다.
방과 펫이 같다는 이유로 작업 문맥도 같다고 본 것이 문제였다.
해결은 작업별 연속성으로 바꾸는 것이었다. 첫 실행이 남긴 작업 전용 문맥을 인증된 실행기만 복구해 같은 격리 작업공간에서 이어 갔다. 이전 데이터처럼 작업 전용 문맥이 없는 경우에는 다른 작업의 대화를 빌리지 않았다. 대신 정제된 원 요청을 한 번 포함한 새 문맥에서 복구했다.
재개 중에는 승인 전 임시 결과를 최종 산출물처럼 게시하지 않았다. 작업이 실제 종료 상태가 되기 전까지 채팅에는 원 요청과 현재 진행 상태만 유지했다.
거부할 수 있어야 연속성도 안전해졌다
같은 장애에서 최종 PR의 거부 버튼이 보이지 않는 문제도 발견했다. 예약 작업의 요청자와 그룹관리자가 같은 경우, 초기 UI는 자기 요청 거부 방지 조건을 모든 단계에 똑같이 적용했다.
수정 실행 전의 자기 승인 제한과 최종 PR 거부는 의미가 다르다. 코드 결과를 본 뒤 “이 변경은 반영하지 않겠다”고 결정할 수 있어야 한다. 서버에는 권한이 있었지만 화면이 그 결정을 막고 있었다.
우리는 승인 단계를 구분했다. 최종 반영 대기에서는 권한 있는 그룹관리자가 자기 요청도 사유와 함께 거부할 수 있게 했다. 과거 작업의 실패와 닫힌 PR은 성공으로 바꾸지 않았다. 남아 있는 원격 브랜치와 산출물은 다음 작업의 근거가 될 수 있지만, 새 결정은 새 이력으로 만들어야 했다.
연속성은 무조건 이어 가는 기능이 아니었다. 멈추고, 거부하고, 그 이유를 보존한 뒤 올바른 지점에서 다시 시작할 권리까지 포함했다.
매 작업마다 설치하던 의존성을 지문으로 바꿨다
격리 작업공간은 코드 변경을 서로 섞이지 않게 했지만, 의존성 준비 비용도 매번 반복했다. 새 작업 폴더에는 패키지가 없었고, 설치 승인과 네트워크 대기가 다시 생겼다.
운영 PC의 공용 패키지 저장소를 그대로 연결하려 했을 때는 계정 권한이 섞여 읽기 오류가 났다. 프로젝트 바깥 캐시를 직접 가리킨 링크는 빌드 도구의 프로젝트 루트 검증에도 막혔다. 속도를 높이기 위한 공유가 격리와 재현성을 해치고 있었다.
우리는 캐시의 기준을 “폴더가 이미 있다”가 아니라 “검증된 의존성 입력이 같다”로 바꿨다.
- 패키지 선언, 잠금파일과 허용된 설정으로 프로젝트 지문을 만든다.
- 저장소가 고정한 패키지 관리자 버전과 공식 공급 경로만 사용한다.
- 최초 준비는 원본 체크아웃이 아닌 임시 입력 복사본에서 수행한다.
- 설치 스크립트와 사용자 정의 훅은 실행하지 않는다.
- 고위험 취약점 검사를 통과한 패키지 데이터만 읽기 전용으로 재사용한다.
- 각 격리 작업공간에는 프로젝트 내부에서 완결된 의존성 구조를 만든다.
같은 지문을 가진 다음 작업은 다운로드와 전체 설치를 반복하지 않았다. 잠금파일이 달라지면 기존 캐시를 덮어쓰지 않고 새 버전을 준비했다. 새 의존성은 여전히 사람 승인 흐름을 거쳤다.
캐시는 빠른 우회로가 아니라 검증 결과의 재사용이었다.
최신 기준을 가져오되 사용자 변경은 덮지 않았다
동적 프로젝트는 연결한 날의 기본 브랜치를 계속 붙들고 있으면 안 됐다. 새 작업은 가능한 한 최신 권위 저장소에서 시작해야 한다. 그렇다고 로컬 변경이 남은 기준 체크아웃을 자동으로 맞춰 버리면 사용자 작업을 잃을 수 있다.
그래서 작업 준비 직전에 원격 기준을 확인하되, 기준 체크아웃에 예상하지 못한 변경이 있으면 자동 정리를 하지 않고 닫힌 상태로 멈추게 했다. 격리 작업을 새로 만드는 것과 기존 사용자 변경을 버리는 것은 같은 권한이 아니었다.
이 원칙은 이후 복구 작업에서도 반복됐다. 시스템은 원본을 최신으로 만들 권한이 아니라, 안전한 새 작업 기준을 선택할 책임만 가진다.
진행 상태는 원시 로그가 아니었다
AI 작업이 길어지자 사용자는 “작업 중” 한 줄만 보고 기다려야 했다. 작업이 실제로 움직이는지, 승인 대기인지, 검증 중인지 알기 어려웠다. 반대로 원시 로그를 그대로 보여 주면 로컬 경로, 명령과 내부 오류가 노출되고 채팅도 빠르게 커진다.
우리는 허용된 진행 단계만 구조화해 한 개의 상태 메시지에 갱신했다. 선택한 작업의 작업보기에는 정제된 단계와 시각을 시간순으로 남겼다. 실시간 전송은 가벼운 상태만 보내고, 실제 상세는 기존 인증 API가 다시 확인했다. 연결이 끊기면 저빈도 조회가 대신했다.
이후 한 작업에서는 브릿지에 정제된 실패 진단이 있었지만 Haru Space 변환 계층이 이를 버려 공통 오류만 보이기도 했다. 제한된 길이와 비밀 마스킹을 거친 실패 이유를 결과에 포함하고, 같은 본문이라도 진단이 달라지면 다른 결과로 구분하도록 고쳤다.
복구에 필요한 설명과 공개하면 안 되는 원시 정보를 동시에 구분해야 했다.
외부 인증창을 닫아도 처음으로 돌아가지 않게
개발 온보딩의 저장소 연결은 외부 인증창으로 이동했다 돌아온다. 사용자가 인증을 취소하거나 웹뷰를 닫았을 때, Haru Space 팝업은 여전히 “연결 중”으로 잠겨 있었다. 서비스를 다시 열면 어느 단계였는지 표시도 사라졌다.
우리는 같은 브라우저에 그룹과 단계 시각만 담은 짧은 재개 표식을 남겼다. 토큰, 저장소 자격 증명, 프롬프트와 사용자 콘텐츠는 저장하지 않았다. 돌아왔을 때 화면은 그 표식을 안내로 사용하지만, 실제 저장소 연결과 실행기 준비 상태는 서버에서 다시 계산했다.
외부 인증을 한 번 성공했다는 클라이언트 표시는 권한의 증거가 아니었다. 재개 지점은 기억하되 사실은 다시 검증했다.
이 방식은 다른 기기까지 이어 주지는 않았다. 같은 브라우저에서 중단된 여정을 되찾는 범위였다. 기기 간 동기화는 어떤 상태를 계정에 저장할지 별도의 개인정보 검토가 필요한 문제로 남겼다.
빈 저장소의 첫 작업도 “완료”처럼 끝났다
신규 프로젝트의 첫 작업에서는 검증된 시작 템플릿을 배치했지만 AI가 이를 읽고 설명만 한 채 파일을 바꾸지 않고 끝나는 경우가 있었다. 작업 자체는 성공 응답처럼 보였지만 편집 작업의 목적은 달성되지 않았다.
초기 템플릿과 결과 지문이 같고 첫 편집이라는 제한된 조건에서만, 같은 작업공간과 문맥으로 한 번의 교정 실행을 허용했다. 실제 변경, 구조화된 의존성 요청 또는 명확한 실패 중 하나가 나와야 했다. 두 번째 무변경 결과는 성공으로 꾸미지 않았다.
교정 실행에도 네트워크나 저장소 반영 권한을 추가하지 않았다. 사용량은 첫 실행과 합쳐 기록했다. 복구가 새 작업을 숨겨 만드는 방식이 되지 않게 했다.
너무 긴 문맥은 보존이 아니라 부채였다
일주일 끝에는 예약 글 작업이 파일 변경 없이 멈췄다. 예약과 자동 승인은 정상이고 실행기도 작업을 시작했지만, 오랫동안 이어진 공용 대화 문맥이 새 요청에 함께 붙었다. 최신 조사, 이미지와 세 언어 원고를 처리하는 동안 실행 예산이 먼저 소진됐다.
이 사건은 “대화가 이어지면 항상 좋다”는 생각을 뒤집었다.
예약 실행은 매번 새 작업 문맥에서 시작하게 했다. 필요한 지속 정보는 저장소 문서, 현재 요청과 제한된 참조에서 가져왔다. 일반 대화의 연속성은 유지하되 반복 자동 작업의 숨은 대화 누적은 끊었다.
한편 응답 스트림이 완료 전에 끊긴 작업도 있었다. 당시 확인한 원칙은 자동 재실행 전에 변경 여부를 먼저 보는 것이었다. 변경이 없으면 새 작업을 요청할 수 있지만, 파일이 남아 있다면 같은 작업의 검증과 완료를 이어야 중복 편집을 피할 수 있다. 이 제한 복구는 당시 후속 과제로 남았고, 완료된 기능인 것처럼 기록하지 않는다.
우리가 남기기로 한 것과 버리기로 한 것
다시 시작할 수 있는 AI 작업에는 다음이 필요했다.
남겨야 하는 것
- 사람이 확인한 원 요청과 실행 범위
- 작업별 격리 변경물과 Git 상태
- 의존성 요청·결정과 검증된 잠금파일 지문
- 현재 단계, 제한된 실패 이유와 추가 전용 결정 이력
- 기준 저장소 revision과 변경 결과 지문
- 재개할 수 있는 경우의 작업 전용 문맥 참조
남기지 말아야 하는 것
- 다른 작업과 공유되는 마지막 대화 포인터
- 전체 프롬프트와 원시 모델 로그의 반복 복사본
- 인증 토큰, 로컬 경로와 내부 명령
- 끝없이 누적되는 예약 작업의 과거 대화
- 종료 전의 임시 결과를 완성 산출물로 보이게 하는 상태
다시 검증해야 하는 것
- 현재 그룹과 작업방 접근 권한
- 기준 브랜치와 저장소 상태
- 승인 대상 지문과 의존성 입력
- 파일 변경 존재 여부
- 작업이 정말 종료 상태인지 여부
다시 시작한다는 말의 의미
8월 3–9일의 실패들은 모두 “이어하기”라는 한 단어 아래 있었지만 원인은 달랐다. 의존성 승인 뒤 잘못된 대화로 돌아간 작업, 매번 반복된 설치, 외부 인증창에서 끊긴 온보딩, 무변경으로 끝난 첫 편집, 너무 큰 문맥 때문에 시작도 못 한 예약 작업이 있었다.
하나의 재시도 버튼으로 해결할 수 없는 이유였다.
작업의 목적은 요청 기록에, 변경은 격리 작업공간에, 결정은 감사 원장에, 재현성은 잠금파일 지문에 남겨야 했다. 대화 문맥은 그중 하나일 뿐이었다. 유효하면 이어 쓰고, 작업이 다르거나 비용만 키우면 새로 시작해야 했다.
AI가 중단돼도 다시 시작할 수 있게 한 것은 모든 것을 기억하게 만든 일이 아니었다. 잃으면 안 되는 것과 과감히 끊어야 하는 것을 처음으로 구분한 일이었다.
반응을 남기면 중복 방지를 위한 무작위 식별자가 이 브라우저에 저장될 수 있습니다.

