목록으로 돌아가기
Devlog2026-05-118분 읽기

k-gov-skills(2): 영수증 하나 때문에 하루를 쓴 이유

k-gov-skills(2): 영수증 하나 때문에 하루를 쓴 이유

k-gov-skills(2): 영수증 하나 때문에 하루를 쓴 이유

k-gov-skills 두 번째 개발일지는 생각보다 소박한 주제입니다.

영수증입니다.

정확히는 출장·여비 정산에 필요한 교통비 증빙을 AI 에이전트가 어떻게 정리하게 만들 것인가에 관한 이야기입니다.

처음에는 단순했습니다.

“하이패스 영수증을 PDF와 PNG로 잘 저장하면 되지 않을까?”

그런데 막상 해보니 이 일은 단순한 스크래핑 문제가 아니었습니다. 하이패스, SRT, KTX/Korail은 각각 로그인 방식도 다르고, 화면 구조도 다르고, 영수증으로 인정될 만한 산출물의 형태도 달랐습니다.

결국 오늘 하루는 transport-receipt-collector를 하이패스 중심 스킬에서 하이패스·SRT·KTX/Korail 3종 교통비 증빙 스킬로 확장하는 데 썼습니다.

왜 영수증 자동화가 필요한가

출장 정산에서 제일 귀찮은 일은 대단한 분석이 아닙니다.

영수증을 찾고, 다시 로그인하고, 날짜 범위를 맞추고, 저장하고, 파일명을 바꾸고, 제출용 이미지와 PDF를 맞추는 일입니다.

한 번이면 괜찮습니다. 그런데 매달 반복되면 다릅니다.

  • 어디에서 받은 영수증인지 기억해야 합니다.
  • PDF가 필요한지 PNG가 필요한지 확인해야 합니다.
  • 파일명이 제각각이면 나중에 다시 찾기 어렵습니다.
  • 실패한 건을 따로 기록하지 않으면 같은 일을 다시 반복합니다.

그래서 transport-receipt-collector의 목표는 “멋진 자동화”가 아니라 아주 현실적인 정리였습니다.

날짜_provider_구간_금액.pdf
날짜_provider_구간_금액.png
날짜_provider_구간_금액.json

이렇게 월별 폴더에 모아두면 나중에 정산할 때 훨씬 덜 피곤합니다.

하이패스에서 시작했다

처음 구현한 대상은 하이패스였습니다.

하이패스는 공공기관 출장 정산에서 자주 등장합니다. 영수증도 비교적 명확합니다. 로그인하고, 사용내역을 조회하고, 영수증 출력 화면에 들어가고, PDF와 PNG를 저장하면 됩니다.

여기서 중요한 것은 파일을 그냥 캡처하는 것이 아니라, 제출용으로 다시 찾기 좋은 형태로 남기는 것입니다.

  • 거래일
  • provider
  • 입구·출구 또는 구간
  • 금액
  • PDF/PNG 쌍
  • 실패 사유

이 정도만 고정해도 반복 업무가 크게 줄어듭니다.

SRT와 KTX/Korail은 다른 문제였다

SRT와 KTX/Korail은 하이패스와 달랐습니다.

같은 “교통비 영수증”처럼 보이지만, 실제로는 사이트와 앱의 흐름, 저장되는 화면, 제출 가능한 증빙 형태가 다릅니다.

특히 KTX/Korail은 단순히 화면을 흉내 내는 것만으로는 부족했습니다.

정산 증빙은 “비슷하게 만든 이미지”가 아니라, 가능한 한 공식 데이터와 실제 저장본의 형식에 가까워야 합니다. 그래서 오늘 작업의 핵심은 기능 추가가 아니라 증빙 품질을 어디까지 인정할 수 있을지 기준을 세우는 일이었습니다.

최종적으로 공개 저장소에는 세부 구현을 모두 넣지 않기로 했습니다.

대신 공개 스킬은 이렇게 정리했습니다.

  • 하이패스는 공개 가능한 범위의 자동 로그인·조회·저장 흐름을 제공
  • SRT는 공개 페이지 기반 영수증 저장 흐름을 제공
  • KTX/Korail은 세부 구현을 공개하지 않고 로컬/private 커넥터를 통해 처리

이 선택이 중요했습니다.

공개 저장소에는 어디까지 써야 하나

오늘 가장 크게 배운 것은 이 부분입니다.

기능이 된다고 해서 구현 디테일을 전부 공개 문서에 써도 되는 것은 아닙니다.

