LearningCollector: 이전 실행 실패 항목 재시도를 통한 안정성 향상
이번 커밋은 이전 실행에서 'draft_created' 상태가 False로 실패했던 항목들을 다음 실행에서 자동으로 재시도할 수 있도록 `core/orchestrator.py` 파일을 수정했습니다. 이 변경을 통해 데이터 수집 및 처리 과정의 안정성이 향상되었으며, 놓치는 데이터 없이 꾸준히 수집하고 처리할 수 있게 되었습니다.
LearningCollector: 이전 실행 실패 항목 재시도를 통한 안정성 향상
이번 커밋은 이전 실행에서 'draft_created' 상태가 False로 실패했던 항목들을 다음 실행에서 자동으로 재시도할 수 있도록 core/orchestrator.py 파일을 수정했습니다. 이 변경을 통해 데이터 수집 및 처리 과정의 안정성이 향상되었으며, 놓치는 데이터 없이 꾸준히 수집하고 처리할 수 있게 되었습니다.
요약
이번 작업은 core/orchestrator.py 파일의 run() 함수에 _merge_pending() 단계를 추가하는 것을 중심으로 진행되었습니다. 이 새로운 단계는 json_saver.get_pending_jsons() 함수를 호출하여 이전 실행에서 초안 생성에 실패한 항목들을 가져옵니다. 그리고 이번 실행에서 새로 수집된 항목들과 병합하여, 실패했던 항목들도 다음 실행에서 다시 처리될 수 있도록 보장합니다. 이를 통해 run() 함수의 총 처리 항목 수를 계산하는 로직도 수정하여, 실제 처리될 항목 수를 정확히 반영하도록 변경했습니다. 총 37줄의 코드가 추가되었고 4줄의 코드가 삭제되었습니다.
배경 및 목적
소프트웨어 개발 과정에서 예상치 못한 오류나 외부 요인으로 인해 작업이 실패하는 경우는 빈번하게 발생합니다. 특히 데이터 수집 및 처리와 같이 여러 단계를 거치는 파이프라인에서는, 특정 단계에서 실패하더라도 전체 작업이 중단되지 않고 실패한 부분만 재시도할 수 있는 메커니즘이 중요합니다. 기존에는 draft_created 상태가 False로 기록된 항목에 대한 별도의 재시도 로직이 없어, 이런 항목들은 영구적으로 누락될 가능성이 있었습니다.
이 작업의 목적은 다음과 같습니다.
- 안정성 향상: 이전 실행에서 발생한 'draft_created' 실패 항목들을 다음 실행에서 자동으로 재시도하여 데이터 누락을 방지합니다.
- 견고한 파이프라인 구축: 예외 상황에서도 데이터 처리 흐름이 끊기지 않고 지속될 수 있도록 파이프라인을 더욱 견고하게 만듭니다.
- 효율적인 리소스 활용: 실패한 항목들을 효과적으로 관리하고 재시도함으로써, 반복적인 수동 개입을 줄이고 리소스 활용도를 높입니다.
구현 내용
core/orchestrator.py 파일의 run() 함수와 관련하여 다음과 같은 변경이 이루어졌습니다.
주요 변경사항 상세 설명
run()함수의 흐름 변경:run()함수 내에서 데이터 수집(_collect_all) 이후, 실제 수집 결과를 처리하기 전에_merge_pending()함수를 호출하도록 순서를 조정했습니다._merge_pending()함수 추가: 이 함수는self.json_saver.get_pending_jsons()를 통해 이전 실행에서 'no_draft'로 분류된 항목들을 가져옵니다. 가져온 항목들을 현재 수집된ai_chat_jsons,baekjoon_jsons,commit_jsons리스트에 중복되지 않도록 추가합니다.- 총 처리 항목 수 로직 수정:
total_new변수명을total로 변경하고,_merge_pending()함수를 통해 병합된 항목 수를 정확히 반영하도록 수정했습니다. 이를 통해 "새로 수집된 데이터가 없습니다"라는 메시지 대신 "처리할 데이터가 없습니다"와 같이 보다 포괄적인 메시지를 출력하도록 변경했습니다.
변경된 파일 목록
core/orchestrator.py
추가/삭제된 코드 라인 수
- 추가: 37 라인
- 삭제: 4 라인
핵심 코드 설명
# ... (이전 코드) ...
# 2. 수집 결과 요약 및 처리
- total_new = len(ai_chat_jsons) + len(baekjoon_jsons) + len(commit_jsons)
-
- if total_new == 0:
+ # 2. 이전 실행에서 실패한 pending 항목 병합
+ ai_chat_jsons, baekjoon_jsons, commit_jsons = self._merge_pending(
+ ai_chat_jsons, baekjoon_jsons, commit_jsons
+ )
+
+ # 3. 수집 결과 요약 및 처리
+ total = len(ai_chat_jsons) + len(baekjoon_jsons) + len(commit_jsons)
+
+ if total == 0:
print("\n" + "=" * 50)
print("📊 수집 결과")
print("=" * 50)
- print(" 새로 수집된 데이터가 없습니다.")
+ print(" 처리할 데이터가 없습니다.")
else:
if self.auto:
self._auto_process(ai_chat_jsons, baekjoon_jsons, commit_jsons)
# ... (이후 코드) ...
+ def _merge_pending(self, ai_chat_jsons, baekjoon_jsons, commit_jsons):
+ """이전 실행에서 초안 생성 실패한 pending 항목을 병합"""
+ pending = self.json_saver.get_pending_jsons()
+ no_draft = pending["no_draft"] # [(subdir, filename), ...]
+
+ if not no_draft:
+ return ai_chat_jsons, baekjoon_jsons, commit_jsons
+
+ # 이번에 새로 수집된 파일명 (중복 방지)
+ new_set = set(ai_chat_jsons + baekjoon_jsons + commit_jsons)
+
+ pending_count = 0
+ for subdir, filename in no_draft:
+ if filename in new_set:
+ continue
+ pending_count += 1
+ if subdir == "ai_chat":
+ ai_chat_jsons.append(filename)
+ elif subdir == "baekjoon":
+ baekjoon_jsons.append(filename)
+ elif subdir == "commits":
+ commit_jsons.append(filename)
+
+ if pending_count > 0:
+ print(f"\n 📋 이전 실행에서 미처리된 항목 {pending_count}개 발견 (재시도 대상)")
+
+ return ai_chat_jsons, baekjoon_jsons, commit_jsons
위 코드 조각에서 볼 수 있듯이, _merge_pending 함수는 pending 데이터에서 no_draft 리스트를 순회하며 각 파일명을 new_set과 비교하여 중복을 피합니다. 만약 중복되지 않는다면 해당 파일명을 적절한 리스트(ai_chat_jsons, baekjoon_jsons, commit_jsons)에 추가합니다. 또한, 재시도 대상 항목이 발견되면 사용자에게 알림 메시지를 출력합니다.
기술적 의사결정
이번 작업에서 특별히 새로운 라이브러리나 프레임워크를 도입하지는 않았습니다. 기존에 구현되어 있던 json_saver의 get_pending_jsons() 함수를 활용하는 것이 가장 효율적이고 자연스러운 방법이라고 판단했습니다.
- 기술/라이브러리 선택: 기존
json_saver모듈 및 해당 모듈의get_pending_jsons()메서드 활용. - 선택 이유:
- 기존 코드 활용: 이미 구현되어 있고 테스트된 기능을 재사용함으로써 개발 시간과 노력을 절감할 수 있습니다.
- 데이터 일관성:
json_saver는 파일 시스템과 직접 상호작용하며 데이터를 저장하고 관리하므로,draft_created상태와 같은 메타데이터를 가장 정확하게 파악하고 제공할 수 있습니다. - 모듈화:
json_saver는 데이터 관리의 책임을 명확히 분리하고 있으므로, 이 기능을 활용하는 것이 코드의 모듈성을 유지하는 데 도움이 됩니다.
- 다른 대안:
- 새로운 데이터 저장소 사용: 예를 들어, 데이터베이스나 별도의 상태 관리 파일을 사용할 수 있습니다.
- 인메모리 상태 관리: 프로그램 실행 중에만 상태를 유지하는 방식입니다.
- 대안과의 비교 및 장단점:
- 새로운 데이터 저장소: 장점은 강력한 데이터 관리 기능과 확장성을 제공할 수 있다는 것입니다. 하지만 이는 새로운 인프라 구축 및 관리 부담이 따르며, 기존
json_saver의 기능과 중복될 수 있습니다. - 인메모리 상태 관리: 장점은 구현이 간단하다는 것입니다. 하지만 프로그램이 종료되면 상태 정보가 사라지므로, 재시도 로직에는 부적합합니다.
따라서 기존json_saver를 활용하는 것이 현재 프로젝트의 구조와 목적에 가장 부합하는 최적의 선택이라고 결론 내렸습니다.
- 새로운 데이터 저장소: 장점은 강력한 데이터 관리 기능과 확장성을 제공할 수 있다는 것입니다. 하지만 이는 새로운 인프라 구축 및 관리 부담이 따르며, 기존
배운 점 및 개선점
이번 작업을 통해 이전 실행에서 실패했던 항목들을 어떻게 효과적으로 재시도할 수 있는지에 대한 좋은 경험을 얻었습니다. 특히, draft_created와 같은 상태 정보를 활용하여 파이프라인의 복원력을 높이는 것의 중요성을 다시 한번 깨달았습니다.
배운 점
- 프로세스 실패 시 재시도 메커니즘의 중요성
- 기존에 잘 설계된 모듈의 기능을 적극적으로 활용하는 방법
_merge_pending과 같이 특정 로직을 별도의 함수로 분리하는 코드 구조의 유용성
앞으로 개선할 점
_merge_pending함수에서pending_count를 로깅하는 것 외에, 재시도되는 항목들의 구체적인 파일명을 기록하여 추후 디버깅에 활용할 수 있도록 개선할 수 있습니다.get_pending_jsons()에서 반환되는no_draft항목에 대한 최대 재시도 횟수를 제한하여, 무한 루프에 빠지는 것을 방지하는 로직을 추가할 수 있습니다.json_saver의get_pending_jsons()함수가 더 명확하고 일관된 방식으로 실패 정보를 반환하도록 개선될 여지가 있는지 검토할 수 있습니다.
다음 단계 계획
- 테스트 강화:
_merge_pending함수가 다양한 시나리오(예: 아무런 실패 항목이 없을 때, 여러 항목이 실패했을 때, 새로 수집된 항목과 겹칠 때)에서 올바르게 작동하는지 자동화된 테스트 케이스를 작성하여 검증합니다. - 모니터링 및 알림: 재시도 로직이 제대로 작동하고 있는지, 혹은 재시도에도 불구하고 실패가 반복되는 항목이 있는지 지속적으로 모니터링하는 시스템을 구축합니다.
- 문서화:
_merge_pending함수의 역할과 작동 방식에 대한 설명을 코드 내 주석이나 별도의 문서에 추가하여, 다른 개발자들이 쉽게 이해하고 활용할 수 있도록 합니다.
참고 자료
claude.ai/code/session_011gagwizSUXWiCxmjL8HWZq(주어진 커밋 메시지 내 참고 링크)