11. PHP 게시판 만들기, view 제작 2

2015. 4. 14. 23:49
저자 : Kurien

주의: 본 게시판은 보안을 생각하지 않고 만들어졌으므로 실제로 사용되어서는 안되는 코드입니다.

공부할 때 게시판이 이처럼 동작한다는 정도로만 이해해주세요.


오늘은 view 부분의 조회 기능을 만들어보겠습니다.

아래의 파일을 받아주세요.


20150414_project.zip




<?php

require_once("../dbconfig.php");

$bNo = $_GET['bno'];


if(!empty($bNo) && empty($_COOKIE['board_free_' . $bNo])) {

$sql = 'update board_free set b_hit = b_hit + 1 where b_no = ' . $bNo;

$result = $db->query($sql); 

if(empty($result)) {

?>

<script>

alert('오류가 발생했습니다.');

history.back();

</script>

<?php 

} else {

setcookie('board_free_' . $bNo, TRUE, time() + (60 * 60 * 24), '/');

}

}

$sql = 'select b_title, b_content, b_date, b_hit, b_id from board_free where b_no = ' . $bNo;

$result = $db->query($sql);

$row = $result->fetch_assoc();

?>

<!DOCTYPE html>

<html>

<head>

<meta charset="utf-8" />

<title>자유게시판 | Kurien's Library</title>

<link rel="stylesheet" href="./css/normalize.css" />

<link rel="stylesheet" href="./css/board.css" />

</head>

<body>

<article class="boardArticle">

<h3>자유게시판 글쓰기</h3>

<div id="boardView">

<h3 id="boardTitle"><?php echo $row['b_title']?></h3>

<div id="boardInfo">

<span id="boardID">작성자: <?php echo $row['b_id']?></span>

<span id="boardDate">작성일: <?php echo $row['b_date']?></span>

<span id="boardHit">조회: <?php echo $row['b_hit']?></span>

</div>

<div id="boardContent"><?php echo $row['b_content']?></div>

<div class="btnSet">

<a href="./write.php?bno=<?php echo $bNo?>">수정</a>

<a href="./delete.php?bno=<?php echo $bNo?>">삭제</a>

<a href="./">목록</a>

</div>

</div>

</article>

</body>

</html>


오늘은 수정한 부분이 적습니다.

기존 view.php 파일에서는 조회수가 올라가지 않았는데요,

이 부분에 대해서만 수정 했습니다.

각 글에 대한 조회수는 b_hit라는 열에 저장되어있습니다.

만약 글을 클릭해서 view.php에 들어온다면 해당 글(b_no)에 대한 b_hit 값을 +1 해주는 sql을 만들고 쿼리를 날려야 합니다.

그런데 여기서 제한이 없이 view.php에 들어올 때마다 b_hit가 늘어난다면 새로고침을 할 때마다 +1이 되는 것을 볼 수 있을겁니다.


여기서 조회수를 제한할 수 있는 세 가지의 방법이 있는데요,

쿠키와 세션, DB를 이용한 방법이 있습니다.


여기서 쿠키를 이용한 방법은 제가 사용했으니 세션과 DB에 대해서 먼저 설명하겠습니다.


세션은 서버에 저장되는 변수라고 생각하시면 되겠습니다.

서버의 한 장소에 데이터를 저장해놓고 필요할 때 찾아서 사용하는 방식이죠.

이런 방식을 사용하는 이유는 기본적인 HTML이나 JavaScript 만을 가지고는 사용자 자신이 누군지 서버에게 알려줄 수가 없기 때문입니다.

세션같은 것이 없다면 로그인을 하더라도 다음 페이지로 넘어가는 순간 풀려버리게 되는거죠.


여기서 세션을 사용하지 않은 이유는 세션은 위에 적었듯이 서버에 저장이 됩니다.

조회수가 프로그램상 정말 중요한 부분이라면 세션이나 DB를 사용해야겠지만,

