한글 데이터가 DB에 저장될 때 깨지는 문제는 문자 인코딩 설정이 일치하지 않아서 발생합니다. 각 단계별로 해결하는 방법들을 알아보겠습니다.
<?php
// PDO 연결
$dsn = "mysql:host=localhost;dbname=mydb;charset=utf8mb4";
$pdo = new PDO($dsn, $username, $password, [
PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci"
]);
// MySQLi 연결
$mysqli = new mysqli($host, $username, $password, $database);
$mysqli->set_charset("utf8mb4");
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>한글 입력 폼</title>
</head>
<body>
<form method="POST" action="save.php" accept-charset="UTF-8">
<input type="text" name="korean_text" placeholder="한글을 입력하세요">
<button type="submit">저장</button>
</form>
</body>
</html>
<?php
// 파일 상단에 인코딩 설정
header('Content-Type: text/html; charset=UTF-8');
mb_internal_encoding('UTF-8');
// POST 데이터 처리
if ($_POST['korean_text']) {
$text = $_POST['korean_text'];
// UTF-8 검증
if (!mb_check_encoding($text, 'UTF-8')) {
$text = mb_convert_encoding($text, 'UTF-8', 'auto');
}
// DB 저장
saveToDatabase($text);
}
-- 데이터베이스 문자셋 확인
SHOW VARIABLES LIKE 'character_set%';
-- 테이블 문자셋 변경
ALTER TABLE users CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- 컬럼별 문자셋 변경
ALTER TABLE users MODIFY COLUMN name VARCHAR(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
<?php
class KoreanDataHandler {
private $pdo;
public function __construct($pdo) {
$this->pdo = $pdo;
// 연결 문자셋 설정
$this->pdo->exec("SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci");
}
public function saveKoreanText($text) {
// 인코딩 검증 및 변환
if (!mb_check_encoding($text, 'UTF-8')) {
$text = mb_convert_encoding($text, 'UTF-8', 'EUC-KR,CP949,UTF-8');
}
// 준비된 문장으로 안전하게 저장
$stmt = $this->pdo->prepare("INSERT INTO posts (content) VALUES (?)");
return $stmt->execute([$text]);
}
public function getKoreanText($id) {
$stmt = $this->pdo->prepare("SELECT content FROM posts WHERE id = ?");
$stmt->execute([$id]);
$result = $stmt->fetchColumn();
// 출력 시 인코딩 확인
return mb_convert_encoding($result, 'UTF-8', 'UTF-8');
}
}
<?php
function handleKoreanFilename($uploadedFile) {
$originalName = $uploadedFile['name'];
// 한글 파일명 안전하게 처리
$safeName = preg_replace('/[^가-힣a-zA-Z0-9._-]/', '', $originalName);
// 또는 영문으로 변환
$englishName = transliterateKorean($originalName);
$uploadPath = 'uploads/' . date('Y-m-d_H-i-s') . '_' . $safeName;
if (move_uploaded_file($uploadedFile['tmp_name'], $uploadPath)) {
return $uploadPath;
}
return false;
}
function transliterateKorean($korean) {
// 간단한 한글 -> 영문 변환 (실제로는 더 복잡한 라이브러리 사용 권장)
$map = [
'가' => 'ga', '나' => 'na', '다' => 'da',
'라' => 'ra', '마' => 'ma', '바' => 'ba'
// ... 더 많은 매핑
];
return strtr($korean, $map);
}
<?php
function safeJsonEncode($data) {
// 한글이 깨지지 않도록 옵션 설정
return json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
}
function processKoreanJson($jsonString) {
// JSON 디코딩 시 인코딩 확인
$data = json_decode($jsonString, true);
if (json_last_error() !== JSON_ERROR_NONE) {
// 인코딩 문제일 수 있으므로 변환 시도
$jsonString = mb_convert_encoding($jsonString, 'UTF-8', 'auto');
$data = json_decode($jsonString, true);
}
return $data;
}
<?php
// 세션 시작 전 인코딩 설정
ini_set('session.serialize_handler', 'php_serialize');
mb_internal_encoding('UTF-8');
session_start();
function setKoreanSession($key, $value) {
// UTF-8 인코딩 확인
if (is_string($value) && !mb_check_encoding($value, 'UTF-8')) {
$value = mb_convert_encoding($value, 'UTF-8', 'auto');
}
$_SESSION[$key] = $value;
}
function getKoreanSession($key) {
if (isset($_SESSION[$key])) {
$value = $_SESSION[$key];
// 문자열인 경우 인코딩 확인
if (is_string($value)) {
return mb_convert_encoding($value, 'UTF-8', 'UTF-8');
}
return $value;
}
return null;
}
<?php
function sendKoreanEmail($to, $subject, $message) {
// 헤더에 UTF-8 인코딩 명시
$headers = [
'MIME-Version: 1.0',
'Content-Type: text/html; charset=UTF-8',
'Content-Transfer-Encoding: 8bit',
'From: sender@example.com'
];
// 제목 인코딩
$encodedSubject = '=?UTF-8?B?' . base64_encode($subject) . '?=';
return mail($to, $encodedSubject, $message, implode("\r\n", $headers));
}
<?php
function checkEncodingSettings() {
$checks = [
'PHP 내부 인코딩' => mb_internal_encoding(),
'HTTP 출력 인코딩' => mb_http_output(),
'MySQL 문자셋' => 'SELECT @@character_set_database',
'파일 인코딩' => mb_detect_encoding(file_get_contents(__FILE__))
];
foreach ($checks as $name => $value) {
echo "$name: $value\n";
}
// UTF-8 지원 확인
if (!function_exists('mb_check_encoding')) {
echo "경고: mbstring 확장이 설치되지 않았습니다.\n";
}
}
이러한 설정들을 모두 적용하면 한글 데이터가 깨지지 않고 안전하게 저장됩니다. 특히 데이터베이스 문자셋을 utf8mb4로 설정하는 것이 가장 중요합니다.