프롤로그
이제 진짜로 php와 MySQL연결을 해보자.
로컬환경 MySQL 설치
여기서부터 다시 맥북으로 넘어갔다가 다시 만들고(여러 군데에서 작업하기 위함)
brew install mysql
해서 mysql을 설치한 후에, mysql -u root -p 로 들어가서
CREATE DATABASE knockon;
이렇게 입력을 해주고
show databases;를 해주면
이렇게 데이터베이스가 설치되었다.
저렇게 knockon 이라는 데이터베이스 생성했다고 보면 된다.
이게 맥북이랑 윈도우랑 번갈아가면서 작업하기 때문에, 모든 환경에서도 똑같이 적용시켰다고 일단 보면 된다.
윈도우에서도 적용시켰으면 일단 준비 끝.
깃허브에 올려놨었던 데이터를 git clone한다
https://github.com/Vak-kas/php.git
이게 내 작업 환경이기 때문에 이것을 다운받아서 진행했었다.
사전 준비
일단, 회원가입을 진행할 시에, 나는 이름, 아이디, 비밀번호 이렇게 3개만 있으면 회원가입이 되게 만들 것이다. 그 외에 원래라면 더 필요하겠지만, 지금은 임시방편으로 저렇게만 둘 것이다.
그렇기에 일단 데이터베이스에 테이블 부터 만들어야한다.
이름 - name
아이디 : username
비밀번호 - password 로 할 거기 떄문에 쿼리로 만든다면
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
username VARCHAR(100) NOT NULL UNIQUE,
password VARCHAR(255) NOT NULL
);
이렇게 될 것이다.
실제로 실행을 하게 되면, 이렇게 만들어진 것을 확인할 수 있다.
MySQL와 PHP 연동하기
이제 php와 mysql을 연동해보자.
sudo apt install php-mysqli
터미널에서 이거 하나 깔아주고
databases.php 파일을 하나 만들어서
<?php
$servername = "localhost";
$username = "root";
$password = "11111111";
$dbname = "knockon";
$conn = new mysqli($servername, $username, $password, $dbname);
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
else{
echo "데이터베이스 연결 성공";
}
?>
이렇게 작성해주자.
password랑 dbname은 알아서 본인 거에 맞게 잘 설정해주면 된다.
결국엔 핵심은
$conn = new mysqli($servername, $username, $password, $dbname);
이 코드이다.
php -S localhost:8000
을 터미널에 입력해주고
http://localhost:8000/databases.php
여기로 접속하게 되면
데이터베이스 연결이 성공한 것을 확인할 수 있다.
메인페이지 작성
일단, 우리가 당장 만들 것이 메인페이지, 게시판, 내정보, 로그인 이렇게 4개가 필요할 것이라고 생각해서
index.php를 이와 같이 작성한다.
<?php
session_start();
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>홈페이지</title>
<link rel="stylesheet" href="login.css">
</head>
<body>
<nav>
<ul>
<li><a href="index.php">메인화면</a></li>
<li><a href="board.php">게시판</a></li>
<li><a href="profile.html">로그아웃</a></li>
<li><a href="login.html">로그인</a></li>
</ul>
</nav>
</div>
</body>
</html>
css는 여기부분은 나중에 꾸밀거니까 일단 이렇게 꾸며두고 실행을 시켜보면
일단, 로그인 버튼을 클릭하면 login.html로 넘어가게 만들었으니까, login.html을 작성하자.
로그인 페이지 작성
다음 login.html와 login.css을 아래와 같이 작성한다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>로그인</title>
<link rel="stylesheet" href="login.css">
</head>
<body>
<div class="login-main-container">
<div class="login-info-container">
<form action="login.php" method="POST">
<div class="login-id-input">
<label class="un_label" for="user_name">ID</label>
<input type="text" id="user_name" name="username" class="UserName" required />
</div>
<div class="login-pw-input">
<label class="pw_label" for="user_pw">PW</label>
<input type="password" id="user_pw" name="password" class="UserPassword" required />
</div>
<div class="btn-container">
<button type="submit" class="login-button">LOGIN</button>
<button class="user-join" onclick="window.location.href='signup.html'">REGISTER</button>
</div>
</form>
</div>
</div>
</body>
</html>
<!-- login.css -->
.login-main-container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 100vw;
height: 100vh;
}
.login-info-container {
display: flex;
flex-direction: column;
width: 400px;
height: 350px;
box-shadow: 0px 0px 2px gray;
padding: 10px;
border-radius: 10px;
}
.login-id-input {
display: flex;
flex-direction: row;
justify-content: space-around;
align-items: center;
margin: 20px 0px 20px 0px;
}
.login-pw-input {
display: flex;
flex-direction: row;
justify-content: space-around;
align-items: center;
margin: 20px 0px 20px 0px;
}
.un_label {
font-family: -apple-system;
font-weight: 1000;
font-size: 1.2rem;
text-align: center;
width: 30px;
}
.UserName {
height: 40px;
background: transparent;
border: none;
border-bottom: 1px solid black;
width: 300px;
outline: none;
font-size: 1.3rem;
}
.pw_label {
font-family: -apple-system;
font-weight: 1000;
font-size: 1.2rem;
width: 30px;
text-align: center;
}
.UserPassword {
height: 40px;
background: transparent;
border: none;
border-bottom: 1px solid black;
width: 300px;
outline: none;
font-size: 1.3rem;
}
.btn-container {
width: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.login-button {
margin-top: 3vh;
text-decoration: none;
color: white;
background-color: rgba(255, 81, 81, 0.7);
border: 0px;
border-radius: 12px;
width: 320px;
height: 45px;
font-size: 1.2rem;
box-shadow: 0px 0px 2px rgba(137, 137, 137, 0.8);
}
.login-button:hover {
background-color: rgba(255, 81, 81, 1);
/* border: 1px solid rgb(200, 200, 200); */
box-shadow: 0px 0px 2px rgba(137, 137, 137, 0.8);
}
.user-join {
margin-top: 3vh;
color: black;
background-color: rgb(255, 255, 255);
border: 0px;
border-radius: 12px;
width: 320px;
height: 45px;
font-size: 1.2rem;
box-shadow: 0px 0px 2px rgba(137, 137, 137, 0.8);
}
.user-join:hover {
background-color: rgba(236, 236, 236, 0.4);
box-shadow: 0px 0px 2px rgba(137, 137, 137, 0.8);
border: 1px solid rgb(200, 200, 200);
}
그리고 나서 실행 후에 로그인 버튼을 클릭하게 되면
이렇게 창이 되었다.
login 버튼을 클릭하게 되면 login.php로 POST요청이 가게 만들어놨고,
그다음에 REGISTER을 클릭시에 window.location.href로 signup.html로 넘어가게 만들어놨다.
회원가입 페이지 작성
다음 signup.html과 signup.css를 작성한다.
<!-- signup.php -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>회원가입</title>
<link rel="stylesheet" href="signup.css">
<link rel="stylesheet" href="login.css">
</head>
<body>
<div class="container">
<div class="login">
<h1>Sign Up</h1>
<form class="form_container" action="signup.php" method="POST">
<div class="input_container">
<!-- 이름 입력 -->
<div>
<label class="input_label" for="name">Name</label>
<input
type="text"
id="name"
name="name"
class="input_box"
required
/>
</div>
<!-- ID 입력 -->
<div>
<label class="input_label" for="id">ID</label>
<input
type="text"
id="id"
name="username"
class="input_box"
required
/>
</div>
<!-- 비밀번호 입력 -->
<div>
<label class="input_label" for="password">Password</label>
<button
class="set_visible_btn"
type="button"
onclick="togglePasswordVisibility('password')"
>
◉
</button>
<input
type="password"
id="password"
name="password"
class="input_box"
required
/>
</div>
<!-- 비밀번호 확인 입력 -->
<div>
<label class="input_label" for="confirmPassword">Confirm Password</label>
<button
class="set_visible_btn"
type="button"
onclick="togglePasswordVisibility('confirmPassword')"
>
◉
</button>
<input
type="password"
id="confirmPassword"
name="confirmPassword"
class="input_box"
required
/>
</div>
</div>
<!-- 회원가입 버튼 -->
<div>
<button
type="submit"
class="signup_btn"
onclick="return validatePassword()"
>
Create Account
</button>
</div>
<div>
<p id="sign">
Already have an account? <a href="/login.html">Sign in</a>
</p>
</div>
</form>
</div>
</div>
<script>
// 비밀번호 보이기/숨기기
function togglePasswordVisibility(id) {
var input = document.getElementById(id);
if (input.type === "password") {
input.type = "text";
} else {
input.type = "password";
}
}
// 비밀번호 확인 검증
function validatePassword() {
var password = document.getElementById("password").value;
var confirmPassword = document.getElementById("confirmPassword").value;
if (password !== confirmPassword) {
alert("비밀번호가 일치하지 않습니다. 다시 확인해주세요.");
return false;
}
return true;
</script>
</body>
</html>
.container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.login > h1 {
font-size: 50px;
text-align: center;
}
.form_container {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.input_container {
display: flex;
flex-direction: column;
justify-content: space-around;
gap: 30px;
height: 400px;
border: 1px solid black;
border-radius: 12px;
padding: 20px;
margin-bottom: 20px;
}
.input_box {
height: 40px;
background: transparent;
border: none;
border-bottom: 1px solid black;
width: 100%;
outline: none;
font-size: 1.3rem;
}
.input_label {
font-size: 1.2rem;
font-family: -apple-system;
font-weight: 700;
margin-right: 18px;
}
.set_visible_btn {
background-color: transparent;
border: none;
font-size: 1.3rem;
transition: all 1s ease-out;
}
.set_visible_btn:hover {
color: red;
filter: drop-shadow(0 0 1px rgb(137, 137, 137));
}
.signup_btn {
margin-top: 3vh;
text-decoration: none;
color: white;
background-color: rgba(255, 81, 81, 0.7);
border: 0px;
border-radius: 12px;
width: 320px;
height: 45px;
font-size: 1.3rem;
box-shadow: 0px 0px 2px rgba(137, 137, 137, 0.8);
}
.signup_btn:hover {
background-color: rgba(255, 81, 81, 1);
box-shadow: 0px 0px 2px rgba(137, 137, 137, 0.8);
}
이러고 실행시키면..
이렇게 된다.
name, id, password, confirm password 입력후에 create account 버튼을 누르면
signup.php가 실행되게 만들었다.
**원래 장고에서든, 플라스크에서든 기본적으로 url->함수 실행시키는 게 정상적인데, 지금 여긴 그런 건 없다. 아마 아파치에서 설정해야할 거 같은데, 거기 설정하면서 해당 코드들 수정될 가능성 있음 **
회원가입 처리 코드 작성
폼으로부터 이름은 name, 비밀번호는 password, 아이디는 username으로 설정했기에, 폼에서부터 받은 데이터를 처리해야한다.
일단 아까 databases.php 데이터베이스에 연결하는 코드 이와 같이 수정한다.
<?php
$servername = "localhost";
$username = "root";
$password = "11111111";
$dbname = "knockon";
$conn = new mysqli($servername, $username, $password, $dbname);
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
// else{
// echo "데이터베이스 연결 성공";
// }
?>
그냥 else구문만 없앤 거다.
그다음에, signup.php 코드를 작성한다.
<?php
require('databases.php');
$name = $_POST['name'];
$username = $_POST['username'];
$password = $_POST['password'];
$sql = "INSERT INTO users (name, username, password) VALUES ('$name', '$username', '$password')";
if ($conn->query($sql) === TRUE) {
echo "회원가입이 완료되었습니다!";
} else {
echo "회원가입 실패: " . $conn->error;
}
$conn->close();
?>
맨 위의 줄에 require('databases.php');
이부분, 아까 만들었던 databases.php를 가져와서 연결시키는 코드이다.
include도 있고 require도 있는데, include는 저거 데이터베이스 연결 가져오는데 실패하면 경고 표시하고 나머지 코드는 그대로 실행, require는 실패시에 치명적인 오류발생하고 코드를 멈춰버린다.
저렇게 하고 이제 코드를 실행하게 되면
회원가입이 완료되었습니다 뜨고,
데이터가 제대로 들어갔는지 확인해보자.
mysql -u root -p
use knockon;
select * from users;
회원가입이 정상적으로 잘 이루어진 것을 확인할 수 있다. 원래라면 저 비밀번호 부분 해시처리하는 게 맞는데, 일단은 모의해킹을 위한 과정이기에 그냥 저대로 저장되게 냅두겠다.
이제 회원가입이 완료되었습니다는, 자바스크립트로 <alert>하게 만들어준 후에 로그인창으로 넘어가게 하고, 실패되었으면 메인화면으로 넘어가게 하자.
<?php
require('databases.php');
$name = $_POST['name'];
$username = $_POST['username'];
$password = $_POST['password'];
$sql = "INSERT INTO users (name, username, password) VALUES ('$name', '$username', '$password')";
if ($conn->query($sql) === TRUE) {
echo "
<script>
alert('회원가입이 완료되었습니다!');
window.location.href = 'login.html';
</script>
";
} else {
echo "
<script>
alert('회원가입 실패! 다시 시도해주세요.');
window.location.href = 'index.php';
</script>
";
}
$conn->close();
?>
이렇게 signup.php를 수정한 다음에 실행시켜보자
이렇게 뜨고
로그인 창으로 넘어오게 되었다.
아까 아이디는 중복허용이 되지 않게 했기 때문에, 아이디 중복으로 회원가입시에 회원가입 실패 경고음이 뜨지 않을까? 테스트를 해봤는데
그냥 서버가 꺼진다.
어..?
저기는 나중에 디테일 잡을 때 따로 하도록 하자. 일단은 회원가입 처리는 되었고, 데이터베이스도 확인해보면
잘 저장이 되는 것을 확인할 수 있다.
로그인 처리 코드 작성
아까랑 비슷하게 이번에 폼에서 입력받는 것은 아이디와 비밀번호 일 것이다.
아이디 : username
비밀번호 password로 넘어올 것이기에 코드 작성해보자.
login.php 파일을 만들어서
<?php
require('databases.php');
$username = $_POST['username'];
$password = $_POST['password'];
$sql = "SELECT * FROM users WHERE username = '$username'";
$result = $conn->query($sql);
if ($result->num_rows > 0) {
$user = $result->fetch_assoc(); // 사용자의 데이터 가져오기
if($user['password'] == $password){
session_start();
$_SESSION['username'] = $user['username'];
$_SESSION['name'] = $user['name'];
echo "
<script>
alert('로그인 성공!');
window.location.href = 'index.php';
</script>
";
}
else{
echo "
<script>
alert('비밀번호가 일치하지 않습니다. 다시 시도해주세요.');
window.location.href = 'login.html';
</script>
";
}
}
else{
echo "
<script>
alert('존재하지 않는 아이디입니다. 다시 시도해주세요.');
window.location.href = 'login.html';
</script>
";
}
$conn->close();
?>
이렇게 작성하였다.
맨 밑의 else는 아이디 자체가 없는 사용자일때 다시 login.html로 리다이렉트 되는 거고
그 위의 else는 아이디는 있는데 비밀번호가 틀렸을 경우이다.
맨 위의 require로 데이터베이스 접근하고, username과 password를 사용자의 폼으로부터 입력받았다. 그 다음에
username에 일치하는 데이터를 가져오기 위해 select * from user로 가져왔다.
사용자 식별을 쿠키, 세션으로 처리하라고 했기 때문에, 세션아이디를 부여해주기 위하여
session_start();
$_SESSION['username'] = $user['username'];
$_SESSION['name'] = $user['name'];
이 코드를 이용하였는데,
session_start() 는 PHP 에서 세션을 시작하는 함수이다. 세션 아이디를 생성하고, 클라이언트에는 세션 아이디가 크키로 전달되어 서버와 클라이언트 간에 세션 상태를 유지하게 된다.
그리고 $_SESSION 을 이용하여 세션데이터에 접근할 수 있다.
로그인 시도를 하면
이런식으로 뜨고 메인화면으로 가거나, 다시 로그인창으로 넘어가게 되었다.
메인페이지 처리 코드 작성
로그인 성공시 메인화면으로 넘어오는데
여기서 로그인이 다시 뜨기 때문에, 로그인이 되어있는 상태에서는 로그아웃으로 뜨게 만들고
메인페이지 에 크게 NAME님, 환영합니다 뜨게 index.php 를 조금 수정해야할 것 같다.
<?php
session_start();
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>홈페이지</title>
<link rel="stylesheet" href="login.css">
</head>
<body>
<nav>
<ul>
<li><a href="index.php">메인화면</a></li>
<li><a href="board.php">게시판</a></li>
<?php if (isset($_SESSION['username'])): ?>
<li><a href="profile.html">내정보</a></li>
<li><a href="logout.php">로그아웃</a></li>
<?php else: ?>
<li><a href="login.html">로그인</a></li>
<?php endif; ?>
</ul>
</nav>
<div>
<?php if (isset($_SESSION['username'])): ?>
<p>안녕하세요, <?php echo $_SESSION['name']; ?>님!</p>
<?php else: ?>
<p>로그인을 해주세요</p>
<?php endif; ?>
</div>
</body>
</html>
중간에 <? php if ~~~~` ?>
이 것으로 session['username']이 설정되어 있다면가 그렇지 않다면으로 나누었다.
로그인이 되어 있지 않다면 위와 같이 뜨는데, 로그인을 하면
이렇게 창이 바뀐 것을 확인할 수 있다.
로그아웃 처리 코드 작성
<li><a href="logout.php">로그아웃</a></li>
이 부분 logout.php를 작성해주면 회원가입, 로그인 기능은 전부 끝난다.
<?php
session_start();
session_unset(); // 모든 세션 변수 삭제
session_destroy();
header("Location: index.php");
exit();
?>
session_start는 세션을 시작하는 함수인데, 세션 데이터를 사용할 때마다 이 함수가 호출되어야한다.
unset으로 모든 세션 변수들 지워버린다. 그리고
session_destory()로 세션을 완전히 종료 시켜서 세션 파일을 삭제하거나 세션 데이터를 지운다.
이리하여 모든 세션 데이터가 제거되었고, 그 이후 세션 변수에 접근할 수 없다.
이렇게 있을 때, 로그아웃 버튼을 누르면
다시 로그인 창이 뜬다.
여기 쿠키에 세션 아이디가 남아있기는 하지만 로그아웃은 되어있다. 세션지워야하는데, 저건 나중에..
에필로그
지금까지 작업내용은
https://github.com/Vak-kas/php/tree/login
여기에 저장해놨다.
아이디 중복 검사, 비밀번호 해쉬, SQL인젝션 방지, 세션 쿠키 만료시간 설정 해야한다.
바로 게시판 CRUD 해보자.
'KnockOn' 카테고리의 다른 글
[3주차 TIL] KnockOn Bootcamp PHP 게시판 수정 및 삭제 (1) | 2024.12.22 |
---|---|
[3주차 TIL] KnockOn Bootcamp PHP 게시판 생성 및 조회 (0) | 2024.12.22 |
[3주차 TIL] KnockOn Bootcamp PHP (0) | 2024.12.21 |
[3주차 TIL] KnockOn Bootcamp MySQL (1) | 2024.12.20 |
[3주차 TIL] KnockOn Bootcamp Apache (2) | 2024.12.20 |