MySQL 5.7에서 8.0으로 버전을 올려서 최신 DB 환경을 구축했거나 Docker로 MySQL 인스턴스를 새로 띄운 뒤 PHP로 접속을 시도하다가 SQLSTATE[HY000] [2054] 에러를 마주친 적이 있을 것이다. DB 서버는 올바르게 동작하고 접속 정보도 분명 정확한데 PHP 스크립트를 실행하는 즉시 커넥션이 튕겨나간다.
다만 정확한 원인이나 해결책을 모르는 채 php.ini 설정을 무작정 수정하거나 DB 서버를 계속 재부팅하는 경우가 많다.
이번에는 MySQL 8.0의 기본 인증 플러그인 변경 원인이 정확히 뭔지, 왜 PHP PDO 연동에서 오류가 발생하는지, 그리고 운영 환경별로 안전하게 해결하는 방법을 완벽하게 정리해서 소개하겠다.
MySQL 8.0 버전부터는 보안 강화를 위해 기본 사용자 인증 플러그인이 기존 mysql_native_password에서 caching_sha2_password로 변경되었다. 보안 관점에서는 SHA-256 기반의 비대칭 암호화와 빠른 캐싱을 지원하므로 훨씬 안전하다.
문제는 기존의 PHP PDO extensions(특히 php_pdo_mysql) 및 mysqlnd 드라이버 구버전이 이 새로운 인증 메커니즘을 제대로 처리하지 못한다는 점이다. 클라이언트인 PHP가 DB 서버가 요구하는 SHA-256 인증 교환 방식을 알지 못하니 연결 시도 단계에서 2054 에러를 내뿜으며 끊어진다.
이 문제의 본질은 DB 계정이 사용 중인 인증 플러그인과 PHP 클라이언트가 지원하는 인증 플러그인의 불일치다. 상황에 맞춰 계정 단위로 방식을 바꾸거나 서버 전역 설정을 변경해 해결할 수 있다.
가장 안전하고 권장되는 방식이다. 전역 보안 설정을 건드리지 않고, PHP 애플리케이션이 사용하는 특정 사용자 계정에만 이전 인증 방식을 적용한다. MySQL 관리자 권한(root)으로 접속한 뒤 다음 SQL 명령을 실행한다.
ALTER USER 'app_user'@'localhost' IDENTIFIED WITH mysql_native_password BY 'your_password';
FLUSH PRIVILEGES;
개발 환경이나 여러 클라이언트가 동시에 구형 방식을 사용해야 하는 경우에는 서버 기본값을 바꿀 수 있다. /etc/mysql/my.cnf 또는 /etc/my.cnf 파일의 [mysqld] 섹션에 아래 설정을 추가하고 MySQL 서비스를 재시작한다.
[mysqld]
default_authentication_plugin = mysql_native_password
인증 방식을 수정한 후 PHP PDO를 통해 안전하게 데이터베이스에 연결하는 실전 코드 구조다.
✗ 잘못된 연동 시도 (caching_sha2_password 미지원 환경에서 기본 계정 연결 시도)
<?php
// 인증 방식 불일치 상태에서 기존 코드 그대로 접속 시도
$dsn = 'mysql:host=127.0.0.1;dbname=production_db;charset=utf8mb4';
$user = 'app_user';
$password = 'secret1234';
$pdo = new PDO($dsn, $user, $password);
// 원인: 서버는 caching_sha2_password를 요구하지만 PHP 드라이버가 응답하지 못해 Fatal Error 발생
?>결과: Fatal error: Uncaught PDOException: SQLSTATE[HY000] [2054] The server requested authentication method unknown to the client
✓ 올바른 연동 코드 (mysql_native_password 계정 설정 후 PDO 예외 처리)
<?php
$dsn = 'mysql:host=127.0.0.1;dbname=production_db;port=3306;charset=utf8mb4';
$user = 'app_user';
$password = 'secure_password123!';
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
];
try {
$pdo = new PDO($dsn, $user, $password, $options);
echo "MySQL 8.0 데이터베이스 연결에 성공했습니다.";
} catch (PDOException $e) {
error_log("DB 접속 실패 상세: " . $e->getMessage());
exit("데이터베이스 커넥션에 실패했습니다. 관리자에게 문의하세요.");
}
?>결과: MySQL 8.0 데이터베이스 연결에 성공했습니다.
두 인증 방식의 명확한 특성을 이해하고 서비스 환경에 맞춰 적용해야 한다.
| 비교 항목 | mysql_native_password | caching_sha2_password |
|---|---|---|
| 암호화 알고리즘 | SHA-1 기반 | SHA-256 기반 |
| 보안 수준 | 보통 (오래된 표준) | 매우 높음 (강력한 보안) |
| PHP 구버전 호환성 | 완벽 호환 (PHP 5.x~8.x) | PHP 7.4 이상 + OpenSSL 필요 |
| MySQL 8.0 기본값 | 아님 (기존 방식) | 기본값 (Default) |
✗ 서버 전체 보안을 낮추기 위해 my.cnf 전체 설정을 바꾸고 계정을 root 그대로 운영하는 실수.
✓ 애플리케이션 전용 계정을 별도로 분리 생성하고 해당 계정만 mysql_native_password를 지정하여 운영하는 방법.
MySQL 8.0 인증 플러그인 설정은 백엔드 서비스의 안정적인 DB 연결을 결정짓는 핵심 요소다. 무심코 넘어가기 쉬운 작은 보안 및 인증 습관이 모여서 서비스의 안정성과 가동률을 만든다는 점을 잊지 말자. 이 글의 인증 방식 변경 명령어와 PHP PDO 연결 코드를 참고해 서버 환경을 재점검하면, 더 이상 DB 접속 에러로 시간을 허비하지 않고 안정적인 서비스 운영 결과를 얻을 수 있을 것이다.