안녕하세요, 아는형입니다.
펌뱅킹(Firm Banking) 수취인 성명조회 서비스를 실행했는데 결과가 이렇게 깨져서 들어온 적 있으신가요? 신규 테스트 서버에서 이 문제를 만났는데, 원인 찾기가 생각보다 까다로웠습니다. 서버에서 확인해본 locale도 정상, file.encoding도 정상인데 정작 데몬은 다른 환경으로 떠 있었던 케이스였거든요. 게다가 한 번 고쳤다고 끝난 게 아니라, HA 테스트를 거치고 나니 똑같은 증상이 다시 나타나서 한 번 더 삽질을 했습니다. 이번 글은 그 두 번의 조치를 처음부터 끝까지 순서대로 풀어보겠습니다.
증상: 수취인명이 깨져서 나온다
신규 테스트 서버에서 펌뱅킹 수취인 성명조회를 실행했는데, 수취인명 필드에 한글이 정상적으로 표시되지 않고 깨진 문자로 들어오는 현상이 발생했습니다. 개발서버에서는 멀쩡하게 잘 나오던 게 신규 테스트 서버에서만 이러니, 일단 서버 설정 쪽을 의심해볼 수밖에 없었습니다.

예전 이슈부터 떠올려봤다
이런 인코딩 문제, 사실 처음이 아니었습니다. 예전에도 비슷한 걸로 애먹었던 기억이 나서, 일단 그때 체크했던 두 가지부터 서버 담당자에게 확인 요청을 드렸습니다.
glibc-commonpackage 설치 확인 — 수취인성명조회 시 한글 깨지는 현상 방지
- firmbank OS user locale에서 UTF-8 제거 — 수취인성명조회 시 한글 깨지는 현상 방지

이 두 가지는 펌뱅킹 인터페이스에서 한글 처리할 때 꽤 자주 원인이 되는 부분이라, 서버 담당자 쪽에 먼저 던져놓고 결과를 기다렸습니다.
그런데도 계속 깨진다면?
여기서 대부분 “그럼 됐네” 하고 넘어가기 쉬운데, 만약 위 두 가지 처리가 다 된 상태에서도 여전히 깨져 보인다면 얘기가 달라집니다. 실제로 firmbank 계정으로 로그인해서 확인해보니 locale charmap = EUC-KR, Java file.encoding = EUC-KR로 정상 확인이 됐습니다. 겉으로 보기엔 문제가 없는 상태였던 거죠.
그런데 진짜 원화 펌뱅킹 JCo 데몬인 BRO_EFT_JCO_KRW_TEST의 실제 프로세스 환경을 뜯어보니, LC_ALL=C로 기동되어 있는 것이 확인됐습니다. 로그인 환경은 정상인데, 정작 데몬이 떠 있는 환경은 따로 놀고 있었던 겁니다.
로그인해서 확인하는 locale과, 실제로 데몬이 기동될 때 적용받는 locale은 서로 다를 수 있습니다. 여기서 삽질 좀 했습니다.
진단 절차: PID 찾아서 environ 뜯어보기
일단 현재 떠 있는 Java 프로세스부터 찾아야 합니다.
ps -ef | grep java
여기서 확인된 PID값을 아래 명령어에 넣어서 조회합니다.
cat /proc/PID/environ | tr '\0' '\n' | \
grep -E '^(LANG|LC_|JAVA_HOME|JRE_HOME|LD_LIBRARY_PATH)'
실행 결과는 이랬습니다.
LANG=ko_KR.UTF-8
LC_ALL=C
이걸 보고 바로 감이 왔습니다. LANG은 정상인데 LC_ALL이 C로 박혀 있으니, 이게 문제였던 겁니다.

