진행 기간: 2026.05–현재 Document Parser를 넘겨받았을 때는 워커별 메모리와 변환 단계별 처리 시간을 확인할 지표가 없었다. OCR 서비스도 HTTP 200 응답 안에 담긴 비즈니스 오류를 따로 집계하지 않았다. 두 서비스 모두 문제가 생긴 뒤 여러 로그를 모아 원인을 추정하는 데 시간이 들었다. 먼저 운영 상태를 확인할 지표와 요청 추적...
진행 기간: 2026.05–현재
Document Parser를 넘겨받았을 때는 워커별 메모리와 변환 단계별 처리 시간을 확인할 지표가 없었다. OCR 서비스도 HTTP 200 응답 안에 담긴 비즈니스 오류를 따로 집계하지 않았다. 두 서비스 모두 문제가 생긴 뒤 여러 로그를 모아 원인을 추정하는 데 시간이 들었다.
먼저 운영 상태를 확인할 지표와 요청 추적 정보를 만들었다. 그다음 매주 오류를 같은 원인끼리 묶고, 기존 기준으로 설명하지 못한 그룹을 다음 개선 대상으로 남기는 절차를 정리했다.
서비스마다 먼저 답해야 할 질문이 달랐다.
| 서비스 | 확인할 질문 | 추가한 정보 |
|---|---|---|
| Document Parser | 어느 워커의 RSS가 늘었는가, 어느 변환 단계가 오래 걸리는가 | 워커별 메모리와 재시작 횟수, 단계별 처리 시간 |
| OCR | HTTP 200 응답 중 실제 실패가 몇 건인가 | 오류 코드와 오류 범주별 Counter |
| 공통 | 한 요청이 어느 구간에서 실패했는가 | 서비스 사이에 이어지는 requestId |
Document Parser에는 워커별 메모리, 요청과 변환 시간, 실패 건수 메트릭을 추가했다.
여러 프로세스가 기록한 값을 하나의 /metrics에서 제공하고 Prometheus와 Grafana로 확인하도록 구성했다.
OCR 서비스에서는 공통 예외 처리기가 반환하는 비즈니스 오류 코드를 Counter로 기록했다. 발생 속도와 최근 한 시간의 건수를 분리해, 현재 증가하는 오류와 누적된 오류를 구분했다.
메트릭은 증가한 구간을 찾는 데 적합하지만 개별 요청의 원인은 설명하지 못한다.
로그에는 같은 requestId를 넣어 API 진입점, 애플리케이션과 모델 서버의 기록을 연결했다.
세부 구현과 검증은 다음 문서에 나누어 기록했다.
Document Parser 내부 로그만 조회하면 응답을 만들기 전에 연결이 끊긴 요청을 찾을 수 없었다. 이 실패는 호출자의 색인 실패 목록에만 남았다. 따라서 서비스 로그와 호출자 기록을 함께 수집했다.
두 기록은 필드와 오류 표현이 달랐다. 먼저 요청 시각, 요청 ID, 오류 코드와 예외 원인을 같은 형식으로 바꾼 뒤 그룹화했다. OCR 서비스는 로그 한 곳에서 수집하지만, 오류 코드와 요청 경로 및 최초 예외를 함께 봐야 같은 원인을 구분할 수 있었다.
재시도로 회복된 요청도 첫 시도에서는 ERROR 로그를 남길 수 있다. 이 로그를 그대로 세면 최종 실패 건수보다 큰 값이 나온다.
오류 지표는 조사할 시간대와 오류 코드를 고르는 데 사용했다. 최종 성공 여부와 재시도 결과는 요청 단위 로그에서 다시 확인했다. 로그 레벨도 집계 입력으로 사용하므로, 회복 가능한 중간 실패와 최종 실패를 같은 수준으로 기록하지 않도록 정리했다.
자동화가 끝까지 실행됐다는 사실만으로 집계 결과가 맞다고 판단할 수 없었다. 실제 주간 기록과 원본 응답을 대조하면서 다음 문제를 찾았다.
| 문제 | 결과 | 보완 방법 |
|---|---|---|
| 주 단위 전수 조회의 종료 조건이 맞지 않음 | 조회가 중간에 끝났지만 부분 집계가 정상 결과처럼 남음 | 시간 구간을 나누어 조회하고 마지막 페이지까지 확인 |
| 자동 요약이 최신 100건만 출력 | 앞쪽 날짜의 오류가 보고서에서 빠짐 | 일별 분포와 전체 건수를 원본 응답에서 다시 계산 |
| 검증 인스턴스 로그가 함께 수집됨 | 운영에 없는 오류가 운영 분포에 포함됨 | 운영 인스턴스 조건을 명시하고 제외 건수를 별도 확인 |
| 와일드카드 제외 조건을 문자열로 전달 | 필터가 적용되지 않았지만 조회는 성공함 | 반대 방향의 포함 조건으로 다시 세어 두 결과를 대조 |
2026년 8월 한 주의 자동 요약에는 사흘 동안의 100건만 보였지만 원본에는 이레 동안 190건이 있었다. 다른 조회에서는 전체 12,138건 중 검증 인스턴스 기록 671건이 포함돼 있었다. 이 대조를 거친 뒤부터는 전체 건수, 날짜 범위와 제외 건수를 결과와 함께 확인했다.
처음에는 오류 코드별 판정 기준이 자동화 설정과 사람이 읽는 운영 문서에 각각 있었다. 두 사본 중 하나만 바뀌면 같은 오류를 다음 주에 다른 원인으로 분류할 수 있었다.
판정 기준은 팀 위키 한 곳에서 관리하고 자동 분류도 실행할 때 같은 내용을 읽도록 바꿨다. 네트워크 조회에 의존한다는 비용은 생겼지만, 사람과 자동화가 서로 다른 기준을 쓰는 문제를 줄였다. 위키의 필수 항목이 빠지면 분류를 중단하도록 형식 검사도 함께 필요하다는 과제가 남았다.
기존 기준에 맞지 않는 오류를 기타 항목에 합치지 않고 별도 그룹으로 남겼다. 이 그룹을 확인하면서 다음 문제를 찾았다.
오류 건수만 집계하면 증가와 감소는 알 수 있다. 기존 기준으로 설명하지 못한 요청을 남겨야 다음에 고칠 대상을 찾을 수 있었다.
주간 오류 분류를 반복한 뒤 오류 로그 비율이 얼마나 내려갔는지는 아직 이 문서에 적혀 있지 않다.
아래 표의 기록 칸을 채워야 이 수치를 다른 글에서 인용할 수 있다.
| 항목 | 단위 | 집계 조건 | 기록 |
|---|---|---|---|
| 비교한 기간 | 주 | 시작 주와 끝 주의 날짜를 함께 적는다 | 아직 적지 않음 |
| 비교한 호출량 | 주 평균 건수 | 어느 서비스의 어떤 호출을 셌는지 적는다 | 아직 적지 않음 |
| 개선 전 오류 로그 비율 | % | 분모와 분자에 각각 무엇을 넣었는지 적는다 | 아직 적지 않음 |
| 개선 후 오류 로그 비율 | % | 개선 전과 같은 분모를 썼는지 적는다 | 아직 적지 않음 |
| 실패 요청만 세도록 바꾼 기준 | 문장 | 어떤 로그를 집계에서 빼고 어떤 로그를 남겼는지 적는다 | 아직 적지 않음 |
분모와 분자를 함께 적는 이유는, 같은 백분율이라도 전체 요청 대비인지 오류 로그 대비인지에 따라 뜻이 달라지기 때문이다.
메트릭, 로그와 호출자 기록은 서로 다른 질문에 답한다. 메트릭은 증가한 오류를 찾고, 로그는 개별 요청의 원인을 설명하며, 호출자 기록은 서비스가 응답하지 못한 실패를 보완한다.
자동 집계는 실패할 때 멈추는 경우보다 일부 데이터만 정상 결과처럼 반환하는 경우를 더 주의해야 했다. 전체 건수와 날짜 범위, 제외 조건을 다른 조회로 대조해야 집계 결과를 운영 판단에 사용할 수 있었다.