본문 바로가기
Lecture/JSP & Java

[본격 게시판짜기 Part2.8 Model2 MVC패턴] count기능추가

by cusmaker 2012. 7. 22.
반응형

2012/06/13 - [Lecture/HTML] - [본격 게시판짜기 Part1.1 - 게시판도 HTML부터] 게시글 리스트

2012/06/13 - [Lecture/HTML] - [본격 게시판짜기 Part1.2 - 게시판도 HTML부터] 글입력폼

2012/06/13 - [Lecture/Javascript-기초] - [본격 게시판짜기 Part1.3 - Dom 맛보기 ] 글입력폼 검사

2012/06/13 - [Lecture/Jsp] - [본격 게시판짜기 Part1.4 - HTML-> JSP] form 파라미터 받기

2012/06/26 - [Lecture/SQL / Oracle] - [본격 게시판짜기 Part1.5 JSP > Oracle] 게시판 DB 테이블 생성

2012/06/26 - [Lecture/Jsp] - [본격 게시판짜기 Part1.6 Oracle > JSP] Database 접속 및 Select

2012/07/05 - [Lecture/Jsp] - [본격 게시판짜기 Part1.7 JSP, SQLDeveloper] 게시글 입력 및 리스트조회기능

2012/07/08 - [Lecture/Jsp] - [본격 게시판짜기 Part1.8 JSP 게시글 조회] 게시글 조회기능 및 게시글 삭제

2012/07/10 - [Lecture/Jsp] - [본격 게시판짜기 Part2.1 Model2 MVC패턴] 뷰(View) 코드 분리

2012/07/10 - [Lecture/Jsp] - [본격 게시판짜기 Part2.2 Model2 MVC패턴] Entity Beans의 사용

2012/07/12 - [Lecture/Jsp] - [본격 게시판짜기 Part2.3 Model2 MVC패턴] Controller구성

2012/07/13 - [Lecture/Jsp] - [본격 게시판짜기 Part2.4 Model2 MVC패턴] Model 구성

2012/07/16 - [Lecture/Mybatis] - [본격 게시판짜기 Part2.5 Model2 MVC패턴] Model 구성2 - i-batis의 사용

2012/07/17 - [Lecture/Mybatis] - [본격 게시판짜기 Part2.6 Model2 MVC패턴] Model 구성2 - i-batis의 사용2

2012/07/21 - [Lecture/Mybatis] - [본격 게시판짜기 Part2.7 Model2 MVC패턴] i-batis의 queryForList 활용 Paging기능구현


안녕하세요 cocy입니다.

이번 포스팅은 counting 기능을 구현 할 텐데요,

이 기능역시 페이징과 마찬가지로 프로그래머마다 구현이 갈라질 수 있는 부분입니다.

프로그램에 정도(正道)는 없습니다.

완벽인 프로그램은 있을 수 없지만
현상황에 최적인 프로그램 프로그램은 있을 수 있지요.


기능을 정리해보면
게시글이 조회되었을때 조회수를 +1시킵니다. 간단하죠?

그럼 +1시키는 시점은..게시글보기 즉 content.do가 실행되었을때로 잡으면 되겠네요!


그런데 여기서 곰곰히 생각해봅시다.

자기가 쓴글의 조회수를 늘리기위해 

새로고침을 누르고 있는 저자를 상상해봅시다. 막아야겟죠?

게시글을 무한 클릭하고있는 저자도 상상해 봅시다. 

이것도 막아야죠? 그런데 우리는 저자를 구분할 수 있는 내용이 조작가능한 writer밖에 없습니다.

게다가 회원정보도 존재하지 않고, 회원가입은 물론 로그인도 구현하지 않았습니다.


그렇다면 글쓴이를 구분할 수 있는 속성이 무엇이 있을까요?

바로 ! ip입니다.

request객체는 해당 요청을 보낸 유저의 ip를 캐치할 수 있습니다.

바로 request.getRemoteAddr() 메서드입니다.

근데 우리가 개발한 게시판에는 ip를 집어넣을 수 있는 컬럼이 존재하지 않습니다.

그럼? 추가해야죠. 이런 식의 수정이 실무에서 가장 흔하게 생길 수 있는 요구사항 중 하나입니다.

우선 DB Table에 "regip" 로 컬럼을 추가합니다.



사진1. 테이블에 regip컬럼 추가하기

기본값은 기존에 데이터에 빈 컬럼을 채우기위해 넣었습니다.

그럼 이제 board 빈을 수정합시다.

string형으로 regip를 선언하고 getter와 setter를 생성해줍니다.


사진2. Board 빈에 변수와 getter/setter 추가하기


그 다음에 할일은

InsertAction.java에서 쿼리를 보내는 과정에 regip를 빈에 등록하는 일입니다.

사진3. InsertAction에서 regip추가


InsertAction은 코드분리나 Model구성을 따로 해드리지 않았는데요, 

직접 구현해 보셨으리라 믿어 의심치 않습니다. :)

그럼 이제 쿼리를 수정할 차례입니다.

쿼리에도 추가도 간단합니다.


사진4. board.xml에서 regip추가

board.xml파일 역시 리스트쿼리 외에는 구현하지 않았는데요,

직접 짜보신 쿼리와 크게 다르지 않을겁니다.


그럼 이제 정말 마지막으로 뷰를 수정하는 일만 남았습니다. 좀 번외일순 있지만 기왕 추가한김에

게시글 리스트에서 ip를 보여주거나, 게시글 조회페이지에서 ip를 보여주면됩니다.

저는 게시글 조회에 추가하도록 하겠습니다. content.jsp의 body부분입니다.

