Cowork

[잡학상식] Postmortem, 포스트모템

너드나무 2024. 11. 29. 07:20
반응형

포스트모템이란?

포스트모템(Postmortem)은 라틴어로 "사후(Post) + 죽음(Mortem)"을 의미하며,
IT 및 비즈니스 분야에서는 프로젝트나 시스템에서 발생한 문제나 실패를 철저히 분석하고,
이를 통해 교훈을 얻는 프로세스를 의미합니다.

 


포스트모템의 목적

  1. 문제 원인 파악
    • 문제의 근본 원인(Root Cause)을 식별하여 같은 문제가 다시 발생하지 않도록 합니다.
  2. 지식 공유
    • 팀 전체가 문제 해결 과정과 교훈을 공유해 조직 전반의 역량을 향상시킵니다.
  3. 책임 전가 방지
    • 비난 대신 개선에 집중하며, 건설적인 문화를 조성합니다.
  4. 미래 실패 방지
    • 교훈을 반영하여 더 나은 시스템, 프로세스를 설계합니다.

포스트모템의 주요 과정

  1. 사건 기록(Event Documentation)
    1. 문제가 발생한 시점부터 종료까지의 과정을 상세히 기록합니다.
      • 사건 발생 시간
      • 주요 이벤트 타임라인
      • 관련된 시스템/서비스
      • 문제를 감지한 방법과 첫 대응 조치
  2. 원인 분석(Root Cause Analysis)
    1. 발생한 문제의 근본 원인을 찾습니다.
    2. 이를 위해 5 Whys(왜를 다섯 번 묻기), Ishikawa 다이어그램 등을 활용할 수 있습니다.
      1. 문제: 서버 다운
        • 왜? → 요청 수 증가로 서버 과부하.
        • 왜? → 부하 분산 설정이 잘못됨.
        • 왜? → 설정 변경 과정에서 테스트 미흡.
  3. 대응 평가(Response Evaluation)
    1. 문제 해결을 위해 취했던 대응 조치를 분석하고, 개선점을 찾습니다.
      • 무엇이 효과적이었는가?
      • 어떤 부분이 미흡했는가?
  4. 교훈 도출(Lessons Learned)
    1. 이 사건에서 얻을 수 있는 교훈을 명확히 정의하고, 이를 조직에 반영할 방법을 모색합니다.
  5. 액션 아이템(Action Items) 정의
    1. 미래의 실패를 방지하기 위해 필요한 구체적인 개선 작업을 정의합니다.

사례: FastAPI 응답 지연 및 500 오류 발생

  • 사건 개요
    • 발생 일시
      • 2024-11-22, 10:00 AM
    • 해결 일시
      • 2024-11-22, 11:30 AM
    • 문제 현상
      • 클라이언트가 특정 API를 호출했을 때 응답 시간이 10초 이상으로 증가.
      • 일부 요청에서 500 Internal Server Error 발생.
    • 영향 범위
      • api/v1/users/{user_id}/details 엔드포인트 사용 불가.
      • 사용자 데이터 요청의 70%가 실패
  • 타임라인
시간 이벤트
10:00 AM /api/v1/users/{user_id}/details에서 응답 지연 및 500 오류 발생 시작.
10:15 AM 장애 보고 후 긴급 대응팀 소집.
10:30 AM FastAPI 애플리케이션의 로그에서 DB 연결 문제 확인.
10:50 AM 문제 원인으로 SQLAlchemy 세션 누수 파악.
11:15 AM SQLAlchemy 세션 관리 코드 수정 및 배포.
11:30 AM 서비스 정상화 및 로그 모니터링 완료.
  • 원인 분석
    • SQLAlchemy 세션 누수
      • get_db 함수가 제대로 종료되지 않아 데이터베이스 연결이 지속적으로 열려 있었음.
      • 일정 시간이 지나면서 데이터베이스 연결이 포화 상태에 도달.
    • DB 풀 부족
      • PostgreSQL 데이터베이스 풀 크기 초과로 인해 요청 대기열이 증가.
from fastapi import APIRouter, Depends
from sqlalchemy.orm import Session
from app.database import get_db
from app.models import User

router = APIRouter()

@router.get("/users/{user_id}/details")
def get_user_details(user_id: int, db: Session = Depends(get_db)):
    user = db.query(User).filter(User.id == user_id).first()
    if not user:
        return {"error": "User not found"}
    return {"id": user.id, "name": user.name}

 

  • 대응 평가
    • get_db 함수에서 yield를 사용하여 요청이 종료되면 세션이 자동으로 닫히도록 설정.
    • 잘한 점
      • 로그를 신속히 분석하여 원인을 SQLAlchemy 세션 누수로 좁힘.
      • 문제 해결 후 즉시 배포 및 서비스 복구 성공.
    • 개선할 점
      • get_db 함수가 세션 종료를 보장하지 않음.
      • 테스트 환경에서 대규모 트래픽 시뮬레이션 부족.
      • SQLAlchemy 세션 관리 문제를 사전에 탐지하지 못함.
from fastapi import APIRouter, Depends
from sqlalchemy.orm import Session
from app.database import SessionLocal

router = APIRouter()

def get_db():
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close()

@router.get("/users/{user_id}/details")
def get_user_details(user_id: int, db: Session = Depends(get_db)):
    user = db.query(User).filter(User.id == user_id).first()
    if not user:
        return {"error": "User not found"}
    return {"id": user.id, "name": user.name}
  • 교훈
    • DB 세션 관리를 철저히 하라
      • FastAPI에서 Depends로 의존성을 주입할 때, 세션의 열고 닫는 과정을 명시적으로 관리해야 한다.
    • 로드 테스트의 중요성:
      • 실제 트래픽 수준을 시뮬레이션하여 데이터베이스 연결 문제가 발생할 가능성을 조기에 발견해야 한다.
    • 프로덕션 로그 모니터링
      • 로그를 실시간으로 모니터링하여 데이터베이스 풀 부족과 같은 징후를 빠르게 감지.
  • 액션 아이템
작업 항목 마감일 담당자
get_db 함수에 세션 종료 로직 추가. 완료 개발 팀
대규모 트래픽 로드 테스트 진행. 2024-11-25 QA 팀
데이터베이스 연결 풀 모니터링 도구 설정. 2024-11-28 DevOps 팀

 

728x90
반응형