본문으로 건너뛰기
JSL107's Tech Note
돌아가기

사람의 반박을 학습하는 PR 리뷰봇의 피드백 루프

8분 분량이 글 고치기
목차 · 7

PR 리뷰봇이 사람의 반박을 학습하려면 답글만 저장해서는 부족해요. 사람의 판단이 올바른 권한 경계를 거쳐 다음 리뷰로 이어지고, 실제 행동이 어떻게 달라졌는지까지 관측할 수 있어야 해요.

문제: 학습하고 있었지만 효과를 설명할 수 없었다

PR 리뷰봇이 PR에 지적을 남기고 사람이 “이 저장소에서는 정상적인 구현이다”라고 반박하면, 그 이유를 저장소 규약으로 정리해 다음 리뷰 프롬프트에 포함해요. 과거 리뷰 사례를 단순히 검색하는 방식이 아니라 사람의 판단을 해당 저장소의 규칙으로 반영하는 구조예요.

문제는 이 학습 루프의 입구와 관측 지점이 제대로 연결돼 있지 않았다는 점이에요.

먼저 사람이 작성한 반박 원문이 보존되지 않았어요. 👍이나 👎 없이 답글만 달리면 LLM이 내용을 판정하는 경로를 거쳤는데, 이 과정에서 사람이 쓴 답글 대신 판정기가 만든 한 줄 요약을 저장했어요. 실제로 수백 자에 이르던 반박이 원장에는 매우 짧은 문장으로 남았어요.

이렇게 짧아진 데이터는 규약을 만드는 단계에서 다시 길이 하한에 걸렸어요. 확인된 일부 카드는 이 조건 때문에 저장소 규약에서 통째로 빠졌어요. 리뷰봇은 사람의 반박을 학습하도록 설계됐지만, 정작 가장 중요한 원문은 학습 입력까지 도달하지 못한 셈이에요.

원문이 남더라도 또 다른 손실이 있었어요. 반박 답글을 고정된 길이로 잘라 저장했기 때문에 결론이 사라질 수 있었어요. 사람은 보통 설명 앞부분에 사례를 나열하고 뒷부분에 판단 기준을 적어요. 앞에서부터 정해진 길이만 남기면 사례는 보존되지만, “이 저장소에서는 무엇을 허용하는가”라는 규칙은 잘려 나가요.

학습 효과를 보여주는 채택률도 전체 기간과 모든 저장소의 결과를 한데 합산했어요. 저장소 규약은 특정 저장소의 리뷰에만 적용되는데, 성적표에는 규약이 없는 다른 저장소의 결과까지 들어갔어요. 누적 수치는 볼 수 있었지만 규약을 적용한 뒤 해당 저장소의 지적이 실제로 개선됐는지는 파악하기 어려웠어요.

리뷰 결과가 깨끗하면 관측하기가 더 어려웠어요. 지적이 없을 때도 리뷰 실행은 내부 원장에 성공으로 기록됐지만, 코드 호스팅 서비스의 PR에는 아무 흔적도 남지 않았어요. 사용자 화면에서는 “검토했지만 문제가 없었던 상태”와 “아직 리뷰가 실행되지 않은 상태”가 똑같아 보였어요.

사람의 답글을 학습 데이터의 원본으로 보존했다

첫 번째로 LLM은 답글의 의미만 판정하고, 저장하는 기각 이유에는 사람이 작성한 원문을 남기도록 바꿨어요. 판정기의 짧은 요약 때문에 데이터가 길이 하한 아래로 떨어지는 일을 막고, 다음 리뷰에 전달할 저장소 규약도 실제 사람의 설명을 근거로 만들게 했어요.

고정된 길이로 자르던 방식도 함께 손봤어요. 반박의 앞부분만 기계적으로 남기면 결론이 사라질 수 있으므로, 사례뿐 아니라 뒤쪽의 판단 기준도 보존하도록 했어요. 피드백 데이터에서는 길이 제한 자체보다 어느 부분을 보존하느냐가 더 중요하다고 판단했어요.

이 변경을 적용하면서 권한 경계도 다시 확인했어요. 기존에는 저장소 소유자뿐 아니라 PR 작성자도 기각 이유를 남길 수 있었어요. 공개 저장소에서는 제3자가 자신의 답글을 저장소 규약으로 굳힐 가능성이 있었어요. 이전에는 LLM 요약이 지나치게 짧아 길이 하한에서 탈락하는 바람에 이 경로가 우연히 드러나지 않았어요. 하지만 원문을 보존하면 실제로 열릴 수 있는 경로였기 때문에, 데이터 손실을 고치는 과정에서 숨어 있던 규약 생성 권한 문제까지 함께 다뤄야 했어요.

소비되지 않는 학습 경로를 제거했다

리뷰봇은 과거에 사람이 기각한 지적을 두 곳에 저장했어요. 하나는 정리된 리뷰 지적 원장이었고, 다른 하나는 의미 검색에 쓰는 사례 저장소의 PR 리뷰 유형 데이터였어요.

학습 방식이 “과거 사례를 의미 검색해 프롬프트 예시로 삽입”하는 구조에서 “기각 이유를 저장소 규약으로 변환해 주입”하는 구조로 바뀌면서, 의미 검색 데이터를 읽는 코드는 이미 사라진 상태였어요. 쓰기 경로만 남아 아무도 쓰지 않는 데이터가 계속 쌓이고 있었어요.

읽는 코드가 없는 저장소는 학습 자산이 아니라 고아 데이터예요. 남아 있던 적재 경로를 제거해 실제 학습에 사용하는 원장과 사용하지 않는 의미 검색 창고의 경계를 분명히 했어요.

