십진 합계와 bigdecimal 0 의 함정, 브라우저에서 읽는 엑셀 업로드
전날에 이어 프로그램 요청을 처리했다. 그중 결의관리 상세 칸이 모두 꺼지던 요청을 따라가다 보니, 넥사크로가 큰 숫자를 객체로 다룬다는 점에서 생기는 차이가 나왔다. 버그 하나를 고치고 끝내지 않고, 같은 꼴이 원본 화면에 몇 곳 더 있는지 찾는 도구까지 만들었다. 오전 후반에는 Nx 가 아직 채우지 못한 넥사크로 기능 세 가지를 메웠다.
한 일
화면에서 바로 보이는 것
- 메뉴 검증 표시(✓): 메뉴 트리의 ✓ 표시를 “이식 완료”에서 “사람이 직접 검증한 메뉴”로 바꿨다. 시스템 관리자가 눌러서 켜고 끈다. 처음에는 별도 표를 만들려다 메뉴 표에 검증자·검증 일시 열을 더하는 쪽으로 정했다. 메뉴 표를 쓰는 SQL 이 모두 열 이름을 적어 쓰고 있어 AS-IS 에는 영향이 없다
- 화면을 여는 동안 조작 막기: 화면이 열리는 중이거나 안에 든 웹 페이지를 불러오는 중에도 통신 중처럼 조작을 막는다. 자동 조회가 끝나기 전에 “신규”를 누를 수 있었다
- 시스템 알림 발송: 화면이 부르는 알림 발송 경로가 TO-BE 서버에 없어 404 가 났다. 레거시와 같은 응답으로 더하고, 조회 전용 사용자는 막는다
- 그리드: 같은 행의 다른 칸을 눌러도 편집기를 닫는다, 열 구분선을 진하게, 열 지우기가 머리글 칸도 지우게(재조회 때 열이 겹치던 것)
- 알림 팝업 목록이 비던 것. 알림 배열 안쪽이 바뀌는 것을 감시하지 못하고 있었다(
watch의deep)
넥사크로 기능 메우기
- 엑셀 업로드: 원본은 파일을 서버로 보내 넥사크로 서버 모듈이 읽었다. TO-BE 는 브라우저에서 exceljs 로 xlsx 를 읽어, 원본이 돌려주던 것과 같은 모양(
Column0,Column1…)의 데이터셋을 만든다. 업로드 공통 팝업이 쓰는 데이터셋 기능(열 이름 바꾸기 등)도 원본 규칙대로 채웠다. 옛.xls는.xlsx로 저장해 달라고 안내한다 - 도움말 창: 떠 있는 창 목록, 새 브라우저 창 열기
- 쿠키 변수: 넥사크로 쿠키 함수가 없어서 회계 공통 부품이 쿠키를 쓰려다 조용히 멈추고 있었다
- 화면 초기화 처리기에서 오류가 나도, 끼운 화면 차례 진행과 조작 막기 풀기는 반드시 하게 했다. 전에는 오류 하나로 30초 동안 화면이 막혔다
십진 합계
bigdecimal 열의 합계·평균·소계를 십진으로 계산한다(0.1 + 0.2 = 0.3). 넥사크로 원본도 bigdecimal 은 십진 객체로 더하기 때문이다. float 열과 식 합계는 원본도 보통 숫자로 더하므로 그대로 둔다.
기술 메모
bigdecimal 0 은 참이다. 결의관리 상세 칸이 모두 꺼지는 요청을 따라가니 원본 화면에 이런 코드가 있었다.
var seq = Number(this.ds_detail.getColumn(row, "SEQ") || -1);
넥사크로에서 bigdecimal 열의 값은 Decimal 객체다. 값이 0 이어도 객체라서 || 는 왼쪽을 고르고, 결과는 0 이다. TO-BE 런타임은 이 값을 보통 숫자로 두는데, 숫자 0 은 거짓이라 결과가 -1 이 되고 상세 칸이 모두 꺼졌다. 빈 값일 때만 -1 이 되게 원본 화면을 고쳤고, AS-IS·TO-BE 양쪽 결과가 같다.
런타임에서 Decimal 객체를 흉내 낼 수도 있었지만, 그러면 화면 스크립트 곳곳의 산술·비교가 객체를 상대하게 되어 더 많은 차이를 만든다. 그래서 런타임은 숫자로 두고, 대신 위험한 꼴을 찾는 점검 도구를 만들었다. 원본 xfdl 에서 bigdecimal 열 값을 || 기본값, 참/거짓 판단, ===, typeof, instanceof 로 쓴 곳을 모두 뽑는다. 지금 남은 것은 1곳이고, 확인해 보니 두 쪽 결과가 같았다. 고치기 전의 위 코드도 이 도구가 잡아낸다.
십진 합계는 BigInt 로. 합계는 반대로 원본과 맞추려면 십진 계산이 필요하다. 각 값을 JavaScript 가 보여 주는 가장 짧은 십진 표기(0.1 은 "0.1", 지수 표기는 풀어서)로 바꾸고, 소수 자릿수를 맞춘 정수(BigInt)로 더한 뒤 마지막에 소수점을 다시 찍는다. 부동소수 오차(0.30000000000000004)가 금액 합계에 나타나지 않는다.
엑셀은 브라우저에서. 업로드한 파일을 서버로 보내지 않으니 서버에 임시 파일이 남지 않고, 서버 쪽 엑셀 파서도 필요 없다. 브라우저에서 읽은 결과를 원본과 같은 모양의 데이터셋으로만 만들어 주면 화면 스크립트는 바꿀 것이 없다.