[TIPS] Docker로 MySQL 8.0·8.4 & MariaDB 완벽 구축: 한글 깨짐(utf8mb4)·Public Key Retrieval·caching_sha2_password 오류 및 프로덕션 Docker Compose 설정

Docker로 MySQL 8.0·8.4 & MariaDB 완벽 구축

[TIPS] Docker로 MySQL 8.0·8.4 & MariaDB 완벽 구축: 한글 깨짐(utf8mb4)·Public Key Retrieval·caching_sha2_password 오류 및 프로덕션 Docker Compose 설정

💡 핵심 요약: Docker 환경에서 MySQL이나 MariaDB 컨테이너를 구동할 때 개발자들을 가장 당혹스럽게 만드는 문제는 한글 및 이모지 저장 시 발생하는 Incorrect string value 한글 깨짐, DBeaver나 Spring Boot 등 외부 클라이언트 연동 시 발생하는 Public Key Retrieval is not allowed 보안 차단, 그리고 MySQL 8.4 LTS 전환에 따른 인증 플러그인(caching_sha2_password 강제 및 mysql_native_password 공식 제거) 비호환 이슈입니다. 본 가이드에서는 과거 레거시 5.7 시절의 임시방편 설정이 현대 RDBMS 컨테이너에서 실패하는 근본 원인을 해부하고, MySQL 8.0 / 8.4 LTS 및 MariaDB 11.4 LTS 최신 표준 콜레이션(utf8mb4_0900_ai_ci vs utf8mb4_uca1400_ai_ci), 엔진 및 버전별 정밀 호환성 매트릭스, 헬스체크와 초기화 스크립트(init.sql)가 완비된 프로덕션급 docker-compose.yml과 my.cnf, 그리고 실무 4대 치명적 에러에 대한 종결형 해결책을 총정리합니다.

1. 왜 과거 방식(MySQL 5.7 / 단순 docker run)은 문제가 되는가?

구글링이나 과거 튜토리얼(2018~2021년경 작성)을 참고하여 Docker 환경에 MySQL 컨테이너를 띄우다 보면 대부분 다음과 같은 단발성 명령어를 마주하게 됩니다:

❌ 과거 레거시 방식 (현대 프로덕션 환경 사용 금지 / CrashLoop 유발)
# [과거 레거시 방식 - 현대 프로덕션 환경 사용 금지]
docker run -d --name legacy-mysql \
  -e MYSQL_ROOT_PASSWORD=mypassword \
  -p 3306:3306 \
  mysql:latest

이 명령어는 겉보기에 정상 동작하는 것처럼 보이지만, 실무 개발 및 서비스 배포 환경에서 즉각 치명적인 문제들을 연쇄적으로 일으킵니다.

1) MySQL 5.7의 공식 수명 주기 종료(EOL)와 8.4 LTS 시대의 도래

MySQL 5.7은 2023년 10월 25일부로 공식 수명 주기(End of Life, EOL)가 완전히 종료되었습니다. Oracle로부터 어떤 보안 패치, 버그 수정, 성능 개선도 제공되지 않는 상태입니다. 현재 실무 환경의 표준은 오랫동안 안정성이 검증된 MySQL 8.0과, 2024년에 공식 출시된 장기 지원 버전인 MySQL 8.4 LTS입니다.

그러나 mysql:latest 태그는 예고 없이 메이저 버전이 올라가며, 과거 5.7 기준 옵션이나 설정 파일(my.cnf)을 최신 이미지에 그대로 주입하면 컨테이너가 시작 직후 CrashLoop에 빠지거나 부팅이 거부됩니다.

2) 불완전한 utf8(utf8mb3)과 기본 캐릭터셋 latin1의 한계

MySQL 5.7 이전 버전의 기본 문자셋은 서유럽 언어용인 latin1이었습니다. 당시 튜토리얼들은 이를 해결하기 위해 CHARACTER SET utf8 옵션을 부여하라고 안내했습니다. 하지만 MySQL 내부에서 utf8은 사실상 최대 3바이트 가변 길이만 지원하는 utf8mb3의 별칭(Alias)에 불과합니다.

