AI 활용

엑셀 너머 대시보드 ② 엑셀을 DB로 옮기며 4번 막힌 적재·집계 작업기

피노K

2026년 5월부터 9월까지 실적 엑셀을 DB로 옮기는 적재·집계 층을 만들었습니다. 그동안 크게 4번 막혔습니다. 파일이 안 열리고, 열이 섞이고, 숫자가 엑셀과 다르게 나왔습니다.

1편에서는 대시보드를 원천, 저장소, 계산, 화면 네 층으로 나눴습니다. 그림으로는 간단했지만, 엑셀을 DB에 넣기 시작하자 엑셀에서는 보이지 않던 문제가 드러났습니다. 대부분 오류 문구만 보고는 원인을 알기 어려웠습니다.

먼저 결론

  • 보안 프로그램이 암호화한 엑셀은 프로그램이 읽지 못해, 내부 저장 형식을 따로 정했습니다.
  • 한 열에 숫자와 문자가 섞여 저장이 실패했고, 첫 수정은 절반만 고쳤습니다.
  • 집계표에 없는 항목은 계약 단위 데이터에서 다시 계산해 숫자 정의를 맞췄습니다.
  • 화면을 켠 채 적재하자 예전 숫자가 조용히 보였고, 방향을 세 번 바꾼 끝에 적재를 분리했습니다.

1. 보안 프로그램이 잠근 엑셀은 프로그램이 읽지 못했다

목표는 사내 시스템에서 내려받은 엑셀 5종을 폴더에 넣으면 DB까지 자동으로 들어가게 하는 것이었습니다. 파일 종류마다 이번 달 것으로 통째로 바꿀지, 이전 것에 이어 붙일지도 정했습니다. 월별 실적은 교체, 지급·환수 내역은 누적 후 중복 제거입니다.

AI에게는 파일 이름으로 종류를 판별하는 흐름을 만들게 했습니다. 엑셀을 Parquet라는 압축 파일로 바꾼 뒤 DuckDB에 넣습니다. 처리한 엑셀은 보관 폴더로 옮겨 같은 파일이 두 번 들어가지 않게 했습니다.

그런데 내려받은 엑셀을 그대로 넣으면 적재가 되지 않았습니다.

회사 보안 프로그램이 다운로드 파일을 자동으로 암호화하고 있었습니다. 사람은 엑셀로 열 수 있어도, 프로그램은 내용을 읽을 수 없었습니다.

처음에 어떤 가설을 거쳤는지는 기록에 남아 있지 않습니다. 남아 있는 결론은 "암호화된 파일은 읽을 권한이 없다"는 것입니다.

그래서 적재 폴더에는 보안을 해제한 일반 엑셀만 넣도록 규칙을 정했습니다. 시스템 안에 저장하는 형식도 다시 잠길 수 있는 엑셀 대신 Parquet와 DB만 쓰기로 했습니다.

2. 숫자와 문자가 섞인 열은 한 번에 다 고쳐지지 않았다

다음 목표는 여러 달 파일을 하나로 이어 붙여 누적 데이터를 만드는 것이었습니다.

2026년 9월 1일, 일부 월 파일이 Expected bytes, got a float 오류를 내며 저장되지 않았습니다. 전화번호 같은 열에 숫자와 문자가 섞여 있었습니다.

저는 엑셀이 칸마다 형식을 따로 추측한 것이 원인이라고 봤고, 맞았습니다. 그래서 파일 하나를 변환하는 단계에서 섞인 열을 문자로 통일했습니다.

열흘 뒤인 9월 11일, 이번에는 여러 달을 합치는 단계에서 Expected bytes, got a 'int' object 오류가 났습니다. 계약번호가 어떤 달은 숫자로, 어떤 달은 문자로 읽혀 합치는 순간 섞인 것입니다.

첫 수정은 파일 하나 단계에만 들어가 있었습니다. 합치는 단계에는 없었습니다.

처음에는 코드를 고치다 생긴 문제인지 의심했습니다. 확인해 보니 코드가 아니라 들어온 데이터가 계기였습니다. 문자로 통일하는 처리를 공용 함수로 빼서 모든 단계에 넣었습니다.

이때 중복 제거도 함께 확인했습니다. 같은 계약번호가 숫자와 문자로 섞이면 서로 다른 값으로 보여 중복이 지워지지 않습니다. 그래서 중복 제거 전에 먼저 문자로 맞추도록 순서를 바꿨습니다.

3. 집계표에 없는 항목은 계약 단위 데이터에서 다시 셌다

이번 목표는 신인 지원금 평가를 자동으로 하는 것이었습니다. 평가 실적은 전체 실적에서 자동차·일반보험, 자기계약, 승환계약을 뺀 값입니다.

먼저 데이터의 합이 맞는지부터 확인했습니다. 전체 실적이 신계약 실적과 유지 실적의 합과 같은지 봤습니다. 신계약 실적이 상품군별 합과 같은지도 대조했고, 둘 다 맞았습니다. 그다음 월별 집계표에서 자동차·일반·자기계약을 빼게 했습니다.

