idea_world_labDEV JOURNAL
2026년 6월 30일 화요일

Qwen Validation Debugger 전략과 구현 기록

작성일: 2026 년 6 월 30 일

목적

이 문서는 tools/qwen-validation-debugger를 만든 이유와 실제 동작 흐름을 기록한다.

6월 28일에는 Qwen으로 Godot 코드 chunk와 JSONL을 수기로 만들고, 프롬프트 + 코드 chunk + JSONL을 직접 붙여 /아니오가 어떻게 나오는지 확인했다. 이 방식은 방향을 잡는 데는 좋았지만, 항목이 늘어날수록 손으로 복사하고, 생성 기준을 기억하고, 결과를 비교하는 비용이 너무 컸다.

그래서 6월 30일에는 이 과정을 별도 웹 도구로 만들었다. 이 도구의 목표는 최종 모델 학습이 아니라, Qwen이 만든 테스트 코드와 JSONL이 서로 어떤 관계인지 눈으로 추적하고, 잘못된 /아니오 판정을 빠르게 발견하는 것이다.

현재 화면

현재 도구는 http://localhost:8520/에서 실행한다.

Qwen Validation Debugger 현재 화면

화면은 크게 세 영역으로 나뉜다.

  • 왼쪽: 50개 Godot 테스트 항목 체크리스트
  • 가운데/오른쪽 상단: 선택한 항목의 AI 라벨과 Godot 코드 생성 결과
  • 하단: docs_chunks, api_mapping, label_prototypes JSONL 생성/검증 슬롯

왜 별도 도구가 필요했나

원래는 Qwen 챗봇에 직접 다음을 요청했다.

Godot 코드 chunk를 하나 만들고,
docs_chunks/api_mapping/label_prototypes 형식에 맞는 정답 JSONL과 오답 JSONL을 만들어줘.
그리고 SOURCE_CODE와 JSONL을 붙였을 때 예/아니오가 맞게 나오는지 확인할 거야.

하지만 수동 테스트를 해보니 실제로 확인해야 하는 축이 생각보다 많았다.

확인해야 하는 것
테스트 항목 _ready(), _process(delta), 이동, 충돌, UI, 저장/로드 등 50개
문법 범위 Godot 3/4 공통인지, 버전별로 분리해야 하는지
코드 기준 공통 코드 1개 또는 Godot 3 코드 + Godot 4 코드
테이블 docs_chunks, api_mapping, label_prototypes
JSONL 성격 설명 근거, 다른 코드 설명, 변환 필요, 이미 적용, 공통/불필요, 무관 변환
검증 대상 JSONL을 만든 코드와 같은 코드에 검증하는지, 반대 버전 코드에 검증하는지

공통 문법이면 슬롯이 6개다.

공통 코드
  docs_chunks       설명 근거 / 다른 코드 설명
  api_mapping       공통/불필요 / 무관 변환
  label_prototypes  공통/불필요 / 무관 변환

버전 분리 문법이면 슬롯이 12개다.

Godot 3 코드
  docs_chunks       설명 근거 / 다른 코드 설명
  api_mapping       변환 필요 / 무관 변환
  label_prototypes  변환 필요 / 무관 변환

Godot 4 코드
  docs_chunks       설명 근거 / 다른 코드 설명
  api_mapping       이미 적용 / 무관 변환
  label_prototypes  이미 적용 / 무관 변환

이걸 손으로 계속 만들면, 테스트 자체보다 복사/붙여넣기와 결과 정리에 더 많은 시간이 들어간다. 그래서 GUI로 항목, 코드, JSONL, 검증 결과를 한 화면에 묶었다.

전체 흐름

flowchart TD
  A["50개 테스트 항목"] --> B["항목 선택"]
  B --> C["Qwen 라벨링"]
  C --> D{"공통문법인가?"}
  D -->|"common"| E["공통 코드 생성"]
  D -->|"separate"| F["Godot 3 코드 생성"]
  D -->|"separate"| G["Godot 4 코드 생성"]
  E --> H["JSONL 슬롯 6개"]
  F --> I["Godot 3 기준 JSONL 6개"]
  G --> J["Godot 4 기준 JSONL 6개"]
  I --> K["Godot 3 코드 검증"]
  I --> L["Godot 4 코드 검증"]
  J --> K
  J --> L
  H --> M["공통 코드 검증"]

도구는 Qwen을 세 번의 역할로 나눠 호출한다.

