Skip to content

fix: EgovStringUtil의 식별자 표기 변환이 로케일에 따라 다른 결과를 내는 문제 수정 - #331

Open
wantaekchoi wants to merge 1 commit into
eGovFramework:mainfrom
wantaekchoi:fix/string-util-identifier-case-locale
Open

fix: EgovStringUtil의 식별자 표기 변환이 로케일에 따라 다른 결과를 내는 문제 수정#331
wantaekchoi wants to merge 1 commit into
eGovFramework:mainfrom
wantaekchoi:fix/string-util-identifier-case-locale

Conversation

@wantaekchoi

@wantaekchoi wantaekchoi commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

수정 사유 Reason for modification

  • 버그수정 Bug fixes
  • 기능개선 Enhancements
  • 기능추가 Adding features
  • 기타 Others

수정된 소스 내용 Modified source

convertToCamelCaseconvertToUnderScore는 자기 javadoc이 식별자 표기 변환임을 명시합니다.

This method convert "string_util" to "stringUtil"
Convert a camel case string to underscore representation.

그런데 인자 없는 toLowerCase()를 써서 JVM 기본 로케일을 따릅니다. 터키어·아제르바이잔어 로케일에서는 I가 점 없는 ı(U+0131)로 바뀝니다.

convertToCamelCase("PRINT_STATUS", '_')  ->  "prıntStatus"   (기대 "printStatus")
convertToUnderScore("printId")           ->  "print_ıd"      (기대 "print_id")

같은 일을 하는 형제 구현이 이 저장소에 둘 있고 둘 다 로케일 독립입니다.

구현 모듈 방식
CamelCaseUtil.convert2CamelCase fdl.security Character.toUpperCase(char) / toLowerCase(char)
CamelUtil.convert2CamelCase psl.dataaccess 동일
EgovStringUtil 위 두 메서드 fdl.string String.toLowerCase()

AS-IS

String allLower = targetString.toLowerCase();
result = result.concat(Character.toString(currentChar).toLowerCase());

TO-BE

String allLower = targetString.toLowerCase(Locale.ROOT);
result = result.concat(Character.toString(currentChar).toLowerCase(Locale.ROOT));

같은 결함 클래스를 Locale.ROOT로 고친 선례가 이 저장소에 있습니다 — DefaultMapUserDetailsMapping의 컬럼명 소문자화(#321).

범위

같은 파일의 capitalizeswapFirstLetterCase도 인자 없는 변환을 쓰지만 뺐습니다. 두 메서드는 식별자 용도라는 근거가 없습니다.

  • swapFirstLetterCase는 javadoc 예시가 'Password'/'password'이고, 기존 테스트(EgovStringUtilTest.testSwapFirstLetterCase)도 그 단어만 다룹니다.
  • capitalize는 javadoc이 메서드명 한 줄뿐이고, 저장소 안에 호출처도 테스트도 없습니다.

로케일을 고정하면 터키어 단어를 대문자화하려는 정상 사용을 오히려 깨뜨립니다.

ASCII 식별자는 기본 로케일이 무엇이든 결과가 같습니다. 바뀌는 것은 터키어 계열 로케일에서 i/I가 든 이름뿐입니다.

JUnit 테스트 JUnit tests

  • JUnit 테스트 JUnit tests
  • 수동 테스트 Manual testing

EgovStringUtilLocaleTest 2건을 추가했습니다. 기본 로케일을 tr-TR로 바꾼 상태와 원래 로케일 양쪽에서 같은 결과가 나오는지 봅니다. 기본 로케일은 finally에서 되돌립니다.

수정 지점만 되돌린 상태(RED)

[ERROR] Tests run: 2, Failures: 2, Errors: 0, Skipped: 0
[ERROR]   EgovStringUtilLocaleTest.convertToCamelCaseIsLocaleIndependent expected: <printStatus> but was: <prıntStatus>
[ERROR]   EgovStringUtilLocaleTest.convertToUnderScoreIsLocaleIndependent expected: <print_id> but was: <print_ıd>

수정 후(GREEN, 모듈 전체)

[INFO] Tests run: 58, Failures: 0, Errors: 0, Skipped: 0
[INFO] BUILD SUCCESS

convertToCamelCase와 convertToUnderScore는 자기 javadoc이 식별자 변환임을
명시한다("This method convert 'string_util' to 'stringUtil'", "Convert a camel
case string to underscore representation"). 그런데 인자 없는 toLowerCase()를
써서 JVM 기본 로케일을 따르므로, 터키어·아제르바이잔어 로케일에서 I가 점 없는
ı(U+0131)로 바뀐다.

  convertToCamelCase("PRINT_STATUS", '_')  -> "prıntStatus"  (기대 "printStatus")
  convertToUnderScore("printId")           -> "print_ıd"     (기대 "print_id")

같은 일을 하는 형제 구현이 이 저장소에 둘 있고 둘 다 로케일 독립이다 —
fdl.security의 CamelCaseUtil.convert2CamelCase와 psl.dataaccess의
CamelUtil.convert2CamelCase가 Character.toUpperCase(char)/toLowerCase(char)를
쓴다. 같은 목적의 EgovStringUtil 메서드만 String 단위 변환을 거친다.

두 호출 지점에 Locale.ROOT를 명시했다. 같은 결함 클래스를 Locale.ROOT로 고친
선례가 이 저장소에 있다 — DefaultMapUserDetailsMapping의 컬럼명 소문자화(eGovFramework#321).

같은 파일의 capitalize와 swapFirstLetterCase도 인자 없는 변환을 쓰지만 범위에서
뺐다. 두 메서드는 식별자 용도라는 근거가 없다. swapFirstLetterCase는 javadoc
예시가 'Password'/'password'이고 기존 테스트도 그 단어만 다룬다. capitalize는
javadoc이 메서드명 한 줄뿐이고 저장소 안에 호출처도 테스트도 없다. 로케일을
고정하면 터키어 단어를 대문자화하려는 정상 사용을 오히려 깨뜨린다.
@wantaekchoi
wantaekchoi force-pushed the fix/string-util-identifier-case-locale branch from 39b64c9 to 208114b Compare August 13, 2026 23:06
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