전체 제품

기업 운영 시스템

2026.07 ~고객사 ㈜천지토건에서 2026.08.03부터 실제 업무에 사용

토목 건설 현장에 중장비와 기사를 보내는 고객사의 현장직과 사무직이 종이 달력과 카카오톡, 엑셀로 나눠 하던 일을 한 시스템으로 옮겼습니다.

현업 인터뷰와 요구사항 정리부터 업무 모델과 시스템 구조 설계, 구현, 배포와 운영까지 맡았고, 구현은 AI 에이전트를 지휘해 진행했습니다. 시스템은 고객사 사무실 서버에서 돌아가고 있으며, 지금도 실제 업무 기록을 보며 고쳐 나갑니다.

기업 운영 시스템 PC 대시보드 화면
오늘의 현황. 금액과 거래처는 가렸습니다.
고객사와 현장

장비 한 대가 하루 일한 기록이 매출과 정산, 세금 자료로 이어집니다

고객사는 굴삭기, 덤프, 로더 같은 중장비를 기사와 함께 토목 건설 현장에 보내는 회사입니다. 현장에 나가는 장비는 회사가 가진 것도 있고 지입차도 있습니다. 지입차주는 자기 장비를 가진 개인사업자로, 고객사 이름으로 현장에 나가지만 세금계산서는 저마다 따로 발행합니다. 그래서 장비 한 대가 하루 일한 기록이 발주처에는 청구할 매출이 되고, 지입차주에게는 정산할 돈이 되고, 회사에는 비용과 부가세 신고 자료가 됩니다.

기사와 현장 관리자

현장에서 휴대폰으로 그날 배정된 일을 보고, 작업이 끝나면 결과와 연장 시간을 알리고, 법인카드로 쓴 기름값 같은 지출을 올립니다.

행정 담당자

사무실 PC에서 배차를 잡고, 계산서를 만들고, 입금을 확인하고, 월말에 지입차주 정산을 합니다.

대표와 이사

현장을 돌면서 휴대폰으로 오늘 배차와 받을 돈, 나갈 돈을 확인합니다.

지입차주와 발주처

지입차주는 자기 장비의 배차와 정산을 확인하고, 발주처는 회사 밖에서 계산서와 견적서를 받아 봅니다.

시스템을 만들기 전에는 배차를 종이 달력에 적고 카카오톡으로 알렸습니다. 계산서는 엑셀로 손수 만들었고, 누가 언제 얼마를 보냈는지는 엑셀에 따로 적어 챙겼습니다. 지입차주 정산은 그달 배차 기록을 손으로 세어 계산했고, 매입 세금계산서는 담당자가 메일함을 하나씩 열어 확인했습니다. 사무직은 계산서, 수금, 지급, 재무를 사무용 구독 앱 여러 개를 오가며 따로 관리했습니다.

이 업무 흐름은 제게 처음이 아니었습니다. 고객사 DX팀에서 일할 때 배차, 정산, 문서가 어디서 끊기는지 분석한 적이 있고, 이번 시스템의 요구사항과 데이터 모델도 그 분석에서 출발했습니다.

기업 운영 시스템 배차 캘린더 화면
배차 캘린더. 종이 달력으로 하던 일을 이제 이 화면에서 합니다.
문제 정의

요청은 화면마다 따로 나왔지만, 진짜 문제는 같은 사실을 여러 곳에 따로 적는 데 있었습니다

대표이사와 이사, 행정 사원, 지입차주를 인터뷰하면 요청은 화면 단위로 나옵니다. 배차를 등록할 때 외주 장비와 일용직 기사, 오전과 오후 같은 작업 시간대를 같이 넣고 싶다, 현장에서 작업 결과를 바로 올리고 싶다, 법인카드 지출을 현장에서 입력하고 싶다, 한 거래처의 여러 현장을 묶어서 받을 돈을 보고 싶다 같은 것들입니다.

요청을 하나씩 들어주기 전에, 이 요청들이 공통으로 가리키는 것을 먼저 찾았습니다. "오늘 어떤 장비가 어느 현장에서 얼마에 일했나"라는 하나의 사실이 종이 달력, 계산서 엑셀, 정산 메모, 지출 기록에 각각 옮겨 적히고, 옮겨 적을 때마다 숫자가 어긋날 틈이 생겼습니다. 월말에 사람이 배차를 다시 세는 일도, 계산서 발행을 잊는 일도, 누가 금액을 바꿨는지 모르는 일도 여기서 나왔습니다.