단계 Qwen에게 시키는 일 저장되는 것
라벨링 테스트 항목이 공통문법인지 버전 분리인지 판정 classification
코드 생성 공통 코드 또는 Godot 3/4 코드를 생성 codes
JSONL 생성 테이블과 슬롯 성격에 맞는 JSONL 생성 slots[].jsonlText
검증 SOURCE_CODE + JSONL이 직접 근거인지 /아니오 판정 slots[].verifications

라벨링 단계

항목을 클릭하면 먼저 Qwen이 공통문법인지 버전 분리인지 판단한다.

라벨링 중 화면

예를 들어 _process(delta)는 Godot 3과 Godot 4에서 모두 프레임 업데이트 함수로 쓰이므로 공통문법으로 볼 수 있다.

공통 코드 슬롯 화면

반대로 플레이어 이동 속도 및 가속도 적용은 물리 바디와 move_and_slide() 호출 방식이 버전별로 달라질 수 있으므로 Godot 3 코드와 Godot 4 코드를 따로 만든다.

버전 분리 슬롯 화면

JSONL 슬롯 설계

처음에는 슬롯을 단순히 정답 JSONL오답 JSONL로만 나누었다. 그런데 이 기준은 너무 뭉툭했다.

docs_chunks는 설명 근거다. 따라서 코드와 직접 맞는 설명이면 , 다른 코드 동작을 설명하는 문서이면 아니오가 자연스럽다.

하지만 api_mappinglabel_prototypes는 단순 설명이 아니라 Godot 3에서 Godot 4로 넘어갈 때의 변환 근거다. 그래서 이미 Godot 4로 작성된 코드에 api_mapping이나 label_prototypes로 붙으면, “이미 Godot 4인데 또 마이그레이션하라”는 식으로 읽힐 수 있다.

그래서 슬롯 이름을 다음처럼 바꿨다.

테이블 코드 기준 슬롯 의미 생성 기준 기대
docs_chunks 공통/Godot 3/Godot 4 설명 근거 JSONL
docs_chunks 공통/Godot 3/Godot 4 다른 코드 설명 JSONL 아니오
api_mapping Godot 3 변환 필요 JSONL
api_mapping Godot 4 이미 적용 JSONL 아니오
api_mapping 공통 공통/불필요 JSONL 아니오
api_mapping 모든 코드 무관 변환 JSONL 아니오
label_prototypes Godot 3 변환 필요 JSONL
label_prototypes Godot 4 이미 적용 JSONL 아니오
label_prototypes 공통 공통/불필요 JSONL 아니오
label_prototypes 모든 코드 무관 변환 JSONL 아니오

이 기준 덕분에 예/아니오가 단순 관련성 판정이 아니라, 테이블 용도에 맞는 판정으로 바뀌었다.

생성 기준 코드와 검증 대상 코드 분리

오늘 가장 중요하게 바뀐 부분은 이 지점이다.

처음 구현에서는 한 슬롯이 자기 코드에 대해서만 검증됐다.

Godot 3 코드로 만든 JSONL
  -> Godot 3 코드에만 검증

Godot 4 코드로 만든 JSONL
  -> Godot 4 코드에만 검증

하지만 실제로 필요한 검증은 이것보다 넓다.

Godot 3 코드로 만든 JSONL이 Godot 4 코드에 붙었을 때도 아니오가 나와야 한다. 반대로 Godot 4 코드로 만든 JSONL이 Godot 3 코드에 붙었을 때 어떤 결과가 나오는지도 봐야 한다. 그래야 source/target 문자열이 섞여서 잘못 가 나오는 문제를 찾을 수 있다.

그래서 버튼을 하나에서 둘로 나눴다.

Godot 3/4 검증 버튼 분리

이제 버전 분리 항목의 각 슬롯은 다음 검증을 모두 수행할 수 있다.

Godot 3 코드로 생성한 JSONL
  -> Godot 3 코드 검증
  -> Godot 4 코드 검증

Godot 4 코드로 생성한 JSONL
  -> Godot 3 코드 검증
  -> Godot 4 코드 검증

도구 내부에서는 이를 다음처럼 분리한다.

의미
slot.versionKey JSONL을 만들 때 사용한 코드 버전
sourceVersionKey 검증 API에 전달하는 JSONL 생성 기준 버전
targetVersionKey 실제 검증에 사용할 코드 버전
slot.verifications.godot3 이 JSONL을 Godot 3 코드에 붙여 검증한 결과
slot.verifications.godot4 이 JSONL을 Godot 4 코드에 붙여 검증한 결과

기대 응답 계산 기준

검증 결과는 여전히 Qwen에게 또는 아니오로 받는다. 다만 기대 응답은 이제 슬롯 하나만 보고 계산하지 않고, 테이블 + JSONL 생성 기준 버전 + 검증 대상 버전 + 슬롯 성격을 같이 본다.

