[댓글조회] Ajax로 댓글 조회 기능 구현

    * 세미 프로젝트에서 구현한 기능들을 복습 겸 정리해보려고 합니다.

    당연한 이야기이지만, 제 코드가 정답은 아니기 때문에 감안하고 읽어주시면 감사하겠습니다.

     

     

    [댓글작성] Ajax로 댓글 작성 기능 구현

    * 세미 프로젝트에서 구현한 기능들을 복습 겸 정리해보려고 합니다. 당연한 이야기이지만, 제 코드가 정답은 아니기 때문에 감안하고 읽어주시면 감사하겠습니다. 레시피 상세 보기 페이지에

    seongeun-it.tistory.com

     

    위의 포스팅과 이어지는 내용입니다.

    이번 포스팅은 댓글 조회 기능 구현입니다. 

     

    저의 경우 댓글 조회 기능 -> 댓글 작성 기능 순으로 구현했습니다.

     


    대략적인 UI는 다음과 같습니다. 

     

     

     

    1. SQL

    <entry key="selectReplyList">
    
          SELECT 
                REPLY_NO
                ,NICKNAME
                ,REPLY_CONTENT
                ,R.ENROLL_DATE
                ,PROFILE_IMG
                FROM REPLY R
          JOIN MEMBER M USING (USER_NO)
          WHERE M.STATUS = 'Y'
          AND R.DELETE_STATUS ='N'
          AND RECIPE_NO = ?
          ORDER BY R.ENROLL_DATE DESC
          
    </entry>

     

    댓글 조회 시 필요한 정보는

    댓글 번호 / 사용자의 닉네임 / 댓글 내용 / 댓글 작성일 / 프로필 이미지 경로 총 5개입니다.

    사용자의 닉네임과 프로필 이미지 경로를 알아내기 위해 MEMBER 테이블과 Join 하였습니다. 

    탈퇴되지 않은 회원의 정보가 Y이고, 댓글 삭제 여부가 N인 댓글을 댓글 작성일 최신 순으로 정렬하는 기준을 세웠습니다. 이때 어떤 레시피에 담긴 댓글인지를 확인하기 위해 RECIPE_NO을 ?로 두었습니다.

     

     


    2. View

    <div id="reply-list-area">
      <!--댓글 한개의 div 영역 -->
      <div class="reply-detail" align="center" id="reply-content-area">
        <table style="width: 500px;">
          <tbody>
    			
          </tbody>
        </table>
      </div>
    </div>

     

    아이디가 reply-list-area인 div를 생성했습니다. 그 안에 기본 골격을 만들어줬습니다.

     

    조회 기능의 경우 동적으로 버튼을 클릭해야지만 조회되는 것이 아니기 때문에

    제이쿼리를 이용해서 요소들이 다 생성된 이후에 바로 selectReplyList()라는 함수를 호출했습니다.

     

    $(function(){
      selectReplyList();
      setInterval(selectReplyList,1000);
      selectReviewList();
    })

     

    setInterval(selectReplyList,1000); 이 구문은 함수를 주기적으로 호출하는 기능입니다. 저는 1000으로 설정하여 1초 단위로 selectReplyList라는 함수가 실행되도록 구현했습니다. (== 1초마다 selectReplyList가 호출되어 다른 사용자가 작성한 댓글들도 실시간으로 조회될 수 있습니다. 해당 기능은 실시간 채팅에도 활용할 수 있다고 합니다. 사실 "실시간"이라는 개념이 사람마다 다르기 때문에 이 명칭은 정확하지는 않을 수 있지만, 저는 1초 단위로 설정했습니다.) 

     

    호출되는 selectReplyList함수는 아래와 같습니다.

     

    function selectReplyList(){
    
    $.ajax({
      url : "rlist.recipe",
      data : {recipeNo: "<%=rc.getRecipeNo()%>"},
      success : function(list){
    
      var result = "";
    
        for(var i in list){
          result += 
          "<br>"	+	
          "<td>"+
          "<div class='box' style='background: #BDBDBD;''>" + 
          "<img class='profile' src='" + list[i].profileImg + "'>" + 
          "</div>" +
          "</td>" + 	
          "<td>" + "<b>" + list[i].replyWriter + "</b>" + "</td>" +
          "<td>" + list[i].enrollDate + "</td>" + 
          "<td style='color: gray;'>" + "<a href='' class='report-user-btn'>" + "신고하기" + "</a>" + "</td>" + 
          "<br>" +
          "<tr class='reply-deatil-content'>" + 
          "<td colspan='3'>" + list[i].replyContent  + "</td>" + 
          "</tr>" +
          "<br>"
        } 
     	 $("#reply-content-area tbody").html(result);	
      }
      })
    }

     

     

    url은 실행시 구동되는 Servlet의 맵핑값을 적었습니다.
    data는 SQL에서 필요했던 ?recipeNo을 넘겨주었습니다. recipeNo은 레시피 상세보기 페이지에서 조회할 때 Recipe라는 객체에 recipeNo이라는 필드에 담겨있습니다.
    success에는 성공 시 호출되는 함수를 기입했습니다. result라는 비어있는 문자열을 생성하고 그 뒤에 반복문을 돌려서 list에 담긴 값들(댓글 조회 시 필요한 정보들)을 모두 조회할 예정입니다.

     

    반복문이 끝난 후 아이디가 reply-content-area의 tbody요소 안에 result를 담아줍니다.

     

     


    3. Controller

    int recipeNo = Integer.parseInt(request.getParameter("recipeNo"));
    ArrayList <Reply> list = new RecipeService().selectReplyList(recipeNo);
    
    response.setContentType("application/json;charset=utf-8");
    new Gson().toJson(list,response.getWriter());
    

    data에서 넘어온 recipeNo을 파싱해줍니다. 왜 파싱을 해주냐면, 아무리 int로 vo클래스에서 선언해도

    view에서 Controller로 값이 넘어올 때는 무조건 String 타입으로 넘어오기 때문입니다. 귀찮아도 꼭 해주면 됩니다..

    사실 안하면 빨간 줄이 떠서 안 하려야 안 할 수가 없습니다. ㅎ

     

    RecipeService에 selectReplyList로 recipeNo을 담아서 보내줍니다.

    이때 하나의 레시피에서 여러 개의 댓글이 조회될 수 있기 때문에 ArrayList <Reply>에 값을 담습니다. 

     


    4. Service

    public ArrayList<Reply> selectReplyList(int recipeNo){
    
      Connection conn = getConnection();
    
      ArrayList<Reply> list = new RecipeDao().selectReplyList(conn,recipeNo);
    
      close(conn);
    
      return list;
    
    
    }

    service단은 크게 다르지 않습니다. 생성된 Connection 객체와 recipeNo을 dao단으로 보내줍니다.

     


    5. DAO

    public ArrayList <Reply> selectReplyList(Connection conn, int recipeNo){
    		
    		ArrayList<Reply> list = new ArrayList<>();
    		PreparedStatement pstmt = null;
    		ResultSet rset = null;
    		String sql = prop.getProperty("selectReplyList");
    		try {
    			pstmt = conn.prepareStatement(sql);
    			
    			pstmt.setInt(1, recipeNo);
    			
    			rset = pstmt.executeQuery();
    			
    			while(rset.next()) {
    				list.add(new Reply(rset.getInt("REPLY_NO")
    						,rset.getString("NICKNAME")
    						,rset.getString("REPLY_CONTENT")
    						,rset.getDate("ENROLL_DATE")
    						,rset.getString("PROFILE_IMG")
    						));
    			}
    			
    		} catch (SQLException e) {
    			e.printStackTrace();
    		}finally {
    			close(rset);
    			close(pstmt);
    		}
    		return list;
    		
    	}

    조회하기는 작성하기/삭제하기/수정하기와는 구문이 다릅니다.

    ? 자리에 우리가 view단에서부터 가져온 소중한 recipeNo을 담아줍니다. 

    그리고 우리가 필요했던 정보들을 list에 차곡 차곡 담아줍니다. 

    저는 Reply의 매개변수 생성자를 이용해서 값을 담았기 때문에 Reply VO 클래스에 가서 

    조회되는 순.서.대.로 (댓글 번호, 닉네임, 댓글 내용, 작성일, 프로필 이미지 경로 순으로 ) 매개변수를 생성했습니다.

    분명 문제없이 잘 실행되는데 조회되는 결과에 생뚱맞은 값들이 보인다면 매개변수 생성자의 순서를 확인해보시면 좋을 것 같습니다.

     

    그리고 list를 Service단으로 반환했습니다.

     

     


     

    작성 수정 삭제를 좀 더 멋진 말로 얘기하고 싶다면? 

    더보기

    데이터 조작 언어, DML문(Data Manipulation Language)라고 합니다. 

    DML문(insert, update, delete == 작성, 수정 삭제)은 처리되는 행 수가 조회됩니다.

     

    DML문에 관한 내용입니다. 피드백 해주시면 수정하겠습니다.

     

    DML (DATA MANIPULATION LANGUAGE)

    데이터 조작 언어

    www.notion.so

     

     

    ResultSet에 관한 내용은 하단의 토글을 참고해주시면 감사하겠습니다.

     


     

    실행되는 결과는 다음과 같습니다. 

     

     

    728x90

    댓글