일반적인 게시판에서는 조회수가 큰 작용을 하지 않기 때문에 쿠키를 이용했습니다.


DB의 경우도 서버에 저장되지만 조회수를 올렸던 사용자가 누구인지 알기 위해서는 ip, 조회수를 올렸던 시간, 글 번호 이 세 가지가 필요합니다.

게다가 계속 DB에 쌓이면 느려지니 삭제도 해줘야 하구요.


쿠키는 위의 두 방법과는 다르게 클라이언트(사용자)의 PC에 저장됩니다.
클라이언트에 저장되는 세션이라고 생각하시면 되겠습니다.


대신 쿠키는 사용자가 맘대로 접근을 할 수 있기 때문에 쿠키를 이용할 때는 보안과는 관련 없는 기능에 사용해야하죠.

그리고 쿠키를 지우게 되면 조회수가 한번 더 오르기 때문에 딱히 하든 안하든 차이가 없는 것 같지만,

조회수 같은 중요하지 않은 기능에 그런 시간을 투자할만한 사람은 적다고 생각됩니다.


이러한 이유로 쿠키를 이용했구요.

이 글을 보시는 분들은 원하는 방법으로 사용하시면 되겠습니다.


if(!empty($bNo) && empty($_COOKIE['board_free_' . $bNo])) {

$sql = 'update board_free set b_hit = b_hit + 1 where b_no = ' . $bNo;

$result = $db->query($sql); 

if(empty($result)) {

?>

<script>

alert('오류가 발생했습니다.');

history.back();

</script>

<?php 

} else {

setcookie('board_free_' . $bNo, TRUE, time() + (60 * 60 * 24), '/');

}

}


위의 코드를 설명해보자면, 만약 $bNo이 있고, $_COOKIE['board_free_' . $bNo(글 번호)]가 없을 때 update 쿼리를 전송합니다.

결과가 없다면 오류가 발생했다는 메시지를 출력하고 이전 화면으로 돌아갑니다.


결과가 성공이라면 setcookie 함수를 이용해서 'board_free_' . $bNo이라는 쿠키를 만듭니다.

여기서 사용된 setcookie의 매개변수는 setcookie('쿠키 명', '쿠키 값', '쿠키 유지시간', '경로') 순입니다.


쿠키 명은 말 그대로 쿠키를 사용할 때 쓰는 쿠키의 이름으로 배열에서 키 값과 동일한 역할이라고 보시면 되겠구요.

여기서 board_free_$bNo이라는 이름으로 만든 이유는 free라는 이름을 가진 게시판의 글 번호를 나타낸겁니다.


쿠기 값도 배열의 값와 같다고 보시면 되겠습니다.

쿠키 유지시간은 쿠키가 얼마의 시간만큼 유지될 건지를 나타내는 건데요.

time()은 현재 시간을 나타내주고 거기에 + (60(초) * 60(분) * 24(시간))의 값을 더해줍니다.

60 * 60 * 24란 하루를 초로 나타낸 값입니다.

그러므로 하루 후에 다시 조회가 가능하게 되는거죠.


그리고 마지막으로 경로인데 만약 경로부분이 비어있다면 http://kurien.dothome.co.kr/board/에서 글을 조회했을 때는 /board/라는 경로에

쿠키가 생성되고 http://kurien.dothome.co.kr/project/board/에서 글을 조회했을 때는 /board/project/라는 경로에 쿠키가 생성됩니다.


그러므로 한 사람이 2의 조회수를 올릴 수 있게 되는거죠.

이 경로를 /로 고정 함으로써 하루 한번의 조회만 가능하게 했습니다.


여기까지 조회 기능을 만들었는데요.

짧고 간단한 부분인데 설명이 무진장 기네요 ㅠ


어려운 부분은 댓글에 남겨주시고, 현재 진행 상황은 http://kurien.dothome.co.kr에서 확인할 수 있습니다.