Alembic 마이그레이션이 프로덕션에서 실패했을 때, 되돌리는 순서

이 글에서는 Alembic 마이그레이션이 프로덕션에서 실패했을 때 무엇부터 확인하고 어떤 순서로 되돌려야 하는지를 정리합니다. 결론부터 말씀드리면, 스키마를 먼저 되돌리기 전에 애플리케이션 코드 롤백 여부와 alembic_version 테이블의 실제 상태부터 확인하는 게 순서입니다. 순서를 반대로 하면 스키마는 되돌렸는데 코드는 새 스키마를 기대하는 상태가 되어 장애가 더 커지는 경우가 많습니다. 이 내용은 Alembic 1.13 계열, SQLAlchemy 2.x, PostgreSQL … Read more

FastAPI 의존성 주입에서 DB 세션이 새는 이유, yield 패턴부터 점검하기

SQLAlchemy 커넥션 풀을 pool_size=5로 두고 운영하다가 로그에 QueuePool limit of size 5 overflow 10 reached, connection timed out이 찍히기 시작했다면, 원인은 거의 하나로 좁혀집니다. FastAPI 의존성 주입에서 만든 DB 세션이 요청이 끝난 뒤에도 반납되지 않고 계속 쌓이는 경우입니다. 이 글은 yield 패턴을 어떻게 써야 세션이 새지 않는지, 어떤 조건에서 그 원칙이 깨지는지를 실제 코드로 짚어 … Read more

LLM 응답을 임베딩과 함께 저장할 때 자주 나오는 스키마 실수

결론부터 말씀드리면, LLM 응답을 임베딩과 함께 저장할 때 나는 대부분의 문제는 임베딩 차원을 고정하지 않은 테이블 설계, 원본 응답과 임베딩 대상 텍스트를 한 컬럼에 몰아넣는 구조, 그리고 모델 버전 기록 누락에서 시작됩니다. 이 세 가지만 스키마 단계에서 잡아도 나중에 벡터 차원 불일치 에러나 검색 품질 저하로 테이블을 갈아엎는 일을 피할 수 있습니다. 아래에서는 PostgreSQL과 pgvector … Read more

파이썬 멀티프로세싱에서 pickle 에러 잡는 법

이 글에서는 파이썬 멀티프로세싱에서 pickle 에러가 나는 정확한 원인, 직접 재현한 코드와 출력, 상황별 우회법 네 가지를 순서대로 다룹니다. 결론부터 짧게 말씀드리면, 이 에러는 대부분 대상 함수를 모듈 최상위가 아닌 곳(함수 안의 함수, 람다, 클래스 메서드)에 정의했을 때 나타나고, 함수를 최상위로 옮기거나 dill 기반 도구로 바꾸면 대부분 해결됩니다. 다만 이 방법들이 항상 만능은 아니라서, 어디서 … Read more

도커 이미지 빌드가 매번 느려질 때, 캐시 순서부터 확인하세요

“도커 이미지 빌드가 매번 느려지는 게 캐시가 안 먹어서 그런 건가요?” 맞습니다. 대부분은 Dockerfile 안에서 자주 바뀌는 파일을 명령어 앞쪽에 배치해 뒤따르는 레이어 전체의 캐시를 매번 무효화시키기 때문입니다. 이 글에서는 Dockerfile 명령 순서를 어떻게 재배치해야 캐시가 살아남는지, 그리고 BuildKit의 캐시 마운트 기능으로 의존성 설치 시간 자체를 없애는 방법을 실제 예시와 함께 정리합니다. 도커 이미지 빌드가 … Read more

Nginx 리버스 프록시에서 SSE가 버퍼링될 때 고치는 설정 세 줄

이 글에서는 Nginx 리버스 프록시에서 SSE(Server-Sent Events) 응답이 브라우저까지 실시간으로 오지 않고 중간에 뭉쳐서 도착하는 문제를 어떤 설정으로 풀 수 있는지 확인하실 수 있습니다. 결론만 먼저 말씀드리면, 해당 location 블록에 proxy_buffering off, proxy_cache off, chunked_transfer_encoding off 이 세 줄을 넣는 것으로 대부분의 지연이 해결됩니다. 다만 SSE가 버퍼링될 때의 원인이 이 세 줄만으로 설명되지 않는 경우도 … Read more

Celery 워커가 죽었는데 모니터링에 안 걸릴 때, 헬스체크 이렇게 설계하세요

이 글에서는 Celery 워커가 죽었는데 모니터링 대시보드에는 멀쩡하게 떠 있는 상황이 왜 생기는지, 그리고 그런 사각지대를 없애는 헬스체크 구조를 어떻게 짜는지 확인하실 수 있습니다. 답을 먼저 드리면, systemd나 supervisor가 보는 건 프로세스의 생존 여부일 뿐 실제 태스크 소비 여부가 아니라서 이런 틈이 생깁니다. 워커가 큐를 실제로 소비하고 있는지는 celery inspect ping으로 직접 두드려 보거나, 워커별로 … Read more

Redis 캐시 히트율이 낮을 때, TTL과 키 설계부터 점검하세요

모니터링 대시보드를 열었더니 어제까지 90%를 넘던 캐시 히트율이 오늘따라 60%대로 주저앉아 있는 걸 본 적 있으실 겁니다. Redis 캐시 히트율이 낮을 때는 대부분 TTL 설정과 키 설계, 이 두 곳 중 하나에 원인이 있는 경우가 많습니다. 이 글에서는 실제 redis-cli 출력과 함께 어디를 먼저 봐야 하는지 순서대로 정리했습니다. 캐시 히트율, 감으로 말고 redis-cli로 직접 확인하기 … Read more

임베딩 API 호출이 느려질 때 배치 크기와 병렬 처리 조정법

결론부터 말씀드리면, 임베딩 API 호출이 느려질 때 가장 먼저 손봐야 할 것은 코드 최적화가 아니라 배치 크기와 동시 요청 수의 조합입니다. 텍스트를 한 건씩 호출하고 있다면 배치로 묶는 것만으로도 체감 속도가 크게 달라지고, 이미 배치를 쓰고 있는데도 느리다면 동시성 설정이 레이트 리밋에 걸려 있을 가능성이 높습니다. 이 글에서는 OpenAI Python SDK(1.x 버전) 기준으로, 실제 동작하는 … Read more

LLM 함수 호출 파라미터 타입 오류, JSON 스키마로 잡는 법

LLM 함수 호출에서 파라미터 타입이 자꾸 틀리면 모델 성능이 부족해서라고 생각하기 쉬운데요, 사실은 스키마가 “반드시 지켜야 할 규칙”이 아니라 “참고용 힌트”로만 전달되는 경우가 많아서 벌어지는 문제예요. city 자리에 숫자가 들어오거나 enum 값 바깥의 문자열이 채워지는 오류는, OpenAI의 Structured Outputs 기능에서 strict 옵션을 켜면 상당 부분 구조적으로 막을 수 있습니다. 다만 이 옵션을 켠 뒤에도 검증 … Read more