시장에 나와 있는 제품으로는 이 틈을 메울 수 없었습니다. 대형 건설 ERP는 이 규모의 회사에는 과했고 비용도 감당하기 어려웠습니다. 배차 앱들은 장비와 현장을 연결하는 데서 멈추고 정산은 결국 사람 손에 남겼습니다. 그래서 풀어야 할 문제를 "배차와 지입차 정산, 세금계산서 관리, 현금흐름을 한곳에서 같은 기록으로 다루는 것"으로 정했습니다.

배차 한 건

  • 일자
  • 장비
  • 거래처
  • 금액
  • 상태
  • 소유권회사 소유 / 지입차

발주처 청구

매출, 수금

세금계산서

발행 현황, 매입 계산서 자동 수집

그달 확정되거나 끝난 배차에서 금액을 모으고, 취소되거나 대기 중인 건은 뺍니다

비용 기록

재무, 현금흐름

현금흐름은 청구 금액 대신 실제 입금을 기준으로 봅니다

지입차주 정산

매입, 지급

회사 소유 장비와 지입차를 구분합니다

PM의 판단

무엇을 만들지보다 무엇을 어디에 맡길지부터 정했습니다

판단 1

배차 한 건을 모든 금액의 출발점으로 삼았습니다

상황
배차 한 건은 발주처에는 매출, 지입차주에게는 매입이 되고 비용과 부가세 신고로도 이어집니다. 고객사는 이것을 종이 달력과 엑셀, 메일함에 따로 적었고, 월말이면 사람이 배차 기록을 다시 세어 맞췄습니다.
선택지
부서마다 하던 일을 각각 화면으로 옮기는 방법이 가장 빨랐습니다. 회계 장부를 가운데 두는 ERP식 구조도 있었습니다.
판단
배차는 현장에서 매일 생기는 사실이라, 이것을 원천으로 두고 청구와 정산, 현금흐름은 거기서 계산하게 했습니다. 계산서 금액은 그달 확정되거나 끝난 배차에서 자동으로 모으고, 취소되거나 대기 중인 건은 뺍니다.
이유
업무별로 따로 옮기면 지금 엑셀에서 생기는 어긋남이 화면 사이에서 그대로 다시 생깁니다. 회계 장부는 세무사가 맡고 있었고, 회사가 직접 보고 싶어 한 것은 받을 돈과 나갈 돈의 흐름이었습니다.
결과
행정 담당자는 지입차주와 달만 고르면 그달 배차 건수와 금액이 채워진 정산서를 받습니다. 실사용 첫날에는 이 모델의 전제 하나가 틀렸다는 것도 드러났습니다. 계산서 한 장을 여러 지입차가 나눠 갖는다고 보고 차량 번호로 주인을 판단했는데, 실제로는 지입차주마다 세금계산서를 따로 발행했습니다. 계산서의 주인을 공급자 한 명으로 바꾸고, 금액을 비율로 나누던 계산을 걷어 냈습니다.
판단 2

만들지 않을 것을 먼저 정했습니다

상황
인터뷰를 하자 요청이 한꺼번에 쏟아졌고, 그중에는 외부 계약이나 인증서가 있어야 가능한 것도 섞여 있었습니다. 세금계산서를 시스템에서 바로 발행하자는 안도 나왔습니다.
선택지
들은 것을 모두 만드는 방법도 있었고, 회사가 매일 겪는 문제와 직접 닿아 있는 것만 남기는 방법도 있었습니다.
판단
회계 장부와 재무제표, 급여, 장비 위치 추적, 앱스토어용 앱, 여러 회사가 같이 쓰는 구조는 만들지 않았습니다. 세금계산서 발행도 지금처럼 홈택스에서 사람이 하고, 시스템은 발행 여부와 기한을 챙기는 데까지만 맡았습니다. 요청은 바로 만들 것, 일부만 가능한 것, 외부 계약을 기다려야 하는 것으로 나누고, 데이터 모델과 권한을 먼저 세운 뒤 화면을 얹었습니다.
이유
장부는 세무사가 맡을 일이고, 이 회사에 필요한 건 현금흐름을 보는 것이었습니다. 세금계산서는 고객사가 지금처럼 직접 발행하기를 원했고, 한 번 나가면 되돌릴 수 없어서 자동화로 아끼는 시간보다 사고가 났을 때 치르는 비용이 더 큽니다. 반응형 웹이면 앱 심사 없이도 현장 휴대폰에서 바로 쓸 수 있습니다.
결과
자동으로 맞추기 어려운 곳은 일부러 사람에게 남겼습니다. 지입료 입금은 통장 기록과 자동으로 짝지어지지 않는 경우가 많았고, 거래명세서 품목명은 쓰는 사람마다 달랐습니다. 자동 처리가 틀리면 나중에 찾아낼 방법이 없으니, 이런 곳에서는 사람이 고르게 했습니다.
판단 3

