숫자는 거짓말을 하지 않는다고 한다.
그런데 숫자가 맞는데도 화면을 보는 사람에게는 틀린 것처럼 보일 때가 있다. 업무용 손익계산기를 만들면서 딱 그런 일을 만났다.
매출에서 매입을 빼면 매출총이익은 정확했다. 다시 사업 고정비와 개인비용을 빼 보니 화면의 합계와 맞지 않았다. 계산기를 몇 번이나 두드려도 차이가 남았다.
“계산은 맞다는데, 그럼 이 돈은 어디로 간 거지?”
범인은 계산식이 아니라 화면에서 보이지 않던 세금 두 항목이었다. 부가세 납부 추정액과 종합소득세 적립 추정액이 상세 계산에는 들어가 있었지만, 위쪽 요약에는 보이지 않았다. 프로그램은 알고 있었고 사람만 모르고 있었던 셈이다.
이 작은 혼란에서 Claude와 함께 업무용 손익계산기의 화면과 계산 흐름을 다시 만드는 작업이 시작됐다.
맞는 계산보다 이해되는 계산
처음 화면에는 매출, 매입, 고정비, 개인비용 같은 큰 항목이 보였다. 아래쪽 합계에는 세금까지 반영됐지만, 중간 과정이 화면에서 생략되어 있었다. 결과 숫자는 맞아도 사용자가 눈으로 따라가며 검산할 수 없는 구조였다.
그래서 계산 순서를 장부처럼 위에서 아래로 읽히게 바꿨다.
- 매출에서 매입 및 내부 사용분을 뺀다.
- 사업 고정비를 뺀다.
- 개인비용을 뺀다.
- 세금 반영 전 합계를 보여준다.
- 부가세 납부 추정액을 뺀다.
- 종합소득세 적립 추정액을 뺀다.
- 최종 금액을 크게 보여준다.
이제 사용자는 각 줄을 하나씩 따라가며 “어디에서 얼마가 빠졌는지” 확인할 수 있다. 숫자를 맞히는 프로그램에서, 숫자를 설명하는 프로그램으로 한 단계 바뀐 것이다.
중요한 숫자는 먼저, 결론은 더 크게
계산 순서만큼 화면 배치도 중요했다. 자주 확인하는 핵심 지표가 아래쪽에 흩어져 있으면 매번 스크롤하며 찾아야 한다.
그래서 계산 결과 맨 위에 네 개의 정보 박스를 배치했다.
- 매출총이익
- 마진율
- 부가세 납부 추정액
- 종합소득세 적립 추정액
그 아래에는 세금 반영 전 손익을 순차 계산하고, 이어서 세금을 반영한 최종 금액을 큰 글씨로 표시했다. 마지막에는 손익분기 정보를 모았다.
- 사업 고정비의 매입세액공제 참고 설명
- 손익분기 매출
- 이번 달 매출과 손익분기점의 차이
- 안전마진
화면을 펼치면 먼저 현재 상태를 보고, 아래로 내려가며 계산 근거를 확인하고, 마지막에 앞으로 얼마를 더 팔아야 안전한지 판단할 수 있다. 순서 자체가 하나의 설명서가 되도록 만든 셈이다.
“계속 말해서 바꾸는 것”의 이름은 반복 개선
이번 프로그램은 처음부터 완벽한 설계도를 그려 한 번에 만든 것이 아니다.
실행해 보고, 숫자를 확인하고, 헷갈리는 부분을 말하고, Claude가 코드를 바꾸고, 다시 화면을 보며 순서를 조정했다. “이 박스를 위로 올려줘”, “합계를 세금 반영 전과 후로 나눠줘”, “손익분기는 맨 아래가 좋겠어” 같은 요청이 차례로 이어졌다.
이런 과정을 개발에서는 흔히 반복 개선 또는 이터레이션(iteration)이라고 한다. 사용해 본 결과를 다음 수정에 반영하며 프로그램을 점점 실제 업무에 맞춰 가는 방식이다. 중간에 요구사항이 달라졌다고 해서 실패한 것이 아니다. 오히려 직접 사용해 봤기 때문에 무엇이 불편한지 더 정확하게 알게 된 것이다.
한 번에 완벽하게 만드는 것보다, 써 보고 말하고 다시 고치는 일이 더 현실적인 개발이었다.
Claude는 코드를 작성하고 수정했지만, 무엇을 먼저 보여주고 어떤 숫자를 따로 구분할지는 실제 업무를 아는 사람이 결정했다. AI와 사람이 번갈아 질문과 답을 주고받으며 화면이 다듬어졌다.
보이지 않는 곳도 마지막까지 확인했다
손익계산기는 금액 자료를 저장하므로 화면만 예쁘게 나온다고 끝낼 수 없었다. 마지막에는 보안과 호환성도 함께 점검했다.
작업 기록상 확인한 항목은 다음과 같다.
- 비밀번호를 평문이 아닌 해시로 저장
- 로그인 반복 실패 시 일정 시간 잠금
- HTTPS 전용 세션 쿠키와 비밀번호 변경 시 기존 세션 무효화
- 데이터 파일과 폴더의 접근 권한 제한
- CSP, X-Frame-Options, HSTS 등 보안 헤더
- 잘못된 월·자료 유형 및 경로 조작 입력 차단
- 동시 저장 시 다른 기간의 자료가 사라지지 않도록 파일 잠금 처리
- 모바일 화면 대응과 파비콘 연결
- 데이터 저장·조회, 엑셀 내보내기, 백업·복원 회귀 테스트
마지막 종합 점검에서는 인증과 권한, 입력값 검증, 동시 저장, 백업과 복원, 엑셀 출력, 새 계산 화면 렌더링 등 23개 테스트 항목이 통과한 것으로 기록됐다.
다만 보안은 한 번 검사했다고 영원히 끝나는 작업이 아니다. 실제 운영 서버에서는 HTTPS 설정, 정기 백업의 복원 연습, 접근 권한 관리, 의존성 업데이트와 로그 점검을 계속해야 한다.
작업 폴더가 사라져도 ZIP은 남았다
개발 도중 작업 디렉터리가 초기화되는 작은 사고도 있었다. 세션 사이의 임시 파일이 유지되지 않는 환경이었던 것이다. 다행히 이전에 내보낸 최신 ZIP 파일이 남아 있어 그 상태에서 복구하고 작업을 이어갈 수 있었다.
이 장면은 프로그램 기능만큼 중요한 사실을 다시 알려줬다.
백업은 문제가 생겼을 때 만드는 것이 아니라, 문제가 생기기 전에 만들어 두는 것이다.
최종 전달본은 서버 전체를 무작정 바꾸는 방식이 아니라, 변경된 화면 템플릿을 적용한 뒤 서비스를 재시작하는 방식으로 정리했다. 실제 운영에서는 적용 전 현재 버전을 한 번 더 백업하고, 적용 후 저장·조회·엑셀 출력까지 확인하는 절차가 필요하다.
이 손익계산기가 계산해 주는 것은 숫자만이 아니다
업무용 손익계산기는 매출과 비용을 넣어 결과 한 줄을 보여주는 단순 계산기에서 출발했다. 반복 개선을 거치며 매출총이익과 마진율을 먼저 보여주고, 세금 반영 전 합계와 세금 반영 후 최종 금액을 구분하고, 손익분기점까지 설명하는 업무 도구가 됐다.
무엇보다 이번 작업에서 배운 것은 계산식이 정확한 것만으로는 충분하지 않다는 점이다. 사용자가 화면을 보며 같은 계산을 따라갈 수 있어야 하고, 중요한 숫자는 중요한 위치에 있어야 하며, 저장되는 자료는 안전하게 보호되어야 한다.
Claude에게 한 번 명령하고 끝낸 프로그램은 아니었다. 보고, 질문하고, 바꾸고, 다시 확인하는 일을 수없이 반복했다. 귀찮아 보일 수도 있지만 그 반복 덕분에 프로그램은 점점 실제 업무의 모양을 닮아갔다.
좋은 프로그램은 첫 답변에서 완성되는 것이 아니라, 좋은 수정 요청을 먹고 자란다.
※ 업무 정보 보호를 위해 실제 매출·매입·비용·세금 금액, 계정 정보, 서버 주소 및 저장 자료는 공개하지 않았습니다. 보안 및 테스트 내용은 당시 개발·점검 기록을 기준으로 정리했습니다.