Notes.
A linear view of published notes, essays, and experiments.
보안 스캔을 사용자 응답 경로에서 분리한 이유
외부 도구 호출 응답의 DLP 스캔을 동기 응답 경로에서 분리하고, 실패 이벤트를 감사 추적과 재처리 대상으로 남긴 과정을 정리합니다.
토큰 검증보다 먼저 정한 Gateway 인증 경계
인증 판단을 Gateway와 Redis 세션 중심으로 옮기며 토큰 갱신, 쿠키 처리, 권한 상태 불일치를 어떻게 분리해 확인했는지 정리합니다.
unlock은 왜 락 소유자를 확인해야 하는가
소유자 검증 없는 락 해제가 임계 구역을 어떻게 무너뜨렸는지, 그리고 Redis 전체가 아니라 분산 락 경로만 Redisson으로 전환한 이유를 정리합니다.
대용량 Export는 언제 성공했다고 말할 수 있을까
ZIP 손상처럼 보이던 증상을 response lifecycle, cursor paging, lookup 재사용 기준으로 분리해 정리합니다.
인덱스를 타도 느린 쿼리는 왜 느린가
인덱스가 있다는 사실보다, 결국 몇 번의 추가 읽기와 몇 건의 재확인을 만드는지가 더 중요하다는 점을 설명합니다.
동시성 문제를 격리 수준 하나로 설명하지 않기
잠금과 격리 수준을 이름으로 외우기보다, 무엇을 어떤 경로로 잠그고 어떤 읽기를 허용하는지로 보는 방법을 설명합니다.
MVCC에서 잠금 없는 읽기가 보는 것
undo log, read view, current read를 기준으로 MVCC가 왜 잠금 없는 읽기를 가능하게 하는지 설명합니다.
EXPLAIN이 말하지 않는 InnoDB의 실제 비용
MySQL 엔진과 InnoDB가 어디서 역할을 나누고, handler와 클러스터링 구조가 왜 실행 계획의 감각을 바꾸는지 설명합니다.
알림 누락을 추적 가능한 작업으로 바꾼 Outbox 설계
사용자 제보와 운영 로그로 확인한 푸시 알림 누락을 Outbox와 Redis Streams로 추적·재처리 가능한 작업으로 다시 정리한 과정입니다.
JPA saveAll이 batch insert가 아닐 때
JPA batch insert가 기대한 만큼 묶이지 않았던 원인을 따라가며, 실제로 어디에서 성능이 새는지 다룹니다.
롤링 배포에서 한 서버를 남겨둔 이유
병렬 배포가 만들던 다운타임과 운영 복잡도를 줄이기 위해, 롤링 배포와 AWX 중심으로 배포 구조를 다시 정리한 과정을 다룹니다.
Timeout은 어디서 시작됐나
느린 쿼리가 커넥션 풀 포화와 timeout으로 번지는 흐름을 k6, HikariCP, MySQL 지표로 좁혀간 과정을 정리합니다.
검색 조건이 늘어날 때 JPQL 대신 QueryDSL을 쓴 이유
복잡해진 TripPlan 조회를 QueryDSL로 다시 구성하면서, 가독성과 확장성을 어떻게 회복했는지 다룹니다.
카운터 캐시는 언제 원본 데이터와 어긋나는가
팔로우 수가 실제 상태와 다르게 보이던 원인을 추적하고, 정합성을 복구하기 위해 어떤 선택을 했는지 다룹니다.
Git 병합 전략은 히스토리 정책입니다
merge, squash, rebase, fast-forward를 명령어가 아니라 팀 히스토리 정책 관점에서 비교합니다.
부분 수정에서 merge()가 위험해지는 순간
부분 업데이트에서 merge가 만드는 전체 복사 위험을 짚고, 변경 감지 방식이 왜 더 안전한지 정리합니다.
응답 지연을 볼 때 JVM 안에서 확인할 것들
자바 코드가 클래스 로딩, 메모리 영역, 실행 엔진, GC를 거쳐 실행되는 과정을 정리합니다.