케이스 기대 응답
docs_chunks 설명 근거 JSONL을 같은 버전 코드에 검증
docs_chunks 설명 근거 JSONL을 반대 버전 코드에 검증 아니오
docs_chunks 다른 코드 설명 JSONL 아니오
Godot 3 기준 api_mapping/label_prototypes 변환 필요 JSONL을 Godot 3 코드에 검증
Godot 3 기준 api_mapping/label_prototypes 변환 필요 JSONL을 Godot 4 코드에 검증 아니오
Godot 4 기준 api_mapping/label_prototypes 이미 적용 JSONL 아니오
공통 코드 기준 api_mapping/label_prototypes 공통/불필요 JSONL 아니오
무관 변환 JSONL 아니오

이 기준은 완성된 최종 평가 기준이라기보다, 지금 단계에서 Qwen의 근거 매칭이 어디서 흔들리는지 보기 위한 디버깅 기준이다.

검증 프롬프트의 변화

검증 프롬프트에는 이제 두 가지 버전 정보가 들어간다.

JSONL_GENERATED_FROM_CODE_VERSION:
godot3

VERIFY_TARGET_CODE_VERSION:
godot4

이렇게 넣는 이유는 Qwen이 단순히 JSONL 안의 target_api가 현재 코드와 맞는다고 해서 라고 답하지 않게 하기 위해서다.

api_mappinglabel_prototypes에서는 다음 기준이 중요하다.

  • source_api, source_pattern, input_pattern, before_code, required_when_seen_in_code가 현재 코드에 직접 있어야
  • target_api, after_code, recommended target 형태만 현재 코드와 맞으면 이미 적용된 상태이므로 아니오
  • signature_stable, no_change, common처럼 변환이 필요 없음을 뜻하면 아니오
  • Godot 4 코드 또는 공통문법 코드에 마이그레이션 JSONL이 붙어도 추가 변환이 필요하지 않으면 아니오

50개 항목 테스트 기록

1/50 _ready() 함수 초기화 및 뷰포트 크기 설정

7월 3일에 50개 테스트 항목 중 1번 항목을 먼저 검증했다. 이 항목은 공통 코드로 라벨링했고, 기준 코드는 다음과 같았다.

func _ready():
    var vp_size = get_viewport().get_visible_rect().size
    position = Vector2(vp_size.x / 2, vp_size.y / 2)

처음에는 docs_chunks의 오답 슬롯을 무관 설명 JSONL로 불렀다. 그런데 실제 테스트를 해보니 이 이름이 부정확했다. 이 슬롯은 일부러 이상하거나 틀린 JSONL을 만드는 자리가 아니라, Retriever가 검색 후보로 가져올 수 있는 다른 공식문서 설명을 넣고 Qwen이 최종 검증에서 걸러내는지 보는 자리다.

따라서 이 슬롯의 의미를 다른 코드 설명 JSONL로 정리했다.

이 테스트에서 문제 된 JSONL은 Viewport.get_visible_rect_ready()를 설명하고 있었지만, 실제 내용은 safe area, UI scaling, $Label, $Button.rect_position 같은 다른 코드 동작에 대한 설명이었다. SOURCE_CODE는 뷰포트 크기를 읽어 현재 노드의 position을 화면 중앙으로 옮기는 코드이므로, 일부 API가 겹쳐도 직접 근거는 아니라고 봐야 한다.

기대 응답은 아니오였지만 Qwen은 를 반환했다. 원인은 검증 프롬프트가 실제 문자열/API 호출과 직접 일치를 너무 넓게 해석하도록 되어 있어서, 같은 API가 포함된 다른 문서 설명까지 직접 근거로 받아들인 점이었다.

수정내역:

  • docs_chunks 오답 슬롯 이름을 무관 설명 JSONL에서 다른 코드 설명 JSONL로 바꿈
  • JSONL 생성 프롬프트에서 이 슬롯을 “검색 후보처럼 일부 API/주제가 겹칠 수 있지만 실제로는 다른 코드 동작을 설명하는 공식문서형 JSONL”로 정의함
  • 검증 프롬프트에서 docs_chunks 기준을 단순 API 문자열 일치가 아니라 코드의 핵심 목적, 대상 객체, 최종 동작/결과가 직접 맞는지로 강화함
  • 같은 API나 같은 메서드가 등장해도 JSONL이 다른 목적, 다른 대상 객체, 다른 결과를 설명하면 검색 후보일 뿐 직접 근거가 아니므로 아니오라고 명시함
  • 프론트 UI의 슬롯 라벨과 미리보기 문구도 같은 기준으로 맞춤
  • 해당 기준이 프롬프트에 유지되는지 core.test.js에 테스트를 추가함

