본문 바로가기
728x90

전체 글25

PostgreSQL 인덱스 재구성 시점 — 달력이 아니라 밀도로 정한다 PostgreSQL 인덱스는 주기적으로 재구성할 필요가 없다. 공식 문서도 B-tree에 정기 재구성이 필요하다고 말하지 않는다.재구성이 값어치를 하는 건 특정 사용 패턴일 때다. 각 범위에서 대부분의 키가 지워지는데 몇 개만 남는 패턴이면 페이지가 계속 할당된 채 남아 공간이 낭비된다.그러니 달력이 아니라 측정값으로 판단한다. pgstatindex의 avg_leaf_density를 보면 지금 재구성할 값어치가 있는지 나온다.언제 재구성이 필요한가문서가 드는 경우는 넷이다.인덱스가 손상됐을 때 — 소프트웨어 버그나 하드웨어 장애로 유효한 데이터를 잃은 경우인덱스가 부풀었을 때 — 비었거나 거의 빈 페이지가 많아진 경우저장 파라미터를 바꿨을 때 — fillfactor 같은 값을 바꾸고 완전히 반영하고 싶을.. 2026. 9. 21.
차단했는데 12시간을 더 쓴다 — 세션 인증에는 무효화가 없다 계약이 끝난 점포의 계정을 전부 "사용 안 함"으로 바꿨는데, 이미 로그인해 있는 사람은 그대로 쓸 수 있었다. 세션 만료(12시간)까지 정상 사용자다.버그가 아니라 세션 인증의 성질이다. 로그인할 때 한 번 검증하고 그 뒤로는 세션이 있다는 것만으로 인증된 요청이 된다. 발급한 것을 회수하는 경로는 따로 만들어야 한다.그리고 세션을 지우려다 엉뚱한 걸 지울 뻔했다. 삭제 기준으로 잡은 속성이 "그 사람이 누구인지"가 아니었다.세션 인증에는 "무효화"가 없다로그인 시점에 계정을 검증하고, 통과하면 세션에 사용자 정보를 담는다. 그 다음부터는 세션이 있다는 것만으로 인증된 요청이 된다.요청마다 하는 검사는 이 정도다.// 요청한 점포와 세션의 점포가 같은지if (!requestOffice.equals(se.. 2026. 9. 21.
전환 뒤에 켜진 알람들 — 새 문제가 아니라 원래 있던 것이 보인 것 새 구조로 넘긴 직후부터 오류 알림이 꾸준히 왔다. 전환 전 11일간 같은 오류가 0건이었으니 전환이 만든 것으로 보였고, 실제로 그렇게 보고 하루를 썼다.결론부터 쓰면 둘 다 전환이 만든 것이 아니라 전환이 드러낸 것이었다. 하나는 3년간 감시 밖이었던 서비스, 하나는 옛 구조에서 다른 이름으로 기록돼 아무도 안 보던 장애다.전환 전 "0건"은 정상의 근거가 아니다. 오래 조용한 것은 건강한 게 아니라 안 보이는 것일 수 있다.사건 1 — 푸시 오류: 감시가 없었을 뿐이다알림은 이렇게 왔다com.google.firebase.messaging.FirebaseMessaging$3 - https://fcm.googleapis.com/...서비스명 자리에 클래스명이 있고, 오류 자리에 URL만 있다. 상태코드.. 2026. 9. 21.
CloudFront 캐시 무효화 비용 — 파일 수가 아니라 경로 수로 센다 CloudFront 캐시 무효화 요금은 지운 파일 수가 아니라 요청한 경로 수로 매긴다. /* 하나로 수천 개를 지워도 1건이고, 파일 100개를 하나씩 적으면 100건이다.매달 무료 1,000건이 있는데, 이건 배포(distribution)마다가 아니라 계정 전체 합산이다. 배포가 여럿이면 생각보다 빨리 넘는다.그리고 경로 대신 태그로 무효화하는 기능이 생겼다. 태그 하나도 경로 1건으로 센다.과금 단위는 "경로"다AWS 문서가 과금 규칙을 이렇게 정리한다.한 달에 처음 1,000개 경로는 무료이고, 넘는 경로마다 요금이 붙는다경로는 파일 하나(/images/logo.jpg)일 수도, 여러 파일(/images/*)일 수도 있다*가 들어간 경로는 수천 개를 지워도 1건이다요청 하나에 경로를 여러 개 묶어.. 2026. 9. 18.
메서드 이름이 트랜잭션을 결정한다 — Spring AOP 일괄 트랜잭션의 함정 AOP로 트랜잭션을 일괄 적용하는 Spring 프로젝트라 @Transactional이 거의 없다. 적용 기준이 클래스 이름이 Impl로 끝나고 메서드 이름이 insert·update·delete·callSP로 시작하는가다.savePayment라고 이름을 지으면 트랜잭션이 안 걸린다. 에러도 안 나고 단일 INSERT면 테스트도 통과한다.차이는 여러 테이블을 쓰다가 예외가 났을 때만 드러난다. 앞의 것은 커밋되고 뒤에서 죽어, 원장에 반쪽짜리 데이터가 남는다.구조AOP 설정이 이렇다.// 대상: com.example.app..*Impl.*(..)// 메서드명이 insert*, update*, delete*, callSP* 로 시작하면 쓰기 트랜잭션// 어떤 Exception 이든 롤백처음 보면 깔끔하다. .. 2026. 9. 17.
튜닝하다 조건을 떨어뜨렸다 — 쿼리를 고치면 결과부터 대조한다 쿼리 튜닝을 하다가 조건을 떨어뜨렸다. VIP 대상자가 7천 명으로 나왔고, 에러는 하나도 없었다. 석 달 동안 아무도 몰랐다.성능 튜닝의 진짜 위험은 느려지는 게 아니라 답이 조용히 달라지는 것이다. 빨라진 건 눈에 보이고 답이 달라진 건 안 보인다.그래서 규칙을 하나 만들었다. 쿼리를 고치면 성능이 아니라 결과부터 대조한다.점포에서 온 문의회원 등급 설정에서 신규 VIP 대상이 7천 명으로 나오는데 이게 맞나요?그 점포 전체 회원이 그 정도 규모다. 거의 전원이 VIP 대상이라는 뜻이다. 누가 봐도 이상한데, 화면은 아무 에러 없이 그 숫자를 보여주고 있었다.조건이 사라져 있었다대상자를 세는 쿼리는 이런 모양이다. 회원별 누적 결제금액을 구하고, 설정한 금액 이상인 사람만 센다.SELECT COUNT.. 2026. 9. 16.
728x90