현장직과 사무직을 한 시스템에 두고, 화면은 일하는 사람에 맞췄습니다

상황
기사와 현장 관리자는 현장에서 휴대폰으로, 행정 담당자는 사무실 PC로 일합니다. 대표는 현장을 돌며 휴대폰으로 회사 상황을 봅니다. 지입차주는 같은 회사 이름으로 일하지만 정산은 따로 하는 사업자이고, 발주처는 회사 밖 사람입니다.
선택지
현장용 앱과 사무실용 프로그램을 따로 두거나, 하나의 시스템에서 역할마다 다르게 보여 줄 수 있었습니다.
판단
데이터와 시스템은 하나로 두고 역할마다 첫 화면과 메뉴를 달리했습니다. 기사는 로그인하면 바로 "오늘의 현장"으로 가고, 쓸 일이 없는 대시보드는 메뉴에서 뺐습니다. 대표는 휴대폰 첫 화면에서 오늘 배차, 검사가 다가온 장비, 처리할 계산서, 이번 달 현금흐름을 한 번에 봅니다. 발주처에는 회원가입을 시키지 않고, 90일 뒤 만료되고 언제든 회수할 수 있는 링크로 계산서와 견적서를 보냅니다.
이유
현장에서 올린 기록이 그대로 사무실의 정산과 비용이 되어야 다시 옮겨 적는 일이 사라집니다. 들어갈 수 없는 메뉴를 보여 주면 누를 때마다 튕겨 나오고, 보고 양식이 둘이면 목록과 읽음 표시도 두 벌이 됩니다.
결과
현장의 작은 결정도 같은 기준으로 내렸습니다. 법인카드가 아직 등록되지 않았어도 지출 입력은 받습니다. 입력이 막히면 그 지출은 아예 기록되지 않기 때문입니다. 지입차주가 "지입료를 보냈다"고 알리는 버튼을 만들 때는 "입금 확인 중" 같은 상태를 새로 만들지 않았습니다. 그 신고는 지입차주의 주장일 뿐이고, 실제 입금은 행정 담당자가 통장을 보고 확정해야 하니까요. 상태는 그대로 두고 신고한 시각만 남겨, 행정 담당자 목록에 확인 요청 표시가 뜨게 했습니다.
판단 4

돈과 개인정보를 다루기 때문에 권한, 변경 기록, 복구를 처음부터 넣었습니다

상황
이 시스템에는 계산서와 통장 내역, 법인카드 사용 내역, 거래처 사업자등록증과 기사 신분증 사본이 담깁니다. 같은 목록을 대표, 행정 담당, 지입차주, 기사가 각자 다른 범위로 봅니다.
선택지
기능을 먼저 만들고 권한과 이력은 나중에 붙일 수도 있었고, 처음부터 구조에 넣을 수도 있었습니다.
판단
권한은 역할, 관리 화면에서 고칠 수 있는 권한 표, 레코드 소유권 세 가지를 함께 따지고, 설정이 없으면 막는 것을 기본으로 했습니다. 변경 기록은 기능마다 기록 코드를 넣는 대신, 데이터를 저장하는 단계에서 필드마다 바뀌기 전 값과 바뀐 값을 자동으로 남기게 했습니다. 삭제한 것은 모두 휴지통으로 보내 되살릴 수 있게 했습니다.
이유
기능마다 기록 코드를 직접 넣게 하면 어딘가는 반드시 빠뜨리게 되고, 빠뜨렸다는 것도 알 수 없습니다. 실제로 쓰기 시작하면 오타 하나만 있어도 시스템 전체를 믿지 못하게 되고, 회사 데이터를 되살릴 수 없게 지워 버리면 그것만으로 사고입니다.
결과
처음에는 대표 계정 하나로만 화면을 확인하다가 지입차주 화면의 권한 문제를 놓쳤습니다. 그 뒤로는 모든 역할로 직접 로그인해 같은 화면을 확인하는 절차를 넣었습니다. 그렇다고 무조건 막지는 않았습니다. 아직 계열사가 연결되지 않은 현장 관리자에게는 조회는 열어 두고 쓰기만 막았습니다. 화면이 텅 비어 있으면 사람들은 권한 설정 때문인 줄 모르고 고장 난 것으로 여기기 때문입니다.
판단 5

