AI 코드 이관, 컴파일 성공 대신 DB 결과와 출력 바이트를 비교하세요

AI가 고친 코드가 컴파일되고 예외 없이 끝났다고 해서 이관 검수가 끝나는 것은 아닙니다. 원래 프로그램이 버리던 소수 자릿수를 새 코드가 반올림하면, 실행에는 성공해도 업무 결과는 달라질 수 있습니다. 검수의 출발점은 “잘 실행되는가”보다 “무엇이 원본과 같아야 하는가”입니다.

OpenAI가 2026년 10월 19일 공개한 저자원 프로그래밍 언어 평가 설명은 이 차이를 드러냅니다. 하나는 새로운 SQLite 호환 엔진을 구현하는 MultiLangBench이고, 다른 하나는 기존 COBOL 프로그램의 동작을 보존하는 이관 평가입니다. 이 글에서는 모델 순위보다 두 평가가 정답을 정의하는 방식을 살펴보고, 실제 팀에서 사용할 수 있는 승인 판단표로 바꿔 봅니다.

1. 새로 만드는 능력과 바꾸지 않는 능력은 다릅니다

MultiLangBench는 지정한 언어로 SQLite 호환 엔진을 처음부터 구현하게 합니다. 공식 설명의 대상은 20개 언어입니다. 코드를 구성하고 상태를 관리하며 기능을 추가하는 능력을 보되, 판정은 작성된 설명이나 모델의 자기 평가가 아니라 테스트 결과에 연결합니다.

COBOL 이관 평가는 이미 있는 프로그램을 C++, Java, Kotlin, Python 또는 Rust로 옮기는 과제입니다. 목적은 같은 문제를 새 방식으로 해결하는 데 그치지 않습니다. 원래 프로그램이 외부에 내놓던 결과를 유지해야 합니다. OpenAI는 숨겨진 테스트에서 관찰 가능한 출력의 바이트 단위 일치를 요구하고, 모든 테스트를 통과한 이관만 성공으로 센다고 설명합니다.

두 평가의 “통과”를 같은 의미로 읽으면 안 됩니다. SQLite 쪽 테스트 통과율과 COBOL 쪽 모든 테스트 통과 조건의 이관 정확도는 분모와 성공 단위가 다릅니다. 평균 점수 하나가 높다는 이유만으로 특정 업무 시스템의 전환을 승인할 수는 없습니다.

MultiLangBench의 새 SQLite 호환 구현과 COBOL 이관의 출력 보존을 구분한 두 열 비교도

그림 1. 새 구현은 DB 검증 결과, COBOL 이관은 관찰 출력의 바이트 일치와 모든 테스트 통과로 판단한다. 서로 다른 성공 단위를 합친 성능 비교가 아니다. 출처: openai.com/index/low-resource-programming-languages.

검수 설계의 핵심을 한 문장으로 정리하면 이렇습니다. 새 구현의 검수에서는 기준 엔진이 읽은 DB 결과를 비교하고, 기존 코드 이관에서는 원본과 새 코드의 관찰 가능한 출력 바이트를 비교한다. 둘 다 정답 기준이 필요하지만, 같아야 하는 대상이 다릅니다.

2. MultiLangBench는 수정된 DB를 기준 엔진으로 읽습니다

고정 커밋의 README는 각 테스트를 세 요소로 설명합니다. initial_database는 초기 DB를 만드는 SQL, user_query는 후보 구현이 수행할 SQL, validation_query는 변경된 DB를 진짜 SQLite 3.40.1로 읽어 검증하는 SQL입니다. 마지막 검증 쿼리가 정확한 기대 출력 문자열을 내면 해당 테스트를 통과합니다.

즉, 후보가 “INSERT를 구현했다”고 말하는 것과 실제 DB에 기대한 내용이 저장된 것은 별개입니다. 후보 구현이 만든 DB를 독립된 기준 엔진으로 읽는 단계가 그 차이를 드러냅니다. 이 구조를 업무용 검수에 응용할 때도 구현자의 설명과 검사자의 기준을 분리하는 편이 좋습니다. 다만 이는 이 글의 검수 설계 제안이지, 모든 종류의 DB 이관이 이 평가 하나로 검증된다는 뜻은 아닙니다.

초기 DB 생성, 후보 구현의 SQL 실행, SQLite 3.40.1 기준 검증을 잇는 세 단계 흐름도

그림 2. 고정 커밋 README의 세 테스트 요소를 도식화했다. 수정된 DB를 기준 SQLite 3.40.1로 읽은 결과 문자열을 비교하며, DB 파일 자체의 바이트 동일성을 뜻하지 않는다. 출처: github.com/openai/MultiLangBench/blob/995755bffdba3da60ca367448a1606ba0e50573a/README.md.