LC_ALL이 LANG보다 우선순위가 높다는 것
이게 진짜 웃긴 게, LC_ALL은 LANG보다 우선순위가 높습니다. 즉 데몬이 예를 들어 이런 상태로 떠 있다고 하면,
LANG=ko_KR
LC_ALL=C
실질적으로는 LC_ALL=C가 우선 적용됩니다. 그래서 로그인해서 확인한 locale charmap이 EUC-KR로 정상이어도, 실제 펌뱅킹 데몬은 완전히 다른 Locale 환경으로 기동되어 있을 수 있는 겁니다. 혹시 이런 식으로 로그인 환경은 멀쩡한데 실제 배치나 데몬 프로세스에서만 이상하게 동작하는 케이스, 보신 분 계신가요? 대부분 여기서 놓칩니다.
서버 담당자에게 요청한 내용
원인이 어느 정도 좁혀졌으니, 서버 담당자에게 아래처럼 정리해서 요청드렸습니다.
신규 테스트 서버 펌뱅킹 수취인성명조회 한글 깨짐 관련 확인 요청드립니다.
현재 firmbank 계정 로그인 환경에서는 locale charmap = EUC-KR, Java file.encoding = EUC-KR로 정상 확인되었습니다.
다만 실제 원화 펌뱅킹 JCo 데몬(BRO_EFT_JCO_KRW_TEST)의 프로세스 환경을 확인한 결과 LC_ALL=C로 기동되어 있는 것으로 확인됩니다.
개발서버 정상 환경과 동일하게 펌뱅킹 KRW 데몬 기동 시 Locale이 EUC-KR을 사용하도록 아래 사항 확인 부탁드립니다.
- 기동 Script 또는 Service 설정에서 LC_ALL=C 설정 여부 확인
- LC_ALL=C가 설정되어 있다면 제거 또는 LC_ALL=ko_KR로 변경
- LANG=ko_KR 설정 확인
- 변경 후 펌뱅킹 KRW JCo 데몬 재기동
- 재기동 후 실제 프로세스의 LANG, LC_ALL 값 확인
서버 전체 Locale 변경이 아니라 펌뱅킹 데몬 기동 환경에 한해서 적용 부탁드립니다.
실제 처리 방법: 두 가지 옵션
서버 담당자 쪽에서 실제로 적용할 수 있는 방법은 두 가지입니다.
| 구분 | 방법 1 (권장) | 방법 2 |
|---|---|---|
| 처리 방식 | LC_ALL 제거 | LC_ALL을 ko_KR로 명시 |
| 동작 원리 | LANG 설정을 그대로 따라감 | LC_ALL을 직접 지정해 덮어씀 |
| 명령어 | export LANG=ko_KRunset LC_ALL |
export LANG=ko_KRexport LC_ALL=ko_KR |
방법 1은 LC_ALL이 LANG을 덮어쓰지 않으므로, 현재 서버에서 확인된 ko_KR → EUC-KR 환경을 그대로 따라갑니다. 방법 2는 명시적으로 맞추는 방식이고요.
현재 상황에서는 서버 담당자에게 “LC_ALL=C를 무조건 ko_KR로 변경해달라”기보다는, “왜 펌뱅킹 데몬 기동 시 LC_ALL=C가 들어가는지 확인 후 제거하거나 ko_KR을 적용해달라”고 요청하는 것이 더 정확합니다.
변경 후에는 반드시 데몬을 재기동해야 합니다. 이미 실행 중인 Java 프로세스는 환경변수를 자동으로 다시 읽지 않습니다.
재기동 후 최종 확인
재기동 후에는 서버 담당자에게 아래 명령 결과까지 확인해달라고 요청하시면 됩니다.
cat /proc/<KRW_JCO_PID>/environ | tr '\0' '\n' | \
grep -E '^(LANG|LC_)'
정상적으로는 예를 들어 이렇게 나오거나,
LANG=ko_KR
LC_ALL=ko_KR
혹은 이렇게 나오면 됩니다.
LANG=ko_KR
그리고 locale charmap 기준으로는 이미 확인했던 것처럼 EUC-KR이 되어야 정상입니다. 이렇게 해서 1차 조치는 마무리됐고, 실제로 unset LC_ALL을 적용한 뒤로는 수취인명이 깨지지 않고 정상적으로 조회됐습니다. 여기서 끝났으면 좋았을 텐데, 얘기가 하나 더 남아 있습니다.
그런데 얼마 뒤, HA 테스트 후 다시 깨졌다
문제가 또 발생했습니다. HA 테스트 후 다시 펌뱅킹 데몬을 실행하니 수취인성명조회 결과가 다시 깨져서 나오는 문제가 발생했습니다.
분명 unset LC_ALL로 해결했던 건데 왜 또 이러나 싶었는데, HA 테스트 과정에서 데몬이 재기동되면서 기동 스크립트에 반영해둔 환경변수 설정이 제대로 안 먹혔거나, 혹은 기동 방식 자체가 예전 상태로 되돌아간 걸로 보였습니다. 어쨌든 증상은 똑같았고, 이번에는 좀 더 확실하게 잡아야겠다 싶어서 기동 스크립트 자체에 손을 댔습니다.
2차 조치: LC_CTYPE까지 넣은 이유
이번에는 sh 파일에 아래 내용을 추가했습니다.
# Korean Locale for Firmbank
unsetenv LC_ALL
setenv LANG ko_KR
setenv LC_CTYPE ko_KR
여기서 LC_CTYPE을 왜 넣었는지 궁금하실 텐데요. LC_CTYPE은 문자 분류 및 문자셋 처리와 직접 관련된 Locale 카테고리입니다. 지금까지 실제 테스트에서 확인된 건 이렇습니다.
- LC_ALL=C → 수취인성명 깨짐
- unset LC_ALL → 수취인성명 정상
이게 확인됐기 때문에, LC_ALL을 제거하는 것에서 한 걸음 더 나아가 Java 프로세스가 확실하게 한국어 Locale을 사용하도록 LANG=ko_KR과 LC_CTYPE=ko_KR까지 명시하는 방식으로 갔습니다. 1차 조치가 “우선순위 문제를 없앤 것”이었다면, 2차 조치는 “문자 처리 담당 카테고리를 아예 못 박아버린 것”이라고 보시면 됩니다.
unset LC_ALL은 현재 셸 환경에서 LC_ALL 환경변수 값을 제거하는 것이지, “서버의 Locale 설정 자체를 삭제한다”는 뜻은 아닙니다. LC_ALL이 없어지면 이후로는 LANG 설정을 따라가게 되는 구조입니다.
이 내용을 Script에서 Class Path 지정 전에 반영했더니 성공적으로 깨짐이 없어졌습니다. 최종적으로 적용한 기동 스크립트는 아래와 같습니다.
#!/usr/bin/csh -f
ps -ef | grep -v grep | grep BRO_EFT_JCO_KRW_TEST
if ($status == 0) then
echo ""
echo "=================================="
echo "Ucess*EFT KRW TEST process is running."
echo "Stopping process..."
echo "=================================="
echo ""
echo ""
set process_id=`ps -ef | grep -v grep | grep BRO_EFT_JCO_KRW_TEST | nawk '{print $2}'`
kill -9 $process_id
endif
#-------------------------------------------------
# Firmbank Korean Locale
#-------------------------------------------------
unsetenv LC_ALL
setenv LANG ko_KR
setenv LC_CTYPE ko_KR
setenv BMTP_HOME /develop/firmbank/KRW
setenv CLASSPATH .:$BMTP_HOME ~ 중략
echo $CLASSPATH
cd /develop/firmbank/KRW
java -DBRO_EFT_JCO_KRW_TEST \
-Xms256M \
-Xmx256M \
-DBMTP_HOME=$BMTP_HOME \
com.b2binternet.apro.process.ClientServer -debug &
정리하며
신규 테스트 서버의 펌뱅킹 KRW JCo 데몬이 LC_ALL=C 환경으로 기동되고 있어 수취인명 한글 깨짐의 원인으로 의심되는 상황이었고, 1차로는 unset LC_ALL로 해결이 됐습니다. 그런데 HA 테스트를 거치면서 같은 증상이 재발했고, 이번에는 LC_CTYPE=ko_KR까지 스크립트에 명시해서야 완전히 잡혔습니다.
로그인 환경만 보고 “정상인데 왜 깨지지?” 하고 넘어갔으면 한참 더 헤맸을 것 같은 케이스였습니다. 그리고 한 번 고쳤다고 방심하면 안 된다는 것도 다시 한번 느꼈습니다. HA나 이중화 구성이 걸린 환경에서는 데몬 기동 스크립트가 생각보다 쉽게 예전 상태로 돌아갈 수 있으니, 관련 작업 하실 때 참고하시면 좋을 것 같습니다.