[MySQL/PHP] "Server sent charset (255) unknown to the client" 에러 원인과 해결 방법 (AWS Aurora/RDS 적용)

 개발을 하다 보면 간혹 잘 작동하던 서비스나 새로 이전한 환경에서 뜬금없는 DB 연결 에러를 마주하곤 합니다. 오늘 정리할 오류는 PHP(특히 CodeIgniter 등 구형 프레임워크나 레거시 환경)에서 MySQL 8.0 이상(또는 AWS Aurora MySQL v3 등) 버전에 연결할 때 발생하는 전형적인 문자셋(Character Set) 에러입니다. 1. 발생한 에러 메시지 어느 날 갑자기 아래와 같은 PHP Warning 에러가 발생하며 DB 연결이 끊어지는 현상이 나타납니다. Severity: Warning Message: mysqli::real_connect(): Server sent charset (255) unknown to the client. Please, report to the developers Filename: mysqli/mysqli_driver.php Line Number: 161 이어서 (HY000/2054): Server sent charset unknown to the client 라는 메시지도 함께 출력됩니다. 2. 왜 발생했을까? (원인 분석) 이 에러의 핵심은 "DB 서버가 쓰는 최신 표준 언어(문자셋)를 구형 PHP 클라이언트가 알아듣지 못해서" 발생합니다. MySQL 8.0+ / Aurora v3+의 변화 : MySQL 8.0 버전부터 기본 문자셋(Default Character Set)이 기존 utf8 에서 이모지까지 완벽 지원하는 utf8mb4 로 변경되었습니다. 이때 서버가 클라이언트에 전달하는 문자셋 인덱스 번호가 255 번입니다. 구형 PHP 클라이언트 라이브러리의 한계 : 서버에 접속하는 PHP 환경이 다소 오래되었거나(PHP 7.2 이하 등), 내부의 php-mysqlnd 라이브러리가 구버전일 경우 이 255 번( utf8mb4 )이라는 문자셋의 존재 자체를 인지하지 못합니다. 결과 : PHP가 "서버가 보낸 255번 문자셋이 뭔지 모르겠어!"라며 연결을 거부하고 ...

아이패드 크롬에서만 로그인이 안 돼요 — nginx, 로드밸런서, 그리고 사라진 https

 "갤럭시 패드 크롬은 되고요, 아이패드 사파리도 되는데, 아이패드 크롬만 로그인이 안 돼요."   운영하다 보면 이런 신고가 제일 골치 아픕니다. 특정 브라우저, 특정 기기에서만 재현되는 버그. 코드를 아무리 들여다봐도 "브라우저마다 다르게 동작할 이유"가 안 보이거든요. 이 글은 그 신고 한 건이 사실은 nginx가 로드밸런서 뒤에서 https를 http로 떨어뜨리던 고전적인 인프라 함정이었다는 걸 추적한 기록입니다.   증상 : 관리자 대시보드에서 다른 시스템으로 넘어가는 로그인 버튼이 있는데, 이게 특정 환경에서만 실패했습니다.  아이패드 크롬  :  실패,  아이패드 사파리 : 성공  갤럭시탭 크롬 :  성공  PC: 성공    "크롬 문제다"라고 단정하기엔 갤럭시 크롬은 멀쩡합니다. "iOS 문제다"라고 하기엔 사파리는 됩니다. 딱 iOS × 크롬 교집합에서만 터집니다.   로그를 나란히 놓고 본다   증상이 아니라 데이터를 봅니다. 백엔드 referer 검증 로그를 실패/성공 케이스로 나란히 놓으니 결정적 차이가 한 줄에 드러났습니다.   아이패드 크롬 (실패):   referer: http://app.example.com/        ← http, 그리고 루트 경로   허용목록: ['https://admin.example.com/', 'https://app.example.com/']   → referer 체크 후 리다이렉트 (301, 로그인 차단)   아이패드 사파리 (성공):   referer: https://app.example.com/   ← https, 정상 경로   → 통과, 정상 로그인 진행   검증 코드는 단순했습니다.   허용 목록은 전부 https://로 시작합니다. 그런데 ...