처음에는 개발 기록을 충실하게 남기려다 보니, 내부 호출 구조나 파라미터 수준의 정보까지 문서에 들어갈 뻔했습니다. 하지만 공개 저장소라면 그렇게 하면 안 됩니다.

공개 문서에 필요한 것은 사용자가 이해해야 할 수준입니다.

  • 이 스킬이 무엇을 하는가
  • 어떤 provider를 지원하는가
  • 어떤 산출물이 나오는가
  • 어떤 인증·본인확인은 자동화하지 않는가
  • 민감정보를 어떻게 다루는가
  • 실패하면 어디서 멈추는가

반대로 공개하지 않아야 할 것도 있습니다.

  • 내부 endpoint 이름
  • 요청 파라미터
  • 캡처한 요청·응답 원문
  • 승차권 토큰
  • 카드 승인정보 원문
  • 계정·세션 관련 정보

그래서 KTX/Korail은 공개 저장소에서 “로컬/private 커넥터”라는 경계로 정리했습니다. 기능은 확장하되, 구현 디테일은 공개하지 않는 방식입니다.

영수증 이미지도 그냥 만들면 안 된다

오늘 또 하나의 큰 포인트는 이미지 품질이었습니다.

처음 만든 영수증 이미지는 기능적으로는 맞았지만, 실제 앱 저장본과는 차이가 있었습니다. 폭, 글꼴, 굵기, 상단 여백, 하단 사업자 정보 위치가 달랐습니다.

이런 차이는 사소해 보이지만, 정산 증빙에서는 중요합니다.

그래서 실제 저장본을 기준으로 템플릿을 다시 맞췄습니다.

  • QR 상단 영역은 재현하지 않고 제외
  • 영수증 본문 중심의 짧은 이미지로 정리
  • 제목, 날짜, 결제방식, 총 영수 금액은 더 강하게 표시
  • 불필요한 소제목 제거
  • 총액 바로 아래에 사업자·주소·발행정보 배치
  • 전체 색과 굵기를 실제 저장본에 더 가깝게 조정

완벽한 복제보다 중요한 것은 제출 가능한 증빙으로 보일 만큼의 구조와 신뢰성을 갖추는 것이었습니다.

현재 transport-receipt-collector가 하는 일

이번 업데이트 후 transport-receipt-collector는 세 가지 provider를 다룹니다.

hipass
srt
korail

산출물은 provider에 따라 조금 다릅니다.

  • 하이패스: PDF + PNG
  • SRT: PNG
  • KTX/Korail: 코레일톡 스타일 PNG + redacted JSON

공통 목표는 같습니다.

outputs/receipts/YYYY-MM/
  YYYY-MM-DD_provider_route_or_train_amount.pdf
  YYYY-MM-DD_provider_route_or_train_amount.png
  YYYY-MM-DD_provider_route_or_train_amount.json

물론 모든 provider가 항상 모든 형식을 내는 것은 아닙니다. 중요한 것은 한 거래를 나중에 다시 찾고 검토할 수 있게 남기는 것입니다.

자동화하지 않는 것도 기능이다

이 스킬에서 일부러 하지 않는 일이 있습니다.

  • CAPTCHA 자동 통과
  • 2차 인증 자동 처리
  • 공동인증서 조작
  • 결제, 취소, 환불
  • 계정 변경
  • 타인 명의 조회

자동화는 할 수 있는 일을 늘리는 기술이기도 하지만, 하지 말아야 할 일을 명확히 정하는 일이기도 합니다.

공공기관 실무용 스킬이라면 특히 그렇습니다. 빨리 되는 것보다 안전하게 멈추는 것이 더 중요할 때가 많습니다.

오늘의 결론

오늘 작업은 겉으로 보면 “영수증 저장 기능 추가”입니다.

하지만 실제로는 세 가지를 정리한 날이었습니다.

  1. 교통비 증빙 스킬을 하이패스·SRT·KTX/Korail 3종 구조로 확장했다.
  2. 정산 증빙은 비슷한 이미지가 아니라 공식 데이터와 실제 저장본 형식에 가까워야 한다는 기준을 세웠다.
  3. 공개 저장소에는 기능 설명과 사용 경계만 남기고, 내부 구현 디테일은 로컬/private 커넥터로 분리했다.

이런 작업은 화려하지 않습니다.

하지만 공공기관 실무에서 실제로 시간을 줄이는 것은 대개 이런 종류의 일입니다. 매번 다시 찾고, 다시 저장하고, 다시 이름 바꾸는 일을 줄이는 것.

k-gov-skills는 그런 반복 업무를 하나씩 줄이는 방향으로 계속 다듬어 가려 합니다.