Skip to content

리트코드 스터디 학습 현황 코멘트에서 API 사용량이 업데이트되지 않음 #36

@sounmind

Description

@sounmind

문제 상황

리트코드 PR이 올라오면 learning-status 핸들러가 학습 현황 코멘트를 작성/업데이트하면서 하단에 🔢 API 사용량 (gpt-4.1-nano) 섹션을 함께 보여줍니다. 의도는 PR이 새 커밋으로 갱신될 때마다 호출 기록(#1, #2, #3 …)이 누적되어 표에 행이 추가되는 것이지만, 실제로는 항상 가장 최근 호출 1건만 표시됩니다.

예시:

  • 2번째 호출이 들어와도 표에는 #1 한 행만
  • 3번째 호출이 들어와도 표에는 #1 한 행만 (이전 댓글로 PR 승인 기능 추가 #1, #2가 사라짐)
  • 합계 행도 절대 나타나지 않음 (history.length > 1 조건이 만족된 적 없음)

원인

utils/learningComment.js에서 직전 호출 기록을 코멘트에 숨겨진 마커로 저장/파싱하는 부분에 정규식과 실제 저장 포맷의 불일치가 있습니다.

저장 (line 96): 배열을 그대로 직렬화

lines.push(`<!-- usage-data: ${JSON.stringify(history)} -->`);
// 실제 저장 결과 예시:
// <!-- usage-data: [{"prompt":1234,"completion":56}] -->

파싱 (line 16): {...} 객체 패턴만 캡처

const USAGE_DATA_RE = /<!-- usage-data: ({.*?}) -->/;

문서 주석(line 13~14)에는 {"prompt":N,"completion":N,"requests":N} 형태의 단일 객체로 저장한다고 적혀 있는데, 실제 코드는 객체 배열([{...}, {...}, ...])을 저장하고 있어 정규식이 갱신되지 않은 상태입니다.

그 결과 parseUsageFromComment에서 다음 일이 벌어집니다:

  1. 정규식이 배열 안의 첫 객체 {"prompt":..,"completion":..}만 캡처 (대괄호는 캡처 그룹 밖)
  2. JSON.parse는 단일 객체를 반환 → 배열이 아님
  3. Array.isArray(parsed) ? parsed : [] 조건이 false → 항상 [] 반환
function parseUsageFromComment(body) {
  if (!body) return [];
  const match = body.match(USAGE_DATA_RE);
  if (!match) return [];
  try {
    const parsed = JSON.parse(match[1]);
    return Array.isArray(parsed) ? parsed : [];   // ← 항상 여기서 [] 로 떨어짐
  } catch {
    return [];
  }
}

따라서 upsertLearningStatusComment에서:

const prevHistory = parseUsageFromComment(existing?.body);   // 항상 []
const history = [
  ...prevHistory,                                            // []
  { prompt: currentUsage.prompt_tokens, completion: currentUsage.completion_tokens },
];

prevHistory가 항상 비어 있어서 history에는 방금 호출한 1건만 들어갑니다. 코멘트가 PATCH로 덮어써지므로 이전 행은 영구히 사라집니다.

재현 경로

  1. 리트코드 PR을 올린다 → 학습 현황 코멘트 생성, #1 행만 표시 (정상)
  2. 같은 PR에 새 커밋을 push해서 webhook을 다시 트리거 → #1 행 1개만 표시 (이전 호출이 누적되지 않음)
  3. 같은 PR에 또 한 번 push → 여전히 #1 행 1개만 표시

영향 범위

  • utils/learningComment.jsparseUsageFromComment / USAGE_DATA_RE / formatUsageSection
  • 호출 측: handlers/learning-status.js에서 upsertLearningStatusComment(..., totalUsage) 호출 시 누적이 동작하지 않음

수정 방향 (제안)

  1. USAGE_DATA_RE를 배열 포맷에 맞게 수정. 예:
    const USAGE_DATA_RE = /<!-- usage-data: (\[.*?\]) -->/;
    또는 더 명확하게 비탐욕 매칭으로 마커 사이의 JSON을 캡처:
    const USAGE_DATA_RE = /<!-- usage-data: (.+?) -->/;
  2. line 13~14 문서 주석을 실제 저장 포맷(Array<{prompt,completion}>)에 맞춰 갱신.
  3. (선택) 기존에 잘못된 포맷으로 저장된 코멘트가 있을 수 있으므로, 파싱 실패 시 조용히 []로 떨어지는 현재 동작은 유지(자연스러운 마이그레이션).
  4. 회귀 방지를 위해 parseUsageFromComment / upsertLearningStatusComment에 누적 동작을 검증하는 단위 테스트 추가.

Metadata

Metadata

Labels

No labels
No labels

Type

Projects

Status

Done

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions