헬창 개발자

[postmortem] 배포 회고 본문

공부방

[postmortem] 배포 회고

찬배 2025. 11. 13. 10:29

사건 개요

지난 10월 28일, 사내 AI서비스를 제공하는 서버에 OCR 모델을 수정한 버전을 배포를 진행했다. 동료가 작업한걸 이제 내가 배포만 하면되는 상황이였는데, 깃액션을 통해 배포를 진행하는 과정에서 테스트는 실행되지 않고, PDF 생성은 실패, API 키도 인식되지 않았다.

 

 


원인이 무엇일까 고민하면서 과거에 있던 커밋을 보는 순간 아차차 했다.

 

 

내가 커밋을 하고 코드 검증을 안한것이다. 결과적으로 로컬 테스트만 돌린 체 머지를 진행했다.


타임라인 (Timeline)

근본 원인

1. 의존성 관리 자동화 미비

내가 컷밋한 업데이트 내용에서는 테스트 과정을 추가했는데 그때 추가한 모듈이 있다. reportlab라는 모듈인데 PDF를 생성해주는 모듈이다. 이걸 로컬에서 설치하고 만족했지만, CI에서는 필수 라이브러리가 누락됐다.
의존성 파일에는 reportlab이 없으니 PDF 생성은 당연히 실패… 로컬에서 ‘돌아가네’ 하고 안일하게 생각한 게 화근이었다.

# 잘못된 방식
uv pip install reportlab

# 올바른 방식
uv add reportlab
uv pip compile pyproject.toml -o requirements.lock

uv pip install 명령 수행 후 의존성 추가를 안함

결과적으로 requirements.lock에 reportlab 미반영

 

 

기존 uv를 이용한 가성환경에서는 uv pip install 이라는 명령어를 이용해서 모듈을 추가했지만, 해당 명령어는 requirements 와 pyproject.toml에는 자동으로 반영이 안된다. 그래서 uv add명령어를 이용해서 모듈을 추가하면 자동으로 의존성을 추가해줘서 관리가 용이하다는 점이 있다.

 

2. CI 환경 설정 불일치

 

의존성을 처리했으니까 이제 통과하겠지?? 라고 생각을 했지만, 다음 오류에 부딪였다.

 

401 unauthorized 라고??? 분명 API키를 생성해서 옵션으로 넘겨주는 테스트는 성공했는데??

로그에는 Issue Test API Key가 성공이 되어있지만, 아무리봐도 키가 제대로 넘어가질 않아 인증 실패가 나오는것 같다. 그래서 codecheck.yml 파일을 확인을 해봤다.

 

      - name: Issue Test API Key
        id: issue_key
        env:
          PYTHONPATH: src:.
        run: |
          API_KEY=$(.venv/bin/python tests/scripts/issue_test_api_key.py | grep '^sk-')
          echo "api_key=$API_KEY" >> $GITHUB_OUTPUT
      - name: Run OCR tests
        env:
          PYTHONPATH: src:.
          USER_API_TEST_KEY: ${{ secrets.USER_API_TEST_KEY}}
        run: .venv/bin/pytest -v -s tests/test_api.py

해당 부분을 설명하자면
1️⃣ issue_test_api_key.py 실행 → 테스트용 API 키(sk-...) 발급
2️⃣ 발급된 키를 GITHUB_OUTPUT에 저장해 다음 단계에서 사용 가능하게 함
3️⃣ 이후 단계에서 pytest로 OCR API 테스트 실행 (USER_API_TEST_KEY를 환경변수로 주입)

 

이런 플로우다. 지금 API Key가 생성은 되었지만, 환경변수 값으로 제대로 넘어가질 않는것 같아서 아에 깃 시크릿 변수로 할당을 하여 변수명을 다음 처럼 수정해주었다.

 

 

3. 코드 검증 프로세스 부재

다음은 어처구나 없는 오류였다. llm_summation.py 151~152행에서 문자열 닫는 따옴표(") 누락으로 문법 오류 발생.

Ruff 검사 실패(exit code 1)로 워크플로우가 실패 처리됨.

 

아차차..

 

 

따옴표(") 를 붙어주었다.

 

4. 테스트 경로 설정 문제

 

CI 테스트가 스테이징 도커 환경의 고정 포트에 연결되도록 작성되어 있었으나, 실제 배포된 컨테이너 포트와 불일치하여 테스트 실패가 발생했다. 테스트 스크립트의 하드코딩된 포트를 환경변수 기반으로 수정했다.


영향 및 피해 평가

이번 이슈는 실서비스 장애로 이어지진 않았지만, 배포 과정의 신뢰성이 크게 떨어졌다. 테스트 자동화가 실패하면서 배포 완료 여부를 신뢰할 수 없었고, 결국 수동 확인과 재배포가 필요했다.

그 과정에서 약 2시간의 추가 인력 투입이 발생했으며, 테스트 프로세스 자동화의 중요성을 다시 한번 실감하게 되었다.

 

항목영향  범위상세  내용
기능 동작 중간 영향 PDF 생성 기능 실패 (reportlab 누락으로 인한 ImportError)
배포 신뢰성 중간 영향 CI 환경에서 테스트 미실행으로 검증 부재
운영 중단 없음 서비스 장애는 없음
개발 효율성 높음 배포 후 수동 검증 및 재배포로 약 2시간 소요

즉시 조치 사항

이슈를 인지한 후, 바로 원인별로 빠르게 대응을 진행했다. 의존성은 uv add 방식으로 재정비했고, 환경 변수는 GitHub Secrets로 일원화하여 전달 오류를 방지했다.
또한 코드 검증 프로세스가 자동화되도록 린트 및 포트 설정을 정리했다.
결과적으로 17:30경, 모든 테스트가 정상적으로 통과되며 안정화되었다.


재발 방지를 위한 조치 항목

의존성 자동화 uv add 시 uv pip compile 자동 실행하도록 pre-commit hook 추가
환경변수 관리 .env.example 기준으로 CI 환경 검증
코드 검증 프로세스 강화 모든 PR에 린트 + 테스트 자동 실행 적용
체크리스트화 PR 템플릿에 “CI 테스트 통과 여부” 명시 항목 추가

배운점

드디어 통과된 테스트

 

“로컬에서 된다”는 건 검증이 아니다.

테스트는 반드시 CI 환경에서 실행된 결과로 검증되어야 한다.
의존성과 환경 변수는 항상 자동화된 방식으로 관리되어야 한다.
자동화의 부재는 실수의 반복을 부르고,
검증 없는 배포는 결국 ‘운에 맡긴 배포’에 불과하다는 사실을 체감했다.

 

참고문서

[1] https://github.com/astral-sh/uv