좀비 프로세스 근본 수정
나는 QA Agent 알파 환경 안정화 작업을 이어간 날이었다.
며칠 전에 SIGTERM 처리를 개선했는데, 좀비 프로세스가 여전히 남았다.
그래서 더 근본적으로 고쳤다.
그리고 큐 경합이랑 캐시 갱신 문제도 잡고 LLM 호출을 관측할 수 있게 Langfuse 연동 설계도 시작했다.
며칠 전에 Chromium 종료 신호 처리를 개선했는데, 그래도 좀비 프로세스가 남았다.
agent-browser가 띄운 Chromium 자식 프로세스가 깔끔하게 종료되지 않고 고아가 되는 문제였다.
고아 프로세스가 쌓이면 리소스를 잡아먹고 결국 서버가 느려지거나 죽는다.
그래서 더 직접적인 방법으로 고쳤다.
/proc/cmdline을 직접 읽어서 고아 Chromium 프로세스를 감지하고 죽인다.
그리고 SingletonLock도 정리한다.
종료 로직이 프로세스 트리에 의존하지 않고 직접 프로세스를 찾아내서 처리하는 거다.
이게 왜 중요하냐면 “타임아웃 인질” 문제 때문이다.
순차 실행 환경에서 한 케이스가 멈추면, 그 케이스를 죽이지 못하면 뒤의 케이스들이 영원히 시작하지 못한다.
케이스 7이 멈추면 8부터 50까지가 막히는 거다.
그래서 프로세스를 확실히 죽이는 게 필수적이다.
슬랙 스레드 단위 정리
그리고 브라우저는 슬랙 스레드 단위로 격리되어 있다.
작업 디렉토리, 브라우저 프로필, 세션 키, 레지스트리 전부 스레드 ID로 묶여 있다.
그러니까 종료할 때 해당 스레드의 Chrome만 죽여야 한다.
다른 스레드의 Chrome을 잘못 죽이면 안 된다.
프로필 디렉토리 기반으로 해당 스레드의 Chrome만 찾아서 죽이는 방식으로 구현했다.
실행 큐 경합 수정
두 번째는 실행 큐 동시성 경합 문제였다.
여러 QA 실행이 큐를 공유하다
보니까 스케줄링에서 경합이 생겼다.
동시에 실행되는 실행들이 큐를 서로 잡아당기면서 꼬이는 문제였다.
큐 처리 로직을 정리해서 경합을 해결했다.
병렬로 돌아가는 실행들이 큐를 안전하게 공유할 수 있게 만들었다.
Planning 캐시 갱신 문제
세 번째는 Planning 캐시 갱신 문제였다.
며칠 전에 시트 단위 캐시를 만들었다.
같은 시트를 다시 실행하면 전체 플래닝을 생략하는 거다.
근데 버그가 있었다.
대상 URL이 바뀌었는데도 캐시가 갱신되지 않았다.
그러니까 옛날 URL에 대한 계획을 그대로 쓰고 있었다.
URL이 바뀌면 캐시를 무효화하고 다시 플래닝해야 하는데, 그게 안 됐다.
캐시 무효화 조건을 추가해서 URL 변경 시 캐시가 갱신되도록 고쳤다.
Langfuse 연동 설계
안정화 작업과 별개로 LLM 호출 관측을 위한 Langfuse 연동 설계도 시작했다.
문제는 QA Agent가 LLM을 호출하지만 그 호출을 관측할 수단이 없다는 거였다.
어느 단계에서 토큰을 얼마나 쓰는지, 프롬프트 품질이 어떤지, 비용이 얼마나 나오는지 전부 안 보였다.
이걸 보려면 LLM 호출을 추적하는 시스템이 필요했다.
그래서 Langfuse 프록시를 설계했다.
LLM 호출마다 입력, 출력, 토큰 사용량을 추적한다.
단계별 성능 분석, 프롬프트 품질 모니터링, 비용 추적까지 가능해진다.
구조는 프로바이더별로 프록시를 따로 두는 걸로 잡았다.
LLM 프로바이더마다 호출 방식이 다르니까, 각자 전용 프록시를 둬서 추적하는 게 깔끔했다.
이날은 설계까지만 하고 구현은 다음으로 넘겼다.
회사 프로젝트 작업
QA Agent 외에 회사 교육 플랫폼 작업도 했다.
모바일에서 채널톡 버튼이 하단 내비게이션 바랑 겹치는 문제였다.
모바일 화면에서 채팅 버튼이 눌리지 않아서 사용자가 문의를 할 수 없었다.
미디어 쿼리를 추가해서 모바일 화면에서는 채널톡 버튼 위치를 위로 올렸다.
하단 바 높이에 여유를 더해서 버튼이 하단 바 위에 떠 있게 만들었다.
수정하고 일일 알파 배포 브랜치에 머지해서 배포했다.
마무리
좀비 프로세스를 근본적으로 잡은 게 가장 큰 수확이었다.
종료 신호 처리만으로는 부족했고 직접 프로세스를 찾아서 죽이는 방식이 필요했다.
“타임아웃 인질” 문제를 피하려면 프로세스를 확실히 죽일 수 있어야 한다.
이제 그 확신이 생겼다.
큐 경합이랑 캐시 갱신도 잡아서 실행 안정성이 올라갔다.
그리고 Langfuse 연동 설계로 LLM 호출을 관측할 수 있는 길이 열렸다.
관측할 수 없으면 개선할 수 없으니까, 관측성 확보는 중요한 기반이다.