📚 PHP 중급 - 4주차: 파일 업로드 및 이미지 처리 - 02 $_FILES 슈퍼 글로벌 변수

2025. 7. 25. 09:38프로그램/PHP 중급

📚 PHP 중급 - 4주차: 파일 업로드 및 이미지 처리 - 02 $_FILES 슈퍼 글로벌 변수

📚 PHP 중급 - 4주차: 파일 업로드 및 이미지 처리 - 02 $_FILES 슈퍼 글로벌 변수



지난 시간에는 #HTML #폼을 이용해 #파일을_업로드하는 기본적인 방법과 #보안_고려사항에 대해 알아보았습니다. 이제 사용자가 전송한 #파일_데이터가 #PHP 스크립트에서 어떻게 접근되고 처리되는지에 대한 핵심인 #$_FILES #슈퍼_글로벌_변수(Super Global Variable)에 대해 깊이 있게 다뤄보겠습니다. #$_FILES 변수를 정확히 이해하고 활용하는 것이 #안전하고 #효율적인 #파일_업로드_처리(#File Upload Handling)의 시작입니다.

 


1. $_FILES 슈퍼 글로벌 변수의 이해

#$_FILES는 #PHP가 #HTTP_POST_메서드를 통해 #업로드된_파일의_정보를_자동으로_수집하여_저장하는 #연관_배열(Associative Array)입니다. 이 변수는 오직 #enctype="multipart/form-data"로 설정된 #HTML #폼에서만 유효하게 채워집니다.

 

$_FILES 배열은 #폼의 #input type="file" 태그의 #name 속성 값을 #키(Key)로 사용하며, 각 파일에 대한 상세한 정보를 담고 있는 또 다른 배열을 값으로 가집니다.

 

$_FILES 배열의 주요 요소

 

$_FILES['input_name'] (여기서 input_name은 HTML <input type="file"> 태그의 name 속성 값)은 다음과 같은 5가지 주요 정보를 포함합니다.

 

  1. name: 클라이언트 #컴퓨터에서 #업로드된_파일의 #원본_이름(Original Name)입니다. 사용자가 선택한 파일의 실제 이름을 나타냅니다.
    • 예시: my_document.pdf
  2. type: 업로드된 파일의 #MIME_타입(MIME Type)입니다. 브라우저가 제공하는 정보이므로, #보안_검사_시_이_값에만_의존해서는_안_됩니다. 이 값은 클라이언트 측에서 쉽게 위변조될 수 있습니다.
    • 예시: image/jpeg, application/pdf, text/plain
  3. tmp_name: 서버에 #임시로_저장된_파일의 #전체_경로와_이름입니다. 업로드된 파일은 서버의 특정 임시 디렉터리(php.ini의 upload_tmp_dir 설정 또는 시스템 기본 임시 디렉터리)에 저장됩니다. #PHP_스크립트에서 이 임시 파일을 읽거나 영구적인 위치로 이동시켜야 합니다.
    • 예시: /tmp/phpA2F3g5 (리눅스), C:\Windows\Temp\php1A2B.tmp (윈도우)
  4. error: #파일_업로드_시_발생한_오류를_나타내는_오류_코드(Error Code)입니다. #UPLOAD_ERR_OK (값: 0)는 파일이 성공적으로 업로드되었음을 의미하며, 다른 값들은 오류를 나타냅니다.
    • UPLOAD_ERR_OK (0): 오류 없이 파일 업로드 성공.
    • UPLOAD_ERR_INI_SIZE (1): php.ini의 upload_max_filesize를 초과.
    • UPLOAD_ERR_FORM_SIZE (2): HTML 폼의 MAX_FILE_SIZE 값을 초과.
    • UPLOAD_ERR_PARTIAL (3): 파일이 부분적으로만 업로드됨.
    • UPLOAD_ERR_NO_FILE (4): 파일이 업로드되지 않음.
    • UPLOAD_ERR_NO_TMP_DIR (6): 임시 디렉터리가 없음.
    • UPLOAD_ERR_CANT_WRITE (7): 파일 쓰기 실패.
    • UPLOAD_ERR_EXTENSION (8): PHP 확장 기능에 의해 업로드 중지됨.
  5. size: 업로드된 #파일의_크기를 #바이트(Byte) 단위로 나타냅니다.
    • 예시: 102400 (100KB)

 


2. $_FILES 변수 활용 예시

지난 시간에 작성했던 #HTML #폼 (upload_form.html)에서 name="my_file"로 파일을 업로드했을 때, $_FILES 변수를 출력해보면 다음과 같은 구조를 가집니다.

 

PHP
 
<?php
// upload_process.php

