웹 애플리케이션 개발 시 HTML 폼(Form) 내부에서 이미지 파일을 선택하고, 이를 서버에 전송하기 전 사용자에게 미리보기를 제공해야 할 경우가 많습니다. 기본적으로 HTML 표준에서는 폼 내부에 또 다른 폼을 중첩하는 것을 허용하지 않으므로, 하나의 폼 안에서 파일 선택과 데이터 입력을 동시에 처리하는 효율적인 구조가 필요합니다.
이미지 업로드와 미리보기를 구현하는 가장 권장되는 방식은 JavaScript의 File API를 사용하여 클라이언트 측에서 즉시 미리보기를 생성하고, 사용자가 전체 폼을 제출할 때 파일을 서버로 전송하는 방식입니다. 이 방식은 불필요한 서버 통신을 줄여 사용자 경험을 향상시킵니다.
1. 클라이언트 측 구현 (HTML 및 JavaScript)
아래 코드는 선택된 이미지 파일의 로컬 URL을 생성하여 <img> 태그로 화면에 출력하는 로직입니다. URL.createObjectURL 메서드를 활용하면 서버 업로드 없이도 브라우저 메모리에 저장된 파일 경로를 참조할 수 있습니다.
<!-- HTML 구조 -->
<form id="uploadForm" method="post" action="upload_handler.php" enctype="multipart/form-data">
<div id="previewContainer" style="margin-bottom: 10px;">
<!-- 이미지가 여기에 표시됩니다 -->
</div>
<label for="fileInput" style="display: inline-block; padding: 6px 12px; background-color: #007bff; color: white; cursor: pointer; border-radius: 4px;">
이미지 선택
</label>
<input type="file" id="fileInput" name="user_image" style="display: none;" onchange="renderPreview(this)">
<input type="submit" value="저장하기" style="padding: 6px 12px; cursor: pointer;">
</form>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script type="text/javascript">
function renderPreview(input) {
if (input.files && input.files[0]) {
const readerUrl = window.URL || window.webkitURL;
const blobUrl = readerUrl.createObjectURL(input.files[0]);
const imageTemplate = `<img src="${blobUrl}" alt="미리보기" style="max-width: 150px; border: 1px solid #ddd; padding: 5px;">`;
$('#previewContainer').html(imageTemplate);
}
}
</script>
2. 서버 측 구현 (PHP)
폼이 제출되면 서버에서는 전달된 파일을 검증하고 지정된 디렉토리로 저장해야 합니다. 파일 확장자 체크 및 HTTP POST 방식 업로드 여부를 확인하는 보안 절차가 포함된 로직입니다.
<?php
if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_FILES['user_image'])) {
$fileData = $_FILES['user_image'];
$targetDirectory = "uploads/";
// 파일 정보 추출
$fileName = basename($fileData['name']);
$fileExtension = strtolower(pathinfo($fileName, PATHINFO_EXTENSION));
// 허용할 확장자 정의
$allowedExtensions = ['jpg', 'jpeg', 'png', 'gif'];
// 유효성 검사
if (!in_array($fileExtension, $allowedExtensions)) {
die("허용되지 않는 파일 형식입니다.");
}
if (!is_uploaded_file($fileData['tmp_name'])) {
die("정상적인 업로드 요청이 아닙니다.");
}
// 저장 경로 설정 및 파일 이동
$destination = $targetDirectory . uniqid() . "_" . $fileName;
if (move_uploaded_file($fileData['tmp_name'], $destination)) {
echo "파일 업로드 성공: " . $destination;
} else {
echo "파일 저장 중 오류가 발생했습니다.";
}
}
?>
이와 같은 방식을 사용하면 사용자는 이미지를 선택하자마자 결과를 확인할 수 있으며, 최종적으로 '저장하기' 버튼을 눌렀을 때만 데이터가 서버로 전송되어 효율적인 리소스 관리가 가능해집니다.