MySQL password 대응

MySQL 8에서 사라진 PASSWORD() 함수, 어떻게 대처해야 할까? MySQL을 5.x 버전대에서 8.0 이상으로 업그레이드한 개발자라면 한 번쯤 마주쳤을 법한 오류가 있습니다. 바로 이전에 잘 사용하던 PASSWORD() 함수가 더 이상 작동하지 않는 문제입니다. 기존에는 아래와 같은 쿼리로 사용자의 비밀번호를 손쉽게 해시하여 저장할 수 있었습니다. -- MySQL 8.0 이전 버전에서 사용되던 방식 UPDATE user SET password_column = PASSWORD('my_password'); 하지만 MySQL 8.0부터 PASSWORD() 함수는 지원 중단(deprecated) 후 제거 되었기 때문에, 위 쿼리를 실행하면 오류가 발생합니다. 왜 PASSWORD() 함수가 사라졌을까? 가장 큰 이유는 보안 입니다. PASSWORD() 함수는 ' mysql_native_password ' 인증 방식에 사용되는 해시 값을 생성했는데, 이 해싱 알고리즘은 솔트(salt)를 사용하지 않는 오래된 방식입니다. 최신 보안 표준에 비해 취약점이 존재하여, MySQL 8.0부터는 기본 인증 플러그인이 더 강력한 caching_sha2_password 로 변경되면서 PASSWORD() 함수도 자연스럽게 사라지게 된 것입니다. 임시 해결책: PASSWORD() 함수 직접 구현하기 만약 기존 시스템과의 호환성 문제로 PASSWORD() 함수와 동일한 결과값이 반드시 필요한 상황이라면, 아래와 같이 수동으로 해시 값을 생성할 수 있습니다. 이는 PASSWORD() 함수의 내부 동작을 SQL 함수로 그대로 구현한 것입니다. UPDATE user SET password_column = CONCAT ('*', UPPER( SHA1 ( UNHEX (SHA1('my_password'))))); 이 쿼리는 다음 단계로 실행됩니다. SHA1('m...

MySQL 8.0 Incorrect date value error

  aws Aurora MySQL  5.7에서 8 업그레이드 하면서 나온 에러 date 컬럼에 where '' 했더니 에러 하지만 '0000-00-00' 검색 됨 . 이유는 고마우신분이 작성한 글 내용 MySQL 서버에서 sql_mode 옵션에 NO_ZERO_DATE 옵션과, NO_ZERO_IN_DATE 옵션이 존재한다. 이 2개 옵션은 다음과 같이 동작한다. ​ NO_ZERO_DATE enable: 0000-00-00 값을 invalid date로 인식한다. disable: 0000-00-00 값을 저장할 수 있다. ​ NO_ZERO_IN_DATE enable: date의 month 또는 day 부분에 0이 입력되면 invalid date로 인식한다. disable: 2022-12-00 또는 2022-00-01과 같은 형태의 date 입력이 가능하다. ​ MySQL 5.7, 8.0 이상의 버전에서는 아래와 같은 테이블을 생성하고 데이터를 넣지 않은 상태에서 mysql > CREATE TABLE `new_table` ( `id_table` int(11) NOT NULL AUTO_INCREMENT, `text_table` varchar(45) DEFAULT NULL, `date_table` date DEFAULT NULL, PRIMARY KEY (`id_table`) ) ENGINE=InnoDB 다음의 WHERE절 조건을 가진 쿼리를 수행하면, mysql > SELECT id_table, text_table FROM new_table WHERE date_table = '' OR mysql > SELECT id_table, text_table FROM new_table WHERE date_table = '0000-00-00' Incorrect date value라는 오류가 발생한다. 데이터를 넣는 경우에도 마찬가지이다. 반면에 MySQL 5.6 버전 에서는 경고(Warning)...