문제는 월별 집계표에 승환계약 열이 없다는 점이었습니다. 승환계약을 빼지 않으면 평가 실적이 실제보다 크게 나옵니다.

저는 집계표에는 없어도 계약 단위 데이터에는 승환 여부가 있을 것이라고 봤고, 있었습니다. 계약 단위 데이터에서 승환계약을 사람별·월별로 다시 합산해 집계표에서 뺐습니다.

이중으로 빼지 않는지도 확인했습니다. 승환계약은 전부 생명·장기 상품이었습니다. 따로 빼는 자동차·일반보험과 겹치지 않았습니다. 마지막으로 한 사람의 한 달 값을 골라 손계산과 대조했습니다.

4. 화면을 켠 채 적재하자 틀린 숫자가 조용히 보였다

9월 중순, 대시보드를 한 번 여는 데 26초가 걸렸습니다. 요약 계산을 70번가량 부르면서 매번 DB 연결을 새로 열고 있었습니다. 목표는 연결을 다시 쓰고 결과를 저장해 두도록 고쳐 시간을 줄이는 것이었습니다.

시간은 줄었지만, 화면을 켠 채 데이터를 적재하자 DB가 연결을 거부했습니다. 화면은 읽기 전용으로, 적재는 쓰기로 같은 DB 파일을 열려다 충돌한 것입니다.

첫 가설은 "화면과 적재가 한 프로그램에 있어서"였습니다. 적재를 별도 실행 프로그램으로 떼어 냈더니 충돌은 사라졌습니다. 하지만 데이터를 넣을 때마다 화면을 끄고 다른 프로그램을 켜야 해서 번거로웠습니다.

같은 날 두 번째 가설을 세웠습니다. "읽기와 쓰기 모드가 섞인 것이 원인"이라고 보고, 내 PC에서는 화면도 쓰기 모드로 열도록 통일했습니다. 별도 프로그램은 지웠습니다.

그런데 적재 과정에는 기존 DB 파일을 지우고 새로 만드는 단계가 있었습니다. 화면이 파일을 잡고 있어 삭제가 꼬였고, DB 본체가 사라지는 사고가 났습니다. 그래서 파일을 지우지 않고, 열린 DB 안에서 표를 바꿔 끼우는 방식으로 고쳤습니다.

나흘 뒤, 화면에 이번 달 실적이 실제의 약 4분의 3만 표시되는 것을 발견했습니다. 오류 메시지는 없었습니다.

원천 표는 새로 들어왔지만, 그것으로 만드는 보고용 표가 다시 만들어지지 않았던 것입니다. 이전에는 실패하면 빈 화면이 떴습니다. 이제는 틀린 숫자가 조용히 보이는 상태로 바뀌어 있었습니다.

세 번째로 저는 화면을 켠 채 적재하는 것 자체가 문제라고 판단했습니다. 적재는 화면을 끈 상태에서만 돌도록 다시 분리했고, 화면이 켜져 있으면 끌지 묻게 했습니다.

같은 일이 다시 조용히 지나가지 않도록 검사도 붙였습니다. 적재가 끝나면 최신 월의 원천 건수와 보고용 표 건수를 비교합니다. 97% 미만이면 실패로 표시합니다. 다시 적재한 뒤 이번 달 실적이 정상 값으로 돌아온 것을 확인했습니다.

바꾼 것과 아직 못 한 것

바꾼 것은 세 가지입니다. 시스템 안에는 엑셀 대신 Parquet와 DB만 저장합니다. 섞인 열은 모든 단계에서 문자로 맞춥니다. 적재는 화면과 분리하고, 끝날 때 건수를 대조합니다.

아직 못 한 것도 있습니다. 예외 계약을 다시 반영하는 기능은 여전히 화면 안에서 DB에 쓰고 있어 같은 위험이 남아 있습니다. 사내 시스템에서 데이터를 직접 받아오는 방식도 아직 엑셀 적재에 머물러 있습니다.

오류 문구보다 데이터가 들어온 길을 먼저 봐야 했다

네 번 모두 오류 문구보다 "데이터가 어떻게 들어왔는지"를 먼저 봐야 원인이 보였습니다. 같은 일을 겪을 때의 확인 순서를 남겨 둡니다.

  • 저장 실패: 코드보다 그달 파일의 열 형식을 먼저 확인했습니다.
  • 숫자 불일치: 화면을 고치기 전에 데이터의 합이 맞는지 항등식부터 대조했습니다.
  • 조용한 오류: 실패를 막는 것보다 실패가 보이게 만드는 검사를 먼저 붙였습니다.

적재와 집계는 화면이 없어서 잘 드러나지 않는 층입니다. 여기서 틀린 숫자는 아무리 좋은 화면에 올려도 틀린 숫자입니다. 이번 작업에서 가장 오래 걸린 일도 데이터가 어떻게 들어오고 언제 갱신되는지를 맞추는 일이었습니다.

다음 편에서는 이 판을 내 PC 밖 서버로 올리면서 생긴 화면, 개인정보, 동시 접속 문제를 적습니다.

'AI 활용' 카테고리의 다른 글