A Free Model's Server Passed My Smoke Test, Then Hung on Shutdown. The Exit Contract Caught It.
개요
MonkeyCode의 무료 모델로 생성된 Python HTTP 서버는 초기 시작 테스트는 통과했지만, 종료 시 예기치 않게 지연되는 문제를 보였으며, 이는 "Exit Contract" 테스트를 통해 발견되었습니다.
주요 내용
* 문제점: 생성된 Python 서버는 ThreadingHTTPServer를 사용하며, SIGTERM 신호를 받으면 메인 스레드는 종료되지만, 활성 상태인 비데몬(non-daemon) 핸들러 스레드가 작업을 완료할 때까지 프로세스가 종료되지 않아 리소스를 점유하는 문제가 발생합니다.
* 구체적인 상황: /slow 엔드포인트에서 30초간 실행되는 요청 중에 서버 종료 신호(SIGTERM)가 전달되면, 해당 요청을 처리하는 스레드가 완료될 때까지 프로세스가 실제로 종료되지 않습니다.
* Exit Contract 테스트: 프로세스가 시작된 후 느린 요청을 보내고 SIGTERM 신호를 보낸 뒤, 정해진 시간 안에 프로세스가 완전히 종료되는지를 검증하는 테스트를 설계했습니다.
* 해결 방안: ThreadingHTTPServer 객체에 server.daemon_threads = True 설정을 추가하여, 요청을 처리하는 스레드가 비데몬 스레드가 아닌 데몬 스레드로 작동하도록 변경하면, 메인 스레드 종료 시 관련 스레드도 함께 정리되어 프로세스가 깨끗하게 종료됩니다.
* 무료 서버 인프라에서의 중요성: 무료 서버는 임시 테스트나 데모 환경에 유용하지만, 사용량이 적을 때 재시작되거나 중지될 가능성이 높습니다. 이러한 환경에서 서비스가 깨끗하게 종료되지 못하면, 재시작 시 지연, 헬스 체크 오류, 리소스 낭비 등의 문제가 발생할 수 있습니다.
* 효과적인 워크플로우: 먼저 /health 응답과 종료 시간 제약을 포함하는 "observable contract"를 정의하고, 최소한의 서버를 생성하여 로컬에서 Exit 테스트를 수행한 후, 무료 서버에 배포하여 환경별 테스트를 반복하는 것이 좋습니다.
* 한계점: 이 테스트는 모델의 품질, 보안, 데이터 정확성, 지연 시간, 프롬프트 주입 내성, 토큰 사용량 등 모델 자체의 성능이나 보안 취약점을 검증하지는 않습니다. 또한, 컨테이너 런타임에서만 발생하는 버그는 잡아내지 못할 수 있으며, 코드 리뷰를 대체하지는 못합니다.
* 사용 시 주의사항: 생성된 무료 티어 서버는 프로덕션 결제 데이터, 개인 건강 정보, 비밀번호 등 민감한 정보를 다루거나, 내구성 있는 스토리지 및 안정적인 가동 시간을 요구하는 워크로드에는 적합하지 않습니다.
시사점
생성형 AI 모델을 활용한 코드 개발에서 비용 절감 효과와 더불어, 행위적 계약(Exit Contract)과 같은 명확한 테스트를 통한 검증 비용의 중요성이 재확인되었으며, 저렴한 모델 생성이 후보군 생산 비용을 낮추는 반면, 행동 검증 비용은 여전히 사용자에게 남는다는 점을 시사합니다.
댓글
GitHub Discussions