📚 PHP 중급 - 2주차: 회원가입 및 로그인 시스템 구현 - 03 로그인 기능 (세션 기반 인증)

2025. 7. 18. 13:42프로그램/PHP 중급

📚 PHP 중급 - 2주차: 회원가입 및 로그인 시스템 구현 - 03 로그인 기능 (세션 기반 인증)

📚 PHP 중급 - 2주차: 회원가입 및 로그인 시스템 구현 - 03 로그인 기능 (세션 기반 인증)



안녕하세요! #PHP 중급 과정 2주차, 회원가입 및 로그인 시스템 구현의 세 번째 시간입니다. 지난 시간에는 #회원가입 기능을 통해 #사용자 데이터를 #데이터베이스에 안전하게 저장하는 방법을 알아보았습니다. 이제는 사용자들이 시스템에 접근할 수 있도록 #로그인 기능을 구현할 차례입니다.

이번 포스팅에서는 #세션 기반의 #인증 방식을 사용하여 #로그인 기능을 구현하는 과정에 대해 상세히 다룰 것입니다. 사용자 경험을 고려한 #로그인 #폼부터, 입력된 정보를 검증하고 #데이터베이스와 연동하여 #사용자 인증을 처리하는 #백엔드 #로직, 그리고 #세션을 활용하여 #로그인 상태를 유지하는 방법까지, 단계별로 자세히 설명해 드리겠습니다.

 


 

1. 로그인 폼 (login.php) 구현

사용자가 #로그인을 시도할 때 가장 먼저 마주하는 부분은 #로그인 #폼입니다. 사용자에게 #아이디와 #비밀번호를 입력받는 간단하면서도 직관적인 #HTML #폼을 구성합니다.

 

PHP
 