AI를 쓸 곳과 쓰지 않을 곳을 직접 시험해 보고 정했습니다

상황
영수증과 사업자등록증 입력, 업무 조회, 사내 문서 질문, 매입 세금계산서 읽기에 AI를 붙일 수 있었습니다. 하지만 금액 하나만 틀려도 정산과 세금이 같이 틀어집니다.
선택지
붙일 수 있는 곳에는 모두 AI를 쓸 수도 있었고, 정확도부터 확인한 뒤 맡길 범위를 정할 수도 있었습니다.
판단
매입 세금계산서에는 AI를 쓰지 않았습니다. 영수증은 AI가 입력값을 먼저 채워 두고, 사람이 원본과 대조했다고 확인해야 등록 버튼을 누를 수 있습니다. 업무 조회에서 AI는 질문을 해석하기만 하고, 답에 들어가는 숫자는 서버가 데이터베이스에서 직접 가져옵니다. AI가 등록할 때도 화면에서 쓰는 것과 같은 업무 함수와 권한 검사를 거치고, 등록할 대상이 하나로 좁혀지지 않으면 실행하지 않습니다.
이유
홈택스 보안메일은 풀면 형식이 정해진 표가 나오기 때문에, 규칙으로 읽는 기존 방식으로도 시험한 계산서를 모두 정확하게 읽었습니다. 이미 정확한 방식을 두고 틀릴 수도 있는 추정으로 바꿀 이유가 없었습니다. 영수증 시험에서는 AI가 공급가액과 부가세를 잘못 읽었는데, 틀린 값끼리 더한 합계가 맞아서 검산을 통과해 버렸습니다. 그래서 화면에서 검산 통과 표시를 없앴습니다. 그 표시를 보면 안심하고 원본 대조를 건너뛰게 되기 때문입니다.
결과
모델도 같은 업무 문장을 넣어 비교해 보고 골랐습니다. 할 수 있는 동작이 많은 업무 패널에서는 Haiku 4.5가 필요한 동작을 자주 고르지 못해 Sonnet 5를 쓰고, 영수증 판독에는 값이 싼 Haiku 4.5를 그대로 썼습니다. 사내 문서 질문은 RAG로 관련 문서를 찾아 답하게 했는데, 소형 임베딩 모델보다 키워드 검색(BM25)이 문서를 더 잘 찾아서 키워드 검색을 기본으로 하고 벡터 데이터베이스 없이 운영합니다.
판단 6

고객사 사무실 서버에서 돌아가야 한다는 조건에 맞춰 구조와 배포 방식을 정했습니다

상황
시스템은 고객사 사무실에 둔 작은 서버에서 돌아갑니다. 사무실에는 서버를 돌볼 사람이 없고 유지보수는 저 혼자 합니다. 데이터에는 회계 정보와 개인정보가 들어 있습니다.
선택지
클라우드에 관리형 데이터베이스와 여러 구성 요소를 갖춘 흔한 구성으로 올릴 수도 있었고, 고객사 사무실 서버 한 대에 의존성을 최대한 줄여 올릴 수도 있었습니다.
판단
보안과 편의성을 이유로 고객사 사무실 서버를 골랐습니다. 회계 정보와 개인정보가 회사 밖 클라우드로 나가지 않고, 사무실에서 바로 쓰고 관리할 수 있습니다. 데이터베이스는 PostgreSQL 대신 SQLite(WAL)를 골랐습니다. 외부 접속은 사무실 공유기 포트를 열지 않고 Cloudflare Tunnel로 연결했습니다. 업무 데이터는 암호화된 저장소에 두었기 때문에, 서버가 재부팅되면 사람이 패스프레이즈를 입력해 열어야 업무를 시작할 수 있습니다. 배포는 태그를 붙인 버전만 되게 했습니다. 서버가 5분마다 새 태그를 확인해 백업, 빌드, 시험, 기동 확인을 차례로 하고, 하나라도 실패하면 직전 버전으로 돌아갑니다.
이유
사용자가 적고 서버가 한 대라 PostgreSQL을 띄우면 운영 부담만 늘고 얻는 게 없었습니다. 혼자 유지보수하다 보니 의존성이 하나 늘 때마다 챙길 일도 늘어납니다. 코드를 올릴 때마다 배포되면 저녁에 고치다 만 코드가 다음 날 아침 사무실에서 돌아갑니다. 이전 버전으로 되돌릴 때도 데이터베이스는 그대로 둡니다. 데이터베이스까지 되돌리면 그사이 직원이 입력한 내용도 함께 사라지기 때문입니다.
결과
이제 제 개발 PC를 꺼도 고객사 업무는 계속 돌아갑니다. 코드가 배포본과 달라지면 15분 안에 알림이 오는데, 잘못 울리는 경보도 버그로 다뤘습니다. 거짓 경보가 반복되면 진짜 경보까지 무시하게 되기 때문입니다.
판단 7

