서버 환경을 새로 구축하거나 잘 구동되던 웹 서비스에서 갑자기 "ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)" 혹은 "(111)" 에러를 마주친 적이 있을 것이다. 소스 코드는 전혀 수정하지 않았는데 갑자기 DB 접속이 안 되어 당황했던 경험이 한 번쯤은 있을 것이다. 다만 대부분의 개발자들은 이 에러가 발생하면 소켓 파일 위치나 소켓 통신과 TCP/IP 통신의 차이를 모른 채 무작정 서버를 재부팅하거나 인터넷에서 검색한 chown 명령어를 무지성으로 따라치곤 한다. 이번에는 MySQL ERROR 2002 에러가 정확히 왜 발생하는지, 소켓 방식과 TCP/IP 접속 방식의 원리는 무엇인지, 그리고 상황별 원인과 해결 방법을 완벽하게 정리해서 소개하겠다.

 

1. MySQL ERROR 2002 에러의 발생 원인과 기초 이해

MySQL 데몬에 접속할 때 발생하는 ERROR 2002(HY000)는 클라이언트가 MySQL 서버와 통신 채널을 형성하지 못했을 때 발생하는 대표적인 연결 오류다. 리눅스 환경에서 localhost로 접속을 시도할 경우, MySQL 클라이언트는 기본적으로 네트워크(TCP/IP) 포트를 타지 않고 로컬 유닉스 도메인 소켓(Unix Domain Socket, 예: /tmp/mysql.sock 또는 /var/run/mysqld/mysqld.sock)을 통해 직접 통신을 시도한다.

이때 발생하는 주요 에러 메시지의 차이는 다음과 같다.

에러 번호/메시지주요 원인설명
(2) No such file or directory소켓 파일 부재 / 경로 불일치mysqld 서비스가 정지되어 소켓 파일이 생성되지 않았거나, my.cnf의 소켓 경로가 서로 다름
(111) Connection refused데몬 미구동 / 포트 차단MySQL 프로세스가 비정상 종료되었거나, TCP/IP 포트(3306)가 닫혀 있음
(13) Permission denied소켓 파일 접근 권한 부족소켓 파일이 속한 디렉토리나 파일 자체의 소유권/권한 설정 문제

 

2. 상황별 단계별 해결 방법

ERROR 2002를 해결하기 위해서는 차근차근 점검 절차를 거쳐야 한다. 단순히 소켓 파일 경로만 바꾼다고 해결되지 않는 경우가 많기 때문이다.

 

방법 1: MySQL 데몬(서비스) 상태 확인 및 재시작

가장 흔한 원인은 MySQL 서비스 자체가 멈춰있는 경우다. 데몬이 실행 중이지 않으면 당연히 소켓 파일도 생성되지 않는다.

# 서비스 상태 확인
systemctl status mysqld

# 서비스가 꺼져 있다면 재시작
systemctl start mysqld

 

방법 2: 소켓(Socket) 경로 일치시키기

MySQL 서버 설정파일(/etc/my.cnf 또는 /etc/mysql/my.cnf)에서 정의된 소켓 위치와 클라이언트(PHP, CLI)가 찾아가는 위치가 다를 때 발생한다. my.cnf 파일 내 [mysqld] 영역과 [client] 영역의 socket 경로를 동일하게 맞춰주어야 한다.

[mysqld]
socket=/var/run/mysqld/mysqld.sock

[client]
socket=/var/run/mysqld/mysqld.sock

 

방법 3: localhost 대신 127.0.0.1 (TCP/IP)로 접속하기

급하게 서비스를 복구해야 할 때 유용한 팁이다. DB 호스트명을 localhost로 지정하면 유닉스 소켓 통신을 시도하지만, 127.0.0.1로 지정하면 Loopback TCP/IP 통신을 하므로 소켓 파일 문제 영역을 즉시 우회할 수 있다.

 

3. 실전 예제: PHP 및 CLI 환경에서의 오류 해결