<!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; background-color: #f4f4f4; display: flex; justify-content: center; align-items: center; min-height: 100vh; margin: 0; }
        .login-container { background-color: #fff; padding: 30px; border-radius: 8px; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); width: 300px; text-align: center; }
        .login-container h2 { margin-bottom: 25px; color: #333; }
        .login-container input[type="text"],
        .login-container input[type="password"] { width: calc(100% - 20px); padding: 10px; margin-bottom: 15px; border: 1px solid #ddd; border-radius: 4px; font-size: 16px; }
        .login-container button { width: 100%; padding: 12px; background-color: #007bff; color: white; border: none; border-radius: 4px; font-size: 17px; cursor: pointer; transition: background-color 0.2s ease; }
        .login-container button:hover { background-color: #0056b3; }
        .login-container .error-message { color: red; margin-top: 10px; font-size: 14px; }
        .login-container .register-link { margin-top: 20px; font-size: 14px; }
        .login-container .register-link a { color: #007bff; text-decoration: none; }
        .login-container .register-link a:hover { text-decoration: underline; }
    </style>
</head>
<body>
    <div class="login-container">
        <h2>로그인</h2>
        <form action="login_process.php" method="POST">
            <input type="text" name="username" placeholder="아이디" required>
            <input type="password" name="password" placeholder="비밀번호" required>
            <button type="submit">로그인</button>
        </form>
        <?php
        if (isset($_GET['error'])) {
            $error_message = '';
            if ($_GET['error'] == 'invalid_credentials') {
                $error_message = '아이디 또는 비밀번호가 올바르지 않습니다.';
            } else if ($_GET['error'] == 'empty_fields') {
                $error_message = '아이디와 비밀번호를 모두 입력해주세요.';
            } else if ($_GET['error'] == 'db_error') {
                $error_message = '데이터베이스 오류가 발생했습니다.';
            }
            echo '<p class="error-message">' . htmlspecialchars($error_message) . '</p>';
        }
        ?>
        <div class="register-link">
            아직 계정이 없으신가요? <a href="register.php">회원가입</a>
        </div>
    </div>
</body>
</html>

 

login.php 파일은 다음과 같은 특징을 가집니다.

  • #아이디와 #비밀번호를 입력받는 두 개의 #input 필드(name="username", name="password")가 있습니다.
  • 폼의 action 속성은 login_process.php로 설정되어, 사용자가 #로그인 버튼을 클릭하면 입력된 데이터가 #PHP #백엔드 파일로 전송되도록 합니다.
  • method는 POST 방식을 사용하여 #보안을 강화하고, 입력값이 #URL에 노출되지 않도록 합니다.
  • required 속성을 사용하여 사용자가 #아이디와 #비밀번호를 반드시 입력하도록 강제합니다.
  • #GET 방식으로 전달된 error 파라미터가 있을 경우, 해당하는 #오류 #메시지를 사용자에게 표시합니다. 이는 #로그인 #실패 시 사용자에게 어떤 문제가 발생했는지 알려주는 역할을 합니다.
  • #회원가입 페이지로 이동하는 링크를 하단에 제공하여, 아직 계정이 없는 사용자를 배려합니다.

 


 

2. 데이터베이스 연결 설정 (db_config.php)

#회원가입 기능 구현 시 사용했던 db_config.php 파일을 그대로 활용합니다. 이 파일은 #데이터베이스 #접속에 필요한 정보를 담고 있으며, 여러 #PHP 파일에서 재사용됩니다.

 

PHP
 
<?php
// db_config.php
$db_host = 'localhost'; // 데이터베이스 호스트
$db_user = 'root';      // 데이터베이스 사용자명
$db_pass = 'your_password'; // 데이터베이스 비밀번호
$db_name = 'user_db';   // 사용할 데이터베이스명

// 데이터베이스 연결
$conn = new mysqli($db_host, $db_user, $db_pass, $db_name);

// 연결 오류 확인
if ($conn->connect_error) {
    die("데이터베이스 연결 실패: " . $conn->connect_error);
}

// 문자셋 설정 (선택 사항: 한글 깨짐 방지)
$conn->set_charset("utf8mb4");
?>

 

  • $db_pass 부분은 실제 사용하시는 #데이터베이스 #비밀번호로 반드시 변경해주세요.
  • 이 파일은 #데이터베이스와의 #연결을 설정하고, 연결에 실패할 경우 오류 메시지를 출력합니다.

 


 

3. 로그인 처리 로직 (login_process.php) 구현

login_process.php 파일은 #로그인 #폼에서 제출된 데이터를 받아 #사용자 #인증을 처리하는 핵심 #백엔드 #로직을 담당합니다. 이 과정에서 #데이터베이스에서 #사용자 정보를 조회하고, 입력된 #비밀번호를 #해싱된 #비밀번호와 비교하여 #일치 여부를 확인합니다.

 

PHP
 
<?php
// 세션 시작 (반드시 모든 PHP 코드 시작 시 가장 먼저 선언)
session_start();

// 데이터베이스 설정 파일 포함
require_once 'db_config.php';

// POST 요청으로 데이터가 전송되었는지 확인
if ($_SERVER["REQUEST_METHOD"] == "POST") {
    // 폼 데이터 가져오기 및 보안 처리
    $username = $conn->real_escape_string($_POST['username']);
    $password = $_POST['password']; // 비밀번호는 해싱 비교를 위해 그대로 둠 (나중에 해시 함수로 처리)

    // 입력값 유효성 검사 (빈 값 체크)
    if (empty($username) || empty($password)) {
        header("Location: login.php?error=empty_fields");
        exit();
    }

    // 1. 데이터베이스에서 사용자 정보 조회
    $stmt = $conn->prepare("SELECT id, username, password FROM users WHERE username = ?");
    $stmt->bind_param("s", $username);
    $stmt->execute();
    $result = $stmt->get_result();

    if ($result->num_rows === 1) {
        $user = $result->fetch_assoc();

        // 2. 비밀번호 확인 (해싱된 비밀번호와 비교)
        // password_verify() 함수를 사용하여 입력된 비밀번호와 데이터베이스에 저장된 해싱된 비밀번호를 비교합니다.
        if (password_verify($password, $user['password'])) {
            // 로그인 성공! 세션에 사용자 정보 저장
            $_SESSION['user_id'] = $user['id'];
            $_SESSION['username'] = $user['username'];
            
            // 로그인 성공 후 대시보드 페이지 또는 인덱스 페이지로 리다이렉트
            header("Location: dashboard.php"); // 또는 index.php
            exit();
        } else {
            // 비밀번호 불일치
            header("Location: login.php?error=invalid_credentials");
            exit();
        }
    } else {
        // 사용자 없음 (아이디 불일치)
        header("Location: login.php?error=invalid_credentials");
        exit();
    }

    $stmt->close();
} else {
    // POST 요청이 아닌 경우 로그인 페이지로 리다이렉트
    header("Location: login.php");
    exit();
}

// 데이터베이스 연결 닫기
$conn->close();
?>

 

login_process.php 파일의 핵심 단계는 다음과 같습니다.

  1. #세션 #시작: session_start(); 함수를 사용하여 #세션을 시작합니다. 이는 #로그인 성공 후 #사용자 정보를 #세션에 저장하고, 다른 페이지에서 해당 #세션 정보를 사용할 수 있도록 하는 필수 단계입니다. 반드시 모든 #PHP 코드의 가장 첫 줄에 위치해야 합니다.
  2. #데이터베이스 #연결: db_config.php 파일을 require_once하여 #데이터베이스에 연결합니다.
  3. #POST #요청 확인 및 데이터 가져오기: 폼이 POST 방식으로 제출되었는지 확인하고, #아이디와 #비밀번호를 안전하게 가져옵니다. 이때 real_escape_string()을 사용하여 #SQL #인젝션 공격을 방지합니다. 비밀번호는 아직 #해시되지 않은 상태로 유지합니다.
  4. #입력값 #유효성 #검사: #아이디와 #비밀번호가 모두 입력되었는지 확인합니다. 빈 값이 있을 경우 #오류 #메시지와 함께 #로그인 페이지로 리다이렉트합니다.
  5. #데이터베이스에서 #사용자 #정보 #조회: users 테이블에서 입력된 #아이디에 해당하는 #사용자 정보를 조회합니다. #Prepared #Statement를 사용하여 #SQL #인젝션에 대비합니다.
  6. #비밀번호 #확인 (password_verify() 사용):
    • 조회된 #사용자가 존재할 경우, password_verify() 함수를 사용하여 사용자가 입력한 #비밀번호와 #데이터베이스에 저장된 #해싱된 #비밀번호를 비교합니다. 이 함수는 #암호학적으로 안전하게 #비밀번호의 #일치 여부를 확인해 줍니다.
    • #비밀번호가 #일치하면 #로그인 #성공으로 간주합니다.
  7. #세션에 #사용자 #정보 #저장: #로그인 #성공 시, #_SESSION 슈퍼글로벌 변수에 #user_id와 #username 같은 사용자 정보를 저장합니다. 이 정보는 사용자가 #로그인 상태를 유지하고, 다른 페이지에서 #로그인 여부를 확인하는 데 사용됩니다.
  8. #리다이렉트: #로그인 성공 시, 사용자를 #dashboard.php (또는 index.php) 페이지로 리다이렉트합니다. #로그인 #실패 시에는 적절한 #오류 #메시지와 함께 다시 #로그인 페이지로 리다이렉트합니다.
  9. #데이터베이스 #연결 #닫기: 모든 작업이 끝난 후에는 mysqli 연결을 닫아 리소스를 해제합니다.

 


 

4. 로그인 상태 확인 및 대시보드 페이지 (dashboard.php)

#세션 기반의 #인증이 제대로 작동하는지 확인하고 #로그인된 사용자에게만 접근을 허용하는 #대시보드 #페이지를 구현합니다.

 

PHP
 
<?php
// 세션 시작 (세션 정보에 접근하기 위해 필수)
session_start();

// 로그인 여부 확인
if (!isset($_SESSION['user_id'])) {
    // 로그인되지 않았다면 로그인 페이지로 리다이렉트
    header("Location: login.php");
    exit();
}

// 로그인된 사용자 정보 가져오기
$user_id = $_SESSION['user_id'];
$username = $_SESSION['username'];
?>

<!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; background-color: #f4f4f4; display: flex; flex-direction: column; justify-content: center; align-items: center; min-height: 100vh; margin: 0; }
        .dashboard-container { background-color: #fff; padding: 30px; border-radius: 8px; box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); width: 400px; text-align: center; }
        .dashboard-container h2 { margin-bottom: 20px; color: #333; }
        .dashboard-container p { font-size: 18px; color: #555; margin-bottom: 30px; }
        .dashboard-container .logout-button { display: inline-block; padding: 10px 20px; background-color: #dc3545; color: white; text-decoration: none; border-radius: 4px; font-size: 16px; transition: background-color 0.2s ease; }
        .dashboard-container .logout-button:hover { background-color: #c82333; }
    </style>
</head>
<body>
    <div class="dashboard-container">
        <h2>환영합니다, <?php echo htmlspecialchars($username); ?>님!</h2>
        <p>로그인에 성공하셨습니다. 이제 대시보드 기능을 이용하실 수 있습니다.</p>
        <a href="logout.php" class="logout-button">로그아웃</a>
    </div>
</body>
</html>

 

dashboard.php 파일은 다음과 같이 작동합니다.

  • #세션 #시작: 이 페이지도 역시 session_start();를 통해 #세션에 접근합니다.
  • #로그인 #여부 #확인: !isset($_SESSION['user_id'])를 사용하여 #_SESSION에 #user_id가 설정되어 있는지 확인합니다.
  • #접근 #제한: 만약 #user_id가 없다면, 즉 #로그인 상태가 아니라면, 사용자를 강제로 login.php 페이지로 리다이렉트하여 접근을 막습니다.
  • #사용자 #정보 #표시: #로그인된 사용자에게 #세션에 저장된 #username을 이용하여 환영 메시지를 표시합니다.
  • #로그아웃 링크: #logout.php 파일로 연결되는 #로그아웃 버튼을 제공합니다.

 


 

5. 로그아웃 처리 로직 (logout.php) 구현

#로그아웃 기능은 현재 #사용자의 #세션 데이터를 모두 파괴하여 #로그인 상태를 해제하는 역할을 합니다.

 

PHP
 
<?php
// 세션 시작 (세션 데이터에 접근하기 위해 필수)
session_start();

// 모든 세션 변수 제거
$_SESSION = array();

// 세션 쿠키 삭제 (세션 ID를 저장하는 쿠키)
if (ini_get("session.use_cookies")) {
    $params = session_get_cookie_params();
    setcookie(session_name(), '', time() - 42000,
        $params["path"], $params["domain"],
        $params["secure"], $params["httponly"]
    );
}

// 세션 파괴
session_destroy();

// 로그인 페이지로 리다이렉트
header("Location: login.php");
exit();
?>

 

logout.php 파일은 다음과 같은 중요한 작업을 수행합니다.

  1. #세션 #시작: #세션을 시작하여 현재 `#사용자의 #세션 #데이터에 접근할 수 있도록 합니다.
  2. #세션 #변수 #제거: $_SESSION = array();를 사용하여 현재 #세션에 저장된 모든 #세션 #변수를 초기화합니다.
  3. #세션 #쿠키 #삭제: session_get_cookie_params()와 setcookie() 함수를 사용하여 #브라우저에 저장된 #세션 #쿠키를 삭제합니다. 이는 #브라우저가 세션 ID를 더 이상 저장하지 않도록 하여 보안을 강화합니다.
  4. #세션 #파괴: session_destroy(); 함수를 호출하여 서버의 #세션 #데이터 파일을 완전히 삭제합니다.
  5. #로그인 #페이지로 #리다이렉트: 모든 #로그아웃 처리가 완료되면 사용자를 login.php 페이지로 리다이렉트합니다.

 


 

결론

이번 포스팅에서는 #세션 기반 #인증 방식을 활용한 #로그인 기능을 완벽하게 구현하는 방법을 살펴보았습니다. #로그인 #폼부터 #데이터베이스를 통한 #사용자 #인증, #비밀번호 #해싱 #비교, 그리고 #세션을 이용한 #로그인 #상태 #관리까지, 실제 서비스에서 중요한 #보안 및 #사용자 경험 요소를 모두 다루었습니다.

이제 여러분의 #PHP #회원가입 및 #로그인 시스템은 사용자 #인증을 통해 안전하게 작동할 준비를 마쳤습니다. 다음 시간에는 #로그인된 사용자가 자신의 정보를 #수정하거나 #삭제하는 마이페이지 기능을 추가하여 시스템을 더욱 완성도 높게 만들어 보겠습니다.

 

 

마케팅 VPN 필요효할땐 루젠VPN

https://vpn.luzensoft.com/

 

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

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

vpn.luzensoft.com