여기서 파일 전체의 해시를 비교하는 방법과도 구별해야 합니다. README가 설명하는 판정은 기준 SQLite가 검증 쿼리를 실행해 내놓은 결과 문자열입니다. DB 파일의 모든 바이트가 같아야 한다고 읽으면 다른 검사를 하게 됩니다. 반대로 COBOL 평가의 출력 바이트 일치 조건을 DB 평가의 내부 파일 표현에 그대로 옮겨도 안 됩니다.

배포 전 검수 문서에는 입력을 만든 방식, 후보가 실행할 쿼리, 결과를 읽는 기준 엔진과 버전, 비교할 출력 형식을 따로 적어 두세요. 같은 데이터를 넣었다고 생각해도 초기 상태나 정렬 조건이 달라지면 원인 분석이 어려워집니다. 기준 결과를 후보 코드가 스스로 다시 생성하게 두는 것도 순환 검증이 될 수 있으므로 피하는 설계가 필요합니다.

3. 바이트 일치는 “비슷한 숫자”보다 엄격합니다

공식 COBOL 설명은 고정소수점 연산에서 명시적으로 반올림을 요청하지 않으면 초과 소수 자릿수를 버리는 동작을 예로 듭니다. 이 규칙을 새 언어의 익숙한 숫자 처리로 대체하면 프로그램은 실행되어도 값이 달라질 수 있다는 지적입니다. 이 글은 특정 COBOL 문장이나 실제 업무 데이터를 실행한 것은 아닙니다.

다음은 원리를 설명하기 위한 합성 출력 예시입니다. 원본 기준 출력이 ASCII 12.34\n인데 후보가 12.35\n을 내면 금액 자릿수가 달라집니다. 값이 같아 보이는 12.34\r\n도 줄바꿈 바이트가 다릅니다. 실제 업무에서 어느 출력이 정답인지는 원본 실행과 명세로 고정해야 하며, 이 예시 숫자를 COBOL 실행 결과나 모델 성능으로 해석하면 안 됩니다.

합성 ASCII 출력 12.34 LF를 숫자가 다른 출력과 CRLF 출력에 대조한 바이트 불일치 예시

그림 3. 설명용 합성 예시이며 실제 COBOL·모델 실행 결과가 아니다. 숫자 변화와 줄바꿈 차이는 서로 다른 불일치다. 실제 정답은 원본 실행과 업무 명세로 고정해야 한다. 출처: openai.com/index/low-resource-programming-languages.

“공백과 줄바꿈은 지우고 비교하자”는 편의 기능은 오히려 결함을 숨길 수 있습니다. 호출자가 고정 폭 레코드나 특정 인코딩을 기대한다면 그 형식도 외부 계약입니다. 반대로 외부 계약이 순서 없는 레코드 집합이라면 먼저 그 의미를 명세해야 합니다. 엄격한 바이트 비교와 의미 비교 중 어느 쪽이 항상 우월한 것이 아니라, 변경해서는 안 되는 경계를 합의하는 것이 먼저입니다. OpenAI의 COBOL 평가가 채택한 기준은 관찰 가능한 출력의 바이트 일치라는 점을 유지해야 합니다.

검수용 입력은 평범한 정상 값에만 몰리지 않도록 구성할 수 있습니다. 소수 자릿수의 경계, 음수, 빈 입력, 누락 레코드처럼 동작 차이를 드러낼 후보를 고르고, 원본의 실제 결과를 기준으로 기록하는 방식입니다. 이 목록은 공식 숨겨진 테스트의 구성을 알아냈다는 뜻이 아니라 이 글에서 제안하는 업무별 진단 항목입니다.

4. 승인 판단표: 컴파일 다음에 무엇을 확인할까요?

다음 표는 공식 평가 구조에서 도출한 편집상 판단 도구입니다. 실제 전환의 승인권자, 허용 차이와 재검사 범위는 팀의 업무 계약에 맞춰 정해야 합니다. 특히 알려진 원본 결함을 고치는 작업은 동작 보존 이관과 분리해 승인하는 편이 원인 추적에 유리합니다.

검수 상황 먼저 고정할 기준 비교할 증거 승인 보류가 필요한 신호
새 SQLite 호환 엔진 구현 초기 DB, 실행 SQL, 기준 SQLite 버전 변경된 DB에 대한 검증 쿼리의 기대 문자열 실행만 성공하고 검증 결과가 다름
기존 COBOL 코드의 언어 이관 원본 입력과 관찰 가능한 출력 형식 같은 입력에 대한 원본·후보 출력 바이트 값·공백·줄바꿈 중 계약 대상이 달라짐
소수 처리 규칙 변경 가능성 절삭·반올림과 자리수 규칙 경계 입력별 원본 기준 결과 익숙한 라이브러리 기본값을 근거 없이 사용
정상 입력만 통과한 후보 누락·빈 값 등 업무상 예외의 원본 동작 예외 입력에서의 출력과 오류 처리 기록 실패 처리 방식이 바뀌었는데 이유가 불명확
빠른 일부 테스트만 수행 테스트 목록과 성공 판정 단위 선택 범위, 통과 수, 실패 사례 부분 통과를 전체 검증 완료라고 보고
원본 계약 고정에서 비교·경계 검사·전문가 검토까지 이어지고 불일치 시 보류하는 승인 경로

