이번 포스팅은 이후에 비슷한 상황 발생시에 참고용으로 사용하기 위한 기록의 목적이 큰 포스팅이다.
Linux 호스트의 로케일이 ko_KR.euckr 인 환경에서 Spring Boot 애플리케이션을 배포해야하는 상황에서 발생한 이슈를 처리하는 과정에 대해 기록한다.
프로세스를 실행하는 유저의 Locale은 아래와 같이 ko_KR.euckr로 되어있다.
이 환경에서 Spring boot 애플리케이션을 실행했을 땐 정상적으로 한글 파라미터를 받아 처리하는 로직이 잘 동작했다.
그런데 DRM을 적용하는 과정에서 .bash_profile을 명시적으로 적용해야하는 상황이었고,
.bash_profile을 적용하자마자 한글이 깨지는 이슈가 발생했다.
적용한 .bash_profile 파일을 살펴보니 안에서 export LANG=ko_KR.euckr 로 LANG 변수를 export해주고 있는 상황
이미 유저의 로케일에 적용한 LANG과 동일했기 때문에 별다른 문제가 없을 것이라 생각하고 배포를 진행했으나,
Spring Boot 애플리케이션이 돌아가는 JVM에서 적용되는 부분이 다른듯하다.
일단 프로젝트를 구성 및 배포하면서 따로 설정해준 값이 없었기 때문에
기존 이슈가 발생하지 않았던 시점에서 JVM에 적용된 Default Locale과 Default Encoding이 어떤것인지 확인해보고
이슈가 발생한 시점에서는 어떻게 적용되어있는지 비교해보기로 했다.
Spring Boot 프로젝트이기때문에 어노테이션 기반 Configuration 클래스의 PostConstruct 시점을 잡아 관련 로그를 찍어서 확인했다.
프로젝트에 있는 여러 Config 클래스중 한 군데에 아래와 같은 코드를 작성했다.
@Slf4j
@Configuration
public class WebConfig {
@PostConstruct
public void printCurrentLocale() {
log.info("\tDefault Locale : {}", Locale.getDefault().toString()); // JVM의 기본 로케일
log.info("\tDefault Encoding : {}", Charset.defaultCharset().toString()); // JVM의 기본 인코딩
log.info("\File Encoding : {}", System.getProperty("file.encoding"); // 파일 인코딩
log.info("\tUser Language : {}", System.getProperty("user.language")); // 사용자 언어
log.info("\tUser country : {}", System.getProperty("user.country")); // 사용자 국가
}
}
확인을 해보니 이슈가 발생하지 않은 시점에서는 호스트 레벨에서 설정되어있는 encoding과는 다르게 Default Encoding이 UTF-8로 설정되어 있다.
.bash_profile을 적용해 이슈가 발생한 시점에서는 아래와 같이 Default Encoding과 File Encoding이 EUC-KR로 설정이 되어있는 것을 볼 수 있었다.
Java 18부터는 JVM이 실행된 이후 Spring Application을 실행하기 전 아래와 같이 코드를 실행해 동적으로 JVM의 encoding을 변경해줄 수 있으나 런타임 중간에 인코딩을 변경하는 것은 권장되지도 않고,
현재 프로젝트의 Java 버전이 18보다는 한참 이전 버전이기 때문에 JVM 옵션으로 직접 주입하는 방식을 사용하기로 했다.
System.setProperty("file.encoding", "UTF-8");
Charset.defaultCharset(); // 반드시 다시 호출하여 기본 문자셋을 초기화
JVM을 실행할 때 -Dfile.encoding=UTF-8 옵션을 주어 명시적으로 Default Encoding과 File Encoding을 설정해 한글이 특정 상황 및 환경에서 깨지는 이슈를 해결했다.
'Spring Boot' 카테고리의 다른 글
[Lessons learned] 대용량 파일 다운로드 처리 (0) | 2024.11.29 |
---|---|
[Spring Boot] MappingJackson2HttpMessageConverter 커스터마이징 (0) | 2024.08.22 |