1. 요구사항

  • 매거진 게시글에는 댓글 리스트가 출력되어있다.
  • 각 댓글의 오른쪽 끝단에는 '...' 으로 되어있는 버튼이 있는데 이걸 통해(Modal) 댓글을 삭제한다.
  • 댓글을 삭제할 때 자기가 작성했던 댓글만 위의 버튼이 뜨게 한다. 또한 삭제도 이러한 과정이 이루어져야 한다.

 

2. 해결책

  • 댓글 리스트에 있는 mbr_id와 로그인해서 가져온 mbr_id를 JSTL의 choose 기능을 이용해 서로 비교하여 분기에 따라 UI를 다르게 보이게 한다

 

3. 소스코드

3-1. SecurityConfig

http.authorizeRequests() //
    .antMatchers("/admin").hasAuthority("ADMIN") // admin/** 경로는 권한 1(=ADMIN) 회원만 접속 가능
    .antMatchers("/admin/**").hasAuthority("ADMIN") //
    .antMatchers("/seller").hasAnyAuthority("ADMIN", "SELLER") // seller/** 경로는 권한 2(=seller) 회원만 접속 가능
    .antMatchers("/seller/**").hasAnyAuthority("ADMIN", "SELLER") //
    .antMatchers("/member").hasAnyAuthority("ADMIN", "MEMBER") // member/** 경로는 권한 3(=member) 회원만 접속 가능
    .antMatchers("/member/**").hasAnyAuthority("ADMIN", "MEMBER") //
    .antMatchers("/").permitAll()//
    .antMatchers("/**").permitAll() //
    .and().formLogin() //
    .loginPage("/login").permitAll() //
    .usernameParameter("mbr_id") // 로그인시 username을 mbr_id로 받아옴
    .passwordParameter("mbr_pw") // 로그인시 password를 mbr_pw 받아옴
    .defaultSuccessUrl("/").successHandler(customSuccessHandler) // 성공시 수행할 핸들러 로그인 전 페이지 반환
    .failureHandler(customFailureHandler) // 실패 핸들러 login page에 오류 메세지 반환
    .and()// oauth2userservice 타입으로 받아오기
    .logout().logoutUrl("/logoutsuccess") // 로그아웃 처리
    .logoutSuccessUrl("/main") // 로그아웃 성공 시 이동 페이지
    .invalidateHttpSession(true) // 로그아웃 시 세션 제거
    .deleteCookies("remember-me") // 자동 로그인 쿠키, Tomcat이 발급한 세션 유지 쿠키 삭제
    .and().exceptionHandling() // 권한 없을 경우 접근거부
    .accessDeniedPage("/denied") //
    .and().oauth2Login().loginPage("/login") // 소셜로그인 처리
    .userInfoEndpoint() //
    .userService(principalOauth2UserService);

 

3-2. BoardController.java

// 매거진 게시글
@GetMapping("/board/magazine/{board_id}")
public ModelAndView magazineContent(@AuthenticationPrincipal MemberDetails memberDetails, MbrVO mbrVO, BoardVO boardVO,
            MagazineCommentCriteria cri, ModelAndView mav) {
    log.info("magazineContent...");
    mav.setViewName("board/magazine_content");

    // MemberDetails이 null일 때 ModelAndView에 addObject를 하면 예외처리가 된다
    // 따라서 null일 때(로그인 상태가 아닐때) 해당 정보를 addObject 하지 않고 페이지를 출력한다
    if (memberDetails != null) {
        // 인증 회원 정보
        MbrVO getMbr = securityService.getMbr(memberDetails.getUserID());
        // 회원 정보 받아오기
        mav.addObject("mbr", getMbr);
    }

    // 매거진 내용
    mav.addObject("magazine_content", boardService.getMagazineContent(boardVO.getBoard_id()));
    // 매거진 댓글 수 불러오기
    mav.addObject("magazine_comment_cnt", boardService.getMagazineCommentCnt(boardVO.getBoard_id()));
    // 페이징을 적용한 매거진 댓글 불러오기
    mav.addObject("magazine_comment", boardService.getMagazineComment(mbrVO.getMbr_id(), boardVO.getBoard_id(), cri));

    int total = boardService.getMagazineCommentTotal(cri);
    log.info("total" + total);
    mav.addObject("pageMaker", new MagazineCommentPageVO(cri, total));

    return mav;
}

 

3-3. magazine_content.jsp (코드 간소화)

<!-- 댓글 리스트 -->
<c:choose>
    <%-- 댓글 작성자가 로그인 한 회원과 일치하지 않을 때 --%> 
    <c:when test="${mbr.mbr_id ne comment.mbr_id}">
        <button type="button" disabled>
            ...
        </button>  
    </c:when>
    <%-- 댓글 작성자가 로그인 한 회원과 일치 할 때 --%> 
    <c:otherwise>
        <%-- 모달을 열기 위한 버튼 --%> 
        <button type="button" class="btn btn-primary" data-toggle="modal" data-target="#mdal${comment.comment_id}">
            ...
        </button>
        <%-- 모달 영역 --%> 
        <div class="modal fade myModal" id="mdal${comment.comment_id}" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
        <div class="modal-dialog" role="document">
            <div class="modal-content">
                <div class="modal-header">
                    <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&#88;</span></button>
                </div>
                <div class="modal-body">
                    <p class="lead" align="left">${comment.comment_content}</p>
                </div>
                <div class="modal-footer">
                    <div align="left">
                        <button type="button" data-rno="${comment.comment_id}">
                            삭제하기
                        </button>
                        <%-- 매거진 댓글 삭제 --%>
                        <script type="text/javascript">
                            $(document).ready(function (){
                                $('.cmnt_del').click(function(event){
                                    event.preventDefault();                        
                                    // FormData 객체 생성
                                    var formData = new FormData(); 

                                    // button의 data-rno 값을 가져온다
                                    var cmntInfo = $(this).attr("data-rno");        
                                    console.log("cmntInfo: " + cmntInfo);

                                    // formData에 해당 값을 append한다
                                    formData.append("comment_id", cmntInfo);
                                    console.log("formData: " + formData);

                                    $.ajax({
                                        type : 'DELETE', 
                                        url : $(this).attr("href"), 
                                        cache : false, 
                                        processData: false, 
                                        contentType: false, 
                                        data: formData, 
                                        success: function(result){
                                            console.log(result);
                                            $(location).attr('href', '${pageContext.request.contextPath}/board/magazine/${magazine_content.board_id}')
                                            console.log("COMMENT_REMOVED!")
                                        },
                                        error:function(e){
                                            console.log(e);
                                        }
                                    })
                                });    
                            });    
                        </script>
                    </div>
                </div>
            </div>
        </div>
    </div>
    </c:otherwise>
</c:choose>