2/50 _process(delta) 프레임별 업데이트 루프

7월 3일에 2번 항목을 검증했다. 이 항목은 Qwen이 공통 코드로 라벨링했다.

라벨링 요약:

syntax_scope: common
label: _process(delta) 프레임별 업데이트
reason: Godot 3과 4 모두에서 _process(delta) 함수의 시그니처와 호출 방식이 동일하며, 프레임 단위 로직 작성에 문법적 차이가 없다.

검증 결과는 6개 슬롯 모두 기대 응답과 일치했다.

항목
슬롯 수 6
통과 6
불일치 0

이번 항목은 공통문법에서 docs_chunks는 설명 근거로 , api_mappinglabel_prototypes는 공통/불필요 또는 무관 변환으로 아니오가 나오는 흐름이 정상적으로 동작한 사례로 기록한다.

3/50 플레이어 이동 입력 처리

3번 항목은 Qwen이 버전 분리 코드로 라벨링했다.

라벨링 요약:

syntax_scope: separate
label: 플레이어 이동 입력 처리
reason: 입력 체크 자체는 유사하지만, Godot 4에서 도입된 Input.get_vector()와 CharacterBody2D의 move_and_slide() 시그니처 변경으로 인해 코드 구조를 분리해야 한다.
godot3_focus: KinematicBody2D 상속, 수동으로 velocity.x/y 계산 및 move_and_slide(up_direction) 호출
godot4_focus: CharacterBody2D 상속, Input.get_vector()로 대각선 이동 간소화 및 move_and_slide() 파라미터 제거 적용

검증 결과:

항목
슬롯 수 12
검증 수 24
통과 20
불일치 4

불일치:

슬롯 검증 대상 기대 응답 관찰
godot3:api_mapping:positive Godot 4 코드 아니오 Godot 3 기준 변환 JSONL을 Godot 4 코드에 붙였는데도 가 나왔다. 이미 Godot 4 형태라면 관련 변환 설명이 있어도 지금 마이그레이션을 적용할 대상은 아니다.
godot3:label_prototypes:positive Godot 4 코드 아니오 label_prototypes · 변환 필요 JSONL은 현재 코드가 변경 전 사용 방식일 때만 여야 한다. Godot 4 코드에 붙었을 때 가 나오면 “이미 Godot 4인데 다시 마이그레이션하라”는 의미가 되어 문제가 된다.
godot3:label_prototypes:negative Godot 4 코드 아니오 무관 변환 JSONL은 현재 코드가 Godot 4이든 Godot 3이든, 그 코드에 실제로 적용할 변환이 아니면 아니오여야 한다.
godot4:label_prototypes:negative Godot 3 코드 아니오 Godot 4 기준으로 만든 무관 변환 JSONL을 Godot 3 코드에 붙였을 때 가 나왔다. 이것도 잘못된 결과다. 검증 질문은 “어느 정도 관련 있나”가 아니라 “이 SOURCE_CODE에 이 변환을 적용해야 하나”여야 한다.

프롬프트 관찰:

하이브리드 서치에서는 코드 chunk와 비슷한 JSONL 후보가 함께 올라오는 것이 자연스럽다. 따라서 검증 프롬프트는 검색 후보를 현재 SOURCE_CODE에 실제로 적용해야 하는 근거인지 판정해야 한다. 3번의 불일치는 이 질문이 충분히 고정되지 않아 Qwen이 api_mappinglabel_prototypes를 마이그레이션 필요 여부가 아니라 넓은 관련성 매칭처럼 해석한 사례다.

특히 3번에서는 다음 문제가 드러났다.

  • move_and_slide처럼 Godot 3/4 양쪽에 모두 등장할 수 있는 함수명이 단독으로 매칭되면 Qwen이 로 기울 수 있다.
  • Godot 3 기준 JSONL을 Godot 4 코드에 붙였을 때, 이미 변경 후 코드라면 label_prototypes · 변환 필요로 나오면 안 된다.
  • Godot 4 기준 무관 변환 JSONL을 Godot 3 코드에 붙였을 때도, 현재 코드에 실제로 적용할 변환이 아니면 가 나오면 안 된다.
  • 핵심은 JSONL 생성 방식이 아니라 검증 질문이다. 현재 코드가 변경 전 코드인지, 이미 변경 후 코드인지, 아니면 아예 다른 변환인지 판정하게 해야 한다.

