비전 폴백 패턴 일반화와 삭제는 정리가 아니다

26년 06월 27일

비전 폴백 패턴을 일반화하다

이날은 패턴을 일반화한 날이다.

이미지 읽기 도구가 두 개가 되면서 비전 폴백 패턴을 재사용 가능한 헬퍼로 뽑아냈다.

그리고 npm 삭제 후 남은 dangling 참조를 정리했다.

비전 폴백은 이런 문제를 푼다.

텍스트 전용 모델은 이미지를 못 본다.

근데 에이전트가 이미지 파일을 읽어야 할 때가 있다.

이때 비전 모델한테 조용히 넘겨서 텍스트 설명을 받아오는 거다.

이 패턴을 처음엔 read 도구에만 구현했다.

read로 이미지를 읽으면, 비전 모델이 대신 보고 텍스트를 반환한다.

호출하는 쪽은 비전 모델을 거친 줄도 모른다.

투명한 라우팅이다.

근데 두 번째 이미지 입력 도구가 생겼다.

지라 첨부 이미지를 읽는 도구다.

같은 패턴이 필요했다.

비전 모델한테 넘기고 텍스트를 받아오는 거다.

헬퍼로 뽑아내다

그래서 패턴을 헬퍼로 뽑아냈다.

describeImageWithVision이라는 함수를 만들었다.

프로바이더 분기랑 인증 처리를 안에 넣었다.

새 이미지 도구는 이 함수를 부르기만 하면 된다.

이게 “일회용 구현에서 의도적 추상화로” 가는 과정이다.

처음에는 read에만 필요해서 거기에 짰다.

두 번째가 생기니까 공통으로 빼야 한다는 걸 깨달았다.

세 번째가 생기면 헬퍼를 부르기만 하면 된다.

3단계 상태 모델

그리고 결과를 3단계로 만들었다.

첫째, 비전 가능 모델은 원본 이미지를 그대로 받는다.

둘째, 비전 폴백이 성공하면 설명 텍스트를 받는다.

셋째, 폴백 자체가 실패하면 파일로 저장하고 경로를 반환한다.

모든 실패 경로가 정의된 상태로 끝난다.

에러를 뱉지 않는다.

호출하는 쪽은 항상 무언가를 받는다.

이미지이거나, 설명이거나, 파일 경로거나. 이게 “우아한 축소” 설계다.

실패해도 정의된 상태로 떨어진다.

호출하는 쪽이 비전 시도가 있었다는 걸 몰라도 된다.

삭제는 정리가 아니다

두 번째 작업은 dangling 참조 정리였다.

OpenClaw를 npm에서 삭제했다.

패키지 디렉토리가 사라졌다.

근데 셸 시작할 때마다 에러가 났다.

“그런 파일이나 디렉터리가 없습니다.” 원인은 삭제 후 남은 참조였다.

설치할 때 zshrc에 추가했던 참조가 남아 있었다.

systemd 유닛 파일도 남아 있었다.

패키지는 없는데 패키지를 참조하는 설정은 남아 있는 거다.

npm 삭제는 설정을 안 지운다

핵심 교훈은 “패키지 매니저 삭제는 패키지만 지운다”는 거다.

설치할 때 추가한 설정은 안 지운다.

zshrc 참조, systemd 유닛, 환경변수. 이런 건 수동으로 지워야 한다.

“삭제했으니까 깨끗하겠지”라고 가정하면 안 된다.

삭제 후에는 참조가 남아 있는지 확인해야 한다.

특히 설치 스크립트가 자동으로 설정을 수정하는 패키지는 더 그렇다.

SSH 세션 지속성

마지막으로 SSH 세션 지속성도 확인했다.

아이패드에서 SSH로 접속해서 에이전트를 돌릴 때 연결을 끊으면 어떻게 되는가. 결론은 안 된다.

에이전트는 포어그라운드 TUI 프로세스다.

SSH 세션의 TTY에 묶여 있다.

연결이 끊기면 SIGHUP이 와서 즉시 죽는다.

진행 중인 작업이 날아간다.

클라이언트 도구로는 못 막는다.

모시(Mosh)는 연결 복구에만 도움된다.

프로세스 생존은 못 보장한다.

서버 측 멀티플렉서가 필요하다.

tmux나 screen을 쓰면 SSH 연결이 끊겨도 서버에서 프로세스가 살아 있다.

에이전트한테 시키면 안 되는 일

여기서 함정이 있다.

에이전트한테 “screen 세션을 만들어”라고 하면 안 된다.

에이전트의 bash 도구는 TTY가 없다.

screen은 TTY가 있어야만 실행된다.

멀티플렉서 명령은 사용자가 직접 터미널에서 쳐야 한다.

마무리

내가 이날 배운 핵심은 다음과 같다.

이날의 교훈은 세 가지다.

첫째, 일회용 구현을 재사용 가능한 추상화로 뽑아내는 시점을 알아차려라. 두 번째 인스턴스가 나오면 공통으로 빼야 한다.

세 번째 인스턴스가 나오기 전에 뽑아내면 세 번째는 헬퍼를 부르기만 하면 된다.

둘째, 삭제는 정리가 아니다.

패키지 매니저는 패키지만 지운다.

설치할 때 추가한 설정은 수동으로 지워야 한다.

삭제 후에는 참조가 남아 있는지 확인해야 한다.

셋째, 클라이언트 도구로 서버 문제를 못 푼다.

SSH 세션 지속성은 서버 측 멀티플렉서가 필요하다.

클라이언트가 아무리 똑똑해도 SIGHUP은 못 막는다.