AI에게 의존하여 만든 함수가 작동했습니다. 화면에도 그럴듯한 금액이 표시됩니다. 그럼에도 불구하고, 실제로 자신의 애플리케이션에 통합하기 직전에 "이대로 사용해도 괜찮을까"라며 손이 멈추는 경우가 있습니다.
이러한 불안감을 줄이기 위해서는 AI에게 다시 한번 "맞는지?"라고 묻기보다는, 어떤 입력값일 때 얼마가 되어야 하는지 스스로 결정하고 확인하는 것이 판단 자료가 됩니다. 이번 예시에서는, 999엔과 1,001엔에는 올바르게 답하지만, 그 중간인 1,000엔에서만 틀리는 함수를 다룹니다.
짧은 할인 함수를 사용하여 기대값을 결정하고, 실패 지점을 찾고, 수정을 확인하며, 최종적으로 통합 여부를 판단하는 과정을 진행합니다. 글을 마치면, 자신이 가진 작은 계산 함수에 대해 "무엇을 확인했기 때문에 채택할지", 혹은 "무엇이 불분명하여 보류할지"를 설명할 수 있는 상태가 목표입니다.
Node.js로 파일을 실행할 수 있는 분들을 대상으로 합니다. 작성 당시에는 Windows 및 Node.js v24.19.0을 사용하여 2026년 10월 30일에 실행했으며, 공개 전 독립 검증 시에도 Linux 및 Node.js v24.19.0으로 동일한 출력을 확인했습니다. 이 예시만으로는 인증이나 외부 통신이 수반되는 전체 애플리케이션의 안전성을 판단할 수는 없습니다.
이번 사양은 "구매액이 1,000엔 이상이면 100엔 할인"입니다. 금액은 0 이상의 안전한 정수형으로 받으며, 문자열, 음수, 소수점 등은 거부합니다.
여기서 코드를 보기 전에, 다음 세 가지 질문에 대한 답을 먼저 결정해 주세요.
| 구매액 | 기대하는 지불액 | 확인해야 할 것 |
|---|
| 999엔 | 999엔 | 할인 조건 직전에서는 적용하지 않음 |
| ... | | |
"1,000엔 이상"의 "이상"이 중간 줄에 나타나 있습니다. 일반적인 구매액을 수십 건 시도하더라도, 이 한 줄을 놓치면 경계에서의 오류가 남아 있을 수 있습니다.
기대값을 AI 함수로부터 계산할 경우, 같은 오류를 정답 측으로 옮겨 적을 위험이 있습니다. 먼저 일본어 사양(日本語の仕様)에서 손으로 답을 도출하는 것이 검증의 출발점입니다. 세금이나 반올림 처리가 있다면, 그 답을 누가 결정할지 미리 확정해야 합니다.
새로운 연습용 폴더를 만들고, 다음 내용을 verify.mjs로 저장합니다. 외부 패키지 설치는 필요하지 않습니다.
proposed는 검증할 제안 코드이며, fixed는 수정된 버전입니다. 둘 다 동일한 기대값으로 평가됩니다. 이 예시에는 파일 삭제나 외부 통신은 없습니다. 이는 미지의 AI 생성 프로그램 전반에 대해 확인 없이 자신의 단말기에서 실행해도 좋다는 의미가 아닙니다.
import assert from 'node:assert/strict';
const proposed = yen => yen > 1000 ? yen - 100 : yen;
function fixed(yen) {
...
저장한 폴더에서 실행합니다.
실제 출력은 다음과 같았습니다.
$ node verify.mjs
proposed 999: PASS
proposed 1000: FAIL
...
종료 코드는 0(정상 종료)이었습니다. proposed 1000: FAIL은 연습의 실패가 아닙니다. 잘못된 제안을 발견했다는 증거입니다. 제안 코드의 >는 1,000엔을 할인 대상에 포함하지 않습니다. 수정 버전의 >=는 포함합니다. 수정 버전은 3가지 경계값 외에도 부적절한 입력 4가지를 예외로 거부할 수 있었기 때문에 마지막까지 PASS했습니다.
참고로, 제안 코드의 불일치는 표시만 할 뿐이므로, 이 파일이 정상 종료되었다는 것(종료 코드 0)만으로는 제안 코드가 합격했음을 의미하지 않습니다. 수정 버전의 검사는 assert를 사용하여 멈추도록 설정했습니다. 테스트의 "종료됨"과 "무엇이 통과했는지"를 분리하여 읽어주세요. 종료 코드를 직접 확인하고 싶다면, bash 계열 터미널에서는 `node verify.mjs; echo
⚠️ [IMG:N] 형식 토큰은 이미지 placeholder 입니다. 번역하지 말고 원래 위치에 그대로 유지하세요.
| 발생한 문제 | 먼저 확인할 곳 | 다음 행동 |
|---|
node를 찾을 수 없음 | Node.js 설치 및 터미널 환경 | node --version으로 실행 가능한지 확인한다. 아직 함수 자체의 문제라고 판단하지 않는다. |
| 파일을 찾을 수 없음 | 현재 폴더와 파일 이름 | verify.mjs.txt처럼 되어 있지는 않은지, 저장 위치를 확인한다. |
| 구문 오류로 시작하지 않음 | 복사한 파일 | Markdown의 감싸는 기호까지 저장하지 않았는지 확인한다. |
| 제안 사례가 1,000엔에서 PASS됨 | proposed 조건 | 먼저 수정된 버전으로 대체되지 않았는지 비교한다. |
| 수정된 버전의 assert에서 멈춤 | 예외로 발생한 실제 값・기대 값 | 기대 값을 실제 값에 맞추지 않고, 일본어 명세와 변경된 부분을 대조한다. |
이 표는 결과가 일치하지 않을 경우 확인 순서입니다. 각 환경 트러블을 이번에 모두 재현한 것은 아닙니다.
불일치를 발견할 때마다 기대 값을 변경하면, 테스트가 구현에 따르게 될 뿐입니다. '명세를 바꾼 것'인지 '구현을 수정한 것'인지를 구분하고, 후자라면 원래의 기대 값으로 통과할 때까지 확인해야 합니다.
할인 함수라면 0엔, 정확히 1,000엔, 상한 근처, 부적절한 타입을 후보로 할 수 있습니다. 글자 수 제한이라면 '상한의 1글자 전・일치・1글자 초과', 건수 제한이라면 '0건・1건・상한'으로 읽어낼 수 있습니다. 공통적인 것은 처리 분기점을 일본어 설명에서 구체적인 값으로 바꾸는 것입니다.
다만, 함수만 정확하더라도 호출 측에서 문자열인 '1000'을 전달하고 있다면, 이번 수정 버전은 거부합니다. 그럴 경우에는 함수의 검사를 제외하기 전에 '입력을 숫자로 변환할 책임이 어디에 있는지'를 확인해야 합니다. 폼(form)에서 호출하는 경우라면, 실제 입력이 어떤 타입으로 도착하는지를 별도로 확인해야 합니다.
자신의 프로젝트에 통합하기 전에는 먼저 git status --short로 대상 파일을 확인합니다. ??로 표시되는 새로 추적되지 않은 파일은 일반적인 git diff에서는 나오지 않기 때문에, 파일을 직접 열어 전체를 읽어야 합니다. 차이점이 비어 있더라도 추가된 코드가 없을 것이라고 단정할 수 없습니다.
추적된 변경 사항에는 git diff --check로 공백 등의 문제를 조사하고, git diff --로 변경 내용을 확인합니다. 스테이징된(staged) 경우라면 --cached를 붙인 차이점이 대상입니다. 이들은 코드의 정확성이나 안전성을 판단하는 그 자체가 아닙니다. 할인 조건 수정과 무관한 설정 변경이나 새로운 의존 관계가 섞여 있지 않은지 읽기 위해 사용합니다.
이번 경우에는 다음과 같이 판단할 수 있습니다.
정수 엔 금액에 대한 100엔 할인 처리로서, 경계 3건과 부적절 입력 4건을 확인했습니다. 세금・자릿수 처리・쿠폰 병용은 대상이 아니므로, 해당 부분을 사용하는 곳에 이 결과만으로 채택하지 않습니다.
판단을 보류해야 하는 경우는 기대 값을 정할 수 없거나, 테스트가 실패하거나, 변경의 이유를 설명할 수 없거나, 필요한 실행 환경을 준비할 수 없을 때입니다. 보류는 작업의 후퇴가 아니라, 무엇을 확인하면 진행할 수 있을지가 명확해진 상태입니다.
다음으로 AI로부터 함수를 받았다면, 실행 버튼을 누르기 전에 '조건이 바뀌는 입력'을 하나 찾아보세요. 성공 사례만 살펴보던 확인 과정이, 채택의 근거를 만드는 확인 과정으로 바뀝니다.
이 주제를 스스로 시도하며 배우고 싶은 분들을 위해. 프로그래밍 학습 서비스 CodeNest에서는 AI에게 질문하면서 코드를 작성하며 배울 수 있습니다 (운영: Hatch IT).