DIAGRAM: ENCODING STORAGE ARCHITECTURE
[문자 인코딩 스토리지 구조 비교]
UTF-8 표준 규격 (RFC 3629) ───► 최대 4바이트 (한글: 3바이트, 이모지/특수문자: 4바이트)
MySQL 레거시 'utf8' (utf8mb3) ──► 최대 3바이트까지만 수용 ❌ (이모지 👨‍👩‍👧, 고대 한자 저장 시 유실)
MySQL/MariaDB 'utf8mb4' ───────► 최대 4바이트 온전한 수용 ✅ (모든 현대 유니코드 완벽 지원)

모바일 앱과 최신 웹 서비스에서 사용자가 이모지(Emoji, 4바이트 유니코드)나 특수 한자를 입력할 경우, 3바이트 utf8 데이터베이스는 즉각 예외를 던지며 트랜잭션을 롤백시킵니다.

3) MySQL 8.0의 caching_sha2_password 도입과 8.4 LTS의 mysql_native_password 제거

MySQL 5.7까지 기본 인증 플러그인은 취약한 SHA-1 해시 기반의 mysql_native_password였습니다. MySQL 8.0부터는 보안 강화를 위해 RSA 키 교환 및 SHA-256 기반의 caching_sha2_password가 기본값으로 채택되었습니다.

더욱 치명적인 변화는 MySQL 8.4 LTS에서 발생했습니다:

  • MySQL 8.0: caching_sha2_password가 기본값이지만, 레거시 지원을 위해 default_authentication_plugin=mysql_native_password 설정이 허용되었습니다.
  • MySQL 8.4 LTS: mysql_native_password 플러그인이 엔진 코어에서 기본 비활성화 및 공식 제거(Deprecated/Disabled)되었습니다. 과거 블로그 글을 보고 MySQL 8.4 컨테이너에 --default-authentication-plugin=mysql_native_password 옵션을 넘기면, [ERROR] [MY-011071] [Server] Plugin 'mysql_native_password' is not loaded 또는 알 수 없는 변수 에러를 뿜으며 컨테이너가 즉시 종료됩니다.

2. 최신 공식 표준 해법: MySQL 8.0 / 8.4 & MariaDB 11.4

현대적인 클라우드 네이티브 아키텍처에서 안정적인 데이터베이스를 운영하기 위해서는 데이터베이스 엔진의 공식 정책과 표준 매커니즘을 준수해야 합니다.

1) 공식 컨테이너 이미지 태그 표준

더 이상 모호한 :latest 태그를 사용해서는 안 됩니다. 명확한 메이저·마이너 버전과 LTS(Long Term Support) 태그를 명시해야 합니다.

  • MySQL 8.0 계열: mysql:8.0 또는 mysql:8.0.36 (가장 넓은 생태계 호환성)
  • MySQL 8.4 LTS 계열: mysql:8.4 또는 mysql:8.4.0 (최신 장기 지원 버전)
  • MariaDB 11.4 LTS 계열: mariadb:11.4 (2024년 출시된 최신 엔터프라이즈 LTS)

2) 완벽한 유니코드 표준: utf8mb4와 최신 콜레이션(Collation)

모든 데이터베이스, 테이블, 컬럼의 기본 캐릭터셋은 utf8mb4여야 합니다. 이때 정렬과 문자 비교를 결정하는 콜레이션은 엔진 버전에 따라 표준 권장값이 달라집니다:

  • MySQL 8.0 / 8.4: utf8mb4_0900_ai_ci
    유니코드 9.0 표준 기반. 악센트 구분 없음(Accent Insensitive, ai), 대소문자 구분 없음(Case Insensitive, ci). 과거 utf8mb4_general_ci나 utf8mb4_unicode_ci 대비 한글 자모 결합 정렬 및 다국어 검색 성능이 대폭 개선되었습니다.
  • MariaDB 11.4 LTS: utf8mb4_uca1400_ai_ci
    최신 유니코드 UCA 14.0 표준을 기반으로 하며, 이전 세대의 utf8mb4_unicode_520_ci보다 정확하고 빠른 유니코드 정렬을 제공합니다.

