만든 것
수학 5종 — 분수, 비율, 퍼센트, 소수·분수 변환, 최소공배수
생활 10종 — 퇴직금, 연차, 휴일근로수당, 배란일, 에어컨 전기요금, 부가세, 수수료, 비만도, 체감온도, 음력 변환
원칙: 만들기 전에 로직부터 검증한다
모든 계산기는 Node로 로직을 먼저 돌려보고 나서 화면을 붙였습니다. 브라우저에서 눈으로 확인하는 건 검증이 아닙니다. 몇 개 넣어보고 맞는 것 같으면 넘어가게 되니까요.
| 계산기 | 검증 방식 | 케이스 |
|---|---|---|
| 음력 변환기 | 실제 설날·추석·초파일 날짜와 대조 + 왕복 변환 | 100건 |
| 휴일근로수당 | 근로기준법 제56조 배수 검산 | 51건 |
| 분수 계산기 | 사칙연산·약분·통분 전수 대조 | 155건 |
왕복 변환 검사가 특히 쓸 만했습니다. 양력 → 음력 → 양력을 거쳐 원래 날짜로 돌아오는지 보는 겁니다. 정답표가 없어도 자기모순은 잡아낼 수 있습니다.
삽질 ① 배란일이 하루씩 어긋났다
날짜 계산 결과가 케이스에 따라 하루씩 밀렸습니다. 범인은 이거였습니다.
date.toISOString().slice(0, 10)
toISOString()은 UTC 기준으로 변환합니다. 한국은 UTC+9이라, 한국 시간으로 3월 1일 오전 5시는 UTC로 2월 28일 오후 8시입니다. 날짜가 하루 밀립니다.
로컬 시간 기준으로 포맷하고 파싱하는 함수를 직접 만들어서 해결했습니다.
function fmt(d) {
var m = d.getMonth() + 1, day = d.getDate();
return d.getFullYear() + '-' + (m < 10 ? '0' : '') + m
+ '-' + (day < 10 ? '0' : '') + day;
}
고치고 나서 월 경계와 연 경계를 포함한 9개 케이스를 다시 돌렸습니다. 2월 28일, 윤년 2월 29일, 12월 31일 같은 것들입니다.
삽질 ② 공학용 계산기의 단항 마이너스
3*-2를 넣었더니 -2가 나왔습니다.
수식 파서에서 -2 같은 단항 마이너스를 처리하려고 0-2로 치환했는데, 이러면 연산자 우선순위가 깨집니다. 3*0-2가 되어버리니까요.
u-라는 단항 연산자를 따로 정의해서 해결했습니다. 우선순위 3.5, 우결합입니다. 곱셈(3)보다 높고 거듭제곱(4)보다 낮게 둬야 -2²가 -(2²)로 계산됩니다.
그런데 이 계산기는 결국 폐기했습니다.
검색량만 보고 만들려고 했지 검색 의도를 안 봤기 때문입니다. "공학용 계산기"를 검색하는 사람은 대부분 카시오 계산기를 사려는 사람입니다. CPC가 230원이고 경쟁도가 42라는 건 "구매 의도가 있는 키워드"라는 신호였는데, 저는 그걸 "돈이 되는 키워드"로 읽었습니다.
파서를 다 만들고 나서 접었습니다. 아까웠지만 만들었어도 아무도 안 왔을 겁니다.
검증 방식에서 배운 것
허용오차를 잘못 잡으면 통과가 무의미해진다
휴일근로수당은 시간과 조건에 따라 통상임금의 1.5배, 2.0배, 2.5배가 됩니다. 이 배수가 맞는지 검산하는 코드를 짜면서 허용오차를 0.5로 뒀습니다.
그런데 0.5는 1.5배와 2.0배의 차이 그 자체입니다. 이 테스트는 통과해도 아무것도 보장하지 않습니다. 1e-9로 다시 돌려서 확인했습니다.
통과 메시지를 믿으면 안 된다
퇴직금 조견표 36칸을 검증하는 PowerShell 스크립트가 "36칸 전부 일치"를 출력한 적이 있습니다.
그런데 실제로는 스크립트가 중간에 파싱 에러로 죽어 있었습니다. 루프가 한 번도 안 돌아서 불일치 카운터가 0이었고, 마지막 출력문이 그걸 "전부 일치"로 해석한 겁니다.
결국 Node로 다시 짜서 검증했습니다. 여기서 규칙 하나를 추가했습니다.
테스트는 "실패가 0건"이 아니라 "검사를 몇 건 했는지"를 같이 출력해야 한다.
지금은 검증 스크립트가 항상 통과 30 / 실패 0 형태로 양쪽 숫자를 다 찍습니다. 앞 숫자가 0이면 뭔가 잘못된 겁니다.
정리
이 단계에서 시간의 절반 이상은 화면이 아니라 검증에 썼습니다. 계산기는 틀리면 존재 이유가 없어지니 이 비율이 맞다고 생각합니다.
그리고 검증 코드도 코드라서 똑같이 틀립니다. 위의 두 사례 다 "테스트가 통과했다"는 상태에서 발견한 것들입니다.