낙장 도메인 설정 방법

유용한 코드 작성일: 2025-11-16 수정일: 2025-11-16 19:07
수정
20moa.co.kr 서버의 웹 루트 디렉토리에 업로드하시면 됩니다.

간단 요약
🔧 .htaccess 파일의 역할
"20moa.co.kr로 들어오는 모든 요청을 404.php로 보내는 교통 정리원"
HTTPS 강제 적용 - http를 https로 자동 변경
www 제거 - www.20moa.co.kr → 20moa.co.kr
모든 페이지를 404.php로 - 어떤 주소로 접속하든 404.php로 보냄
원본 URL 전달 - 어떤 주소로 들어왔는지 404.php에게 알려줌

📄 404.php 파일의 역할
"안내 페이지 + 자동 이동 기능"
친절한 안내 메시지 표시
"20moa.co.kr은 더 이상 운영 안 됨"
"100moa.co.kr로 서비스 이전"
3초 카운트다운 후 자동으로 100moa.co.kr로 이동
즉시 이동 버튼 제공 - 기다리기 싫으면 클릭
검색엔진에게 알림 - "이 페이지는 404 에러야" (SEO)


1. .htaccess 파일

# ===================================
# 20moa.co.kr → 100moa.co.kr 리다이렉트
# ===================================
RewriteEngine On

# ---- www 제거 ----
RewriteCond %{HTTP_HOST} ^www\.20moa\.co\.kr$ [NC]
RewriteRule ^(.*)$ https://20moa.co.kr/$1 [R=301,L]

# ---- HTTPS 강제 ----
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]

# ---- 404.php 파일 직접 접근 허용 (무한 루프 방지) ----
RewriteCond %{REQUEST_URI} ^/404\.php$ [NC]
RewriteRule ^ - [L]

# ---- CSS, JS, 이미지 등 정적 파일 직접 접근 허용 ----
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule \.(css|js|jpg|jpeg|png|gif|ico|svg|webp|pdf|woff|woff2|ttf|eot)$ - [L]

# ---- 모든 요청을 404.php로 리다이렉트 ----
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /404.php?from=$1 [L,QSA]

# ---- 404 에러 페이지 설정 ----
ErrorDocument 404 /404.php

# ---- 보안 헤더 ----
<IfModule mod_headers.c>
    Header set X-Content-Type-Options "nosniff"
    Header set X-Frame-Options "SAMEORIGIN"
    Header set X-XSS-Protection "1; mode=block"
    Header set Referrer-Policy "strict-origin-when-cross-origin"
</IfModule>

# ---- 디렉토리 인덱싱 방지 ----
Options -Indexes


2. 404.php 안내 페이지
<?php
// 원래 요청된 URL 가져오기
$requestedUrl = isset($_GET['from']) ? htmlspecialchars($_GET['from']) : '';
$fullUrl = 'https://20moa.co.kr/' . $requestedUrl;