3) allowPublicKeyRetrieval과 RSA 보안 핸드셰이크의 원리

caching_sha2_password 인증 방식은 클라이언트가 서버로 비밀번호를 전송할 때, 일반 평문이 아닌 서버의 공개키(Public Key)로 암호화하여 전송하도록 요구합니다.

DIAGRAM: AUTHENTICATION HANDSHAKE WORKFLOW
[caching_sha2_password 인증 핸드셰이크 흐름]
Client ─────────── 1. 접속 요청 (Handshake Init) ──────────► MySQL Server
Client ◄────────── 2. caching_sha2_password 인증 요구 ────── MySQL Server
Client ─────────── 3. 서버 공개키 요청 (Request Public Key) ─► MySQL Server
                   ※ allowPublicKeyRetrieval=false인 경우 여기서 차단 ❌
                   ※ allowPublicKeyRetrieval=true 또는 TLS 암호화 연결 시 정상 통과 ✅
Client ─────────── 4. 서버 공개키로 암호화된 비밀번호 전송 ────► MySQL Server (인증 완료)

클라이언트가 SSL/TLS 암호화 채널을 타지 않는 로컬 개발 환경(useSSL=false)에서 접속할 경우, 클라이언트는 서버에 직접 공개키를 요청해야 합니다. 이때 보안 옵션인 allowPublicKeyRetrieval=true가 클라이언트 드라이버에 명시되어 있어야만 안전하게 키를 수신하여 로그인을 완료할 수 있습니다.

3. 엔진 및 버전별 호환성 매트릭스

MySQL과 MariaDB는 태생은 같으나 MySQL 8.0 이후 아키텍처, 인증 플러그인, 기본 콜레이션에서 상당한 차이를 보이고 있습니다. 프로젝트 성격에 맞춰 적절한 엔진과 버전을 선정해야 합니다.

비교 항목 MySQL 8.0 (현업 표준) MySQL 8.4 LTS (최신 장기 지원) MariaDB 11.4 LTS (오픈소스 표준)
출시 구분 일반 GA (2018~현재) 공식 LTS (2024 릴리즈) 엔터프라이즈 LTS (2024 릴리즈)
기본 문자셋 utf8mb4 utf8mb4 utf8mb4
권장 기본 콜레이션 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci utf8mb4_uca1400_ai_ci
기본 인증 플러그인 caching_sha2_password caching_sha2_password mysql_native_password (기본 호환)
mysql_native_password 플러그인 내장 (설정 활성화 가능) 공식 제거(Disabled) 완벽 지원
Mac ARM64 (Apple Silicon) 공식 네이티브 지원 (Docker Hub) 공식 네이티브 지원 (Docker Hub) 공식 네이티브 지원 (Docker Hub)
드라이버 권장 버전 MySQL Connector/J 8.0.x+ MySQL Connector/J 8.4.x+ MariaDB Connector/J 3.x+ / MySQL 호환
메모리 최소 요구치 최소 1GB (권장 2GB+) 최소 1.5GB (권장 2GB+) 최소 512MB (권장 1GB+)

💡 Apple Silicon(M1/M2/M3/M4) 개발자 참고: MySQL 8.0, 8.4 및 MariaDB 11.4 공식 도커 이미지는 모두 linux/arm64 멀티 아키텍처를 기본 제공하므로, 에뮬레이션(--platform linux/amd64) 없이 초고속 네이티브 성능으로 동작합니다.

4. 실무 프로덕션 설정 명세: my.cnf & docker-compose.yml

단순한 docker run 명령 대신, 팀 전체가 동일한 설정과 영속성, 헬스체크를 보장받을 수 있는 완전한 인프라 코드를 구성합니다.

1) 완벽한 한글 및 보안 처리가 반영된 my.cnf

