부하 격리 · 설정 드리프트 · 백업과 복구
DocSuri
AI/ML 논문을 수집·구조화·임베딩·색인하는 파이프라인을 만들고 운영했습니다. 대량 백필로 발생한 검색 503 장애를 복구하고, 사용자 열람용 문서를 생성하는 큐와 워커를 분리했습니다.
문제
DocSuri는 AI/ML 논문을 탐색하고 원문에 근거한 한국어 요약을 제공하는 서비스입니다. 제가 맡은 수집 데이터는 검색, 문서 열람, 요약에 사용됩니다. 출처가 다른 논문의 중복과 버전, 철회를 처리하면서, 과거 데이터를 대량으로 채우는 백필이 사용자 응답을 방해하지 않도록 해야 했습니다.
백필이 검색에 미친 영향
2026년 7월 AWS 운영 중 대량의 arXiv 백필이 OpenSearch 조회를 늦추면서 k-NN 검색이 2초 제한을 넘겨 타임아웃 503 오류를 반환했습니다. 사용자 열람용 문서 생성 작업도 약 3.3만 건의 백필 뒤에서 대기했습니다. 각 프로세스가 요청 한도를 지켜도 워커를 3개 실행하면 전체 요청량은 늘어난다는 점을 확인했습니다.
역할
AWS AI School 2기 4인 팀의 데이터 엔지니어로서 논문 코퍼스의 수집·구조화·임베딩·색인 파이프라인과 인프라 운영, 후속 개선을 맡았습니다. 검색·요약·에이전트의 초기 구현과 GROBID TEI 구조 파서는 다른 팀원이 담당했습니다.
핵심 결정
수집량을 제한하고 사용자 작업을 분리
7월 1일 수집 워커를 3개에서 1개로 줄여 검색을 복구하고, 사용자 열람 문서 생성 작업에 전용 우선순위 큐를 마련했습니다. 7월 2일 별도 워커 서비스로 옮겨 실행 자원을 분리했습니다. 외부 데이터 소스의 요청 한도에 맞춰 확장 상한을 정하고, bulk 작업은 30분, 열람 문서 생성은 5분 이상 대기하면 알람이 울리게 했습니다. DLQ 재처리 절차에는 검색 지연도 함께 확인하도록 명시했습니다.
핵심 결정 자세히 보기
새 인덱스로 전환하고 되돌리는 절차
새 인덱스에 데이터를 적재한 뒤 최소 문서 수와 원본 대비 수량을 점검하고, replica와 refresh 설정 복원, alias 전환, 수집 재개를 각각 수행하도록 절차를 나눴습니다. alias에서 이전 대상을 제거하고 새 대상을 추가하는 작업은 한 요청으로 처리합니다. 벡터 차원이 바뀔 때는 읽기·쓰기 서비스가 공유하는 스펙과 실행 이미지를 함께 맞추고, 복구할 때는 이전 이미지와 alias로 되돌리도록 문서화했습니다.
재시도와 완료 상태를 구분
같은 버전 메시지가 다시 전달되는 경우와 bulk 색인의 일부 항목이 실패하는 경우를 테스트했습니다. 실패한 항목은 완료로 기록하지 않고, 재시도 메시지와 DLQ에는 출처와 실패 단계를 남겼습니다. 출처별 처리 지점인 watermark가 뒤로 이동하지 않고 서로 독립적으로 관리되는지는 속성 테스트로 확인했습니다. 인덱스 재구축 중에는 스케줄·이벤트 등록과 기존 작업 실행을 제한했습니다.
서비스 예산과 사용자별 사용량을 별도로 관리
팀이 만든 공통 비용 제어 기능을 바탕으로 에이전트가 warning과 critical 상태를 처리하는 방식을 보완하고, 실행 비용을 관측 지표에 기록했습니다. Redis 기반 사용자 쿼터를 연결해 서비스 전체 예산과 사용자별 사용량 제한을 구분했습니다.
구조
논문 수집부터 검색·열람·요약까지
arXiv, Semantic Scholar, OpenAlex에서 가져온 논문을 수집 큐에 넣고, 문서 구조화와 청크·임베딩 생성을 거쳐 OpenSearch에 색인했습니다. AWS 운영 당시에는 Python, PostgreSQL, SQS, ECS/Fargate, S3, Bedrock, CDK, CloudWatch, Redis를 사용했고, 사용자 열람용 문서 생성은 별도 큐와 워커로 처리했습니다.
구조 자세히 보기
배포 설정과 실제 동작을 대조
자산 조회에 필요한 S3 prefix 범위의 권한을 보완하고, 지표 namespace에 맞는 IAM 권한과 실제 지표 전달 여부를 대조했습니다. 기존 큐를 다시 생성하려다 충돌하는 것을 확인한 뒤 import 방식으로 가져왔으며, 기능 플래그는 보존했습니다. 커밋 태그, 서비스 안정화 상태, health 검사로 배포를 추적했고, 사용이 끝난 도메인의 기본값을 정리할 때도 재현용 테스트 데이터와 식별용 namespace는 남겼습니다.
AWS에서 로컬 서버로 운영 환경 이전
2026년 8월 AWS 운영을 종료하고, 로컬 서버의 컨테이너와 MinIO·ElasticMQ·Ollama를 사용하도록 연결을 변경했습니다. 외부 heartbeat로 호스트 장애를 관측하고, launchd의 실행 권한 때문에 백업 정리가 실패하는 문제는 manifest, 날짜 기준 보존 정책, 재시도를 통해 보완했습니다. 현재는 단일 호스트에서 운영하는 구성입니다.
결과
장애를 재현한 질의로 검색 복구 확인
7월 1일 워커를 3개에서 1개로 줄인 뒤, 장애를 재현했던 질의가 정상 응답하는 것을 확인했습니다. 다음 날 추가로 안정화하면서는 큐를 보존한 채 수집과 자동 확장을 일시 정지했고, 검색은 기능 저하 상태가 아닌 정상 결과 20건을 반환했습니다. 아래 수치는 당시 문서와 커밋에 남아 있는 관측값입니다.
실제 운영 설정과 코드의 차이 확인
별도의 작업 적체 조사에서는 약 15.3만 건이 대기하는 상황에서 코드와 템플릿의 확장 상한은 1인데 실제 설정은 0이라는 차이를 확인했습니다. 워커가 실행되지 않던 원인을 좁혀 간 기록입니다. 관측 모듈에는 중복 이벤트를 추적하는 상태의 메모리 상한과 로그의 민감 정보 가림 처리를 보완했습니다. 다만 오래된 ID를 제거한 뒤에는 같은 이벤트를 다시 받을 가능성이 남습니다.
환경별로 확인한 백업과 복구 범위
AWS 운영 당시에는 팀이 CloudWatch 이메일 수신을 확인하고, RDS snapshot을 새 인스턴스로 복원해 available 상태가 되는 것을 확인했습니다. 로컬 환경으로 옮긴 뒤에는 launchd로 백업을 실행하고 로컬과 iCloud 보관 경로에 dump 파일이 생성된 것을 확인했습니다. dump 생성 확인은 복원 시험과 다르며, AWS에서 수행한 검증도 현재 객체 저장소와 검색 인덱스를 함께 복원할 수 있다는 보장은 아닙니다.
배운 점
작업의 성공과 데이터의 활용을 각각 검증
작업이 성공했는지, 결과가 저장됐는지, 데이터 품질이 적절한지, 사용자가 실제로 활용할 수 있는지는 따로 확인해야 합니다. 재처리와 온라인 조회의 목표를 나누고, 처리량뿐 아니라 실패가 미치는 범위, 복구 방법, 데이터를 사용하는 쪽의 요구까지 함께 살피는 기준을 얻었습니다.
배운 점 자세히 보기
테스트로 확인한 범위를 넘어서 보장하지 않기
중복 전달과 부분 실패를 테스트했다고 해서 모든 동시 실행에서 exactly-once 처리나 저장소 간 원자성이 보장되는 것은 아닙니다. 인덱스 점검은 수량 부족을 감지하는 수준이며, 전환 절차 자체가 검증 실행을 강제하지도 않습니다. 재파싱은 개별 작업이 실패해도 종료 코드가 0일 수 있으므로 로그와 결과를 대조해야 합니다. 자산 저장 역시 분산 트랜잭션으로 묶여 있지는 않습니다.
아직 해결해야 할 데이터 품질과 접근 권한 문제
최신 감사에서는 코퍼스에 테스트용 데이터가 섞인 문제, 공유 캐시가 해당 원문과 정확히 연결되는지의 문제, 사용자 문서의 읽기 권한 문제가 남아 있었습니다. 일부 타입 생성 작업의 실패를 상위 단계에 전달하는 처리와 빈 결과를 degraded 상태로 표시하는 문제도 확인됐습니다. 후속 검증에서는 원본과 색인의 ID·내용 일치, 실패 건수와 종료 상태, 출처 식별과 소유권에 따른 접근 범위, 호스트 장애 이후의 복원을 확인 기준으로 삼았습니다.