Files
vpd-permission-poc/docs/design/739-game-target-contract

Smilegate 게임 대상 계약 통합 설계

1. 배경

현재 game_query_plan은 게임을 찾지 못하면 STOP_NO_MATCH, 여러 게임이면 FAN_OUT을 반환한다. Portal의 ReAct 모델이 이 지시를 종료 조건으로 해석하거나 일부 게임만 다음 도구로 전달하면서 다음 문제가 발생했다.

  • 게임명이 없는 전체 매출 질의가 SQL 생성 전에 중단된다.
  • 여러 게임 중 일부만 매칭되면 매칭된 게임의 조회도 생략될 수 있다.
  • 계획 결과를 전달해도 NL2SQL worker가 질문 전체를 다시 단일 게임 벡터검색하여 범위를 축소할 수 있다.
  • 게임별 사용자 마스터 물리 객체를 모델이 추측해야 한다.

2. 목표

질문의 게임 대상을 NONE, SINGLE, MULTI, ALL 네 가지로 통일하고, 모든 유형에서 원 질문과 전체 계획 결과를 smilegate_fewshot_nl2sql에 한 번 전달한다. 계획 단계는 조회 중단이나 SQL 조립을 결정하지 않는다.

3. 계약

game_query_plan은 다음 필드를 반환한다.

필드 내용
targetType NONE, SINGLE, MULTI, ALL
status NO_TARGET, SUPPORTED, PARTIAL, UNMATCHED
targets 언급 순서를 보존한 게임 대상 배열
nextAction 항상 CALL_FEWSHOT
executionMode UNSCOPED, SINGLE, COMBINED, ALL

targets 항목은 다음 값을 가진다.

필드 내용
mention 질문에서 추출한 게임명. NONEnull
status NONE, MATCHED, UNMATCHED, CATALOG
gameKey, gameId DB 카탈로그가 반환한 게임 식별자
gamePrefix DB 카탈로그가 반환한 prefix
gameName, aliases 표시명과 별칭
userMasterObjectName 현재 Select AI 승인 객체 중 해당 게임의 사용자 마스터 물리 객체. 없으면 null
cosineDistance 후보 검색 거리. 적용되지 않으면 null
reasonCode, reason 매칭 또는 미매칭 근거

유형별 처리 방식은 다음과 같다.

  • NONE: 게임 대상 항목 하나를 모든 게임 필드가 null인 상태로 전달한다. 공통 거래·기준 객체 질의는 계속하되 prefix 전용 객체를 임의 선택하지 않는다.
  • SINGLE: 질문에서 언급된 대상 한 건을 전달한다. 미매칭이면 게임 필드가 null인 대상도 그대로 다음 도구에 전달한다.
  • MULTI: 언급된 대상 모두를 전달한다. 매칭·미매칭을 함께 보존한다.
  • ALL: 게임 카탈로그의 활성 게임을 모두 반환한다. 사용자 마스터 물리 객체가 없는 게임도 null로 보존한다.

4. DB 설계

SG_GAME_CATALOGUSER_MASTER_OBJECT_NAME을 추가한다.

  • 값은 COMN_GAME_ALIAS_BAS/운영 게임 registry의 GAME_PREFIX와 현재 USER_CLOUD_AI_PROFILE_ATTRIBUTES.object_list, USER_OBJECTS를 조합해 계산한다.
  • 공통 정책이나 애플리케이션 코드에는 특정 게임명, prefix, 테이블명을 넣지 않는다.
  • 운영 registry에만 존재하는 게임도 카탈로그에 동기화하고 임베딩을 생성한다.
  • 게임별 물리 객체가 없으면 컬럼은 null이다.

SG_GAME_CATALOG_SEARCH는 물리 객체명을 후보 결과에 포함한다. SG_GAME_QUERY_PLAN은 추출된 mention마다 후보 선택 결과를 targets로 만들며, ALL은 벡터 선택 없이 전체 카탈로그를 사용한다.

5. MCP와 NL2SQL 설계

game_query_plan 도구 설명은 “항상 먼저 호출하고 결과를 원 질문과 함께 다음 도구에 전달”하도록 바꾼다. smilegate_fewshot_nl2sql의 입력은 다음과 같다.

  • prompt: 사용자가 입력한 원 질문
  • queryPlan: 바로 앞 game_query_plan의 전체 JSON
  • scopeGameKey: 하위 호환용 선택 값. 새 흐름에서는 사용하지 않는다.

NL2SQL worker는 전달된 queryPlan을 권위 있는 게임 범위로 사용한다. 계획이 있으면 질문 전체를 다시 게임 카탈로그 벡터검색하지 않는다.

  • 공통 객체에 게임 식별 컬럼이 있으면 질문 의미에 따라 INGROUP BY를 사용할 수 있다.
  • 대상별 물리 객체가 다르면 제공된 객체만 사용해 UNION ALL할 수 있다.
  • 물리 객체가 null인 대상을 임의 객체로 대체하지 않는다.
  • NONE에서 생성 SQL이 prefix 전용 객체를 참조하면 실행 전에 차단한다.
  • 최종 SQL은 기존과 같이 단일 SELECT/WITH, read-only transaction, 최대 행수와 timeout 제한을 적용한다.

6. Portal ReAct 설계