프로젝트 루트의 docker/mysql/conf.d/my.cnf 경로에 생성합니다:

docker/mysql/conf.d/my.cnf
# [MySQL 8.0 / 8.4 프로덕션 최적화 my.cnf]
[client]
default-character-set = utf8mb4

[mysql]
default-character-set = utf8mb4

[mysqld]
# 1. 서버 기본 문자셋 및 정렬 규칙
character-set-server = utf8mb4
collation-server     = utf8mb4_0900_ai_ci

# 2. 클라이언트-서버 통신 핸드셰이크 시 서버 문자셋 우선 적용
character-set-client-handshake = FALSE
skip-character-set-client-handshake

# 3. 네트워크 및 타임존 설정
default-time-zone = '+09:00'
max_connections   = 200
max_allowed_packet = 64M

# 4. InnoDB 기본 튜닝
innodb_buffer_pool_size = 512M
innodb_log_file_size    = 128M

# ※ MariaDB 사용 시: collation-server = utf8mb4_uca1400_ai_ci 로 변경

2) 실무형 docker-compose.yml (헬스체크, 영속 볼륨, 리소스 제한)

docker-compose.yml
version: '3.8'

services:
  db:
    image: mysql:8.0.36
    # MySQL 8.4 LTS 전환 시 아래 주석 해제
    # image: mysql:8.4.0
    container_name: production-mysql
    restart: unless-stopped
    command:
      - --character-set-server=utf8mb4
      - --collation-server=utf8mb4_0900_ai_ci
      - --default-time-zone=+09:00
    environment:
      MYSQL_ROOT_PASSWORD: RootSecurePassword!2026
      MYSQL_DATABASE: servicedb
      MYSQL_USER: appuser
      MYSQL_PASSWORD: UserSecurePassword!2026
      TZ: Asia/Seoul
    ports:
      - "3306:3306"
    volumes:
      - mysql_data:/var/lib/mysql
      - ./docker/mysql/conf.d:/etc/mysql/conf.d:ro
      - ./docker/mysql/initdb.d:/docker-entrypoint-initdb.d:ro
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-pRootSecurePassword!2026"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 30s
    deploy:
      resources:
        limits:
          cpus: '2.0'
          memory: 2G
        reservations:
          memory: 1G

volumes:
  mysql_data:
    name: prod_mysql_data

3) 초기 데이터베이스 및 계정 권한 스크립트 (init.sql)

컨테이너가 최초 생성될 때 자동으로 실행되는 docker/mysql/initdb.d/01_init.sql 파일입니다:

docker/mysql/initdb.d/01_init.sql
-- 데이터베이스 문자셋 검증 및 보정
ALTER DATABASE servicedb CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci;

USE servicedb;

-- 테스트용 다국어 및 이모지 테이블 생성
CREATE TABLE IF NOT EXISTS tb_encoding_test (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    title VARCHAR(100) NOT NULL,
    content TEXT NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

-- 한글 및 4바이트 모바일 이모지 정상 삽입 검증
INSERT INTO tb_encoding_test (title, content) 
VALUES ('유니코드 정상 테스트', '한글 텍스트 및 이모지 저장 검증 완료: 🚀💡🎉🇰🇷');

-- 애플리케이션 전용 계정 권한 부여
GRANT ALL PRIVILEGES ON servicedb.* TO 'appuser'@'%';
FLUSH PRIVILEGES;

5. 자주 겪는 4대 치명적 에러 트러블슈팅

Docker MySQL/MariaDB 환경에서 개발자들이 야근을 하게 만드는 가장 빈번한 4대 핵심 에러의 원인과 종결형 해결책입니다.

[에러 1] Public Key Retrieval is not allowed

❌ 에러 로그 (JDBC 클라이언트 접속 실패)
java.sql.SQLNonTransientConnectionException: Public Key Retrieval is not allowed
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:110)

발생 원인: MySQL 8.0+ 기본 인증인 caching_sha2_password 환경에서, 클라이언트가 비-SSL(useSSL=false)로 연결하면서 서버의 RSA 공개키를 요청할 권한을 얻지 못해 드라이버 차원에서 접속을 차단합니다.