실제 사용 기록을 보고 다시 판단했습니다

상황
실제로 쓰기 시작하자 시험에서는 드러나지 않던 문제가 나왔습니다. 시험 데이터는 제가 직접 채운 값이라 현장에서 생기는 빈칸이 들어 있지 않았습니다.
선택지
보고된 증상만 고칠 수도 있었고, 원인과 판단 기준까지 다시 볼 수도 있었습니다.
판단
기록부터 확인하고 원인까지 고쳤습니다. 서버 시험을 모두 통과해도, 실제 데이터로 화면을 띄워 눌러 보기 전에는 끝난 것으로 보지 않았습니다.
이유
현장 사람들은 시스템이 한 번 틀리면 그다음부터 숫자를 다시 손으로 셉니다. 증상만 지우면 같은 종류의 문제가 다른 화면에서 또 생깁니다.
결과
AI 업무 패널의 호출 기록을 계측해 보니 AI로 등록한 건이 하나도 없었습니다. 값을 다 받아 놓고도 "그 화면에서 등록하세요"로 끝나니, 처음부터 화면에서 입력하는 편이 빨랐던 겁니다. 규칙으로 먼저 답하던 경로를 걷어 내고 패널 안에서 등록까지 끝나게 바꿨습니다. 계측할 때 질문 원문은 남기지 않았습니다. 질문에 거래처 이름과 금액이 그대로 들어 있기 때문입니다. 법인카드 사용 내역에 같은 결제가 여러 번 쌓이던 문제는 연동사가 주는 거래 키가 조회할 때마다 바뀌어서 생긴 것이었습니다. 그래서 카드사 승인번호로 중복을 걸러 내게 바꿨습니다.
기업 운영 시스템 모바일 화면
대표가 현장에서 보는 휴대폰 첫 화면
현업이 얻은 것

2026년 8월부터 고객사 사무실에서 실제 업무에 쓰고 있습니다

  • 행정 담당자는 이제 월말에 배차 기록을 손으로 세지 않습니다. 지입차주와 달을 고르면 그달 배차가 모여 정산서가 채워집니다.

  • 매입 세금계산서를 확인하려고 메일함을 열지 않아도 됩니다. 시스템이 홈택스 보안메일을 받아서 풀고, 읽은 내용을 지급 관리에 올립니다.

  • 법인카드 사용 내역과 통장 입출금이 연동으로 들어옵니다.

  • 거래처는 회원가입 없이 링크로 계산서와 명세서를 봅니다.

  • 계산서 발행 누락, 수금 기한, 장비 검사일처럼 놓치기 쉬운 일은 시스템이 매일 확인해 알림톡과 사내 메신저로 알려 줍니다.

  • 현장에서 올린 작업 보고와 지출은 따로 옮겨 적을 필요 없이 그대로 사무실 기록이 됩니다.

인터뷰했던 대표이사와 이사, 행정 사원, 지입차주 모두에게서 일이 쉬워졌다는 이야기를 들었습니다.

기술
  • Python
  • FastAPI
  • SQLAlchemy
  • SQLite(WAL)
  • React
  • TypeScript
  • Playwright
  • Claude API
  • BM25 문서 검색
  • 바로빌 연동(계좌, 법인카드, 알림톡)
  • Cloudflare Tunnel
  • LUKS
다음 프로젝트로

AI 에이전트에게 구현을 맡기면서 "확인했습니다"라는 보고와 실제 결과가 다른 일을 여러 번 겪었습니다. 그래서 이 프로젝트에서는 완료 보고에 실행한 명령과 결과를 붙이고, 시험을 통과해도 실데이터로 화면을 눌러 보기 전에는 끝난 것으로 보지 않는다는 규칙을 세웠습니다. 이 규칙을 사람 대신 시스템이 지키게 하려고 만든 것이 집현입니다.

집현 보기