Hello

MySQL 5에서 8로 업그레이드 시 utf8mb4와 JDBC characterEncoding 옵션 설정 본문

java

MySQL 5에서 8로 업그레이드 시 utf8mb4와 JDBC characterEncoding 옵션 설정

nari0_0 2025. 4. 1. 18:02
728x90

MySQL 5.x 버전의 지원 종료로 8버전으로 업그레이드를 진행하게 되었습니다.

기존에 JDBC characterEncoding 옵션을 utf8로 사용하고 있었으나, 관련 문서에서 utf8mb4를 사용해야 한다는 내용을 확인하고, 이를 변경한 후 발생한 에러를 해결하기 위한 과정에서 characterEncoding 옵션과 관련한 내용을 정리합니다.

 

1. JDBC 연결 문자열 옵션 변경 (utf8 → utf8mb4) 

기존 : ?useUnicode=true&characterEncoding=utf8

변경 : ?useUnicode=true&characterEncoding=utf8mb4

2. 런타임 에러 발생

utf8mb4를 지원하지 않는다는 에러 발생

Caused by: com.mysql.cj.exceptions.WrongArgumentException: Unsupported character encoding 'utf8mb4'
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:1.8.0_242]
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) ~[na:1.8.0_242]
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[na:1.8.0_242]
	at java.lang.reflect.Constructor.newInstance(Constructor.java:423) ~[na:1.8.0_242]
	at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:61) ~[mysql-connector-java-8.0.27.jar:8.0.27]
	at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:105) ~[mysql-connector-java-8.0.27.jar:8.0.27]
	at com.mysql.cj.util.StringUtils.getBytes(StringUtils.java:231) ~[mysql-connector-java-8.0.27.jar:8.0.27]
	at com.mysql.cj.jdbc.JdbcPropertySetImpl.postInitialization(JdbcPropertySetImpl.java:66) ~[mysql-connector-java-8.0.27.jar:8.0.27]
	at com.mysql.cj.conf.DefaultPropertySet.initializeProperties(DefaultPropertySet.java:231) ~[mysql-connector-java-8.0.27.jar:8.0.27]
	at com.mysql.cj.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:390) ~[mysql-connector-java-8.0.27.jar:8.0.27]
	... 126 common frames omitted
Caused by: java.io.UnsupportedEncodingException: utf8mb4
	at java.lang.StringCoding.encode(StringCoding.java:341) ~[na:1.8.0_242]
	at java.lang.String.getBytes(String.java:918) ~[na:1.8.0_242]
	at com.mysql.cj.util.StringUtils.getBytes(StringUtils.java:229) ~[mysql-connector-java-8.0.27.jar:8.0.27]
	... 129 common frames omitted

 

3. 디버깅 및 원인 분석

디버깅을 통해 JdbcPropertySetImpl.postInitialization 메소드에서 발생한 문제의 원인을 확인했습니다. 해당 메소드의 에러는 utf8mb4 인코딩을 처리하려 할 때, Java에서 utf8mb4 인코딩을 지원하지 않아 UnsupportedEncodingException이 발생했으며, 이로 인해 JDBC 연결 문자열 설정 오류가 있음을 확인했습니다.

 

 

 

JdbcPropertySetImpl.postInitialization 일부

String testEncoding = getStringProperty(PropertyKey.characterEncoding).getValue();
if (testEncoding != null) {
    // Attempt to use the encoding, and bail out if it can't be used
    String testString = "abc";
    StringUtils.getBytes(testString, testEncoding);
}

StringUtils.getBytes()에서 testEncoding 값으로 "utf8mb4"가 전달되면서, String.getBytes("utf8mb4") 호출 시 에러가 발생했습니다. 이 문제는 Java에서 utf8mb4 인코딩을 지원하지 않기 때문에 발생했습니다.

따라서, characterEncoding=utf8mb4 설정은 지원되지 않으며, 호환성 문제가 발생할 수 있습니다. 이 문제를 해결하려면 characterEncoding을 UTF-8로 설정해야 합니다.

4. 해결 방법: UTF-8 사용

characterEncoding을 UTF-8로 설정해도 문제가 없는 이유는, utf8과 utf8mb4가 서로 호환되기 때문입니다. UTF-8 인코딩을 사용하면, MySQL 서버에서 utf8mb4를 사용할 때도 데이터가 호환성 문제 없이 정상적으로 처리됩니다.

  • characterEncoding은 Java 애플리케이션에서 MySQL 서버로 데이터를 전송하거나, MySQL 서버에서 Java 애플리케이션으로 데이터를 읽을 때 사용할 문자 인코딩을 정의합니다.
  • Java 클라이언트 측에서는 UTF-8을 사용하고, MySQL 서버 측에서는 utf8mb4를 사용하게 되며, 이 두 인코딩은 실질적으로 동일한 방식으로 데이터를 처리합니다.
    • 이유는 utf8mb4가 UTF-8의 확장판으로, 기본적으로 UTF-8을 기반으로 하여 최대 4바이트 문자까지 처리할 수 있도록 설계되었기 때문입니다. UTF-8은 1~4바이트를 사용하여 데이터를 저장하고, MySQL의 utf8mb4는 4바이트를 지원해 더 넓은 범위의 문자를 처리할 수 있습니다., 두 인코딩은 대부분의 경우 동일하게 작동하며 UTF-8을 사용하는 Java 클라이언트와 utf8mb4를 사용하는 MySQL 서버 간에 데이터가 호환성 문제 없이 주고받을 수 있습니다.

결론

utf8mb4는 MySQL에서만 사용하는 문자셋이기 때문에, Java에서 이를 직접 사용할 수 없습니다. 대신 UTF-8을 사용하여 호환성 문제 없이 MySQL의 utf8mb4와 데이터를 주고받을 수 있습니다.

 

+) character_set_server=utf8mb4 옵션은 db 서버의 character을 설정하는 옵션이다. 디비가 이미 utf8mb4로 설정 되어있다면 이 옵션은 추가적인 영향을 미치지 않는다.

 

728x90