그림 4. 공식 평가 설계를 업무 검수에 응용한 편집상 제안이다. 원본 기준을 먼저 고정하고 불일치는 보류한다. 부분 테스트 통과나 평가 성공은 운영 안전성의 보증이 아니다. 출처: openai.com/index/low-resource-programming-languages.

작업을 시작할 때 이 표에서 해당 행을 고르고, 원본 기준을 먼저 보관한 다음 후보 결과를 비교하면 실패를 분류하기 쉽습니다. 불일치는 숫자 계산, 출력 형식, 상태 변경, 오류 처리로 나눠 기록할 수 있습니다. 원인을 수정한 뒤에는 해당 사례만 재실행하는 데서 끝내지 않고 이미 보존되어야 했던 동작도 함께 회귀 검사하는 것이 이 글의 제안입니다.

실제 배포 결정에는 프로그램 바깥의 의존성도 필요합니다. 파일 인코딩, 호출 순서, 다른 서비스와 주고받는 데이터, 운영 중의 업무 규칙이 평가에 포함됐는지 따로 확인해야 합니다. 공식 설명도 운영 소프트웨어에 적용하려면 전문가 검토와 실제 업무 규칙 및 의존성에 맞춘 테스트가 여전히 필요하다고 명시합니다. 평가 통과는 그 검토를 대신하는 보증서가 아닙니다.

5. 보고서에는 테스트 범위를 숫자와 함께 남깁니다

README에는 기존 TCL 테스트 약 5만 1천 개 가운데 약 2만 4천 개를 이 형식으로 변환했다고 적혀 있습니다. 두 수치는 README의 51k, 24k를 옮긴 반올림 수량이며, 이 글에서 실제 파일 수를 센 결과가 아닙니다. 일반 평가에는 이름이 00, 01, 02로 시작하는 272개 테스트를 쓰도록 권장하고, 전체 세트를 실행했다면 이를 별도로 밝히라고 안내합니다.

따라서 “통과율이 높다”는 표현 옆에는 적어도 부분 세트인지 전체 세트인지, 어떤 구현과 조건에서 나온 수치인지를 붙여야 합니다. 272는 권장 부분 세트의 테스트 수이지 언어 수나 COBOL 과제 수가 아닙니다. COBOL의 숨겨진 테스트 세트가 공개됐다고 주장할 근거도 이 자료에는 없습니다.

실행 환경 안내의 범위도 주의해야 합니다. README는 모델 평가 환경에서 기존 SQLite 구현을 제거하고 인터넷 접근을 허용하지 않는 조건을 설명합니다. 이를 평소 사용하는 컴퓨터에서 SQLite를 삭제하라는 지침으로 받아들이면 안 됩니다. 이 글에서는 제거 스크립트나 벤치마크 코드를 내려받아 실행하지 않았습니다.

모델별 정확도와 API 비용 수치도 이 글의 판단표에는 넣지 않았습니다. 공급자 보고 점수를 운영 안정성이나 예상 이관 성공률로 오해하지 않도록, 여기서는 서로 다른 평가의 판정 대상과 테스트 범위에 집중했습니다. 새 기능의 정답과 기존 동작의 동일성을 나눠 기록하는 것만으로도 “컴파일 성공”이라는 모호한 완료 보고를 더 검증 가능한 결과로 바꿀 수 있습니다.

6. 근거와 해설의 경계

이 글은 공식 평가 설명을 바탕으로 작성한 검수 설계 해설이며, 모델 실행이나 COBOL 이관의 독립 재현 결과가 아니다. AI를 활용해 보존된 공개 자료를 정리했으며, 판단표·진단 항목·합성 출력 예시는 이 글에서 작성한 설명 도구입니다. 그림은 공식 제품 화면이나 측정 차트가 아닌 자체 제작 도해입니다.

OpenAI 본문은 당일 수집기가 보존한 브라우저 본문을 다시 읽었습니다. 수집 기록에는 신규 HTTP 요청의 403 응답이 남아 있어 이 글을 작성하며 해당 페이지의 최신 상태를 새로 확인했다고 주장하지 않습니다. MultiLangBench README도 아래 고정 커밋의 보존 본문을 사용했습니다. 읽은 자료가 뒷받침하는 범위는 평가 설계이며, 숨겨진 테스트의 상세 내용이나 개별 회사 시스템의 안전성이 아닙니다.

평가 설계와 검수 범위를 직접 확인하려면 아래 두 자료를 함께 읽는 것이 좋습니다.

댓글

이 블로그의 인기 게시물

체크아웃은 분리됐는데 Git 상태는 공유된다: Codex 0.154 worktree의 세 경계

잠근 작업이 커밋 뒤 다시 나온다: PostgreSQL 에이전트 큐의 소유권 설계

코딩 에이전트는 API 문서보다 AGENTS.md를 먼저 읽었다