if (isset($_FILES['my_file'])) {
    echo "<pre>";
    print_r($_FILES['my_file']);
    echo "</pre>";
} else {
    echo "파일이 업로드되지 않았습니다.";
}

/*
위 print_r($_FILES['my_file'])의 출력 예시:
Array
(
    [name] => example.jpg
    [type] => image/jpeg
    [tmp_name] => /tmp/phpABCD12
    [error] => 0
    [size] => 123456
)
*/
?>

 


3. $_FILES를 이용한 파일 업로드 처리 로직 (심화)

이제 $_FILES 변수의 각 요소를 활용하여 실제 #파일_업로드_처리_스크립트를 작성해 보겠습니다. 이 과정에서 #보안_검사가_매우_중요합니다.

 

PHP
 
<?php
// upload_process.php

// 1. 업로드 디렉토리 설정 (보안상 웹 접근 불가한 상위 경로 권장)
$upload_dir = './uploads/'; // 현재 스크립트 기준 'uploads' 폴더

// 폴더가 없으면 생성 (권한 0755)
if (!is_dir($upload_dir)) {
    mkdir($upload_dir, 0755, true);
}

// 2. 파일 업로드 오류 확인 (필수)
if (!isset($_FILES['my_file']) || $_FILES['my_file']['error'] !== UPLOAD_ERR_OK) {
    switch ($_FILES['my_file']['error']) {
        case UPLOAD_ERR_INI_SIZE:
        case UPLOAD_ERR_FORM_SIZE:
            echo "오류: 업로드 파일 크기가 허용된 최대 크기를 초과했습니다.";
            break;
        case UPLOAD_ERR_NO_FILE:
            echo "오류: 파일이 선택되지 않았습니다.";
            break;
        default:
            echo "오류: 파일 업로드 중 알 수 없는 오류가 발생했습니다. 코드: " . $_FILES['my_file']['error'];
            break;
    }
    exit;
}

// 3. 업로드된 파일 정보 변수에 저장
$file_name_original = $_FILES['my_file']['name'];
$file_tmp_name = $_FILES['my_file']['tmp_name'];
$file_type = $_FILES['my_file']['type'];
$file_size = $_FILES['my_file']['size'];

// 4. 엄격한 보안 검사 (매우 중요!)

// 4-1. 파일 크기 제한 (예: 2MB)
$max_file_size = 2 * 1024 * 1024; // 2MB
if ($file_size > $max_file_size) {
    echo "오류: 파일 크기가 너무 큽니다. (최대 2MB)";
    exit;
}

// 4-2. 허용된 확장자와 MIME 타입 검사
$allowed_extensions = ['jpg', 'jpeg', 'png', 'gif', 'pdf'];
$allowed_mime_types = ['image/jpeg', 'image/png', 'image/gif', 'application/pdf'];

// 확장자 추출 (소문자로 변환)
$file_ext = strtolower(pathinfo($file_name_original, PATHINFO_EXTENSION));

// MIME 타입 확인 ($_FILES['type']은 클라이언트에서 전송하므로 참고용)
// 더 안전한 방법은 실제 파일의 MIME 타입을 서버에서 재확인하는 것 (예: finfo_open())
if (!in_array($file_ext, $allowed_extensions)) {
    echo "오류: 허용되지 않는 파일 확장자입니다. (허용: " . implode(', ', $allowed_extensions) . ")";
    exit;
}
if (!in_array($file_type, $allowed_mime_types)) { // 1차적인 MIME 타입 검사
    echo "오류: 허용되지 않는 파일 MIME 타입입니다. (허용: " . implode(', ', $allowed_mime_types) . ")";
    exit;
}

// 5. 파일 이름 변경 (보안상 필수: 원본 이름을 그대로 사용하지 마세요!)
// 유니크한 파일 이름 생성 (겹치지 않게, 추측 불가능하게)
$new_file_name = uniqid('upload_') . '.' . $file_ext;
$destination = $upload_dir . $new_file_name; // 최종 저장 경로

// 6. 임시 파일을 영구 저장소로 이동
// move_uploaded_file() 함수는 임시 디렉토리에 있는 업로드된 파일을 안전하게 지정된 목적지로 이동시킵니다.
// 이 함수는 임시 파일 여부와 권한 등을 내부적으로 확인하여 보안상 안전합니다.
if (move_uploaded_file($file_tmp_name, $destination)) {
    echo "파일이 성공적으로 업로드되었습니다.\n";
    echo "저장된 파일명: " . htmlspecialchars($new_file_name) . "\n";
    echo "파일 경로: " . htmlspecialchars($destination) . "\n";

    // 이미지가 웹에서 접근 가능하고 이미지인 경우에만 표시
    if (strpos($file_type, 'image/') === 0) {
        echo "<img src='" . htmlspecialchars($destination) . "' alt='업로드된 이미지' style='max-width:400px; height:auto; display:block; margin-top:20px;'>\n";
    }

} else {
    echo "오류: 파일 업로드에 실패했습니다. (이동 실패)";
}
?>

 


