Skip to content

AI 호출 로그 보존 정리 + 중복 인덱스 제거 - #225

Merged
i3months merged 2 commits into
devfrom
feat/ai-log-retention
Aug 24, 2026
Merged

AI 호출 로그 보존 정리 + 중복 인덱스 제거#225
i3months merged 2 commits into
devfrom
feat/ai-log-retention

Conversation

@i3months

Copy link
Copy Markdown
Member

인덱스 전수 조사 결과

#224 에서 쓴 렌즈 — "인덱스는 있는데 그 컬럼으로 조회하는 코드가 없다" = 의도했으나 미구현의 흔적 — 으로 마이그레이션의 인덱스 33개를 전부 훑었다.

발견 판단
ai_request_logscreated_at 계열 인덱스 3개, 조회도 정리도 없음 이번 PR
idx_user_consents_user_id — 복합 인덱스의 leftmost prefix 로 완전 중복 이번 PR
activity_logs — 테이블·엔티티·리포지토리만 있고 읽기·쓰기 0건 (인덱스 3개도 유휴) 계획된 기능(US-31) → 문서에 미구현 명시만
idx_refresh_tokens_expires_at #224 로 이미 사용하게 됨 (그 인덱스가 #224 가 원래 의도였다는 증거이기도)
idx_resumes_status · idx_repositories_status · idx_analyzed_documents_analysis_status 값은 쓰지만 그 컬럼으로 조회하지 않는 투기적 인덱스. 이 규모에선 비용이 무시할 만해 그대로 둠

1. ai_request_logs 보존 정리

이 코드베이스에서 가장 빨리 자라는 테이블이다. LLM 호출마다 한 행인데:

  • 피드백 한 번 = 패널(직군 수+2) + 첫인상 + 직무적합 + 인성 + 답변 수만큼의 코칭 ≈ 10여 건
  • TTS 는 문장마다 한 건
  • 질문 풀·꼬리질문·분석 4종도 각각

created_at DESC · request_type + created_at DESC · user_id + created_at DESC — 시간 범위 집계를 전제한 인덱스가 3개나 있는데 조회하는 코드도 정리하는 코드도 없다. AiRequestLogService 에는 record() 뿐이다.

보존 90일로 넉넉히 잡은 이유

이 테이블은 성격이 다르다. processed_messages(#224)의 보존 기간은 멱등성 보장 기간 이라 짧으면 동작이 깨진다. 반면 ai_request_logs 는 지운다고 깨지는 건 없고, 가치는 비용 추이다 — 짧게 잡으면 "지난 학기 대비 토큰이 얼마나 늘었나" 에 답할 수 없게 된다.

한 학기를 덮는 값으로 시작하고 환경변수로 조절한다.

2. 중복 인덱스 제거

idx_user_consents_user_type (user_id, consent_type) 이 이미 있어서 idx_user_consents_user_idleftmost prefix 로 완전히 커버된다. 실제 쿼리 두 개(findByUser_IdOrderByIdDesc, findFirstByUser_IdAndConsentType...) 모두 복합 인덱스로 처리된다.

조회에 보탬이 없고 쓰기마다 갱신 비용만 더한다.

테스트

실제 Postgres — 보존 기한이 지난 것만 지우는지. "보존 기간 안의 로그는 남는다" 쪽이 본체다(비용 추이의 근거이므로).

검증 한계

로컬 Docker 데몬이 여전히 응답하지 않아 DB 테스트는 CI 로 검증한다. 컴파일은 로컬 통과.

문서

  • docs/observability.md §8.1 신설 — 로그 테이블별 보존 정책 표 + 보존 기간의 성격이 테이블마다 다르다는 점 명시
  • activity_logs 미구현을 같은 자리에 기록 (구현 시 보존 정책을 함께 정하도록)
  • docs/environment.md 신규 변수 2개

#224 에서 쓴 렌즈("인덱스는 있는데 그 컬럼을 쓰는 코드가 없다")로 전체 인덱스를
훑은 결과다.

ai_request_logs 는 LLM 호출마다 한 행이라 이 코드베이스에서 가장 빨리 자라는
테이블이다 — 피드백 한 번에 10여 건(패널·첫인상·직무적합·인성·답변별 코칭),
TTS 는 문장마다. created_at 계열 인덱스가 3개나 있는데 조회하는 코드도,
정리하는 코드도 없었다.

보존 90일로 넉넉히 잡았다. 이 테이블의 가치는 비용 추이라 멱등 레코드와 성격이
다르다 — 지운다고 동작이 깨지지는 않지만 짧게 잡으면 학기 단위 비교가 불가능해진다.

함께: idx_user_consents_user_id 는 idx_user_consents_user_type
(user_id, consent_type) 의 leftmost prefix 로 완전히 커버된다. 실제 쿼리 두 개
모두 복합 인덱스로 처리되므로 조회에 보탬 없이 쓰기 비용만 더한다.

훑는 김에 확인한 미구현: activity_logs(US-31)는 테이블·엔티티·리포지토리만 있고
읽기도 쓰기도 없다. 인덱스 3개도 함께 놀고 있다. 삭제 대상이 아니라 계획된
기능이므로 docs/observability.md 에 미구현으로 명시만 했다.
created_at 은 @CreationTimestamp + updatable=false 라 엔티티 필드를 리플렉션으로
고쳐도 DB 에 반영되지 않는다(플러시 대상에서 제외). 두 행 모두 '방금'으로 남아
보존 대상이 하나도 안 잡혔다. 실제 컬럼 값을 과거로 밀어야 보존 로직을 시험할 수 있다.
@i3months
i3months merged commit e70f7d3 into dev Aug 24, 2026
4 checks passed
@i3months
i3months deleted the feat/ai-log-retention branch August 24, 2026 04:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant