Phase 3 · 데이터 시스템 자동화

사람이 놓치는 오류를 파이썬이 먼저 찾아냅니다

10만 건의 전표 중 음수 거래, 1억 이상의 고액, 중복 기장된 건을 사람이 어떻게 다 찾을까요?
파이썬이 회계적 룰(Rule)에 따라 검토 대상만 쏙 뽑아주는 자동 검증 시스템을 개발합니다.

예상 학습 시간 : 150분
난이도 : ★★★★☆
사전 단계 : 파일 통합, 데이터 클리닝
다음 단계 : 통계 기반 이상치 탐지 (예정)
01

시스템 업무 흐름: 검토 대상 좁히기

파이썬이 전문가의 판단을 대체하는 것이 아닙니다. 방대한 자료 속에서 "사람이 직접 확인해야 할 자료"를 신속하게 추려내는 것이 파이썬의 역할입니다.

① 데이터 클리닝 (Data Cleaning)

금액의 쉼표/원화 기호 제거, 날짜/사업자번호 형태를 숫자로 변환합니다.

② 룰 기반 검증 (Rule-based Detection)

필수 정보 누락, 중복 여부, 음수나 고액 등의 회계 룰 위반 여부를 검사합니다.

③ 등급 분류 (Classification)

각 행에 대해 정상 검토 오류 등급과 사유를 부여합니다.

④ 리포팅 (Reporting)

정상 데이터는 놔두고, 검토/오류 대상만 따로 뽑아 엑셀 시트로 출력합니다.

02

결측치(누락) 및 형식 불일치 검사

11단계에서 배운 데이터 정제 기술을 활용해 데이터를 규격화하고, 변환에 실패해 NaN(누락)이 된 자료를 색출합니다.

# 1. 필수 열이 아예 없는지 점검
required_cols = ["거래일자", "거래처", "공급가액"]
missing_cols = [c for c in required_cols if c not in df.columns]

# 2. 날짜/금액 변환 (잘못된 글자는 NaN 처리됨)
df["거래일자"] = pd.to_datetime(df["거래일자"], errors="coerce")
df["공급가액"] = pd.to_numeric(df["공급가액"].astype(str).str.replace(",", ""), errors="coerce")

# 3. 데이터가 비어있는 행(누락) 찾기
missing_date = df[ df["거래일자"].isna() ]
missing_amount = df[ df["공급가액"].isna() ]
03

이상거래(음수, 고액) 및 중복 탐지

금액이 음수인 건은 환입이나 취소일 수 있습니다. 중복된 건은 동일 거래처에서의 실거래일 수도 있고, 이중 기장일 수도 있습니다. 무조건 삭제하는 것이 아니라 검토 대상으로 색출해내는 것이 회계 프로그램의 핵심입니다.

# 음수 거래나 1억 원 이상의 터무니없는 고액 거래 (임의 기준)
negative_amt = df[ df["공급가액"] < 0 ]
high_amt = df[ df["공급가액"] >= 100000000 ]

# 날짜, 거래처, 금액이 완전히 동일한 행 찾기 (keep=False로 원본/복사본 모두 추출)
df["중복의심"] = df.duplicated(subset=["거래일자", "거래처", "공급가액"], keep=False)
주의: 음수는 오류가 아닙니다

수정 세금계산서 발급이나 반품 등으로 인해 음수 매출/매입은 정상적으로 발생할 수 있습니다. 프로그램에서 '오류'로 튕겨내지 말고 '검토(Review)' 대상으로 남겨두어 회계사가 판단하게 만들어야 합니다.

04

오류 vs 검토 vs 정상 (등급 분류)

이제 하나의 행(Row)을 받아, 조건에 따라 등급 문자를 반환해주는 Python 함수 apply를 만듭니다.

# 1. 기본은 "정상"
df["검토등급"] = "정상"

# 2. 필수값이 비어있으면 "오류" 덮어쓰기
df.loc[ df["거래일자"].isna() | df["공급가액"].isna(), "검토등급" ] = "오류"

# 3. 누락은 아니지만 값이 이상하거나 중복인 경우 "검토" 덮어쓰기 (오류가 우선되지 않도록 순서 주의)
df.loc[ (df["공급가액"] < 0) | (df["공급가액"] >= 100000000) | (df["중복의심"] == True), "검토등급" ] = "검토"
거래처금액검토등급
ABC상사5,000,000정상
DEF기업150,000,000검토 (고액)
GHI상사-2,000,000검토 (음수)
JKL기업NaN오류 (누락)
05

