전체 글
[운영] 비난 없는 포스트모템 쓰는 법: 타임라인, 원인 사슬, 액션 아이템의 품질
[운영] 비난 없는 포스트모템 쓰는 법: 타임라인, 원인 사슬, 액션 아이템의 품질장애가 복구되면 끝난 것 같지만 사실 가장 가치 있는 단계가 남아 있어요 — 같은 장애를 두 번 겪지 않게 만드는 일. 그게 포스트모템(postmortem, 장애 회고)이에요. 그런데 포스트모템은 잘못 운영하면 역효과가 나요 — "누가 잘못했나"를 찾는 자리가 되는 순간, 사람들은 정보를 숨기기 시작하고 회고는 연극이 돼요.이 글은 비난 없는(blameless) 원칙이 왜 감정이 아니라 공학인지, 포스트모템 문서의 뼈대, 그리고 액션 아이템의 품질 기준을 차례로 짚어볼게요. 운영 기본기 시리즈의 마지막 5편이에요.01. blameless: 질문을 바꾸면 답이 바뀐다같은 사고를 놓고 두 질문이 가능해요. "누가 잘못했나"의 ..
[운영] 점진적 롤아웃과 feature flag: 배포 사고의 폭발 반경 줄이기 (카나리, kill switch)
[운영] 점진적 롤아웃과 feature flag: 배포 사고의 폭발 반경 줄이기 (카나리, kill switch)장애의 가장 큰 단일 원인은 변경이고 변경의 대표가 배포예요 — 장애 대응 편의 첫 질문이 "뭐가 변했나"였던 이유죠. 그런데 배포를 안 할 수는 없어요. 그래서 운영의 관심사는 "배포에서 사고를 0으로"가 아니라 "사고가 나도 폭발 반경(blast radius)을 작게"로 옮겨가요. 이번 편은 그 두 도구 — 점진적 롤아웃과 feature flag — 를 차례로 풀어요. 운영 기본기 시리즈 4편이에요.01. 카나리: 1%에서 잡으면 사고가 아니다새 버전을 전체에 한 번에 내보내는 빅뱅 배포는, 문제가 있으면 전원이 겪고 전원의 비명으로 발견돼요. 카나리(canary) 배포는 순서를 바꿔요 —..
[운영] 운영 DB 데이터 보정 규율: 수동 UPDATE 3단계와 대량 backfill 안전하게 흘리기
[운영] 운영 DB 데이터 보정 규율: 수동 UPDATE 3단계와 대량 backfill 안전하게 흘리기버그로 잘못 저장된 상태값, 연동 누락으로 비어 버린 컬럼, 새 컬럼에 과거 데이터 채우기 — 운영을 하다 보면 운영 DB의 데이터를 직접 고쳐야 하는 순간이 반드시 와요. 그리고 DB 관련 사고 중 가장 뼈아픈 유형이 바로 여기서 나와요 — 장애를 고치려던 손이 더 큰 장애를 만드는 것. WHERE가 빠진 UPDATE, 한 방에 날린 수백만 행 갱신으로 인한 복제 지연 폭증 같은 것들이요.이 글은 운영 데이터에 손을 대는 두 장면 — 소량 수동 보정과 대량 backfill — 각각의 안전 규율을 나눠 살펴봐요. 운영 기본기 시리즈 3편이에요.01. 수동 UPDATE의 3단계: SELECT → 트랜잭션 ..
[운영] 알림 설계: 알림 피로(alert fatigue) 막는 3등급 체계와 좋은 알림의 조건
[운영] 알림 설계: 알림 피로(alert fatigue) 막는 3등급 체계와 좋은 알림의 조건모니터링을 처음 붙이면 누구나 같은 길을 걸어요 — "혹시 모르니" 알림을 하나씩 추가하다가, 어느 날 하루 수십 건이 울려요. 팀 전체가 알림을 읽지 않고 지우는 습관이 생겨요. 그러다 진짜 장애 알림이 그 소음에 묻히고 결국 장애를 고객 문의로 알게 돼요. 알림은 많을수록 안전한 게 아니라, 어느 선을 넘으면 많을수록 위험해져요.지난 편(장애 대응 첫 5분)이 알림이 울린 다음의 이야기였다면, 이번 편은 그 알림 자체를 설계하는 이야기예요 — 3등급 분류, 좋은 알림 한 통의 조건, 그리고 알림을 계속 건강하게 유지하는 루틴을 짚어볼게요. 운영 기본기 시리즈 2편이에요.01. 알림 피로: 많이 울릴수록 위험..
[운영] 장애 대응 첫 5분: 무엇부터 보고 어떻게 움직이나 (롤백 우선, 삼각측량, 전파)
[운영] 장애 대응 첫 5분: 무엇부터 보고 어떻게 움직이나 (롤백 우선, 삼각측량, 전파)장애 알림이 울린 직후의 5분은 이상하게 흘러가요 — 로그를 정신없이 뒤지다 10분이 지나요. 그 사이 피해는 커지고 여기저기서 "무슨 일이냐"는 메시지가 쏟아져요. 장애 대응이 어려운 건 기술이 부족해서가 아니라 그 순간의 우선순위가 평소와 정반대이기 때문이에요. 평소엔 원인을 알아야 고치지만 장애 중엔 원인을 몰라도 복구부터 해요.이 글은 첫 5분의 행동 원칙 — 복구 우선, "뭐가 변했나"라는 첫 질문, 3지표 삼각측량, 역할 분리와 전파 — 을 하나씩 풀어요. 운영 기본기 시리즈 1편이에요.01. 원칙: 원인 규명이 아니라 복구가 먼저장애 중 가장 비싼 행동이 "원인을 완전히 이해한 다음 고치기"예요. 이해..
[Java] JVM 장애 진단 입문: OOM heap dump 분석, GC 멈춤, 스레드 덤프 읽는 법
[Java] JVM 장애 진단 입문: OOM heap dump 분석, GC 멈춤, 스레드 덤프 읽는 법OutOfMemoryError로 죽어요. 간헐적으로 1초씩 멈춰요. CPU는 한가한데 응답이 없고 — JVM 레벨의 장애는 애플리케이션 로그에 안 찍혀서 막막해요.이 글은 세 증상별로 — OOM은 heap dump로 누가 메모리를 쥐었는지, 간헐 멈춤은 GC 로그로, 행(hang)은 스레드 덤프로 — 진단하는 실전 순서를 따라가요. 함정 시리즈의 마지막, 8편이에요.01. OOM, 죽기 전에 증거를 남겨라OOM 진단의 절반은 미리 깔아두는 JVM 옵션 한 줄이에요.-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/dumpsOOM으로 죽는 그 순간의 힙 전체가 파일로..
[백엔드] 웹훅 연동의 함정: 중복 수신, 순서 역전, 유실 그리고 대사(reconciliation)
[백엔드] 웹훅 연동의 함정: 중복 수신, 순서 역전, 유실 그리고 대사(reconciliation)결제사·외부 플랫폼 연동의 절반은 웹훅 받기예요. "이벤트가 오면 처리한다" — 단순해 보이는데, 막상 운영하면 같은 웹훅이 두 번 와요. 취소가 승인보다 먼저 와요. 와야 할 게 안 와요. 웹훅은 친절한 알림이지 신뢰할 수 있는 전달 채널이 아니거든요.이 글은 웹훅의 3대 불확실성(중복·순서 역전·유실), 수신 처리의 정석(빠른 ACK + 멱등 처리), 그리고 돈이 걸린 연동의 필수 장치인 대사(reconciliation)까지 짚어볼게요. 함정 시리즈 7편이에요.01. 웹훅을 믿으면 안 되는 세 가지 이유중복 — 상대도 그 비대칭을 똑같이 겪어요. 내가 200을 줬는데 그 응답이 유실되면, 상대는 "전달..
[Java] HTTP 클라이언트 함정: 타임아웃 기본값, 커넥션 풀, keep-alive, DNS 캐싱
[Java] HTTP 클라이언트 함정: 타임아웃 기본값, 커넥션 풀, keep-alive, DNS 캐싱외부 API 호출 코드는 보통 "그냥 되니까" 기본값으로 둬요. 그리고 그 기본값들은 평소엔 멀쩡하다가 — 상대가 느려진 날, 트래픽이 몰린 날, 상대가 페일오버한 날 — 정확히 최악의 타이밍에 터져요. HTTP 클라이언트의 함정은 코드가 아니라 설정하지 않은 것들에 있어요.이 글은 타임아웃·커넥션 풀의 기본값 함정, 간헐적 Connection reset의 정체(죽은 keep-alive 커넥션), 그리고 의외의 복병인 JVM DNS 캐싱까지 하나씩 뜯어봐요. RestTemplate·RestClient·WebClient·Feign 어느 걸 쓰든 그 밑의 원리는 같아요. 커넥션 풀의 일반 원리는 Hikari..
[MySQL] 대형 테이블 ALTER 함정: online DDL(INSTANT·INPLACE·COPY), pt-osc와 gh-ost
[MySQL] 대형 테이블 ALTER 함정: online DDL(INSTANT·INPLACE·COPY), pt-osc와 gh-ost"컬럼 하나 추가했을 뿐인데 서비스가 30분 멈췄어요." 수천만 건짜리 테이블의 ALTER는 평범한 SQL이 아니라 잠재적 장애 작업이에요. 같은 ALTER라도 메타데이터만 바꾸는 1초짜리가 있고 테이블 전체를 복사하며 쓰기를 막는 30분짜리가 있거든요. 어느 쪽인지 모르고 실행하는 게 이 함정의 본질이에요.이 글은 MySQL online DDL의 세 알고리즘(INSTANT·INPLACE·COPY), 실행 전에 안전을 강제하는 법, 그리고 COPY가 불가피할 때의 도구(pt-online-schema-change·gh-ost)까지 정리해요. 무중단 배포 편의 expand 단계에..
[백엔드] 무중단 배포의 함정: 구버전·신버전 공존, DB 스키마 변경(expand-contract), graceful shutdown
[백엔드] 무중단 배포의 함정: 구버전·신버전 공존, DB 스키마 변경(expand-contract), graceful shutdown"배포할 때만 에러가 튀어요"는 우연이 아니에요. 무중단 배포(롤링·카나리)의 본질은 구버전과 신버전이 동시에 트래픽을 받는 구간이 반드시 존재한다는 거고 그 공존 구간의 호환성을 안 챙기면 배포가 곧 장애 트리거가 돼요. 컬럼 하나 rename했을 뿐인데 구버전 인스턴스가 줄줄이 죽는 식이죠.이 글은 공존 구간이 왜 생기는지부터, DB 스키마 변경의 정석(expand-migrate-contract), 처리 중 요청을 지키는 graceful shutdown, 그리고 배포가 만드는 부수 충격(리밸런싱·직렬화)까지 훑어볼게요. 함정 시리즈 4편이에요.01. 공존 구간, 모든 ..
[DB] 깊은 페이징 성능 문제: OFFSET이 느려지는 이유와 커서 기반 페이징(no-offset)
[DB] 깊은 페이징 성능 문제: OFFSET이 느려지는 이유와 커서 기반 페이징(no-offset)목록 API가 1페이지에선 1ms인데 뒤로 갈수록 느려지다, 관리자가 "전체 내보내기"로 수만 페이지를 훑는 순간 DB가 비명을 질러요. LIMIT 20 OFFSET 100000의 구조적 비용이에요. OFFSET은 "건너뛰기"처럼 보이지만 실제로는 다 읽고 버리기거든요.이 글은 OFFSET이 왜 선형으로 느려지는지, 커서 기반 페이징(no-offset)의 동작과 구현 디테일(유니크 커서·인덱스 설계), 그리고 어디까지 커서로 가고 어디는 OFFSET을 둘지 가려볼게요. 인덱스 원리는 B+Tree 편 위에 서 있는 이야기예요.01. OFFSET은 점프가 아니라 "읽고 버리기"예요offset 기반 Queryd..
[Java] 타임존 버그 정리: LocalDateTime vs Instant, UTC 저장, 날짜 경계 함정
[Java] 타임존 버그 정리: LocalDateTime vs Instant, UTC 저장, 날짜 경계 함정"로컬에선 멀쩡했는데 배포하니 시간이 9시간 밀려요." 타임존 버그는 늘 이렇게 환경을 갈아탈 때, 그리고 자정 근처에서 터져요. 원인의 대부분은 하나로 모여요 — 타임존 정보가 없는 시각(LocalDateTime)을 "절대 시각"처럼 쓴 것.이 글은 LocalDateTime이 왜 위험한지부터, "UTC로 저장하고 표시할 때 변환"이라는 표준 규율, 타입 선택 기준(Instant vs ZonedDateTime vs LocalDateTime), 그리고 "오늘 매출" 집계가 어긋나는 날짜 경계 함정까지 차례로 풀어요. 함정 시리즈 2편이에요.01. LocalDateTime은 "언제"가 아니에요Local..