LLM rate limit 429 몰릴 때, 큐잉과 토큰 버킷 중 뭘 써야 할까요

LLM API에서 429 에러가 몰리면 재시도(retry) 로직만 촘촘하게 짜면 해결된다고 생각하기 쉬운데, 이건 절반만 맞는 이야기예요. 재시도는 이미 터진 429를 수습하는 방법이고, LLM rate limit을 근본적으로 관리하려면 요청을 내보내는 속도 자체를 조절하는 계층이 따로 필요합니다. 혼자 쓰는 배치 스크립트라면 토큰 버킷 하나로 충분하지만, 여러 사용자의 요청이 동시에 들어오는 서비스라면 큐잉까지 함께 둬야 429가 줄어들어요. 429가 … Read more

LLM 스트리밍 취소, 창을 닫으면 과금은 정말 멈출까

“스트리밍으로 답변받던 중에 브라우저 탭을 닫으면 LLM 과금은 바로 끊길까요?” 결론부터 말씀드리면, 정답은 “아니요, 서버가 취소 신호를 받아 실제로 생성을 멈춰야만 멈춥니다”입니다. 클라이언트 소켓이 끊긴 것과 추론 서버가 토큰 생성을 중단하는 것은 완전히 별개의 사건이라서, 요청 취소를 직접 전파하는 코드를 넣어두지 않으면 사용자가 사라진 뒤에도 서버는 혼자 계속 토큰을 뽑아내고 그만큼 과금됩니다. 브라우저 창을 닫으면 … Read more

AI 에이전트 무한 루프, 종료 조건과 최대 스텝은 이렇게 설계하세요

에이전트가 같은 도구만 계속 부르고 멈추지 않는데, 대체 어디서 끊어야 할까요? 답은 모델 호출 루프 안에 종료 조건과 최대 스텝을 코드로 직접 심어두는 것입니다. LLM 자체는 “이제 그만 부르자”는 판단을 스스로 하지 못하는 경우가 많아서, AI 에이전트 무한 루프는 안전장치를 따로 만들지 않으면 언제든 벌어질 수 있는 일입니다. 도구 호출이 멈추지 않는 구조적인 이유 에이전트 … Read more

tool calling이 엉뚱한 도구를 고를 때, 설명문부터 고치는 순서

tool calling 기능을 붙인 에이전트에서 모델이 분명 존재하는 도구를 두고 엉뚱한 함수를 호출하는 문제는, 프롬프트보다 도구 설명문(description)에서 시작되는 경우가 많습니다. 이름이 비슷하거나 설명이 짧은 도구 두세 개만 나란히 등록돼 있어도 모델이 그중 하나를 잘못 고르는 일이 흔하게 일어납니다. 그래서 함수 호출이 꼬였을 때는 시스템 프롬프트부터 뜯어고치기 전에, 도구 설명문을 먼저 점검하는 순서로 접근하는 편이 효율적입니다. … Read more

외부 API 응답을 곧이곧대로 믿으면 안 되는 이유

새벽 배포 직후 알림이 울리고, 로그를 열어보니 결제 API가 갑자기 amount 필드를 문자열 “1,000”으로 보내서 파서가 통째로 죽어 있는 상황, 한 번쯤 겪어보셨을 거예요. 외부 API 응답을 그대로 믿으면 안 되는 이유는 간단합니다. 상대 서버가 문서와 다르게 필드를 바꾸거나, 일부 데이터만 누락된 채 200 OK를 돌려주는 순간 내 서비스가 함께 무너지기 때문이에요. 이 글에서는 스키마 … Read more

크롤링이 403으로 막힐 때 확인할 순서: UA·robots·속도

크롤링이 403으로 막히면 다들 제일 먼저 프록시부터 바꾸는데, 사실 원인의 상당수는 IP가 아니라 요청 헤더와 속도에 있어요. User-Agent 하나만 제대로 채워도 뚫리는 경우가 많고, robots.txt를 무시한 경로만 골라 요청했다가 걸리는 경우도 흔합니다. 이 글에서는 403의 흔한 원인 네 가지를 실제 점검 순서대로 정리하고, 어디까지가 “고치면 되는 문제”이고 어디부터는 우회가 아니라 포기해야 하는 영역인지 구분해 드릴게요. … Read more

Windows에서 파이썬 cp949 오류 없애기: 로그·파일·서브프로세스 3곳 총정리

Windows에서 파이썬 스크립트를 돌리다가 UnicodeDecodeError나 UnicodeEncodeError 메시지에 ‘cp949’라는 단어가 찍혀 있어서 검색하셨다면, 답은 명확합니다. 표준 출력(로그·print)은 스트림 인코딩을 UTF-8로 재설정하고, 파일은 open()에 encoding=’utf-8’을 항상 명시하며, 서브프로세스는 자식 프로세스가 실제로 쓰는 인코딩에 맞춰 encoding 인자를 지정해야 세 곳 모두에서 오류가 사라집니다. 원인은 하나입니다. 한국어 Windows의 로컬 코드페이지가 cp949로 잡혀 있고, 파이썬이 인코딩을 따로 지정하지 않으면 이 … Read more

크론 대신 앱 안에서 스케줄을 돌릴 때, 재시작 중복 실행 막는 법

크론 대신 앱 안에서 스케줄을 돌릴 때 재시작 중복 실행을 막으려면, 스케줄러 라이브러리가 아니라 디스크나 데이터베이스처럼 프로세스 바깥에 남는 곳에 “이미 실행했다”는 흔적을 남겨야 합니다. node-cron 같은 라이브러리는 프로세스 메모리 안에서 타이머를 돌릴 뿐이라, 앱이 재시작되는 순간 그 상태가 통째로 사라지기 때문입니다. 특히 저장소를 1분마다 pull 받아 자동 배포하면서 프로세스를 재시작하는 서버라면, 배포 타이밍과 스케줄 … Read more

무중단 배포인데 진행 중이던 작업이 끊기는 이유, drain 시간과 긴 작업 분리로 해결하기

무중단 배포인데 진행 중이던 작업이 갑자기 끊기는 이유는 뭘까요? 배포 도구가 새 요청은 막아주지만, 이미 실행 중인 요청이나 잡(job)을 끝까지 기다려주는 시간(drain 타임아웃)이 짧거나 아예 설정돼 있지 않기 때문입니다. 몇 초짜리 API 요청은 이 시간 안에 대부분 끝나지만, 파일 변환이나 리포트 생성처럼 오래 걸리는 작업은 애초에 배포 파이프라인 안에서 처리하면 안 됩니다. 이 글에서는 왜 … Read more

Playwright를 서버에서 오래 돌리면 메모리가 계속 느는 이유

Playwright를 서버에 올려서 오래 돌리다 보면 “이 라이브러리는 원래 메모리가 새는구나”라고 오해하기 쉽습니다. 하지만 실제로는 라이브러리 자체의 결함보다 브라우저·컨텍스트·페이지라는 세 계층의 수명을 어떻게 관리하느냐가 메모리 증가 폭을 결정합니다. Playwright를 서버에서 오래 돌리면 메모리가 계속 늘어나는 대부분의 사례는 browser.close()를 안 해서가 아니라, context를 재사용하거나 방치하는 패턴에서 비롯됩니다. 이 글에서는 어떤 계층에서 메모리가 쌓이는지, 왜 close()를 호출해도 … Read more