댓글 처리

Let's Just Go·2022년 7월 31일
0

Spring

목록 보기
16/26

Spring

댓글


Table 및 VO 객체 생성

  • 비동기 방식
    • 댓글은 페이지 이동을 할 필요가 없음으로 비동기 방식으로 진행
  • Table
    • 댓글을 저장할 수 있는 table 생성

      -- 댓글 테이블 
      CREATE TABLE freereply(
          rno NUMBER(10,0) primary key, -- 댓글 번호 
          bno NUMBER(10,0), -- 글 번호 (FK)
          reply VARCHAR2(1000), -- 내용 
          reply_id VARCHAR2(50), -- 글쓴이 아이디 
          reply_pw VARCHAR2(50), -- 비번 
          reply_date DATE DEFAULT sysdate, -- 등록일 
          update_date DATE DEFAULT null
      );
      
      -- 시퀀스 생성 
      CREATE SEQUENCE freereply_seq
          START WITH 1
          INCREMENT BY 1
          MAXVALUE 1000
          NOCYCLE
          NOCACHE;

Mapper

  • Interface Mapper
    • DB와 연결할 수 있는 Mapper를 생성하기 위해 Interface부터 우선 생성

      package com.spring.myweb.reply.mapper;
      
      import java.util.List;
      import java.util.Map;
      
      import com.spring.myweb.command.ReplyVO;
      
      public interface IReplyMapper {
      
      	// 댓글 등록 
      	void replyRegist(ReplyVO reply);
      	
      	// 목록 요청
      	List<ReplyVO> getList(Map<String, Object> data);
      	
      	// 댓글 개수 
      	int getTotal(int bno);
      	
      	// 비밀번호 확인 
      	int pwCheck(ReplyVO reply);
      	
      	// 댓글 수정 
      	void update(ReplyVO reply);
      	
      	// 댓글 삭제 
      	void delete(int rno);
      }

  • Mapper 생성
    • DB와 연결해서 CRUD 수행할 수 있는 Mapper 생성

      <?xml version="1.0" encoding="UTF-8"?>
      <!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
        
        
      <mapper namespace="com.spring.myweb.reply.mapper.IReplyMapper">
      	
      	<resultMap type="ReplyVO" id="replyMap">
      	<!-- mybatis-config에서 별칭을 지정했으므로 type에 별칭 지정 -->
      		
      		<result property = "replyId" column = "REPLY_ID"/>
      		<result property = "replyPw" column = "REPLY_PW"/>
      		<result property = "replyDate" column = "REPLY_DATE"/>
      		<result property = "updateDate" column = "UPDATE_DATE"/>
      	</resultMap>
      	
      	<!-- 댓글 등록 -->
      	<insert id="replyRegist">
      		INSERT INTO freereply(rno, bno, REPLY, REPLY_ID, REPLY_PW)
      		VALUES(freereply_seq.NEXTVAL, #{bno}, #{reply}, #{replyId}, #{replyPw})
      	</insert>
      	
      	<!-- 댓글 리스트  -->
      	<select id="getList" resultMap = "replyMap">
      		SELECT * FROM 
      			(SELECT ROWNUM AS rn, tbl.* FROM 	
      				(SELECT * FROM freereply
      				WHERE bno = #{bno}
      				ORDER BY rno DESC
      				) tbl
      			)
      		<![CDATA[
      		WHERE rn > (#{paging.pageNum}-1) * #{paging.cpp}
      		AND rn <= #{paging.pageNum} * #{paging.cpp}
      		]]>
      		<!-- getList라는 메서드는 page의 정보가 담긴 PageVO객체와 게시물 번호를 매개변수로 받음 
      			 그렇기 때문에 sql에서 해당 정보를 사용할 수 있음 -->
      	</select>
      	
      	<!-- 댓글 개수 -->
      	<select id="getTotal" resultType="int">
      	<!-- count이므로 반환은 int -->
      		SELECT count(*) FROM freereply
      		
      		WHERE bno = #{bno}
      	</select>
      	
      	<!-- 비밀번호 체크 -->
      	<select id="pwCheck" resultType="int">
      		SELECT count(*) FROM freereply
      		WHERE reply_pw = #{replyPw}
      	</select>
      	
      	<!-- 댓글 수정 -->
      	<update id="update" >
      		UPDATE freereply SET 
      		reply = #{reply}, update_date = sysdate
      		WHERE rno = #{rno}
      	</update>
      	
      	<!-- 댓글 삭제 -->
      	<delete id="delete">
      		DELETE FROM freereply
      		WHERE rno = #{rno}
      	</delete>
      	
      	
      	
      </mapper>

  • Mapper 등록
    • Mybatis가 인식할 수 있도록 root-context.xml에 등록

    • Beans Graph에서 등록이 제대로 되었는지 확인

      <mybatis-spring:scan
      		base-package="com.spring.myweb.freeboard.mapper" />
      	<mybatis-spring:scan
      		base-package="com.spring.myweb.reply.mapper" />
      	<mybatis-spring:scan
      		base-package="com.spring.myweb.user.mapper" />
      	<!-- Mapper인터페이스가 어디에 있는지 경로 지정 -->

댓글 등록

  • 댓글 등록
    • 페이지 이동없이 ajax함수를 통해서 사용자에게 입력받은 값들을 서버에게 보내고 요청의 결과(응답)를 받음
    • 비동기 방식으로 댓글을 등록하기 위한 데이터들을 서버로 보내 댓글 등록 진행
      
      	const msg = '${msg}';
      	if (msg !== ''){
      		alert(msg);
      	}
      	
      	$(document).ready(function() {
      		$('#replyRegist').click(function() {
      			
      	     const content = $('#reply').val();
      		 const name = $('#replyId').val();
      		 const pw = $('#replyPw').val();
      		 const bno = '${board.bno}';
      			 // 게시물 번호도 받아와야함 
      			 // 어느 게시물의 댓글인지 알 수 있어야하기 때문
      
      			 
      			 if (content === '' || name === '' || pw === ''){
      				 alert('필수 입력값(내용, 아이디, 비밀번호)의 내용이 비어있습니다. 확인해주세요.');
      				 return;
      				 // 이벤트 종료 
      			 } 
      				  // 객체로 만들어줌 
      				 console.log(content);
      				  $.ajax({
      					  type : 'POST',
      					  url:'<c:url value ="/reply/replyRegist" />',
      
      					  data : JSON.stringify({
      						
      							'bno' : bno,
      							'reply' : content,
      							'replyId' : name,
      							'replyPw' : pw
      
      					  }),
      					  dataType : 'text', // 서버로 부터 어떤 형식으로 받을지
      					  contentType: 'application/json',
      
      					  success: function(result){
      						  // 컨트롤러에서 다시 받은 값 
      						  console.log('통신 성공' + result);
      						  
      						  alert('댓글 등록이 완료되었습니다.');
      						  $('#reply').val('');
      						  $('#replyId').val('');
      						  $('#replyPw').val('');
      						  // 등록 완료 후 댓글 목록 함수를 호출해서 비동기식으로 목록 표현
      						  
      						  getList(1, true);
      						  
      					  },
      					  error : function(){
      						  alert('댓글 등록 실패');
      					  }
      				  }); // end ajax
      				 
      			 
      		}); // 댓글 등록 이벤트 끝
      		
      	

댓글 목록

  • 댓글 목록
    • getJSON()

      • JSON 형식의 파일을 읽어올 수 있으며 get 방식의 요청을 통해 서버로부터 받은 JSON 데이터를 가져옴
    • $.getJSON( [요청보낼 url], [서버로 부터 받은 데이터], [통신 성공 여부])

    • 반복문을 통해 서버로부터 받은 데이터를 넣은 html 코드를 작성하여 화면에 뿌려줌

    • 비동기 방식으로 댓글 목록을 서버로부터 가져와서 댓글 목록 출력 진행

        // 더보기 버튼 클릭 처리 
        // 클릭 시 전역 변수인 page에 +1 한 값 전달 
        $('#moreList').click(function() {
            // 더보기 버튼 클릭 했다면
            
            getList(++page, false);
            // page값을 올려주고 reset을 false로 해줌 
            // 왜 false나면 더보기는 댓글을 더 보기 위해서는 누적으로 봐야함
            // 1페이지 댓글 내용에다가 추가로 페이지를 추가해서 댓글 내용을 보여줌
            
        });
        
        // 목록 요청 
        let page = 1; // 페이지 번호 
        let strAdd = ''; // 화면에 그려넣을 태그를 문자열 형태로 추가할 변수 
        
        getList(1, true);
        // 상세보기 화면에 처음 진입했을 때 댓글 리스트 불러옴  
        
        
        // 목록을 불러오는 list
        // getList의 매개값으로 요청된 페이지 번호와 화면을 리셋할 것인지 여부를 bool 타입의 reset이름의 변수로 받음
        // 페이지 이동은 없고 댓글은 밑에 계속 쌓이므로 상황에 따라 페이지를 리셋해서 새롭게 가져올지 누적해서 쌓을 것인지 여부 확인 
        function getList(pageNum, reset) {
            
            // 글번호를 알아야 댓글이 몇개인지 알 수 있음 
            const bno = '${board.bno}';
            
            // 비동기 방식에서 사용하는 함수 
            // getJSON()를 통해서 JSON형식의 파일을 읽어올 수 있음 
            // get방식의 요청을 통해 서버로부터 받은 JSON 데이터를 가져옴 
            // $.getJSON(요청보낼 url, 서버로 받은 데이터, 통신 성공 여부)
            $.getJSON(
                    
                "<c:url value='/reply/getList/' />" + bno + '/' + pageNum,
                // 요청을 보냄 
                
                function(data){
                    // 요청에 대한 응답의 데이터 
                    // 서버가 전송한 데이터는 data에 저장 
                    console.log(data);
                    
                    // data에는 replyList와 total이라는 이름의 데이터가 존재 
                    let total = data.total;
                    let replyList = data.replyList;
                    console.log(replyList);
                    
                    // insert, update, delete 작업 후에는 댓글을 누적하고 있는 strAdd 변수를 
                    // 초기화를 해서 화면이 리셋된 것처럼 보여줘야 함
                    if (reset === true){
                        strAdd = '';
                        page = 1;						
                    }
                    
                    // 페이지 번호 * 데이터 수 보다 전체 댓글 개수가 작으면 더보기 버튼을 없앰 (굳이 보여줄 필요가 없음)
                    console.log('현재 페이지 : ' + page);
                    if (total <= page * 5){
                        // 전체 댓글 개수가 페이지 * 한화면에 보여줄 댓글 수보다 작으면 굳이 더보기 화면을 보여줄 필요가 없음
                        $('#moreList').css('display', 'none');
                    } else{
                        $('#moreList').css('display', 'block');
                    }
                    
                    // 응답 데이터의 길이가 0과 같거나 더 작으면 함수를 종료 
                    if(replyList.length <= 0){
                        return;
                        // 댓글이 없기 때문에 밑에 있는 반복문 종료 
                    }
                    
                    // 댓글의 개수가 몇개인지 알 수 없으므로 반복문 진행
                    // ``을 이용해서 쉽게 삽입 진행
                    // controller에서 받은 데이터인 댓글이 들어있는 리스트 데이터 활용
                    for (let i =0; i<replyList.length; i++){
                        strAdd += 
                        `<div class='reply-wrap'>
                            <div class='reply-image'>
                                <img src='${pageContext.request.contextPath}/img/profile.png'>
                            </div>
                            <div class='reply-content'>
                                <div class='reply-group'>
                                    <strong class='left'>`+ replyList[i].replyId + `</strong> <small class='left'>` + timeStamp(replyList[i].replyDate) + `</small>
                                    <a href='` + replyList[i].rno + `' class='right replyDelete'><span class='glyphicon glyphicon-remove'></span>삭제</a>
                                    <a href='` + replyList[i].rno + `' class='right replyModify'><span class='glyphicon glyphicon-pencil'></span>수정</a> 
                                </div>
                                <p class='clearfix'>` + replyList[i].reply + `</p>
                            </div>
                        </div>`;
                        // ``을 통해서 한번에 넣어줌
                        // 댓글 영역의 html내용을 가지고 와서 반복문과 ``을 활용해서 필요한 곳에 값을 넣어줌
                    } // for 문 끝
                    $('#replyList').html(strAdd);
                    // 반복문에서 작성한 html을 품을 수 있는 노드를 찾아서 문자열 형식으로 넣어줌
                    // 해당 글에 있는 모든 댓글 내용을 추가 
                    
                }
                );// end getJSON
                
        }// end getList()

댓글 수정

  • 댓글 수정
    • 댓글에 걸어놓은 비밀번호를 통해 댓글을 수정할 수 있는 권한 여부 검증

    • 비동기 방식으로 변경 데이터를 서버에 보내 댓글 수정 진행

      // 수정 처리 함수 
        // 수정 모달을 열어서 주어 내용을 작성후 수정 내용 작성
        $('#modalModBtn').click(function() {
                
                // 수정에 필요한 값들을 모두 가져옴 
            const rno = $('#modalRno').val();
                // console.log('bno값 :' + bno);
                const replyModi = $('#modalReply').val();
                const replyPw = $('#modalPw').val();
                // console.log(replyModi + replyPw);
                
                
                if (replyModi === '' || replyPw === ''){
                    // 값들이 비어있다면 함수 종료 
                    alert('내용, 비밀번호를 확인하세요.');
                    return;
                }
                
                // ajax 실행 
                // 비동기방식으로 controller에 요청을 보내고 객체형식으로 값을 담아서 보냄 
                $.ajax({
                    type:'POST',
                    url : '<c:url value ="/reply/update" />',
                    data : JSON.stringify({
                        'rno' : rno,
                        'reply' : replyModi,
                        'replyPw' : replyPw
                    }),
                    dataType:'text',
                    contentType : 'application/json',
                    
                    success:function(data){
                        // 통신이 성공해서 controller로부터 데이터를 받아왔을 때 실행 
                        console.log('통신성공' + data);
                        
                        if (data === 'modSuccess'){
                            alert('댓글 수정 성공 ');
                            // 값 초기화
                            
                            $('#modalReply').val('');
                            $('#modalPw').val('');						 
                            // 사용자가 작성한 값 비우기
                            
                            $('#replyModal').modal('hide');
                            // 모달 창 숨기기
                            
                            getList(1, true);
                            // 새롭게 댓글 불러옴 
                        }
                
                        else{
                            
                            alert('비밀번호가 틀렸습니다.');
                            
                            $('#modalPw').val('');
                            // 비밀번호만 지움
                            
                            $('#modalPw').focus();
                            // 비밀번호 부분에 집중
                        }
                    },
                    error : function(){
                        // 통신에 실패했을 때 
                        alert("수정에 실패했습니다. 관리자에게 문의해주세요.");
                    }
                }); // end ajax
                
        }); // 수정 처리 이벤트 끄읏

댓글 삭제

  • 댓글 삭제
    • 댓글에 걸어놓은 비밀번호를 통해 댓글 삭제 권한 여부 검증

    • 비동기 방식으로 삭제하기 위해 필요한 데이터를 서버에 보내 댓글 삭제 진행

      // 삭제 함수 
        $('#modalDelBtn').click(function() {
                
                // 삭제 처리를 하기 위해 값을 가져옴 
                const rno = $('#modalRno').val();
                // console.log('bno값 :' + bno);
                const replyPw = $('#modalPw').val();
                
                if (replyPw === ''){
                    alert('비밀번호를 입력해주세요.');
                    return;
                }
                
                // ajax함수를 활용해서 비동기 통신 방식으로 controller에 데이터 전달 
                $.ajax({
                    type:'POST',
                    url : '<c:url value="/reply/delete" />',
                    data : JSON.stringify({
                        'rno' : rno,
                        'replyPw' : replyPw
                    }),
                    dataType:'text',
                    contentType : 'application/json',
                    
                    // 통신에 성공해서 controller에서 값을 다시 줬을 때 
                    success:function(result){
                        console.log('통신 성공' + result);
                        if (result === 'delSuccess'){
                            alert('댓글 삭제 성공');
                            
                            // 사용자가 작성한 값 비우기 
                            $('#modalReply').val('');
                            $('#modalPw').val('');
                            
                            // 모달 창 숨기기 
                            $('#replyModal').modal('hide');
                            
                            getList(1,true);
                            // 댓글창 다시 불러오기
                        }
                        else{
                            alert('비밀번호가 틀립니다.');
                            $('#modalPw').val('');
                            // 비밀번호 지움 
                            
                            $('#modalPw').focus();
                            // 비밀번호 부분 집중
                        }
                    },
                    // controller에 값을 받아오지 못했을 때 
                    error : function(){
                        alert('삭제에 실패했습니다. 관리자에게 문의해주세요.');
                    }
                }); // end ajax
        }); // 삭제 처리 이벤트 끄읏
profile
안녕하세요! 공부한 내용을 기록하는 공간입니다.

0개의 댓글