일단 한 대 쳐 보고

AI가 '처리 완료'라고 한 합계가 틀렸을 때: 손 계산과 행 수 대조로 잡는 방법

AI가 써 준 스크립트가 "처리 완료"라고 출력해도 합계가 맞다는 뜻은 아닙니다. 아래 예시(AI가 써 줬다고 가정하고 직접 만든 스크립트)에서는 7행짜리 매출표를 읽고 "처리 완료: 5행, 합계 90,500원"이라고 출력했는데, 손으로 더하면 57,500원입니다. 오류 메시지는 한 줄도 없었습니다. 이런 경우를 잡는 데는 세 가지면 충분했습니다. 값 몇 개를 손으로 더해 비교하고, 입력 행 수가 "계산한 행 + 일부러 뺀 행"과 같은지 보고, 일부러 틀린 입력을 하나 넣어 보는 것입니다.

왜 '완료'가 증거가 못 되는가

AI가 낸 "완료했습니다"는 코드가 끝까지 돌았다는 뜻이지 결과가 맞다는 뜻이 아닙니다. 글쓴이의 작업 기록에도 같은 모양이 여러 번 있었습니다.

모두 겉으로는 정상 종료였습니다. 오류가 났다면 오히려 쉽게 찾았을 것입니다.

예시: 5행, 90,500원

예시 파일은 날짜, 품목, 금액 세 열입니다. 금액 중 두 칸은 15,000처럼 쉼표가 들어간 글자이고, 마지막 줄은 엑셀에서 흔히 넣는 합계 줄입니다. 파일은 openpyxl로 만들었습니다.

AI가 이런 식으로 써 줬다고 가정한 스크립트입니다.

import pandas as pd
df = pd.read_excel("sales.xlsx")
df["금액"] = pd.to_numeric(df["금액"], errors="coerce")
df = df.dropna(subset=["금액"])
print(f"처리 완료: {len(df)}행, 합계 {df['금액'].sum():,.0f}원")

실행 결과입니다.

처리 완료: 5행, 합계 90,500원

표를 눈으로 보면 이상한 점이 바로 보입니다. 입력은 7행인데 5행을 처리했고, 합계가 개별 금액을 다 더한 값보다 큽니다. 하지만 "처리 완료"라는 말을 믿고 넘어가면 이 차이를 볼 일이 없습니다.

1단계. 손으로 몇 개 더해 본다

금액 칸을 다 더할 필요는 없습니다. 눈에 보이는 개별 줄 6개를 직접 더해 봤습니다.

12000+8000+15000+6000+9500+7000 = 57500

AI 스크립트의 90,500원은 손 계산 57,500원과 33,000원 차이가 납니다. 이 한 번의 계산으로 "합계 값을 믿으면 안 된다"는 것은 확인됩니다. 어디가 틀렸는지는 아직 모릅니다.

2단계. 행 수를 맞춰 본다

원인은 '입력 행 수 = 계산에 쓴 행 + 일부러 뺀 행 + 읽지 못한 행'이 맞는지 보면 잡힙니다. 이 식이 안 맞는 곳에서 무엇이 빠졌거나 더해졌는지 찾을 수 있습니다. 칸의 값 형태를 같이 찍어 봤습니다.

import pandas as pd
raw = pd.read_excel("sales.xlsx")
print("입력 행수:", len(raw))
print("금액 칸 타입:", raw["금액"].map(type).value_counts().to_dict())
num = pd.to_numeric(raw["금액"], errors="coerce")
print("숫자로 못 바뀐 행:"); print(raw[num.isna()])
입력 행수: 7
금액 칸 타입: {<class 'int'>: 5, <class 'str'>: 2}
숫자로 못 바뀐 행:
           날짜  품목      금액
2  2026-10-02  사과  15,000
4  2026-10-03   배   9,500

원인이 두 개로 갈렸습니다.

  1. 15,000과 9,500은 글자라서 errors="coerce"가 조용히 빈 값으로 바꾸고, dropna가 그 줄을 지웠습니다. 두 줄, 24,500원이 사라졌습니다.
  2. 합계 줄 57,500원은 숫자이므로 그대로 더해졌습니다.

계산하면 33,000(AI가 더한 개별 줄 4개) 위에 57,500(합계 줄)이 얹혀 90,500이 됩니다. 첫 번째 함정은 pandas to_numeric Unable to parse string '1,000' 오류: errors='coerce'로 없애면 금액이 사라집니다 글에서 따로 다뤘습니다.

3단계. 같은 점검을 코드 안에 넣는다

고친 스크립트는 결과를 내기 전에 행 수 식을 직접 출력합니다. 이렇게 하면 다음에 입력이 바뀌어도 어긋난 곳이 바로 보입니다.

import pandas as pd
raw = pd.read_excel("sales.xlsx")
sub = raw["품목"].astype(str).str.contains("합계|소계")
body = raw[~sub].copy()
amount = pd.to_numeric(body["금액"].astype(str).str.replace(",", ""), errors="coerce")
bad = body[amount.isna()]
print(f"입력 {len(raw)}행 = 계산 {amount.notna().sum()}행 + 합계 줄 {sub.sum()}행 + 읽지 못함 {len(bad)}행")
if len(bad): print(bad)
print(f"합계 {amount.sum():,.0f}원 (파일의 합계 줄 값: {raw.loc[sub,'금액'].sum():,.0f}원)")
입력 7행 = 계산 6행 + 합계 줄 1행 + 읽지 못함 0행
합계 57,500원 (파일의 합계 줄 값: 57,500원)

손 계산 57,500원과 일치하고, 파일에 적힌 합계 줄과도 같습니다. 읽지 못한 행이 있으면 0으로 처리하지 않고 목록으로 보여 줍니다. 합계 줄을 합계|소계 낱말로 찾는 방식은 이 예시에서만 확인했습니다. 총합, Total, 건수 같은 줄은 못 잡을 수 있어서, 합계 줄이 있는 파일이라면 낱말 목록을 파일에 맞게 고치고 마지막에 "파일의 합계 줄 값"과 비교해야 합니다. 글쓴이가 만든 합계 프로그램도 처음에는 합계, 소계만 걸렀고, 시험에서 총합, 합계:, Total:, 누적 같은 줄이 더해지는 것이 나온 뒤 낱말을 늘렸습니다. 상품 코드와 구별되지 않는 건수 줄은 끝까지 못 잡아서 날짜 칸을 비워 두라고 안내하는 것으로 남겼습니다.

4단계. 일부러 틀린 입력을 넣는다

점검 코드가 정말 도는지도 확인해야 합니다. 정상 파일에서만 시험하면 점검이 아무 일도 안 해도 모릅니다. 위 예시처럼 쉼표가 든 글자 금액, 합계 줄, 날짜가 빈 줄을 일부러 넣은 파일을 만들어 점검이 숫자를 내는지 봅니다. 위에 적은 사례도 점검 결과 0건이라는 말이 틀렸다는 것을, 장부 3종에 118가지 입력을 넣어 본 뒤에야 알았습니다.

매번 AI에게 시킬 때 쓰는 요청 문구

코드를 부탁할 때 처음부터 아래 문장을 붙여 점검 줄을 함께 요청합니다. AI 도구마다 받는 코드는 다르니, 받은 뒤에는 4단계처럼 틀린 입력을 넣어 점검 줄이 실제로 반응하는지 보세요.

결과를 출력할 때 "입력 N행 = 계산 A행 + 제외 B행(이유별) + 읽지 못함 C행"을 함께 출력해 주세요.
읽지 못한 값은 0으로 바꾸거나 지우지 말고 목록으로 보여 주세요.

정리