// HTTP 404 상태 코드 설정 (SEO를 위해 중요)
http_response_code(404);
?>
<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="refresh" content="3;url=https://100moa.co.kr">
    <meta name="robots" content="noindex, nofollow">
    <title>페이지를 찾을 수 없습니다 - 20moa</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        
        body {
            font-family: -apple-system, BlinkMacSystemFont, "Malgun Gothic", "맑은 고딕", "Apple SD Gothic Neo", sans-serif;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            min-height: 100vh;
            display: flex;
            align-items: center;
            justify-content: center;
            padding: 20px;
        }
        
        .container {
            background: white;
            border-radius: 20px;
            box-shadow: 0 20px 60px rgba(0,0,0,0.3);
            padding: 60px 40px;
            max-width: 600px;
            width: 100%;
            text-align: center;
            animation: slideUp 0.5s ease-out;
        }
        
        @keyframes slideUp {
            from {
                opacity: 0;
                transform: translateY(30px);
            }
            to {
                opacity: 1;
                transform: translateY(0);
            }
        }
        
        .icon {
            font-size: 80px;
            margin-bottom: 20px;
            animation: bounce 1s ease-in-out infinite;
        }
        
        @keyframes bounce {
            0%, 100% { transform: translateY(0); }
            50% { transform: translateY(-10px); }
        }
        
        h1 {
            font-size: 32px;
            color: #333;
            margin-bottom: 15px;
            font-weight: 700;
        }
        
        .notice {
            background: #f8f9fa;
            border-left: 4px solid #667eea;
            padding: 20px;
            margin: 30px 0;
            border-radius: 8px;
            text-align: left;
        }
        
        .notice h2 {
            font-size: 18px;
            color: #667eea;
            margin-bottom: 10px;
            font-weight: 600;
        }
        
        .notice p {
            font-size: 15px;
            color: #555;
            line-height: 1.6;
            margin-bottom: 8px;
        }
        
        .url-info {
            background: #fff3cd;
            border: 1px solid #ffc107;
            padding: 15px;
            border-radius: 8px;
            margin: 20px 0;
            font-size: 14px;
            color: #856404;
            word-break: break-all;
        }
        
        .countdown {
            font-size: 48px;
            font-weight: 700;
            color: #667eea;
            margin: 30px 0;
            font-family: 'Arial', sans-serif;
        }
        
        .redirect-info {
            font-size: 16px;
            color: #666;
            margin-bottom: 20px;
        }
        
        .new-site {
            font-size: 24px;
            font-weight: 600;
            color: #764ba2;
            margin: 10px 0;
        }
        
        .button {
            display: inline-block;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            padding: 15px 40px;
            border-radius: 50px;
            text-decoration: none;
            font-weight: 600;
            font-size: 16px;
            margin-top: 20px;
            transition: transform 0.3s ease, box-shadow 0.3s ease;
            box-shadow: 0 4px 15px rgba(102, 126, 234, 0.4);
        }
        
        .button:hover {
            transform: translateY(-2px);
            box-shadow: 0 6px 20px rgba(102, 126, 234, 0.6);
        }
        
        .progress-bar {
            width: 100%;
            height: 6px;
            background: #e9ecef;
            border-radius: 3px;
            margin-top: 30px;
            overflow: hidden;
        }
        
        .progress-fill {
            height: 100%;
            background: linear-gradient(90deg, #667eea 0%, #764ba2 100%);
            width: 0%;
            animation: progress 3s linear forwards;
        }
        
        @keyframes progress {
            to { width: 100%; }
        }
        
        @media (max-width: 600px) {
            .container {
                padding: 40px 25px;
            }
            
            h1 {
                font-size: 24px;
            }
            
            .countdown {
                font-size: 36px;
            }
            
            .new-site {
                font-size: 18px;
            }
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="icon">🔍</div>
        <h1>페이지를 찾을 수 없습니다</h1>
        
        <?php if ($requestedUrl): ?>
        <div class="url-info">
            <strong>요청하신 페이지:</strong><br>
            <?php echo $fullUrl; ?>
        </div>
        <?php endif; ?>
        
        <div class="notice">
            <h2>📢 사이트 이전 안내</h2>
            <p><strong>20moa.co.kr</strong>은 더 이상 운영되지 않습니다.</p>
            <p>서비스는 아래의 새로운 사이트에서 계속됩니다.</p>
        </div>
        
        <div class="redirect-info">
            <div class="countdown" id="countdown">3</div>
            <p>초 후 자동으로 이동합니다</p>
        </div>
        
        <div class="new-site">
            → <strong>100moa.co.kr</strong>
        </div>
        
        <a href="https://100moa.co.kr" class="button">즉시 이동하기</a>
        
        <div class="progress-bar">
            <div class="progress-fill"></div>
        </div>
    </div>
    
    <script>
        // 카운트다운 타이머
        let count = 3;
        const countdownElement = document.getElementById('countdown');
        
        const timer = setInterval(function() {
            count--;
            countdownElement.textContent = count;
            
            if (count <= 0) {
                clearInterval(timer);
                window.location.href = 'https://100moa.co.kr';
            }
        }, 1000);
        
        // 즉시 이동 버튼 클릭 추적 (선택사항)
        document.querySelector('.button').addEventListener('click', function() {
            clearInterval(timer);
        });
    </script>
</body>
</html>
언어: HTML