따라서 프롬프트 기준을 다음처럼 고쳤다.

  • 검증 질문을 JSONL과 코드가 관련 있나가 아니라 이 JSONL을 근거로 현재 SOURCE_CODE에 마이그레이션을 적용해야 하나로 바꾼다.
  • 현재 SOURCE_CODE가 이미 Godot 4 target 형태라면, JSONL이 마이그레이션 설명과 관련 있어 보여도 “이미 적용됨”이므로 아니오라고 명시한다.
  • label_prototypes · 변환 필요는 현재 SOURCE_CODE가 변경 전 사용 방식, 인자 구성, 호출 패턴을 실제로 담고 있을 때만 라고 명시한다.
  • 무관 변환 JSONL은 검증 대상이 Godot 3 코드여도 현재 SOURCE_CODE에 적용할 변환이 아니면 아니오라고 명시한다.
  • JSONL의 각 필드는 판단 문맥이다. 검증 단계에서는 그 문맥을 보고 현재 SOURCE_CODE가 변경 전 상태인지, 이미 변경 후 상태인지 판단한다.
  • source_api와 target_api가 같은 이름을 공유하거나 match_terms에 source/target 용어가 함께 들어갈 수 있으므로, 단일 함수명이나 넓은 match_terms만 일치하면 가 아니라고 명시한다.
  • 함수명이 같아도 호출 인자, 반환값 처리, 상속 노드, 주변 코드 구조처럼 JSONL이 말하는 source-side 변경 전 패턴이 SOURCE_CODE에 직접 남아 있어야만 라고 명시한다.
  • JSONL_GENERATED_FROM_CODE_VERSIONVERIFY_TARGET_CODE_VERSION이 다르면, 현재 SOURCE_CODE가 JSONL의 변경 전 코드인지 이미 변경 후 코드인지 먼저 구분하라고 명시한다.

4/50 플레이어 이동 속도 및 가속도 적용

4번 항목도 Qwen이 버전 분리 코드로 라벨링했다.

라벨링 요약:

syntax_scope: separate
label: 플레이어 이동 속도 및 가속도 적용
reason: Godot 4에서 물리 노드가 KinematicBody에서 CharacterBody로 변경되었고, move_and_slide() 시그니처가 인자 전달 방식으로 바뀌어 코드 구조가 달라진다.
godot3_focus: velocity 프로퍼티에 속도 할당 후 move_and_slide() 호출, KinematicBody2D/3D 사용
godot4_focus: move_and_slide(velocity)로 인자 전달, CharacterBody2D/3D 사용, 가속도 적용 시 lerp() 또는 move_toward() 활용

검증 결과:

항목
슬롯 수 12
검증 수 24
통과 23
불일치 1

불일치:

슬롯 검증 대상 기대 응답 관찰
godot3:api_mapping:positive Godot 4 코드 아니오 Godot 3 기준 move_and_slide 변환 JSONL을 Godot 4 코드에 붙였을 때도 가 나왔다. 이미 Godot 4 형태라면 변환 설명이 관련 있어도 현재 코드에 마이그레이션을 적용할 대상은 아니다.

프롬프트 관찰:

4번의 불일치는 3번보다 적었지만, 원인은 같다. api_mapping에서 source와 target 함수명이 같거나 비슷하면 Qwen이 “이 JSONL이 해당 함수 변경을 설명한다”는 넓은 관련성 판단으로 를 줄 수 있다. 하지만 이 도구에서 필요한 것은 관련성 판정이 아니라 현재 코드에 적용할 마이그레이션 필요 여부다.

따라서 4번까지의 관찰을 기준으로, 검증 프롬프트는 단순 API 이름 일치가 아니라 다음을 함께 보도록 강화했다.

  • 현재 코드가 JSONL의 변경 전 패턴을 실제로 포함하는지
  • 같은 함수명이라도 호출 인자와 반환값 처리 방식이 변경 전 코드와 맞는지
  • 검증 대상 코드가 이미 변경 후 형태이면, 마이그레이션 필요 여부는 아니오인지
  • 무관 변환 JSONL이 단순 관련성 때문에 로 올라오지 않는지

5/50 플레이어의 최대 속도 제한

5번 항목은 Qwen이 버전 분리 코드로 라벨링했다.

라벨링 요약:

syntax_scope: separate
label: 플레이어 최대 속도 제한
reason: Godot 3의 KinematicBody2D와 Godot 4의 CharacterBody2D 간 클래스명 변경, move_and_slide() 메서드 시그니처 및 velocity 전달 방식 차이로 별도 코드가 필요하다.
godot3_focus: KinematicBody2D 상속, self.velocity에 속도 할당 후 move_and_slide() 호출, limit_length()로 속도 제한
godot4_focus: CharacterBody2D 상속, velocity 변수에 속도 할당 후 move_and_slide(velocity)로 명시적 전달, limit_length() 적용