✅ 해결 방법: allowPublicKeyRetrieval 활성화
  1. Spring Boot / JDBC URL 파라미터 추가:
    spring.datasource.url=jdbc:mysql://localhost:3306/servicedb?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Seoul&characterEncoding=UTF-8
  2. DBeaver 설정: 연결 설정 ➔ Driver properties ➔ allowPublicKeyRetrieval 값을 TRUE로 변경.
  3. Node.js (mysql2 드라이버):
    const connection = mysql.createConnection({
      host: 'localhost',
      user: 'appuser',
      password: 'UserSecurePassword!2026',
      database: 'servicedb',
      ssl: false
    });

[에러 2] Incorrect string value: '\xF0\x9F\x9A\x80...' for column (한글/이모지 깨짐)

❌ 에러 로그 (이모지 및 특수 다국어 삽입 시)
java.sql.SQLException: Incorrect string value: '\xF0\x9F\x9A\x80' for column 'content' at row 1
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:129)

발생 원인:

  • 테이블 생성 당시 데이터베이스 기본 인코딩이 latin1 또는 3바이트 가변 길이인 utf8(utf8mb3)로 설정되어 있어, 4바이트 유니코드(스마트폰 이모지 \xF0\x9F\x9A\x80 = 🚀 또는 확장 한자)를 저장할 바이트 공간이 부족합니다.
  • 클라이언트-서버 간 연결 문자셋(character_set_client, character_set_connection)이 세션 핸드셰이크 과정에서 latin1이나 ascii로 다운그레이드되어 전송된 문자열이 손상됩니다.
✅ 해결 방법: 테이블 일괄 변환 및 핸드셰이크 강제
  1. 실시간 테이블 및 컬럼 문자셋 변환 SQL 실행:
    -- 특정 테이블의 모든 문자형 컬럼을 utf8mb4로 일괄 변환
    ALTER TABLE tb_encoding_test CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
    
    -- 신규 테이블 생성을 대비한 데이터베이스 레벨 기본값 동기화
    ALTER DATABASE servicedb CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci;
  2. 서버 측 핸드셰이크 강제 (my.cnf): 클라이언트가 임의로 인코딩을 다운그레이드하지 못하도록 skip-character-set-client-handshake를 선언합니다.
  3. 연결 문자열 보정: JDBC URL에 characterEncoding=UTF-8&connectionCollation=utf8mb4_0900_ai_ci를 명시합니다.

[에러 3] MySQL 8.4 LTS 기동 시 unknown variable 'default_authentication_plugin' 크래시

❌ 에러 로그 (컨테이너 기동 즉시 비정상 종료)
[ERROR] [MY-000067] [Server] unknown variable 'default_authentication_plugin=mysql_native_password'.
[ERROR] [MY-010119] [Server] Aborting

발생 원인: MySQL 8.4 LTS부터 default_authentication_plugin 시스템 변수 및 mysql_native_password 플러그인이 공식적으로 비활성화/제거되었습니다. MySQL 5.7/8.0 시절의 옵션을 그대로 넘기면 서버가 초기화 단계에서 즉각 비정상 종료(Abort)됩니다.

✅ 해결 방법: 변수 선언 완전 제거 또는 8.4 전용 플래그 사용
  • docker-compose.yml 또는 my.cnf에서 default_authentication_plugin 선언부를 완전히 삭제합니다.
  • 레거시 클라이언트 지원을 위해 MySQL 8.4에서 mysql_native_password를 임시로 살려야 한다면, 새로운 8.4 전용 구문인 --mysql-native-password=ON 플래그를 서버 시작 파라미터로 명시해야 합니다.
  • 최신 표준 권장안은 클라이언트 드라이버를 최신(MySQL Connector 8.0.33+ 또는 8.4 LTS)으로 업데이트하고 네이티브 caching_sha2_password를 온전히 사용하는 것입니다.