Portal은 도구 호출 순서를 Java/Python 조건문으로 강제하지 않는다. 외부 환경변수의 system prompt와 MCP 도구 설명으로 다음 절차를 안내한다.

  1. game_query_plan을 호출한다.
  2. targetType과 상관없이 원 질문, 전체 queryPlan으로 smilegate_fewshot_nl2sql을 한 번 호출한다.
  3. SQL, 실행 결과, 매칭·미매칭 대상을 함께 설명한다.

7. 검증

운영 MCP에서 다음 네 질문군을 실제 호출한다.

유형 검증 내용
NONE 게임명이 없는 전체 매출 질의가 공통 테이블로 실행되고 게임 필터가 임의 추가되지 않는다.
SINGLE 한 게임의 AU 질의가 해당 게임 식별자/물리 객체로 실행된다.
MULTI 지원·미지원 게임을 함께 질문해 지원 결과와 미지원 상태가 한 답변에 보존된다.
ALL 전체 게임 질의가 전체 카탈로그 대상을 받아 공통 객체 그룹 또는 게임별 객체 결합 SQL로 실행된다.

추가 검증:

  • Maven 테스트
  • Portal Python 테스트
  • MCP tools/list schema/description 확인
  • 생성 SQL에서 NONE의 prefix 전용 객체 차단 확인
  • 운영 서비스 health와 Portal ReAct 실제 응답 확인

8. Few-shot 참조 거버넌스

Few-shot 원문 SQL은 실행 이력 그대로 검색하지 않는다. 특히 특정 게임의 물리 객체명이 포함된 예제는 다른 게임 또는 게임 미지정 질의의 벡터 후보가 될 수 있으므로, 예제는 검증·정규화·승인 단계를 거쳐야 한다.

SG_QA_VECTOR_EXAMPLE에는 다음 참조 메타데이터를 둔다.

필드 내용
REFERENCE_STATUS DRAFT, APPROVED, RETIRED. 검색은 APPROVED만 사용한다.
REFERENCE_KIND SQL_TEMPLATE, NO_TARGET, OBJECT_UNAVAILABLE, METADATA_POLICY
TARGET_TYPE NONE, SINGLE, MULTI, ALL, ANY. 현재 game query plan과 일치하는 예제만 벡터 순위에 포함한다.
OBJECT_ROLE 물리 테이블명이 아닌 GAME_USER_MASTER 등 논리 객체 역할
INSPECTION_STATUS, INSPECTION_NOTE 전수 실행·정책 검토 결과와 사유
VERIFIED_AT, VERIFIED_BY 승인 감사 이력

물리 테이블명은 Few-shot의 의미 규칙으로 저장하지 않는다. SQL_TEMPLATE<RESOLVED_GAME_USER_MASTER> 같은 논리 placeholder를 사용하며, 실제 객체는 오직 현재 queryPlan.targets[*].userMasterObjectName에서만 해석한다. NO_TARGETOBJECT_UNAVAILABLE 예제는 범위 경계 안내와 검증된 빈 결과 SQL 템플릿을 함께 프롬프트에 포함한다. 이 템플릿은 애플리케이션에서 직접 실행하거나 답변으로 반환하지 않으며, Select AI가 현재 질문의 범위를 해석해 SQL을 생성할 때만 Few-shot 근거로 사용한다.

기존 예제는 삭제하지 않는다. 실행 가능성, 게임 범위 일치, 물리 객체 의존성을 전수 검사해 RETIRED로 분리하고, 검증된 정규화 예제만 APPROVED로 전환한다.

고객 질답 47건 후보화·승인 규칙

SG_AI_QA_QUESTION의 고객 Excel 47건은 SOURCE_TYPE=CUSTOMER_QA_BENCHMARK, SOURCE_CASE_ID로 벡터 예제에 한 번씩 적재한다. 초기 상태는 모두 DRAFT이고, 질문·기대 포인트·기준 SQL을 embedding 문서로 사용한다. 이 상태의 원문은 운영 검색 결과에 절대 포함되지 않는다.

SG_QA_VECTOR_APPROVE_VERIFIED_BENCHMARK는 최신 Portal ReAct 실행이 다음을 모두 만족한 후보만 자동으로 APPROVED로 전환한다.

  1. 고객 지원 범위가 SUPPORTED일 것
  2. 최신 실행이 COMPLETED이며 고객 기준 판정이 PASS일 것
  3. 실행 가능한 읽기 전용 SQL이 있을 것

승인 시 최신 실행 SQL과 응답으로 embedding을 재생성하고, 실행 이력의 query plan에서 확인된 TARGET_TYPE을 함께 보관한다. WARN·FAIL·미지원·SQL 미생성 후보는 DRAFT / REVIEW로 남긴다. 따라서 개선 전 SQL이 Few-shot 근거로 노출되지 않으며, 각 검색 결과는 SOURCE_CASE_ID로 고객 기준 항목까지 추적할 수 있다.

9. 변경 이력

  • Redmine: #739
  • Backoffice branch: smilegate
  • Portal branch: main
  • 2026-07-28: STD-03NO_TARGET 예제에 검증된 빈 결과 SQL 템플릿을 Few-shot 근거로 노출했다. 운영 Portal ReAct에서 game_query_plan → fewshot_nl2sql 경로로 생성·실행한 SQL은 SELECT CAST(NULL AS NUMBER) ... FROM DUAL WHERE 1 = 0이었고, 답변 이력 422PASS로 기록됐다. 직접 정답 실행 분기는 두지 않는다.