생성된 코드 흐름:

버전 핵심 코드 흐름
Godot 3 Input.get_action_strength()로 입력 벡터를 만들고, velocity = move_and_slide()처럼 반환값을 다시 할당한 뒤 velocity.length() > max_speed이면 정규화해서 최대 속도를 제한한다.
Godot 4 extends CharacterBody2D, Input.get_vector(), velocity = direction * max_speed, velocity = velocity.limit_length(max_speed), move_and_slide() 흐름으로 작성됐다.

검증 결과:

항목
슬롯 수 12
검증 수 24
통과 23
불일치 1

불일치:

슬롯 검증 대상 기대 응답 관찰
godot3:docs_chunks:negative Godot 3 코드 아니오 다른 코드 설명용 docs_chunks 후보가 Godot 3 코드에 붙었을 때 가 나왔다. 같은 Godot 3 계열, move_and_slide, 속도/충돌 처리 같은 단서가 겹치면서 Qwen이 검색 후보를 직접 설명 근거처럼 판단한 것으로 보인다.

프롬프트 관찰:

5번은 하이브리드 서치에서 실제로 생길 수 있는 상황에 가깝다. 나중에 DB에서 검색하면 완전히 엉뚱한 JSONL만 올라오는 것이 아니라, 같은 API나 같은 이동/속도 처리 계열의 비슷한 후보가 함께 올라올 수 있다. 이때 검증 프롬프트는 “비슷한 검색 후보인가”가 아니라 “이 JSONL이 현재 SOURCE_CODE의 실제 동작을 직접 설명하는가”를 봐야 한다.

이번 5번에서 api_mappinglabel_prototypes는 Godot 3/4 양쪽 검증에서 기대값대로 동작했다. 특히 Godot 4 코드에 이미 적용된 형태나 no_change, pattern_validation 성격의 JSONL이 붙었을 때 아니오로 떨어진 점은 이전 3번/4번에서 보였던 마이그레이션 판정 문제를 어느 정도 완화한 신호로 볼 수 있다.

반대로 docs_chunks는 아직 더 살펴봐야 한다. docs_chunks는 마이그레이션 적용 여부가 아니라 설명 근거 매칭이므로, 같은 API 이름이나 같은 버전 단서만으로 가 되면 하이브리드 서치 후보 검증 단계에서 노이즈가 남는다. 따라서 이후 검증 프롬프트에서는 docs_chunks에 대해 SOURCE_CODE의 목적, 대상 객체, 결과 상태가 JSONL의 설명과 실제로 같은지 더 강하게 확인해야 한다.

6~10/50 추가 검증 기록

6번부터 10번까지는 먼저 결과를 기록하고, 그 다음에 검증 프롬프트를 고치는 순서로 진행한다. 이번 단계에서는 프롬프트 수정 없이 현재 도구가 어떤 슬롯에서 맞고 틀리는지만 남긴다.

전체 요약:

범위 슬롯 수 검증 수 통과 불일치
6~10번 합계 54 102 97 5

항목별 요약:

번호 항목 라벨 코드 구분 검증 결과
6 마우스 클릭 시 발사체 생성 및 발사 마우스 클릭 발사체 생성 및 이동/충돌 버전 분리 24/24 통과
7 발사체의 이동 및 수명(time-to-live) 관리 발사체 이동 및 수명 관리 버전 분리 22/24 통과, 2 불일치
8 적(Enemy)의 플레이어 추적(AI) 로직 적의 플레이어 추적 AI 로직 버전 분리 21/24 통과, 3 불일치
9 적의 이동 속도 및 회전 로직 적 이동 속도 및 회전 로직 버전 분리 24/24 통과
10 플레이어가 화면 밖으로 나가면 사라지기 화면 밖 이탈 시 노드 제거/숨김 공통 6/6 통과

6번, 9번, 10번은 현재 기준에서 전부 기대값대로 나왔다. 6번은 Godot 3의 PackedScene.instance(), Input.is_mouse_button_pressed(1), get_viewport().get_mouse_position() 흐름과 Godot 4의 instantiate(), InputEventMouseButton, get_global_mouse_position() 흐름이 분리됐고, 정답/오답 후보도 각각 잘 갈렸다. 9번도 적 이동과 회전 관련 버전 분리 후보가 모두 기대값대로 판정됐다. 10번은 공통문법으로 분류됐고, get_viewport_rect().size, global_position, hide() 기반 화면 밖 처리에서 docs 설명 근거는 , api_mapping/label_prototypes 성격의 마이그레이션 후보는 아니오로 정리됐다.