실제 애플리케이션 코드 및 환경 설정에서 이 오류가 발생하는 경우와 이를 해결하는 방법을 살펴보자.

먼저 설정 오류로 인해 접속이 실패하는 잘못된 PHP PDO 예제 코드다.

✗ 잘못된 코드 (localhost 사용 시 소켓 파일 경로 불일치로 인한 예외 발생)

<?php
// localhost 사용 시 기본 유닉스 소켓 경로를 찾지만, 서버 환경과 맞지 않아 2002 에러 발생
$dsn = "mysql:host=localhost;dbname=testdb;charset=utf8mb4";
$username = "dbuser";
$password = "secret1234";

try {
    $pdo = new PDO($dsn, $username, $password);
} catch (PDOException $e) {
    // SQLSTATE[HY000] [2002] Can't connect to local MySQL server... 에러 출력
    echo "연결 실패: " . $e->getMessage();
}
?>

다음은 TCP/IP 방식을 명시하거나 unix_socket 경로를 직접 지정하여 접속을 성공시키는 올바른 코드다.

✓ 올바른 코드 (127.0.0.1 명시 또는 unix_socket 경로 직접 지정)

<?php
$username = "dbuser";
$password = "secret1234";

// 해결 방법 A: 127.0.0.1을 사용하여 TCP/IP 통신으로 소켓 이슈 우회
$dsn_tcp = "mysql:host=127.0.0.1;port=3306;dbname=testdb;charset=utf8mb4";

// 해결 방법 B: unix_socket 경로를 명확하게 지정하여 소켓 연결
$dsn_socket = "mysql:host=localhost;dbname=testdb;unix_socket=/var/run/mysqld/mysqld.sock;charset=utf8mb4";

try {
    $pdo = new PDO($dsn_tcp, $username, $password, [
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
    ]);
    echo "MySQL 연결 성공!";
} catch (PDOException $e) {
    echo "연결 실패: " . $e->getMessage();
}
?>

실행 결과:

MySQL 연결 성공!

 

4. 주의사항 및 흔한 실수

ERROR 2002를 해결할 때 자주하는 실수와 주의해야 할 포인트들을 정리해보았다.

  • 무작정 chmod 777 부여: 소켓 파일이 안 열린다고 /tmp나 소켓 디렉토리에 chmod 777을 남발하는 것은 심각한 보안 위협이다.
  • 올바른 소유권 설정: chown -R mysql:mysql /var/run/mysqld 와 같이 해당 디렉토리와 파일의 소유권을 mysql 계정으로 정확히 지정해야 한다.
  • my.cnf 수정 후 재시작 누락: /etc/my.cnf의 소켓 경로를 수정해놓고 systemctl restart mysqld를 실행하지 않으면 설정이 적용되지 않는다.
  • php.ini의 default_socket 확인: PHP 웹 환경에서는 php.ini의 pdo_mysql.default_socket 또는 mysqli.default_socket 설정이 실제 mysqld 소켓 위치와 일치하는지도 점검해야 한다.

 

5. 마무리 및 요약

MySQL ERROR 2002 에러는 결국 **"MySQL 데몬이 정상 구동되지 않았거나, 클라이언트와 서버가 서로 다른 소켓 경로를 바라보고 있거나, 접근 권한 문제로 소켓 파일을 읽을 수 없는 현상"**이다. 문제 원인을 파악할 때 무작정 복사해온 명령어들을 실행하기보다, 데몬 상태 확인 -> localhost 대 127.0.0.1 차이 이해 -> my.cnf 소켓 경로 점검 순으로 접근하는 것이 정석이다.

안정적인 DB 통신은 웹 애플리케이션 동작의 기본이다. 이번 글에서 다룬 소켓 통신 원리와 설정 점검 포인트를 잘 기억해두고, 추후 디버깅 시 127.0.0.1 우회 테스트와 my.cnf 소켓 경로 통일 작업을 차근차근 진행해보자. 문제 상황을 정확히 진단하는 작은 습관이 모여 서비스 안정성을 획기적으로 높여줄 것이다.