~/leo
Leo's Devlog▌
infra
Claude 멀티세션 하네스와 역할별 모델 배정
저장소마다 Claude 세션을 하나씩 두고 개발하는데, 이 글을 쓰려고 구성을 점검하다 디자인을 지휘에서 분리하고 개발 워커는 Sonnet 5로 바꿨다. 각 역할에 그 모델을 둔 이유와, 그렇게 두고 치르는 값.
2026.08.26 10 min read ai · claude-code · workflow · orchestration · infra
backend
연차 자동부여 배치가 못 보던 수동 부여
연차 적립 배치가 '오늘이 정확히 발생일'일 때만 부여해서, 한 번 못 돌면 그 발생분이 영구히 사라졌다. 조건을 '발생일 ≤ 오늘 && 미부여'로 바꿨더니 릴리스 당일에 연차가 과다 지급됐다는 문의가 왔다. 멱등 키가 자동 부여만 보고 있었기 때문이다.
2026.08.04 8 min read batch · idempotency · typeorm · mysql
backend
커넥션 풀 기본값 10을 재본 기록
mysql2 풀 설정을 한 줄도 안 준 채로 운영해 왔다. 기본값이 무엇을 뜻하는지, 포화되면 어떤 증상이 나는지, prod이 지금 어디쯤에 있는지를 재봤다. 그리고 재고 나서야 이 지표로는 답할 수 없는 질문이 하나 남는다는 걸 알았다.
2026.08.04 8 min read mysql · mysql2 · typeorm · performance · observability
infra
CORS 에러로 신고된 Fargate Spot 회수
프로덕션 API가 30분 죽었고 CORS 에러로 신고가 들어왔다. 원인은 Fargate Spot 회수였는데, Spot이 무엇을 보장하고 무엇을 보장하지 않는지를 문서와 실제 설정을 대조해 찾았다. 2분 경고를 실제로 쓰려면 무엇이 설정돼 있어야 하는지도 같이 봤다.
2026.07.28 11 min read aws · ecs · fargate · spot · incident
backend
날짜를 담는 두 좌표계
날짜 컬럼을 다루는 값이 두 좌표계로 나뉜다. 시간축의 한 점인 instant와, 달력 위의 칸인 civil 날짜다. 둘을 한 루프에서 섞으면 하루가 밀리고, 값을 채우는 시계가 두 개면 같은 행 안에서 아홉 시간이 어긋난다.
2026.07.27 10 min read backend · mysql · timezone · date · typeorm
backend
탐지 기준을 넓혀 다시 짠 가드레일
정적 가드레일 두 개를 만들었고 둘 다 처음엔 '위반 0건'을 보고했다. 둘 다 거짓이었다. 탐지 기준이 위험 경로보다 좁으면 0건이 나와도 안 잡힌 것뿐인데, 그 보고를 보고 나는 안심했다.
2026.07.23 7 min read backend · architecture · static-analysis · testing · mysql
infra· 시리즈
배포 파이프라인 개선 FE·BE·배치가 서로를 모른 채 도는 배포 파이프라인의 7가지 문제를, 워크플로우 통합·자동 롤백·캐시 전략으로 하나씩 잡은 기록.
- Part 01 배포 파이프라인이 어긋나는 곳
- Part 02 배포 순서를 정하는 조건식
- Part 03 구버전과 신버전이 겹치는 두 구간
- Part 04 배포 길목에 박은 CI 품질 게이트
- Part 05 배포 시간을 네 번 잰 기록
최신 2026.07.235부작
backend· 시리즈
동시성 연차 차감은 pessimistic 락을 걸고도 뚫렸고, 인보이스 채번은 락을 선언하지 않고도 안 겹쳤다. 두 처방이 나뉜 건 한 번에 하나씩 처리해야 하는 단위가 달랐기 때문이고, 어느 쪽이든 mock으로는 검증되지 않는다.
최신 2026.07.232부작
backend
N+1의 사례들
AI가 짠 코드에서 만난 N+1 사례들. 쿼리 하나가 무거운 경우는 무엇을 얼마나 가져오느냐에 따라 JOIN·집계·배치로 나뉘고, 배치를 제대로 하는 함수도 호출부가 루프에서 부르면 그 이득이 통째로 사라진다.
2026.06.14 7 min read typeorm · nestjs · n-plus-one · performance · mysql
backend· 시리즈
관측 배치가 에러를 삼키고 조용히 끝나면 그 실패는 아무 데도 안 남는다. 로그를 읽을 수 있게 만드는 것부터 시작했다. AsyncLocalStorage로 요청 하나를 묶고, 호출처 64곳을 한 줄도 안 고치고 모든 로그에 그 ID를 붙였다.
최신 2026.06.072부작
frontend
useMutation 반환 객체를 deps에 넣어 만든 무한 루프
exhaustive-deps는 effect가 쓰는 모든 값을 deps에 넣으라 한다. 대개 맞지만, deps에 든 값이 렌더마다 새로 만들어지고 그 effect가 리렌더를 일으키면 effect가 멈추지 않는다.
2026.05.08 15 min read react · react-query · useeffect
backend
결제 중복을 막는 장치와 그 대가
구독 결제에서 중복을 막아야 하는 곳이 세 군데였다. 결제 원장은 UNIQUE로, 주기 이력은 락으로, 즉시 결제는 결제 ID 프리픽스로 막았다. 그런데 그 장치들이 결제만 나가고 DB 쓰기가 실패한 상태를 재시도로 메울 길까지 같이 막았다.
2026.04.05 8 min read payment · portone · webhook · idempotency · subscription