불일치:

번호 슬롯 검증 대상 기대 응답 관찰
7 godot3:api_mapping:positive Godot 4 코드 아니오 Godot 3 기준 변환 JSONL을 이미 Godot 4 코드에 검증했는데도 가 나왔다. 아직 “현재 코드에 적용해야 하는 변환인가”보다 “관련 있는 변환인가”로 읽는 순간이 남아 있다.
7 godot3:label_prototypes:positive Godot 4 코드 아니오 Godot 3 source-side 사용 패턴을 설명하는 prototype이 Godot 4 코드에도 로 붙었다. 이미 변환된 코드라면 마이그레이션 필요 판단은 아니오여야 한다.
8 godot4:docs_chunks:positive Godot 3 코드 아니오 Godot 4 설명 근거가 Godot 3 코드에도 로 붙었다. docs 후보가 같은 추적/이동 주제나 비슷한 API 단서 때문에 직접 설명 근거처럼 판정된 것으로 보인다.
8 godot4:docs_chunks:negative Godot 3 코드 아니오 다른 코드 설명용 docs 후보가 Godot 3 코드에도 가 됐다. 하이브리드 서치에서 비슷한 docs 후보가 올라왔을 때 목적과 결과가 다른지 더 분명히 판단해야 한다.
8 godot4:docs_chunks:negative Godot 4 코드 아니오 같은 Godot 4 계열이어도 다른 코드 설명 후보라면 아니오여야 하는데 가 나왔다. docs_chunks 검증은 API 이름보다 SOURCE_CODE의 실제 동작 목적, 대상, 결과를 더 강하게 봐야 한다.

관찰:

이번 6~10번을 보면 전체적으로는 개선 신호가 있다. 102회 검증 중 97회가 기대값과 맞았고, 6번/9번/10번은 전부 통과했다. 특히 공통문법인 10번에서 api_mapping과 label_prototypes가 전부 아니오로 떨어진 것은 “공통 코드에 굳이 마이그레이션 근거를 붙이지 않는다”는 방향이 어느 정도 작동한 사례다.

남은 불일치는 두 갈래다. 하나는 7번처럼 Godot 3 기준 마이그레이션 근거가 Godot 4 코드에도 로 붙는 경우다. 이 경우에는 현재 코드가 이미 변경 후 형태인지, 아직 변경 전 형태인지 더 선명하게 물어야 한다. 다른 하나는 8번처럼 docs_chunks 후보가 같은 주제나 비슷한 API 때문에 로 올라오는 경우다. 이 경우에는 설명 근거가 SOURCE_CODE의 실제 동작을 직접 설명하는지, 아니면 비슷한 검색 후보일 뿐인지 더 잘 가려야 한다.

중요한 점은 이 문제를 특정 문자열이나 특정 후보를 막는 방식으로 풀지 않는다는 것이다. 나중에 DB에 JSONL을 넣고 하이브리드 서치로 가져오면 비슷하지만 다른 후보가 같이 올라오는 것이 정상이다. 따라서 후속 수정은 후보를 인위적으로 거르는 방식이 아니라, 검증 프롬프트가 현재 SOURCE_CODE와 검색 후보의 관계를 더 정확히 판정하게 만드는 방향으로 진행한다.

기록 이후 적용한 검증 프롬프트 보강:

  • docs_chunks에서는 JSONL 생성 기준 버전과 검증 대상 버전이 다를 때, JSONL이 현재 검증 대상 버전의 코드 동작까지 설명하는지 먼저 확인하게 했다.
  • 버전이 달라도 공통 API/공통 동작을 명시적으로 설명하면 일 수 있지만, 버전별 코드 구조나 노드/API 차이를 설명하는 후보라면 현재 SOURCE_CODE와 같은 동작인지 따로 확인하게 했다.
  • api_mappinglabel_prototypes에서는 먼저 현재 SOURCE_CODE가 변경 전 코드인지, 이미 변경 후 코드인지, 무관한 코드인지, 변환 불필요 코드인지 판정하게 했다.
  • 는 현재 SOURCE_CODE가 변경 전 코드이고, JSONL이 말하는 변환을 지금 적용해야 할 때만 허용하도록 문장을 선명하게 했다.
  • 이 보강은 특정 문자열을 처리하는 방식이 아니라, 하이브리드 서치로 올라온 후보를 현재 코드 기준으로 판정하는 절차를 강화한 것이다.

검증 결과 확인

검증 결과는 각 슬롯 아래에 버전별로 따로 표시된다.

검증 결과 화면

이 방식으로 한 슬롯 안에서 다음을 바로 볼 수 있다.