4. 다중 파일 업로드 처리

HTML 폼에서 <input type="file" name="my_files[]" multiple>과 같이 #name 속성에 #배열_형식([])을 추가하면 여러 파일을 동시에 업로드할 수 있습니다. 이때 $_FILES 배열의 구조는 약간 달라집니다.

 

HTML (upload_form_multiple.html)

HTML
 
<form action="upload_process_multiple.php" method="POST" enctype="multipart/form-data">
    <label for="my_files">여러 파일 선택:</label>
    <input type="file" name="my_files[]" id="my_files" multiple required>
    <input type="submit" value="파일 업로드">
</form>

 

PHP (예시: upload_process_multiple.php)

 

PHP
 
<?php
// upload_process_multiple.php

// $_FILES['my_files'] 배열 구조:
/*
Array
(
    [name] => Array
        (
            [0] => file1.jpg
            [1] => file2.png
        )

    [type] => Array
        (
            [0] => image/jpeg
            [1] => image/png
        )
    ...
)
*/

if (isset($_FILES['my_files'])) {
    $total_files = count($_FILES['my_files']['name']);

    echo "총 " . $total_files . "개의 파일이 업로드 시도되었습니다.\n\n";

    for ($i = 0; $i < $total_files; $i++) {
        // 각 파일의 정보 추출
        $file_name_original = $_FILES['my_files']['name'][$i];
        $file_tmp_name = $_FILES['my_files']['tmp_name'][$i];
        $file_error = $_FILES['my_files']['error'][$i];
        $file_size = $_FILES['my_files']['size'][$i];
        $file_type = $_FILES['my_files']['type'][$i];

        echo "--- 파일 " . ($i + 1) . ": " . htmlspecialchars($file_name_original) . " ---\n";

        if ($file_error !== UPLOAD_ERR_OK) {
            echo "오류 발생: " . $file_error . "\n";
            continue; // 다음 파일로 넘어감
        }

        // 보안 검사 및 파일 이동 로직은 단일 파일과 동일하게 적용
        // (위의 단일 파일 처리 로직을 이 반복문 안에 넣으면 됨)
        // 여기서는 간단히 이동만 예시
        $upload_dir = './uploads/';
        if (!is_dir($upload_dir)) { mkdir($upload_dir, 0755, true); }

        $file_ext = strtolower(pathinfo($file_name_original, PATHINFO_EXTENSION));
        $new_file_name = uniqid('multi_') . '.' . $file_ext;
        $destination = $upload_dir . $new_file_name;

        if (move_uploaded_file($file_tmp_name, $destination)) {
            echo "성공: " . htmlspecialchars($new_file_name) . " 로 저장되었습니다.\n";
        } else {
            echo "실패: 파일을 이동할 수 없습니다.\n";
        }
        echo "\n";
    }
} else {
    echo "업로드된 파일이 없습니다.";
}
?>

 


#$_FILES 슈퍼 글로벌 변수는 #PHP에서 #파일_업로드를 다루는 데 있어 핵심적인 역할을 합니다. name, type, tmp_name, error, size 등의 정보를 통해 업로드된 파일을 #안전하게_처리하고 #저장할_수_있습니다. 특히 #보안_취약점을_막기_위해 #파일_이름_변경, #확장자_및_MIME_타입_검사, #파일_크기_제한 등의 #보안_로직을_반드시_적용해야_한다는_점_잊지_마세요! 다음 시간에는 업로드된 #이미지를_다루는_방법에 대해 자세히 알아보겠습니다.

 

 

루젠VPN, #VPN추천 끝판왕! #멀티IP와 강력한 #API 지원으로 비즈니스 맞춤 최적화. 안정적이고 빠른 속도로 제한 없이 자유로운 #인터넷 경험을 선사합니다. 지금 바로 루젠VPN을 경험하세요!

https://vpn.luzensoft.com

 

VPN 5,500원 / IP교체 1,100원 / 유동프록시 22,000원 | LuzenVPN 루젠VPN

국내최저가 고정IP서비스,유동프록시(IP4000개이상제공),PPTP,L2TP,IPSec,OpenVPNVPN,통신사VPN,VPN프로그램,고정IP,고정아이피,PPTP,저렴한VPN,리니지MVPN,리니지VPN,아이온VPN,던파VPN,유동프록시,유동PROXY,바이

vpn.luzensoft.com