[에러 4] 호스트 바인드 볼륨 시 Can't create/write to file ... (Errcode: 13 - Permission denied)

❌ 에러 로그 (스토리지 권한 거부)
[ERROR] [MY-012574] [InnoDB] initialize_file: Can't create/write to file './ibdata1' (OS errno 13 - Permission denied)
[ERROR] [MY-010020] [Server] Data Dictionary initialization failed.

발생 원인: Linux 호스트 머신에서 로컬 디렉토리를 ./data:/var/lib/mysql 형태로 마운트할 때, MySQL 공식 도커 이미지 내부의 실행 계정인 mysql 유저의 고정 UID/GID인 999번에 호스트 디렉토리 쓰기 권한이 없어서 발생합니다.

✅ 해결 방법: 디렉터리 소유권(UID 999) 부여 또는 Named Volume 사용
# 호스트 머신(Linux/Ubuntu) 터미널에서 실행
sudo chown -R 999:999 ./data
sudo chmod 750 ./data

💡 실무 팁: Docker Named Volume(volumes: - mysql_data:/var/lib/mysql)을 사용할 경우 Docker 데몬이 권한을 자동 관리하므로 이 문제가 원천 방지됩니다.

6. 클라이언트 연동 검증 및 최종 점검 체크리스트

모든 설정을 마친 후 실제 환경에서 한글 깨짐과 연동 상태를 최종 검증하는 방법입니다.

1) DBeaver / Datagrip 연결 설정

  1. Host: 127.0.0.1 / Port: 3306
  2. Database: servicedb
  3. Username: appuser / Password: UserSecurePassword!2026
  4. Driver Properties (중요):
    • allowPublicKeyRetrieval ➔ true
    • useSSL ➔ false (로컬 개발 환경 기준)
    • serverTimezone ➔ Asia/Seoul

2) Spring Boot (application.yml) 프로덕션 연동 설정

Spring Boot 3.x 및 최신 Hibernate 환경에서는 HikariCP 커넥션 풀과 MySQL Connector/J의 조합이 표준입니다:

application.yml
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/servicedb?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Seoul&characterEncoding=UTF-8&connectionCollation=utf8mb4_0900_ai_ci
    username: appuser
    password: UserSecurePassword!2026
    hikari:
      maximum-pool-size: 10
      minimum-idle: 5
      connection-timeout: 30000
      idle-timeout: 600000
      max-lifetime: 1800000
      connection-test-query: SELECT 1
  jpa:
    open-in-view: false
    hibernate:
      ddl-auto: validate
    properties:
      hibernate:
        dialect: org.hibernate.dialect.MySQLDialect
        format_sql: true
        show_sql: false

3) Node.js (TypeScript / Prisma & mysql2) 연동 설정

현대 백엔드에서 널리 쓰이는 Node.js 환경에서의 올바른 드라이버 설정 예시입니다:

src/db.ts
// db.ts - mysql2 풀 설정 예시
import mysql from 'mysql2/promise';

export const pool = mysql.createPool({
  host: process.env.DB_HOST || '127.0.0.1',
  port: Number(process.env.DB_PORT) || 3306,
  user: process.env.DB_USER || 'appuser',
  password: process.env.DB_PASSWORD || 'UserSecurePassword!2026',
  database: process.env.DB_NAME || 'servicedb',
  waitForConnections: true,
  connectionLimit: 10,
  queueLimit: 0,
  charset: 'utf8mb4',
  timezone: '+09:00',
  enableKeepAlive: true,
  keepAliveInitialDelay: 10000,
  ssl: false // 로컬 개발 환경
});

4) 컨테이너 내부 캐릭터셋 적용 상태 SQL 검증

컨테이너 내부 bash 터미널 또는 클라이언트 GUI 툴에서 현재 적용된 글로벌 및 세션 인코딩을 쿼리로 직접 검증합니다:

BASH: DOCKER EXEC CLI 검증
# Docker CLI를 통한 원라인 검증 쿼리 실행
docker exec -it production-mysql mysql -u root -pRootSecurePassword!2026 -e "
SHOW VARIABLES LIKE 'character_set%';
SHOW VARIABLES LIKE 'collation%';"