Godot 3 코드 검증 전 / 응답 / 기대 / 일치 여부
Godot 4 코드 검증 전 / 응답 / 기대 / 일치 여부

이전에는 “이 JSONL이 맞다/틀리다”만 보였다. 이제는 “어떤 코드에 붙였을 때 맞다/틀리다”를 볼 수 있다.

현재 도구가 해결한 문제

이전 방식 현재 방식
Qwen 챗봇에 직접 코드와 JSONL을 요청 웹 UI에서 항목별로 라벨, 코드, JSONL, 검증 결과를 누적
정답/오답 JSONL만 구분 설명 근거, 다른 코드 설명, 변환 필요, 이미 적용, 공통/불필요, 무관 변환으로 분리
Godot 3 JSONL은 Godot 3 코드에만 검증 Godot 3/4 양쪽 코드에 모두 검증 가능
결과를 수기로 복사해 기억 슬롯별로 raw response, prompt, 검증 결과 저장
실패 원인 추적이 어려움 어떤 슬롯, 어떤 검증 대상에서 틀렸는지 바로 확인
50개 항목 테스트가 사실상 손작업 샘플 로드, 항목 추가/삭제, 전체 생성/전체 검증 버튼 제공

개발 생산성 변화

도구를 만들기 전에는 테스트 하나를 하려면 다음 일을 손으로 했다.

1. Qwen에게 테스트 항목 설명
2. Godot 3 코드 요청
3. Godot 4 코드 요청
4. docs_chunks 정답/오답 JSONL 요청
5. api_mapping 정답/오답 JSONL 요청
6. label_prototypes 정답/오답 JSONL 요청
7. 각 JSONL을 다시 SOURCE_CODE와 붙여 검증
8. 예/아니오 결과를 손으로 기록
9. 기대값이 맞는지 머릿속으로 비교

지금은 같은 흐름이 화면 안에 고정됐다.

1. 항목 클릭
2. AI 라벨 생성
3. 공통 또는 Godot 3/4 코드 생성
4. JSONL 슬롯별 생성
5. Godot 3 코드 검증 / Godot 4 코드 검증
6. 결과와 프롬프트/응답 확인

특히 생산성이 좋아진 부분은 “빠르게 많이 만든다”보다 “헷갈리지 않는다”에 가깝다. 이 작업은 단순 생성량보다 판정 기준이 흔들리지 않는 것이 중요하다. 도구가 생기면서 다음이 쉬워졌다.

  • 공통문법인지 버전 분리인지 먼저 고정
  • 테이블별 JSONL 용도를 화면에서 계속 확인
  • 생성 기준 기대와 실제 검증 결과를 분리
  • 같은 JSONL을 Godot 3/4 코드에 교차 검증
  • 실패한 슬롯의 프롬프트와 raw response를 바로 확인
  • 50개 항목을 반복할 때 사람이 기억해야 하는 상태를 줄임

아직 열어둔 문제

이 도구는 아직 최종 평가기가 아니다. 지금은 디버깅 도구다.

열어둔 문제는 다음과 같다.

  • docs_chunks 설명 근거가 버전이 달라도 공통 설명으로 인정될 수 있는 경우가 있다.
  • api_mapping에서 source/target 문자열이 모두 JSONL에 들어가면 Qwen이 target 문자열만 보고 라고 할 수 있다.
  • label_prototypes는 단순 문자열 일치보다 before/after 패턴 구분이 더 중요할 수 있다.
  • 현재 기대 응답 계산은 디버깅 기준이므로, 나중에 실제 score/F1 계산 기준은 따로 다듬어야 한다.
  • 검색 후보 선정 문제와 검증 프롬프트 판정 문제는 결과만 보고 바로 분리하기 어렵다.

현재 결론

6월 28일에는 “50개 테스트를 수기로 해보자”는 느낌이었다. 실제로 해보니 테스트해야 할 축이 너무 많았고, 공통문법과 버전 분리, 생성 기준 버전과 검증 대상 버전이 섞이면 금방 헷갈렸다.

6월 30일 도구를 만들면서 이 문제가 꽤 많이 정리됐다. 이제는 Qwen이 만든 JSONL을 단순히 맞다/틀리다로 보는 것이 아니라, 어떤 코드에서 생성했고 어떤 코드에 검증했는지까지 볼 수 있다.

이 도구는 이후 docs_chunks, api_mapping, label_prototypes의 실제 검색 결과를 붙였을 때도 같은 방식으로 쓸 수 있다. 즉, 수동 데모 데이터뿐 아니라 DB 검색 결과 검증에도 이어질 수 있는 기반 도구가 됐다.