쿠폰 발급 테이블에 동시 수정이 가능하다는 코드 리뷰가 달렸고, 다음 날 PR에 @Version 필드가 추가됐다. 낙관적 락을 걸면 충돌 시 예외가 터지니까 안전하다 — 이론적으로는 맞다.
새벽 4시 반, 슬랙에 "DB connection pool exhausted" 알림이 쏟아졌다. DB 서버의 CPU 사용률은 15%.
readiness probe 설정할 때 "/actuator/health 쓰면 되죠?"라고 대답하는 개발자가 많다.
동시에 두 명이 포인트를 사용하면 잔액이 마이너스가 되지 않는 게 당연하다고 생각했다. 그 생각이 틀렸다는 걸 화요일 오후 CS 인입량이 알려줬다.
캐시 정리의 최적화라고 생각했다. 서비스 전체에 흩어진 @Cacheable 설정을 보니 TTL이 3분, 7분, 15분, 30분 — 제각각이었다.
새벽 2시, 슬랙 알림이 울린다. 결제 완료 후 포인트 적립이 안 됐다는 CS가 3건 들어왔다.
지난달 팀에서 Spring Boot 4로 올리면서 "Jackson 3? 패키지명만 바뀌었겠지"라고 생각했다.
재시도 로직은 백엔드 개발자의 안전장치지만, 서비스 체인에 겹겹이 쌓이면 증폭기로 돌변한다. 지난달 결제 API 장애 때 우리가 겪은 일이 정확히 이것이었고, 새벽 2시에 PagerDuty가 울렸을 때 처음 본 지표는 외부 API 오류가 아니라 우리 서버의 스레드 풀 고갈이었다.
주문 API에서 결제 게이트웨이 연동 하나 추가한 게 전부였다. 배포하고 트래픽 올라가자마자 HikariCP 커넥션 대기 큐가 쌓이기 시작했고, 30초 만에 ConnectionTimeoutException이 터졌다.
배포할 때마다 502가 몇 건씩 찍힌다. Grafana 봐도 서버 과부하가 아니고, Rolling Update가 돌 때만 나타난다.
운영 서버에 Virtual Thread를 적용한 지 이틀 만에 Slack 알림이 울렸다. Connection is not available, request timed out after 30000ms.
3일 전에 findById 하고 save 했더니 데이터가 두 줄 생긴 이야기를 썼다. 그 글을 쓰면서도 속으로 생각했다 — "이걸 왜 아직도 애플리케이션 레벨에서 해결해야 하지?
작년 겨울, 트래픽 피크 때마다 HPA가 Pod를 늘리는데 Spring Boot 앱이 뜨는 데 12초가 걸렸다. 12초면 이미 늦다.
새벽 2시, 주문 서비스 마스터 DB CPU가 97%로 치솟았다는 알림이 왔다. Replica 세 대는 15%에서 조용히 돌고 있었다.
새벽 2시에 슬랙이 울렸는데, 같은 푸시 알림이 고객한테 3번 갔다는 제보였다. 서버 3대가 각자 @Scheduled 메서드를 실행한 거다.
"Redis 앞에 Caffeine 하나 놓으면 빨라지잖아요." 코드 리뷰에서 이 말이 나오면 반은 맞고 반은 틀리다.
운영 환경에서 repository.saveAll(list)를 호출하고 슬로우 쿼리 로그를 열었더니 INSERT 문이 10,000줄 찍혀 있었다.
금요일 오후 5시, 배포 직전. "컬럼 하나만 추가하면 돼요"라는 슬랙 메시지에 고개를 끄덕였다가 프로덕션이 30분간 먹통이 된 적이 있다.