검증 결과 테이블에서 아래 핵심 항목들이 일치하는지 확인합니다:

+--------------------------+--------------------+
| Variable_name            | Value              |
+--------------------------+--------------------+
| character_set_client     | utf8mb4            |
| character_set_connection | utf8mb4            |
| character_set_database   | utf8mb4            |
| character_set_results    | utf8mb4            |
| character_set_server     | utf8mb4            |
| character_set_system     | utf8mb3            |
| collation_connection     | utf8mb4_0900_ai_ci |
| collation_database       | utf8mb4_0900_ai_ci |
| collation_server         | utf8mb4_0900_ai_ci |
+--------------------------+--------------------+

(참고: character_set_system은 MySQL 엔진 내부 식별자 메타데이터용이므로 utf8mb3로 고정되어 있는 것이 정상입니다.)

5) 실무 5단계 최종 배포 체크리스트

점검 번호 점검 항목 통과 조건 비고
01 이미지 태그 검증 mysql:latest 배제, mysql:8.0.36 또는 mysql:8.4.0 고정 명시 불시 브레이킹 체인지 방지
02 문자셋 & 콜레이션 character-set-server = utf8mb4, collation = utf8mb4_0900_ai_ci 일치 이모지/한글 자모 완전 보장
03 RSA 키 교환 허용 JDBC URL 파라미터 allowPublicKeyRetrieval=true 명시 Public Key 차단 에러 방지
04 8.4 파라미터 검증 default_authentication_plugin 옵션 제거 확인 MySQL 8.4 CrashLoop 방지
05 볼륨 영속성 & 헬스체크 Docker Named Volume 적용 및 mysqladmin ping 헬스체크 통과 컨테이너 재기동 시 데이터 유실 방지

7. 마치며: 견고한 데이터베이스 인프라를 위한 권장 로드맵

마치며: 견고한 데이터베이스 인프라를 위한 권장 로드맵

데이터베이스는 백엔드 시스템 전체에서 가장 보수적이고 안정적으로 관리되어야 하는 핵심 인프라 컴포넌트입니다. 본 가이드에서 다룬 설정들을 요약하면 다음과 같은 세 가지 황금률로 귀결됩니다:

  1. 버전 명시의 원칙: 절대 :latest 태그나 버전 생략 명령어를 프로덕션 또는 협업 환경에서 사용하지 마십시오. 사내 표준 엔진 버전에 맞추어 mysql:8.0.36, mysql:8.4.0, mariadb:11.4와 같이 구체적인 버전을 Docker Compose 파일에 선언해야 예기치 못한 EOL 및 호환성 붕괴를 예방할 수 있습니다.
  2. 유니코드 표준 준수: 과거 3바이트 utf8의 잔재를 완전히 청산하고, 모든 스키마, 테이블, 서버 파라미터, 연결 스트링을 utf8mb4와 최신 콜레이션(utf8mb4_0900_ai_ci 또는 MariaDB utf8mb4_uca1400_ai_ci)으로 일원화하십시오.
  3. 보안 핸드셰이크의 이해: caching_sha2_password는 개발자를 괴롭히기 위한 장애물이 아니라 현대 네트워크 환경에서 패스워드 스니핑을 방지하기 위한 필수 보안 표준입니다. 비-SSL 환경에서는 allowPublicKeyRetrieval=true의 의미를 정확히 인지하고 사용하며, 실제 운영 서버 배포 시에는 반드시 정식 TLS 인증서를 적용하여 안전한 데이터베이스 통신망을 구축하십시오.

컨테이너 기반 데이터베이스 인프라는 한 번 올바르게 표준 명세(IaC)를 정의해 두면, 팀 내 모든 동료 개발자와 CI/CD 파이프라인, 클라우드 운영 환경에서 인코딩 문제나 접속 오류 없이 견고하게 작동합니다.

댓글 쓰기

다음 이전