누적 채택률을 전후 비교 지표로 바꿨다

학습 루프가 연결돼 있어도 효과를 측정하지 못하면 개선됐는지 판단하기 어려워요. 기존 채택률은 기간 조건 없이 집계한 전체 누적 값이었어요. 이 수치만으로는 최근 규약 변경 후 결과가 좋아졌는지, 오래된 데이터가 현재 상태를 가리고 있는지 구분할 수 없었어요.

그래서 최근 14일 구간과 바로 전 구간을 비교하도록 바꿨어요. 카테고리별 채택률과 표본 수에 더해 이전 구간보다 얼마나 오르거나 내렸는지도 함께 표시했어요.

📊 채택률(최근 14일)
테스트 [채택률]([표본 수]) ↑[변화 폭]
정확성 [채택률]([표본 수]) ↑[변화 폭]
신뢰성 [채택률]([표본 수]) ↑[변화 폭]

집계 범위도 실제 규약이 적용되는 저장소에 맞췄어요. 특정 저장소의 규약이 해당 저장소 리뷰에 미친 영향을 보려면 지표도 같은 경계를 따라야 해요. 모든 저장소의 결과를 합산하면 다른 저장소의 판단이 학습 효과를 희석하거나 과장할 수 있으니까요.

채택률은 단순한 성적표를 넘어 피드백 루프를 관측하는 장치가 됐어요. 이제 “이 규약을 추가한 뒤 같은 종류의 지적이 줄었는가”를 원장에서 일일이 찾지 않아도 최근 구간과 직전 구간의 차이로 확인할 수 있어요.

지적이 없어도 리뷰 완료를 명시했다

내부 지표만으로는 관측 가능성을 완성할 수 없어요. 리뷰를 받는 사람도 리뷰가 실행됐는지 확인할 수 있어야 해요.

기존 구현은 지적 목록이 비어 있으면 그대로 반환했어요. 게시할 지적 카드가 없다는 이유로 코드 호스팅 서비스의 코멘트와 협업 메신저 요약을 모두 생략했어요. 리뷰 자체는 성공했지만 외부에서는 성공 여부를 알 수 없었어요.

이 경우에도 PR에 완료 코멘트를 남기도록 바꿨어요. 이번 diff를 검토했고 머지 전에 수정할 사항을 찾지 못했다는 사실과 리뷰 요약을 함께 제공했어요. 이제 사용자는 침묵만 보고 상태를 추론할 필요 없이, 리뷰가 실행됐고 결과도 깨끗했다는 사실을 확인할 수 있어요.

이 변경은 단순히 알림을 추가한 것이 아니에요. 자동화 시스템에서 “결과 없음”과 “실행 안 됨”을 구분하는 데 필요한 최소한의 상태 표현이에요.

같은 diff에서 반복 지적이 크게 줄었다

학습 효과는 동일한 diff를 반복 실행하는 대조 실험으로 확인했어요. 여러 차례 실행한 결과를 두 조건으로 나눠 같은 횟수만큼 비교했어요.

저장소 규약을 충분히 전달하지 않은 조건에서는 같은 지적이 반복해서 나왔어요. 사람의 반박을 보존해 저장소 규약으로 전달한 조건에서는 같은 지적이 드물게 나타났어요.

동일 diff, 각 조건을 같은 횟수로 반복 실행
규약 반영 전: 같은 지적이 반복적으로 발생
규약 반영 후: 같은 지적이 드물게 발생

이 결과만으로 모든 PR에서 같은 개선을 보장할 수는 없어요. 다만 동일한 입력을 반복한 실험을 통해 저장소 규약이 모델의 리뷰 행동을 바꿨다는 점은 확인할 수 있었어요.

운영에서 생기던 빈틈도 함께 줄였어요. 사람의 반박 원문은 요약 과정에서 사라지지 않고, 긴 답글의 결론도 규약 생성 단계까지 전달돼요. 아무도 읽지 않던 의미 검색 적재 경로는 제거했어요. 채택률은 최근 구간과 직전 구간을 저장소 단위로 비교하고, 지적이 없는 리뷰도 코드 호스팅 서비스에 완료 상태를 남겨요.

학습하는 리뷰봇에는 모델보다 경로가 중요하다

이번 작업에서 가장 큰 문제는 모델이 사람의 말을 이해하지 못했다는 데 있지 않았어요. 같은 diff를 사용한 실험에서 규약 자체는 리뷰 행동을 바꾸고 있었어요.

문제는 그 규약에 이르는 경로였어요. 원문은 요약으로 대체됐고, 길이 제한은 결론을 잘랐으며, 사용하지 않는 저장소에는 데이터가 계속 쌓였어요. 효과를 보여주는 지표는 실제 적용 범위와 다른 데이터를 합산했고, 결과가 없으면 리뷰를 수행했는지조차 표시하지 않았어요.

사람의 반박을 학습하는 PR 리뷰봇에는 세 가지가 모두 필요해요. 사람의 표현을 손실 없이 보존해야 하고, 저장소 규약을 생성할 권한과 규약이 적용되는 범위를 명확히 해야 해요. 학습 전후의 행동 변화와 리뷰 실행 상태도 관측할 수 있어야 해요.

피드백 루프는 데이터를 저장하는 것만으로 완성되지 않아요. 사람의 판단이 올바른 권한 경계를 거쳐 다음 리뷰에 전달되고, 그 결과가 실제로 달라졌는지 확인할 수 있어야 비로소 운영 가능한 학습 시스템이 돼요.


이 글 고치기
이 글 공유하기:

이전 글
백테스트에서 파라미터를 바꾸지 않기로 한 근거