검토사유 자동 코멘트화

단순히 '검토'라고만 적혀있으면 실무자가 왜 이 건이 검토 대상인지 다시 확인해야 합니다. 파이썬 함수로 코멘트를 자동 생성해줍니다.

def check_reason(row):
    reasons = []
    if pd.isna(row["거래일자"]): reasons.append("거래일자 누락")
    if pd.isna(row["공급가액"]): reasons.append("공급가액 누락")
    elif row["공급가액"] < 0:      reasons.append("음수 금액")
    elif row["공급가액"] >= 100000000: reasons.append("고액 거래")
    
    if row["중복의심"]: reasons.append("중복 기장 의심")
    
    return ", ".join(reasons) # 리스트 요소들을 쉼표로 이어붙임

# df의 각 행(axis=1)마다 함수를 적용하여 새로운 열 생성
df["검토사유"] = df.apply(check_reason, axis=1)

이렇게 하면 "고액 거래, 중복 기장 의심" 과 같이 한 건에 여러 사유가 겹쳤을 때도 모두 표기해줄 수 있습니다.

06

최종 실무: 10만 건 자동 검증 및 다중 시트 리포팅

13단계의 최종 솔루션 코드입니다. 회사에 돌아가서 바로 엑셀을 돌려볼 수 있습니다.

Master Script
전표 데이터 무결성 체크 및 리포트 자동 생성기
import pandas as pd

# 1. 데이터 읽기 및 정제
df = pd.read_excel("transactions_raw.xlsx")
df["거래일자"] = pd.to_datetime(df["거래일자"], errors="coerce")
df["공급가액"] = pd.to_numeric(df["공급가액"].astype(str).str.replace(r"[^\d-]", "", regex=True), errors="coerce")
df["중복의심"] = df.duplicated(subset=["거래일자", "거래처", "공급가액"], keep=False)

# 2. 사유(코멘트) 함수 정의
def get_issue(row):
    msg = []
    if pd.isna(row["거래일자"]) or pd.isna(row["공급가액"]): msg.append("필수값 누락")
    elif row["공급가액"] < 0: msg.append("음수 금액")
    elif row["공급가액"] > 50000000: msg.append("고액 주의")
    if row["중복의심"]: msg.append("중복 기장")
    return ", ".join(msg)

# 3. 등급 및 사유 부여
df["검토사유"] = df.apply(get_issue, axis=1)
df["검토등급"] = "정상"
df.loc[df["검토사유"] != "", "검토등급"] = "검토"
df.loc[df["검토사유"].str.contains("누락"), "검토등급"] = "오류"

# 4. 검토가 필요한 데이터만 쏙 빼내기!
review_target = df[df["검토등급"] != "정상"]

# 5. 깔끔한 엑셀 보고서 생성
with pd.ExcelWriter("회계검증보고서.xlsx", engine="openpyxl") as writer:
    # 첫 번째 시트: 사람이 확인해야 할 문제 데이터만 모음집
    review_target.to_excel(writer, sheet_name="🚨검토대상요약", index=False)
    # 두 번째 시트: 원본 및 전체 데이터 상태
    df.to_excel(writer, sheet_name="전체자료", index=False)

print(f"✅ 총 {len(df)}건 중 {len(review_target)}건의 검토 대상을 찾아 엑셀로 저장했습니다.")
14단계 예고: 통계 기반 이상치 탐지 (Z-Score)

지금까지는 "1억 원 이상", "음수" 처럼 사람이 정한 룰(Rule) 기반 검증이었습니다. 하지만 거래처 A는 원래 매달 5억을 거래하고, 거래처 B는 50만 원을 거래한다면 룰 하나로 막을 수 없습니다.
다음 14단계에서는 표준편차와 Z-score를 이용해 "이 거래처 평소 거래패턴 치고는 너무 이례적으로 큰데?" 라는 통계/AI 기반의 똑똑한 이상 탐지 기법을 배웁니다.

Step 12 : DB & SQL 연동 Step 14 : 통계 기반 이상치 탐지 (준비중)