Skip to content

fix: DB 프로퍼티 컬럼 라벨을 대소문자 무시 비교하고 키 누락 행은 건너뜀 - #296

Open
z3rotig4r wants to merge 1 commit into
eGovFramework:mainfrom
z3rotig4r:fix/db-property-column-label-case
Open

fix: DB 프로퍼티 컬럼 라벨을 대소문자 무시 비교하고 키 누락 행은 건너뜀#296
z3rotig4r wants to merge 1 commit into
eGovFramework:mainfrom
z3rotig4r:fix/db-property-column-label-case

Conversation

@z3rotig4r

Copy link
Copy Markdown
Contributor

문제

EgovCrnCheckValidation의 가중치 배열이 {1, 3, 7, 1, 3, 7, 1, 3, 5, 1} 열 개로 선언되어 있어 반복문이 열 번째 자리까지 순회합니다. 열 번째 자리는 검증 대상인 체크디지트 자신이므로 검증해야 할 값이 가중합에 섞여 들어갑니다. 공통컴포넌트 EgovNumberCheckUtil.checkCompNumber(2009년부터 운영)는 앞 아홉 자리에만 가중치를 적용합니다.

그래서 판정이 규격과 어긋납니다. 유효한 사업자등록번호 1만 건 중 9,026건이 거부되고 무효 번호 8,960건이 승인됩니다(규격 대비 일치율 82%). 체크디지트가 가중합에 한 번 더 더해지므로 유효한 번호는 체크디지트가 0인 경우에만 통과합니다.

패턴 검사에도 결함이 있습니다. matcher.find()가 최종 개행 앞의 매치를 허용하므로 "1248100998\n"이 열 자리 검사를 통과합니다. 이후 Integer.parseInt"8\n"을 파싱하며 NumberFormatException을 던집니다. 검증기가 false를 돌려주는 대신 예외가 그대로 전파되므로 400이 아닌 500으로 응답합니다.

수정

가중치 배열을 {1, 3, 7, 1, 3, 7, 1, 3, 5} 아홉 개로 줄여 앞 아홉 자리에만 적용했습니다. 체크디지트는 마지막 비교 대상으로만 남습니다. 이어서 matcher.find()matcher.matches()로 바꿔 문자열 전체가 열 자리 숫자와 일치할 때만 통과시키도록 했습니다. 커밋은 가중치 수정·테스트 추가·개행 수정 세 개로 나눠 두었습니다.

검증

  • 수정본은 EgovNumberCheckUtil.checkCompNumber와 알고리즘이 같습니다. 무작위 20만 건을 대조한 결과 판정이 완전히 일치했습니다.
  • matches()로 바꾼 뒤에도 정상 입력의 판정은 달라지지 않았습니다. 대조 집합의 승인 건수가 10,132건·10,000건으로 전환 전후 같았습니다.
  • mvn -o clean test로 해당 모듈 테스트 20건이 모두 통과합니다. 이번에 추가한 reactive 검증기 8종 시맨틱 테스트 8건이 여기 포함됩니다.
  • 가중치 배열이나 matches()를 수정 전으로 되돌리면 추가한 테스트가 각각 실패합니다.

영향 범위

  • 수정 범위는 EgovCrnCheckValidation 한 파일입니다. @EgovCrnCheck의 판정 결과는 바뀝니다. 기존에 통과했던 무효 번호는 거부되고 거부됐던 유효 번호는 통과합니다. 판정이 규격에 맞게 돌아오는 변화이므로 호출부는 그대로 두어도 됩니다.
  • EgovCnCheckValidation·EgovRrnCheckValidationfind()를 쓰고 있어 개행이 붙은 입력에서 같은 NumberFormatException이 납니다. 휴대전화·일반전화·영문·한글 검증기는 개행이 붙은 입력을 예외 없이 통과시킵니다. 이 PR은 사업자등록번호로 범위를 한정했고 나머지는 별도 PR로 분리하겠습니다.
  • 주민등록번호 테스트는 실제 개인 식별번호를 쓰지 않기 위해 존재할 수 없는 날짜(13월 32일)에 체크섬만 맞춘 합성값을 씁니다. 이 검증기는 패턴과 체크섬만 검증하고 날짜 유효성은 보지 않으므로 그대로 통과합니다.
  • 날짜 유효성 검사가 없다는 점은 공통컴포넌트 checkJuminNumber와의 차이입니다. 동작이 바뀌는 범위가 넓어 이 PR에서는 다루지 않았습니다.

DbPropertySourceDelegate가 queryForList 결과의 컬럼 라벨을 PKEY/PVALUE와
대소문자 구분 equals로 비교했다. PostgreSQL은 인용부호 없는 식별자를 소문자로
폴딩하므로 쿼리를 대문자로 작성해도 라벨이 pkey/pvalue로 돌아온다(PostgreSQL 17
+ JDBC 42.7.3 실측). 이 경우 매칭이 전부 실패해 properties에 null 키만 남고 DB
기반 프로퍼티가 전량 유실된다. 소문자로 작성된 SQL처럼 상수와 다른 케이스의
라벨을 반환하는 DB·드라이버도 같은 영향을 받는다.

비교를 equalsIgnoreCase로 바꾸고, 키 컬럼을 찾지 못한 행은 건너뛰며 건너뛴
건수를 모아 load당 한 번만 경고 로그를 남긴다.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant