์จ๋ผ์ธ ๊ฐ์
>PHP - ์ค๊ธ
๐ PHP ์ค๊ธ - 4์ฃผ์ฐจ: ํ์ผ ์ ๋ก๋ ๋ฐ ์ด๋ฏธ์ง ์ฒ๋ฆฌ - 01 HTML ํผ์ ์ด์ฉํ ํ์ผ ์ ๋ก๋
				์ฃผ์ ํ๋ก๊ทธ๋จ ์คํ
- ํ์ : 10.0
 - ๋ผ์ด์ ์ค: free
 - ์ด์์ฒด์ :
 - ํ์ผ ํฌ๊ธฐ: 0
 
ํผ๋๋ฐฑ ๋ฐ ๋ค์ด๋ก๋
- ์ฌ์ฉ์ ํ์ : 10.0
 - ๋ค์ด๋ก๋ ์: 1
 - ์กฐํ์: 73
 
์ ์กฐ์ฌ ๋ฐ ๋ฑ๋ก ์ ๋ณด
- ์ ์์ฌ: LUZENSOFT
 - ๋ฑ๋ก์ผ: 2025-07-24 15:13:35
 
- ์ค๋ช
๐ PHP ์ค๊ธ - 4์ฃผ์ฐจ: ํ์ผ ์ ๋ก๋ ๋ฐ ์ด๋ฏธ์ง ์ฒ๋ฆฌ - 01 HTML ํผ์ ์ด์ฉํ ํ์ผ ์ ๋ก๋
์๋ ํ์ธ์! #PHP ์ค๊ธ ๊ณผ์  4์ฃผ์ฐจ์ ๋๋ค. ์ค๋์ #์น_์ ํ๋ฆฌ์ผ์ด์ ์์ ๊ฐ์ฅ ํํ๊ฒ ์ ํ๋ ๊ธฐ๋ฅ ์ค ํ๋์ธ #ํ์ผ_์ ๋ก๋(File Upload)์ ๋ํด ์์ธํ ์์๋ณด๊ฒ ์ต๋๋ค. ํนํ ์ฌ์ฉ์๊ฐ #HTML #ํผ(Form)์ ํตํด ํ์ผ์ ์๋ฒ๋ก ์ ์กํ๋ ๊ธฐ๋ณธ์ ์ธ ๊ณผ์ ์ ๋ค๋ฃฐ ๊ฑฐ์์. #๊ฒ์ํ์ #์ด๋ฏธ์ง๋ฅผ ์ฒจ๋ถํ๊ฑฐ๋ #ํ๋กํ_์ฌ์ง์ ๋ณ๊ฒฝํ๋ ๋ฑ ๋ค์ํ ๊ณณ์ ํ์ฉ๋ ์ ์๋ ์ค์ํ ๊ธฐ๋ฅ์ด๋ ํจ๊ป ์ดํด๋ณผ๊น์?
1. ํ์ผ ์ ๋ก๋์ ๊ฐ์ ๋ฐ ๋ณด์ ๊ณ ๋ ค์ฌํญ
#ํ์ผ_์ ๋ก๋๋ ์ฌ์ฉ์์ ๋ก์ปฌ #PC์ ์๋ #ํ์ผ์ #์น_์๋ฒ๋ก ์ ์กํ๋ ๊ณผ์ ์ ๋๋ค. ์ด ๊ณผ์ ์ ๋จ์ํ ํ์ผ์ ์ฎ๊ธฐ๋ ๊ฒ์ ๋์ด, #๋ณด์(Security)์ ๋ํ ๊น์ ์ดํด๋ฅผ ์๊ตฌํฉ๋๋ค. ์ ์์ ์ธ ์ฌ์ฉ์๊ฐ #์น_์ ธ(Web Shell)์ด๋ #๋ฐ์ด๋ฌ์ค(Virus)๋ฅผ ํฌํจํ #์ ์ฑ_ํ์ผ์ ์ ๋ก๋ํ์ฌ #์๋ฒ๋ฅผ_๊ณต๊ฒฉํ ์ ์๊ธฐ ๋๋ฌธ์ด์ฃ .
๋ฐ๋ผ์ #ํ์ผ_์ ๋ก๋ ๊ธฐ๋ฅ์ ๊ตฌํํ ๋๋ ๋ค์๊ณผ ๊ฐ์ #๋ณด์_๊ณ ๋ ค์ฌํญ์ ๋ฐ๋์ ์ง์ผ์ผ ํฉ๋๋ค.
#ํ์ฅ์_๊ฒ์ฌ: ์ ๋ก๋ ๊ฐ๋ฅํ #ํ์ผ_ํ์์ ์๊ฒฉํ๊ฒ ์ ํํด์ผ ํฉ๋๋ค. (์:
.jpg,.png,.gif๋ง ํ์ฉ)#MIME_ํ์ _๊ฒ์ฌ: #HTTP_ํค๋์ ํฌํจ๋ #MIME_ํ์ ์ ๋ณด๋ ํ์ธํ์ฌ #ํ์ฅ์_์๋ณ์กฐ๋ฅผ ๋ง์์ผ ํฉ๋๋ค.
#ํ์ผ_ํฌ๊ธฐ_์ ํ: ๋๋ฌด ํฐ ํ์ผ ์ ๋ก๋๋ฅผ ๋ง์ #์๋ฒ_๊ณผ๋ถํ(Server Overload)๋ #์๋น์ค_๊ฑฐ๋ถ_๊ณต๊ฒฉ(DoS Attack)์ ๋ฐฉ์งํฉ๋๋ค.
#ํ์ผ_์ด๋ฆ_๋ณ๊ฒฝ: ์ ๋ก๋๋ ํ์ผ ์ด๋ฆ์ ๋ฌด์์ ๋ฌธ์์ด๋ก ๋ณ๊ฒฝํ์ฌ #๊ฒฝ๋ก_ํ์_๊ณต๊ฒฉ(Path Traversal Attack)์ด๋ #ํ์ผ_๋ฎ์ด์ฐ๊ธฐ๋ฅผ ๋ฐฉ์งํฉ๋๋ค.
#์ ๋ก๋_๋๋ ํฐ๋ฆฌ_๋ถ๋ฆฌ: ์น์์ ์ง์  ์ ๊ทผํ ์ ์๋ ๋ณ๋์ #๋๋ ํฐ๋ฆฌ์ ์ ์ฅํ๊ณ , ํ์์ #์คํฌ๋ฆฝํธ๋ฅผ ํตํด ์ ๊ทผํ๊ฒ ํฉ๋๋ค.
#์น_์๋ฒ_์ค์ _๊ฐํ: #PHP ์ค์ (
php.ini)์์ #ํ์ผ_์ ๋ก๋ ๊ด๋ จ ์ ํ(upload_max_filesize,post_max_size๋ฑ)์ ์ ์ ํ ์ค์ ํฉ๋๋ค.
2. HTML ํผ(Form) ์ค์ 
#ํ์ผ_์ ๋ก๋๋ฅผ ์ํ #HTML #ํผ์ ์ผ๋ฐ์ ์ธ ํผ๊ณผ ๋ช ๊ฐ์ง ์ค์ํ ์ฐจ์ด์ ์ด ์์ต๋๋ค.
2-1. enctype="multipart/form-data"
#ํ์ผ_์
๋ก๋ ํผ์์ ๊ฐ์ฅ ์ค์ํ ์์ฑ์
๋๋ค. ์ด ์์ฑ์ด ์์ผ๋ฉด ํ์ผ ๋ฐ์ดํฐ๊ฐ ์๋ฒ๋ก ์ ๋๋ก ์ ์ก๋์ง ์์ต๋๋ค. #multipart/form-data๋ ํผ ๋ฐ์ดํฐ์ ํ์ผ ๋ฐ์ดํฐ๋ฅผ ํจ๊ป ์ ์กํ  ์ ์๋๋ก ์ธ์ฝ๋ฉํ๋ ๋ฐฉ์์
๋๋ค.
2-2. method="POST"
#ํ์ผ_๋ฐ์ดํฐ๋ #URL์ ํฌํจ๋ ์ ์์ผ๋ฏ๋ก, ๋ฐ๋์ #POST_๋ฉ์๋๋ฅผ ์ฌ์ฉํด์ผ ํฉ๋๋ค.
2-3. <input type="file" name="file_upload">
#ํ์ผ_์ ํ_ํ๋๋ฅผ ์์ฑํฉ๋๋ค. name ์์ฑ์ PHP์์ ํ์ผ์ ๋ฐ์ ๋ ์ฌ์ฉ๋  #๋ณ์_์ด๋ฆ์ด ๋ฉ๋๋ค. ์ฌ๋ฌ ํ์ผ์ ํ ๋ฒ์ ์
๋ก๋ํ๋ ค๋ฉด multiple ์์ฑ์ ์ถ๊ฐํ  ์ ์์ต๋๋ค.
upload_form.html ์์:
HTML
<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>ํ์ผ ์
๋ก๋ ํผ</title>
    <style>
        body { font-family: Arial, sans-serif; margin: 50px; }
        form { background-color: #f9f9f9; padding: 20px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); width: 400px; margin: auto; }
        h2 { text-align: center; color: #333; }
        label { display: block; margin-bottom: 8px; font-weight: bold; }
        input[type="file"] { margin-bottom: 15px; border: 1px solid #ddd; padding: 8px; border-radius: 4px; background-color: #fff; width: calc(100% - 18px); }
        input[type="submit"] { background-color: #007bff; color: white; padding: 10px 15px; border: none; border-radius: 5px; cursor: pointer; font-size: 16px; width: 100%; }
        input[type="submit"]:hover { background-color: #0056b3; }
    </style>
</head>
<body>
    <h2>ํ์ผ ์
๋ก๋</h2>
    <form action="upload_process.php" method="POST" enctype="multipart/form-data">
        <label for="my_file">์
๋ก๋ํ  ํ์ผ ์ ํ:</label>
        <input type="file" name="my_file" id="my_file" required>
        <input type="submit" value="ํ์ผ ์
๋ก๋">
    </form>
</body>
</html>
3. PHP์์ ํ์ผ ์ ๋ก๋ ์ฒ๋ฆฌ
#PHP๋ ์
๋ก๋๋ #ํ์ผ_๋ฐ์ดํฐ๋ฅผ ์ ์ญ ๋ณ์์ธ #$_FILES๋ฅผ ํตํด ์ ๊ทผํ  ์ ์๊ฒ ํฉ๋๋ค. ์ด #$_FILES ๋ฐฐ์ด์ ์
๋ก๋๋ ๊ฐ ํ์ผ์ ๋ํ ์ ๋ณด๋ฅผ ๋ด๊ณ  ์์ต๋๋ค.
$_FILES ๋ฐฐ์ด์ ๊ตฌ์กฐ
$_FILES['input_name']์ ๋ค์๊ณผ ๊ฐ์ ์ ๋ณด๋ฅผ ํฌํจํฉ๋๋ค. (์ฌ๊ธฐ์ input_name์ HTML input type="file"์ name ์์ฑ ๊ฐ์
๋๋ค.)
name: ํด๋ผ์ด์ธํธ #PC์ ์๋ #์๋ณธ_ํ์ผ_์ด๋ฆtype: ํ์ผ์ #MIME_ํ์ (์:image/jpeg,text/plain)tmp_name: #์๋ฒ์_์์๋ก_์ ์ฅ๋_ํ์ผ์_๊ฒฝ๋ก์_์ด๋ฆerror: #ํ์ผ_์ ๋ก๋_์_๋ฐ์ํ_์ค๋ฅ_์ฝ๋ (#UPLOAD_ERR_OK๋ ์ค๋ฅ ์์์ ์๋ฏธ)size: ์ ๋ก๋๋ #ํ์ผ์_ํฌ๊ธฐ(๋ฐ์ดํธ ๋จ์)
ํ์ผ ์ ๋ก๋ ์ฒ๋ฆฌ ๋ก์ง (PHP)
upload_process.php ํ์ผ์์ ์ค์  ํ์ผ ์
๋ก๋ ์ฒ๋ฆฌ ๋ฐ #๋ณด์_๊ฒ์ฌ๋ฅผ ์ํํฉ๋๋ค.
PHP
<?php
// upload_process.php
// 1. ์
๋ก๋ ๋๋ ํ ๋ฆฌ ์ค์  (๋ฐ๋์ ์น ์ ๊ทผ ๋ถ๊ฐ๋ฅํ ์์ ๊ฒฝ๋ก์ ๋๋ ๊ฒ์ด ๋ณด์์ ์ข์)
$upload_dir = './uploads/'; // ํ์ฌ ์คํฌ๋ฆฝํธ๊ฐ ์๋ ํด๋ ํ์์ 'uploads' ํด๋
// 'uploads' ํด๋๊ฐ ์์ผ๋ฉด ์์ฑ (๊ถํ 0755)
if (!is_dir($upload_dir)) {
    mkdir($upload_dir, 0755, true);
}
// 2. ํ์ผ ์
๋ก๋ ์ค๋ฅ ํ์ธ
// UPLOAD_ERR_OK: ํ์ผ ์
๋ก๋ ์ฑ๊ณต
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 "์
๋ก๋ ํ์ผ ํฌ๊ธฐ๊ฐ PHP ์ค์  ๋๋ ํผ์์ ํ์ฉ๋ ์ต๋ ํฌ๊ธฐ๋ฅผ ์ด๊ณผํ์ต๋๋ค.";
            break;
        case UPLOAD_ERR_NO_FILE:
            echo "ํ์ผ์ด ์
๋ก๋๋์ง ์์์ต๋๋ค.";
            break;
        default:
            echo "ํ์ผ ์
๋ก๋ ์ค ์ ์ ์๋ ์ค๋ฅ๊ฐ ๋ฐ์ํ์ต๋๋ค. ์ค๋ฅ ์ฝ๋: " . $_FILES['my_file']['error'];
            break;
    }
    exit;
}
// 3. ์
๋ก๋๋ ํ์ผ ์ ๋ณด ๊ฐ์ ธ์ค๊ธฐ
$file_name = $_FILES['my_file']['name']; // ์๋ณธ ํ์ผ ์ด๋ฆ
$file_type = $_FILES['my_file']['type']; // MIME ํ์
$file_tmp_name = $_FILES['my_file']['tmp_name']; // ์์ ํ์ผ ๊ฒฝ๋ก
$file_size = $_FILES['my_file']['size']; // ํ์ผ ํฌ๊ธฐ
// 4. ๋ณด์ ๊ฒ์ฌ (๋งค์ฐ ์ค์!)
// 4-1. ํ์ผ ํฌ๊ธฐ ์ ํ (์: 5MB)
$max_file_size = 5 * 1024 * 1024; // 5MB
if ($file_size > $max_file_size) {
    echo "ํ์ผ ํฌ๊ธฐ๊ฐ ๋๋ฌด ํฝ๋๋ค. (์ต๋ 5MB)";
    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, PATHINFO_EXTENSION));
// MIME ํ์
 ๊ฒ์ฌ ($_FILES['type']์ ํด๋ผ์ด์ธํธ์์ ์ ๊ณตํ๋ฏ๋ก ์์กฐ ๊ฐ๋ฅ์ฑ ์์)
// ์ค์  ํ์ผ์ MIME ํ์
์ ๊ฒ์ฌํ๋ ๋ฐฉ๋ฒ์ด ๋ ์์ ํ๋, ์ฌ๊ธฐ์๋ ๊ธฐ๋ณธ์ ์ธ ๊ฒ์ฌ๋ง ํฌํจ
if (!in_array($file_ext, $allowed_extensions) || !in_array($file_type, $allowed_mime_types)) {
    echo "ํ์ฉ๋์ง ์๋ ํ์ผ ํ์์
๋๋ค. (ํ์ฉ: JPG, JPEG, PNG, GIF, PDF)";
    exit;
}
// 5. ํ์ผ ์ด๋ฆ ๋ณ๊ฒฝ (๋ณด์์ ์ํด ํ์)
// ์ ๋ํฌํ ํ์ผ ์ด๋ฆ ์์ฑ (์: ํ์ฌ ์๊ฐ์ ๊ธฐ๋ฐ + ์๋ณธ ํ์ฅ์)
$new_file_name = uniqid() . '.' . $file_ext;
$destination = $upload_dir . $new_file_name; // ์ ์ฅ๋  ์ต์ข
 ๊ฒฝ๋ก
// 6. ์์ ํ์ผ์ ์ต์ข
 ๋ชฉ์ ์ง๋ก ์ด๋
// move_uploaded_file() ํจ์๋ ์
๋ก๋๋ ์์ ํ์ผ์ ์์ ํ๊ฒ ์ด๋์ํต๋๋ค.
if (move_uploaded_file($file_tmp_name, $destination)) {
    echo "ํ์ผ์ด ์ฑ๊ณต์ ์ผ๋ก ์
๋ก๋๋์์ต๋๋ค.<br>";
    echo "์ ์ฅ๋ ํ์ผ๋ช
: " . htmlspecialchars($new_file_name) . "<br>";
    echo "ํ์ผ ๊ฒฝ๋ก: " . htmlspecialchars($destination) . "<br>";
    echo "<img src='" . htmlspecialchars($destination) . "' alt='์
๋ก๋๋ ์ด๋ฏธ์ง' style='max-width:300px;'>";
} else {
    echo "ํ์ผ ์
๋ก๋์ ์คํจํ์ต๋๋ค.";
}
?>
4. PHP ์ค์  (php.ini) ํ์ธ
#PHP์ #php.ini ์ค์  ํ์ผ์๋ #ํ์ผ_์
๋ก๋์ ๊ด๋ จ๋ ์ค์ํ ์ง์์ด๋ค์ด ์์ต๋๋ค.
file_uploads = On: ํ์ผ ์ ๋ก๋ ๊ธฐ๋ฅ์ ํ์ฑํํฉ๋๋ค. (๊ธฐ๋ณธ๊ฐ On)upload_max_filesize = 2M: ๊ฐ๋ณ ํ์ผ ์ ๋ก๋์ ์ต๋ ํฌ๊ธฐ๋ฅผ ์ค์ ํฉ๋๋ค. (์:2M์ 2๋ฉ๊ฐ๋ฐ์ดํธ)post_max_size = 8M: #POST_์์ฒญ์ผ๋ก ์ ์ก๋ ์ ์๋ ์ ์ฒด ๋ฐ์ดํฐ์ ์ต๋ ํฌ๊ธฐ๋ฅผ ์ค์ ํฉ๋๋ค. (upload_max_filesize๋ณด๋ค ํฌ๊ฑฐ๋ ๊ฐ์์ผ ํฉ๋๋ค.)upload_tmp_dir =: ์ ๋ก๋๋ ํ์ผ์ด ์์๋ก ์ ์ฅ๋ ๋๋ ํฐ๋ฆฌ๋ฅผ ์ง์ ํฉ๋๋ค. (์ค์ ํ์ง ์์ผ๋ฉด ์์คํ  ๊ธฐ๋ณธ ์์ ๋๋ ํฐ๋ฆฌ ์ฌ์ฉ)max_file_uploads = 20: ํ ๋ฒ์ ์์ฒญ์ผ๋ก ์ ๋ก๋ํ ์ ์๋ ์ต๋ ํ์ผ ๊ฐ์์ ๋๋ค.
์ด ๊ฐ๋ค์ ์น ์๋ฒ์ ์๊ตฌ์ฌํญ๊ณผ ์ ํ๋ฆฌ์ผ์ด์ ์ ํ์์ ๋ง๊ฒ ์กฐ์ ํด์ผ ํฉ๋๋ค. ๋ณ๊ฒฝ ํ์๋ #์น_์๋ฒ(Apache, Nginx ๋ฑ)๋ฅผ #์ฌ์์ํด์ผ ์ ์ฉ๋ฉ๋๋ค.
์ค๋์ #HTML #ํผ์ ์ด์ฉํ #ํ์ผ_์ ๋ก๋์ ๊ธฐ๋ณธ์ ์ธ ๊ตฌํ ๋ฐฉ๋ฒ๊ณผ #๋ณด์_๊ณ ๋ ค์ฌํญ์ ๋ํด ์์๋ณด์์ต๋๋ค.