
Python을 사용하여 AI 도구 청구 CSV에서 미사용 유료 계정 찾아내기
요약
Python을 사용하여 AI 도구의 청구 데이터와 이용 로그 CSV를 대조해 미사용 유료 계정을 식별하는 방법을 소개합니다. 이메일과 도구 이름을 조합하여 정확도를 높이고, 최신 이용일을 기준으로 관리 효율을 높이는 실무적인 접근법을 다룹니다.
핵심 포인트
- 청구 CSV와 이용 로그를 대조하여 비용 절감 기회 포착
- 이메일과 도구(tool)를 조합하여 계정 식별 오류 방지
- max() 함수를 사용하여 가장 최신 이용 로그를 기준으로 판정
- 정확한 데이터 기반의 자산 실사로 관리 신뢰도 확보
2026년 7월, Okta의 기업용 AI 지수에 따르면 「단일 AI 제공자만을 사용하는 회사」가 전월 대비 1.2포인트 감소했다고 합니다. 현장의 감각으로도, ChatGPT만 사용하던 팀에 Claude, Gemini, Notion AI가 겹쳐지고 있습니다. 월 이용료가 몇 천 엔이라도, 계정(seat) 수가 늘어나면 경비의 가시성이 급격히 나빠집니다.
저는 예산 회의에서 AI 이용률을 묻기 전에, 유료 계정의 최종 이용일을 산출하는 것이 우선이라고 생각합니다. 해지 후보를 결정하기 위해서가 아닙니다. 계약 주체, 사용 부서, 대체 수단을 확인하기 위한 짧은 목록을 만들기 위해서입니다.
여기에서는 청구 CSV와 이용 로그 CSV를 대조하여, 45일 이상 움직임이 없는 유료 계정을 찾아내는 Python 코드를 소개합니다. 외부 API는 사용하지 않습니다. 관리 화면에서 추출한 CSV를 그대로 수중에 가지고 확인하는 용도입니다.
AI 도구의 자산 실사(棚卸し)에서 흔히 하는 실수는, 청구서의 계정 수만 집계하고 끝내는 것입니다. 예를 들어 영업부에 10개의 계정이 있다는 것을 알아내더라도, 그 10개의 계정을 누가 언제 사용했는지는 알 수 없습니다. 갱신 월이 다가와서 물어보면, 사용자와 계약 담당자 모두 기억이 모호합니다.
필요한 것은 다음 두 가지뿐입니다.
| CSV | 필수 열 | 역할 |
|---|---|---|
seats.csv | email,tool,plan,monthly_yen | 청구 대상 계정을 결정 |
activity.csv | email,tool,last_used_at | 마지막 사용일을 보유 |
동일한 사람이 여러 도구를 사용하므로, 이메일 주소 단독으로는 연결하지 않습니다. email과 tool의 조합으로 대조합니다. 이 부분을 이메일로만 설정하면, Gemini를 사용하니까 Notion AI도 사용하고 있다고 오판하게 됩니다. 사소해 보이지만, 이 부분이 가장 효과적입니다.
아래 코드는 Python 3.12에서 실행하였으며, 다음과 같은 출력이 나오는 것을 확인했습니다. 기사 내에 샘플 CSV도 문자열로 포함되어 있으므로, 우선 그대로 붙여넣어 실행할 수 있습니다. 실무에서는 SEATS_CSV와 ACTIVITY_CSV의 내용을 CSV 파일에서 읽어온 문자열로 교체해 주세요.
import csv
from datetime import date, datetime, timedelta
from io import StringIO
...
실행 결과입니다. 7월 23일을 기준으로 하면, 6월 8일 이전의 이용은 확인 후보가 됩니다. Cursor는 6월 8일과 7월 20일의 로그가 있지만, 후자를 채택합니다.
판정 기준: 2026-06-08 이전 확인 후보
확인 후보 (3개 계정 / 월 합계 7,400엔)
sales@example.com Notion AI Plus 최종 이용: 2026-05-31 1,500엔
...
이용 로그 CSV는 로그인할 때마다 한 줄씩 늘어나는 형식이 많습니다. 여기서 처음 발견된 날짜만 사용하면, Cursor처럼 6월 8일과 7월 20일 모두에 로그가 있는 계정까지 사용하지 않는 것처럼 보일 수 있습니다. 코드에서는 max()를 사용하여 최신 날짜만 남깁니다.
이 처리는 작아 보이지만, 월간 운영에서는 차이를 만듭니다. 오래된 로그로 잘못 확인을 요청하면, "매일 사용하고 있습니다"라는 답변을 듣게 되고, 자산 실사 자체의 신뢰도가 떨어지기 때문입니다. 후보의 수를 많이 뽑기보다, 확인이 필요한 계정을 적고 정확하게 제시하는 것이 담당자를 움직이게 합니다.
이번 예시에서는 월 7,400엔, 연간으로 환산하면 88,800엔입니다. 하지만 금액이 작다고 해서 뒤로 미루면, 동일한 계정이 다음 달에도 남게 됩니다. 금액의 대소보다, 사유가 공란인 계정을 남기지 않는 것을 목적으로 합니다.
대상 결정 방식이 흔들리지 않는다면, 확인 요청도 매달 동일한 패턴으로 진행할 수 있습니다.
도구 이름의 표기 불일치(表記ゆれ)에도 주의가 필요합니다. 청구 CSV가 Google Gemini이고 이용 로그가 Gemini라면, 이대로는 별개의 제품으로 취급됩니다. 우선 10줄 정도 눈으로 확인하여 제품명이 일치하는지 확인하세요. 일치하지 않는 제품에 대해서는 CSV를 수정하거나 대응표를 한 장 준비합니다. 처음부터 복잡한 데이터 정제(名寄せ)를 만들 필요는 없습니다.
이용 로그가 없는 데에는 적어도 세 가지 이유가 있습니다. 본인이 사용하지 않음. SSO를 통한 로그가 CSV에 포함되지 않음. 혹은 공유 계정이나 다른 이메일 주소로 사용 중임. 세 번째 경우가 의외로 많습니다.
어제도 경리팀의 청구 CSV를 살펴보던 중, 제품명 표기가 "Notion"과 "Notion AI"로 나뉘어 있다는 것을 발견했습니다. 청구의 관점과 이용 로그의 관점은 의외로 일치하지 않습니다. 따라서 이 스크립트의 결과를 그대로 중단 리스트로 만들지 않는 것이 안전합니다.
후보가 나오면 담당자에게 다음 세 가지만 질문합니다.
- 이 좌석을 최근 45일 이내에 사용했는가
- 다른 이메일 주소나 공유 좌석에서 사용하고 있지는 않은가
- 다음 갱신일까지 유지해야 할 이유가 있는가
답변을 seats.csv에 owner와 review_note 열로 남겨두면, 다음 달 확인 작업이 훨씬 빨라집니다. 처음부터 완벽한 자산 대장을 만들려고 하면 작업이 중단되므로, 우선은 후보인 3개 좌석에 대해 설명할 수 있는 상태를 만드는 것을 목표로 합니다.
날짜 형식은 통일해야 합니다. 이 코드는 2026-07-21T09:12:00와 같은 ISO 8601 형식을 가정하고 있습니다. 관리 화면에서 2026/7/21 9:12 형식으로 내보내는 경우에는 datetime.fromisoformat() 호출 전에 형식을 수정해야 합니다.
또 하나는 무료 좌석을 섞지 않는 것입니다. monthly_yen이 0원인 행을 집계에 포함하면 확인 건수만 늘어나 담당자의 수고가 커집니다. 유료 좌석만 청구 CSV에서 추출할 수 있다면 그 편이 훨씬 효율적입니다.
이용 로그를 가져올 수 없는 제품도 있습니다. 이 경우에는 '이용 기록 없음'이라고 표시되므로, 미사용이라고 단정 짓지 말고 계약 담당자가 이용 부서에 확인합니다. 판정은 다소 느슨하게 하더라도, 의사결정은 사람이 담당합니다. 이러한 방식으로 나누면 운영을 시작하기가 훨씬 수월합니다.
AI 도구가 늘어날수록 계약 재고 조사(Inventory)를 연 1회만 하는 것은 늦습니다. Okta의 조사에 따르면, 기업들이 여러 AI 제공업체를 병용하는 흐름이 강해지고 있습니다. Okta Enterprise AI Index의 수치는 대기업만의 이야기가 아닙니다.
월초에 청구 CSV를 내려받고, 이 코드를 통해 확인 후보군만 뽑아냅니다. 좌석을 중단할지 판단하기에 앞서, 사용 중인 이유를 먼저 수집합니다. 이렇게 하면 늘어난 도구들을 '어쩌다 보니 계속 사용'하는 상황을 방지할 수 있습니다. 앞으로는 도입의 속도보다, 각 좌석에 대해 설명할 수 있는 상태를 유지하는 것이 업무에서 더 큰 힘을 발휘할 것입니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Qiita AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기