이미지 업로드 후 썸네일 생성 과정에서 발생하는 오류들과 해결책을 알아보겠습니다.
문제: GD 라이브러리가 설치되지 않았거나 이미지 타입을 지원하지 않음
<?php
// GD 라이브러리 확인
if (!extension_loaded('gd')) {
die('GD 라이브러리가 설치되지 않았습니다.');
}
function createThumbnail($source, $destination, $width = 150, $height = 150) {
$image_info = getimagesize($source);
if (!$image_info) {
throw new Exception('유효하지 않은 이미지 파일입니다.');
}
$mime_type = $image_info['mime'];
// 원본 이미지 로드
switch ($mime_type) {
case 'image/jpeg':
$original = imagecreatefromjpeg($source);
break;
case 'image/png':
$original = imagecreatefrompng($source);
break;
case 'image/gif':
$original = imagecreatefromgif($source);
break;
default:
throw new Exception('지원하지 않는 이미지 형식입니다.');
}
// 썸네일 생성
$thumbnail = imagecreatetruecolor($width, $height);
imagecopyresampled($thumbnail, $original, 0, 0, 0, 0, $width, $height, $image_info[0], $image_info[1]);
// 저장
imagejpeg($thumbnail, $destination, 85);
// 메모리 해제
imagedestroy($original);
imagedestroy($thumbnail);
}
?>
문제: 이미지 비율이 깨져서 찌그러진 썸네일 생성
<?php
function createThumbnailWithRatio($source, $destination, $max_width = 150, $max_height = 150) {
list($orig_width, $orig_height, $type) = getimagesize($source);
// 비율 계산
$ratio = min($max_width / $orig_width, $max_height / $orig_height);
$new_width = (int)($orig_width * $ratio);
$new_height = (int)($orig_height * $ratio);
// 원본 이미지 로드
$original = match($type) {
IMAGETYPE_JPEG => imagecreatefromjpeg($source),
IMAGETYPE_PNG => imagecreatefrompng($source),
IMAGETYPE_GIF => imagecreatefromgif($source),
default => throw new Exception('지원하지 않는 이미지 타입')
};
// 썸네일 생성
$thumbnail = imagecreatetruecolor($new_width, $new_height);
// PNG 투명도 처리
if ($type == IMAGETYPE_PNG) {
imagealphablending($thumbnail, false);
imagesavealpha($thumbnail, true);
}
imagecopyresampled($thumbnail, $original, 0, 0, 0, 0, $new_width, $new_height, $orig_width, $orig_height);
imagejpeg($thumbnail, $destination, 90);
imagedestroy($original);
imagedestroy($thumbnail);
}
?>
문제: 큰 이미지 처리 시 메모리 부족으로 스크립트 중단
<?php
function safeThumbnailCreate($source, $destination, $max_size = 150) {
// 메모리 제한 확인
$memory_limit = ini_get('memory_limit');
if ($memory_limit != -1) {
ini_set('memory_limit', '256M');
}
// 파일 크기 확인
$file_size = filesize($source);
if ($file_size > 10 * 1024 * 1024) { // 10MB 초과
throw new Exception('파일이 너무 큽니다.');
}
list($width, $height, $type) = getimagesize($source);
// 예상 메모리 사용량 계산 (대략적)
$memory_needed = ($width * $height * 4) * 2; // 원본 + 썸네일
$memory_available = (int)$memory_limit * 1024 * 1024;
if ($memory_needed > $memory_available * 0.8) {
throw new Exception('메모리가 부족합니다.');
}
try {
createThumbnailWithRatio($source, $destination, $max_size, $max_size);
} catch (Exception $e) {
throw new Exception('썸네일 생성 실패: ' . $e->getMessage());
}
}
?>
문제: 업로드 검증과 썸네일 생성 과정이 분리되어 오류 처리 미흡
<?php
function handleImageUpload($upload_file, $upload_dir) {
// 업로드 오류 확인
if ($upload_file['error'] !== UPLOAD_ERR_OK) {
throw new Exception('파일 업로드 오류: ' . $upload_file['error']);
}
// 파일 타입 검증
$allowed_types = ['image/jpeg', 'image/png', 'image/gif'];
$file_type = mime_content_type($upload_file['tmp_name']);
if (!in_array($file_type, $allowed_types)) {
throw new Exception('허용되지 않는 파일 형식입니다.');
}
// 파일명 생성
$file_extension = pathinfo($upload_file['name'], PATHINFO_EXTENSION);
$filename = uniqid() . '.' . $file_extension;
$filepath = $upload_dir . '/' . $filename;
$thumbnail_path = $upload_dir . '/thumb_' . $filename;
// 파일 이동
if (!move_uploaded_file($upload_file['tmp_name'], $filepath)) {
throw new Exception('파일 저장 실패');
}
// 썸네일 생성
try {
createThumbnailWithRatio($filepath, $thumbnail_path, 200, 200);
} catch (Exception $e) {
unlink($filepath); // 원본 파일 삭제
throw new Exception('썸네일 생성 실패: ' . $e->getMessage());
}
return [
'original' => $filename,
'thumbnail' => 'thumb_' . $filename
];
}
// 사용 예시
if ($_FILES['image']) {
try {
$result = handleImageUpload($_FILES['image'], './uploads');
echo "업로드 성공: " . $result['original'];
} catch (Exception $e) {
echo "오류: " . $e->getMessage();
}
}
?>
문제: GD 라이브러리로 처리하기 어려운 고급 이미지 처리
<?php
function createThumbnailWithImagick($source, $destination, $width = 150, $height = 150) {
if (!extension_loaded('imagick')) {
throw new Exception('Imagick 확장이 설치되지 않았습니다.');
}
try {
$imagick = new Imagick($source);
// 썸네일 생성 (비율 유지)
$imagick->thumbnailImage($width, $height, true);
// JPEG 품질 설정
$imagick->setImageCompressionQuality(85);
$imagick->setImageFormat('jpeg');
// 저장
$imagick->writeImage($destination);
$imagick->clear();
} catch (ImagickException $e) {
throw new Exception('Imagick 처리 오류: ' . $e->getMessage());
}
}
?>
memory_limit 설정 확인