<body>                                     

    <h1>게시글 조회</h1>                    
 
    <table border="1">                            <!-- border은 테두리를 표시하는 속성입니다. -->
 
        <tr>                                 
 
            <th>번호</th>                    
 
            <td>${article.idx}</td>
 
            <th>작성자</th>
 
            <td>${article.writer}</td>
 
            <th>ip</th>
 
            <td>${article.regip}</td>
 
            <th>날짜</th>
 
            <td>${article.regdate}</td>
 
            <th>조회수</th>
 
            <td>${article.count}</td>
 
        </tr>
 
        <tr>
 
            <th colspan="2">제목</th>         <!-- colspan은 행병합 속성입니다. -->
 
            <td colspan="8">${article.title}</td>
 
        </tr>
 
        <tr>
 
            <th colspan="2">내용</th>                    
 
            <td colspan="8">${article.content}</td>
 
        </tr>
 
    </table>
 
    <a href="delete.do?idx=${article.idx}">게시글삭제</a>
 
    <a href="list.do">목록으로</a>
 
</body>


그럼이제 본래 목적으로 돌아가서 count기능을 추가하도록 합시다.

기능을 정리해보면,

새로고침을 방지하려면 ContentAction에서 처리하지말고,

CountAction.java를 추가하여 (redirect와 비슷한 처리방식이지만 java에서 처리해야할 부분이 있기때문에!)

현재 조회를 요청한 ip와 게시글의 ip를 비교합니다.

만약 ip가 같으면 count를 +하지 않고 로직을 수행합니다.

만약 다르다면 더해주고나서,

ContentAction을 호출합니다. 여기서 마찬가지로 redirect2.jsp페이지를 이용합니다.

redirect.jsp페이지를 조금 변경하셔서 같이 사용하셔도 무방합니다.


우선 수정해야할 부분은 게시글을 조회하는 뷰입니다.

list.jsp에서 content.do를 요청하지말고 count.do를 요청합니다. 파라미터는 동일합니다.

<h1>게시글 리스트</h1>        <!-- 헤드라인 글씨를 표현하는 태그입니다. -->
 
<table>                   <!-- 표 형식의 데이터를 표현하는 태그입니다. -->
 
    <tr>                  <!-- table태그 내에서 행을 정의할때 쓰는 태그입니다. -->
 
        <th>번호</th>     <!-- Table Header의 약자로 table태그 내에서 -->
 
        <th>제목</th>     <!-- 강조하고싶은 컬럼을 나타낼때 쓰는 태그입니다. -->
 
        <th>작성자</th>
 
        <th>날짜</th>
 
        <th>조회수</th>
 
    </tr>
 
    <c:forEach items="${articleList}" var="article">
 
        <tr>
 
            <td>${article.idx}</td>
 
            <td><a href='count.do?idx=${article.idx}'>${article.title} </a></td>
 
            <td>${article.writer}</td>
 
            <td>${article.regdate}</td>
 
            <td>${article.count}</td>
 
        </tr>
 
    </c:forEach>
 
</table>


그럼 이제 명령어를 인식할 수 있도록 Command.properties에 다음 구문을 추가해줍니다.

/count.do=com.board.action.CountAction

그럼 저 경로대로 CountAction을 추가해야겠죠? 기능상으로 가장 비슷한 ContentAction.java를 복붙하여 수정합시다.


CountAction.java의 소스입니다.

public class CountAction implements CommandAction {
 
    @Override
 
    public String requestPro(HttpServletRequest request,
 
            HttpServletResponse response) throws Throwable {
 
        int idx =Integer.parseInt( request.getParameter("idx"));        //전 페이지로부터 넘어온 idx값을 받고
 
         
 
        Board article = BoardDao.getInstance().getArticle(idx);     // 게시글 전체를 가져옵니다.
 
        String regip = request.getRemoteAddr(); // 현재 조회를 요청한 사용자의 ip를 받고
 
 
 
        if(!regip.equals(article.getRegip())){          // 게시글의 ip와 동일하지 않으면
 
            int count = article.getCount();                 // 게시글의 count를 받아서
 
            article.setCount(count++);                      // +1 해주고 게시글빈에 셋팅합니다.
 
            BoardDao.getInstance().setArticleCount(article);    // 이후 이 빈을 파라미터로 업데이트합니다.
 
        }
 
    request.setAttribute("url""content.do?idx="+idx);
 
    return "redirect2.jsp";
 
        }
 
}

소스를 살펴보면 idx를 넘겨받고 해당 게시글을 가져온뒤

현재 조회를 요청한 ip와 가져온 게시글의 ip를 대조후

게시글의 ip와 동일하지 않으면 게시글의 카운트를 받아서 +1 해줍니다.

이때 업데이트를 수행할  Dao쪽 setArticleCount() 메서드를 구현합니다.

BoardDao.java에 추가할 setArticleCount()메서드의 코드입니다.

public void setArticleCount(Board article) throws SQLException {
 
    GetDB().update("setArticleCount", article);
 
}

그리고 Board.xml에 추가할 update 쿼리 태그입니다.

<update id="setArticleCount" parameterClass="board">
 
    update board set count = #count# where idx = #idx#
 
</update>

잘 작동 하시나요?

그럼 이것으로 카운트 기능 추가가 끝났습니다.

이것으로 Model2 게시판도 거의 다 끝났습니다.

다음시간에는 번외로 로그인처리를 위해 회원 테이블을 만들고 로그인구현 및

웹어플리케이션의 보안, 즉, 대표적인 공격방법들에 대해서 다뤄보겠습니다.

하려고 했지만, 본래의 목적과는 좀 동떨어진것 같아서 파일업로드 기능추가를 하도록 하겠습니다.

수고하셨습니다.


다음장 >>http://cusmaker.tistory.com/110