본문 바로가기
Dev/Spring

AJAX를 이용한 댓글 처리

by vellahw 2022. 11. 7.

 

 

 

1. 테이블 설계

  • rno : 댓글 번호 - (10,0): 숫자 10자리까지, 소숫점 자리 0자리까지 들어갈 수 있다 
  • bno: 게시글 번호
  • reply :  댓글(내용)

 

  • tbl_reply 테이블의 bno는 tbl_board의 bno를 참조함 (댓글을 달려면 특정 게시물의 번호가 필요!)

 

 

 

2. 자바빈 클래스 생성

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package org.hw.domain;
 
import java.util.Date;
 
import lombok.Data;
 
@Data
public class ReplyVO {
    private Long rno;
    private Long bno;
    private String reply;
    private String replyer;
    private Date replyDate;
    private Date updateDate;
}
cs

 

 

 

3. 인터페이스 생성과 XML 처리

1
2
3
4
5
package org.hw.mapper;
 
public interface ReplyMapper {
 
}
cs

 

1
2
3
4
5
6
7
8
<?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="org.hw.mapper.ReplyMapper">
 
</mapper>
cs

 

tbl_reply가 tbl_board 테이블의  bno 값과 정확히 일치해야 하므로 bno 몇 개를 확인해두는 작업

 

 

 

4. 테스트 클래스 작성

 1) ReplyMapper 객체를 정상적으로 사용 가능한지 확인하는 테스트

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package org.hw.mapper;
 
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
 
import lombok.Setter;
import lombok.extern.log4j.Log4j;
 
@RunWith(SpringRunner.class)
@ContextConfiguration("file:src/main/webapp/WEB-INF/spring/root-context.xml")
@Log4j
public class ReplyMapperTest {
    
    @Setter(onMethod_ = @Autowired)
    private ReplyMapper mapper;
    
    @Test
    public void testMapper() {
        log.info(mapper);
    }
}
 
cs

정상 작동 확인!

 

 

 

5. CRUD 작업

 1) 등록 (create)

1
2
3
4
5
6
7
8
9
package org.hw.mapper;
 
import org.hw.domain.ReplyVO;
 
public interface ReplyMapper {
    
    public int insert(ReplyVO vo);
 
}
cs

 ▲ ReplyMapper 인터페이스

 

 

1
2
3
4
5
6
7
8
9
10
11
12
<?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="org.hw.mapper.ReplyMapper">
    
    <insert id="insert">
        insert into tbl_reply (rno, bno, reply, replyer)
        values (seq_reply.nextval, #{bno}, #{reply}, #{replyer})
    </insert>
</mapper>
cs

 ▲ ReplyMapper.xml

 

✨ 테스트 코드 작성 

ReplyMapperTest에 댓글 등록 코드 추가

 

 

✨ 실행 결과

로그 확인

 

실제 DB 확인 - 댓글 정상적으로 입력 됨

 

 

 2) 조회 (read)

 ▲ ReplyMapper 인터페이스

 

 ▲ ReplyMapper.xml

 

✨ 테스트 코드 작성 

ReplyMapperTest에 추가한 테스트 코드와 결과

 

 

3) 삭제 (delete)

 ▲ ReplyMapper 인터페이스

 

 ▲ ReplyMapper.xml

 

✨ 테스트 코드 작성 

ReplyMapperTest에 추가한 테스트 코드

 

✨ 실행 결과

로그 확인

 

실제 DB에서 14번 댓글이 삭제됨을 확인

 

 

 

4) 수정 (update)

  • 댓글의 내용과 updateDate를 수정함

 

 ▲ ReplyMapper 인터페이스

 

 ▲ ReplyMapper.xml

 

✨ 테스트 코드 작성 

ReplyMapperTest에 추가한 테스트 코드

 

✨ 실행 결과

수정전 댓글번호 13번 데이터

 

정상적으로 수정 됨을 확인

 

로그에도 update count가 찍힘

 

 

 

6. 특정 게시글의 댓글 가져오기 - @Param 어노테이션 사용

특정한 게시물의 댓글들만을 가져오기 위해선 추가로 게시물의 번호가 필요하다.

MyBatis의 두 개 이상의 데이터를 파라미터로 전달하기 위한 방식으로는 별도의 객체로 구성,  Map을 이용하는 방식, @Param을 이용해서 이름을 사용하는 방식이 있는데 @Param을 이용해서 게시글의 댓글을 가져오는 작업을 진행함.

@Param 의 속성값은 MyBatis에서 SQL을 이용할 때 ' #{ } ' 의 이름으로 사용 가능

 

  • 페이징 처리는 기존과 동일하게 Criteria 이용
  • 추가적으로 해당 게시물의 번호는 파라미터를 전달하도록 ReplyMapper 구성하기

 

 ▲ ReplyMapper 인터페이스

  • cri 라는 이름으로 Criteria 객체 저장
  • bno라는 이름으로 bno 저장

 

 ▲ ReplyMapper.xml

 

 

✨ 테스트 코드 작성 

(위에서 만들어둔 배열)

 

✨ 실행 결과

로그 확인 - 글번호 77846의 댓글들을 가져옴

 

DB 실제 데이터 확인

 

 

 

7. 서비스 영역과 Controller 처리

 7-1) 서비스 인터페이스

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package org.hw.service;
 
import java.util.List;
 
import org.hw.domain.Criteria;
import org.hw.domain.ReplyVO;
 
public interface ReplyService {
    
    //등록
    public int register(ReplyVO vo);
    
    //조회
    public ReplyVO get(Long rno);
    
    //수정
    public int modify(ReplyVO vo);
    
    //삭제
    public int remove(Long rno);
    
    //특정 게시글의 댓글 리스트 가져오기
    public List<ReplyVO> getList(Criteria cri, Long bno);
}
 
cs

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
package org.hw.service;
 
import java.util.List;
 
import org.hw.domain.Criteria;
import org.hw.domain.ReplyVO;
import org.hw.mapper.ReplyMapper;
//import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
 
import lombok.AllArgsConstructor;
//import lombok.Setter;
import lombok.extern.log4j.Log4j;
 
@Service
@Log4j
@AllArgsConstructor
public class ReplyServiceImpl implements ReplyService {
 
    //@Setter(onMethod_ = @Autowired)
    //스프링 5 사용으로 인한 @AllArgsConstructor: 생성자와 자동주입
    private ReplyMapper mapper;
    
    @Override
    public int register(ReplyVO vo) {
        
        log.info("register!!!!! " + vo);
        
        return mapper.insert(vo);
    }
 
    @Override
    public ReplyVO get(Long rno) {
        
        log.info("get!!!!! " + rno);
        
        return mapper.read(rno);
    }
 
    @Override
    public int modify(ReplyVO vo) {
        
        log.info("modify!!!!! " + vo);
        
        return mapper.update(vo);
    }
 
    @Override
    public int remove(Long rno) {
        
        log.info("remove!!!!! " + rno);
        
        return mapper.delete(rno);
    }
 
    @Override
    public List<ReplyVO> getList(Criteria cri, Long bno) {
 
        log.info("get Reply List of a Board " + bno);
        
        return mapper.getListWithPaging(cri, bno);
    }
}
 
cs
  • 스프링 4.3 이상부터 @Setter (onMethod_ = @Autowired 대신 @AllArgsConstructor 어노테이션을 이용하여 생성자와 자동주입을 이용 할 수 있다.

 

 

 7-2) 컨트롤러 설계

  • @RestController 어노테이션을 이용해 설계
  •  다음과 같은 URL을 기준으로 동작 할 수 있게 함
작업  URL HTTP 전송 방식
등록 /replies/new POST
조회 /replies/:rno GET
삭제 /replies/:rno DELETE
수정 /replies/:rno PUT & PATHCH
페이지 /replies/pages/:bno/:page GET
  • 똑같은 URL에 전송 방식만 다르게 설계
  • REST 방식으로 동작하는 URL을 설계할 때는 PK만으로 조회, 수정, 삭제가 가능하기 때문에 PK를 기준으로 작성하는 것이 좋다.
  • 댓글의 목록은 PK를 사용할 수 없기 때문에 파라미터로 필요한 게시물의 번호(bno)와 페이지 번호(page) 정보들을  URL에서 사용하는 방식 사용

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package org.hw.controller;
 
import java.util.List;
 
import org.hw.domain.Criteria;
import org.hw.domain.ReplyVO;
import org.hw.service.ReplyServiceImpl;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
 
import lombok.AllArgsConstructor;
import lombok.extern.log4j.Log4j;
 
@RequestMapping("/replies/")
@RestController
@Log4j
@AllArgsConstructor
public class ReplyController {
    
    //ReplyServiceImpl 객체 주입
    private ReplyServiceImpl service;
}
cs

 

 

 7-2-1) 댓글 등록 작업과 테스트

ReplyController에 코드 추가

  • consumes = json 타입을 받음
  • produces = text로 만듦

 

✨ 테스트 (Yet Another REST Client 사용)

bno, reply, replyer 값을 입력 하여 전송

 

전송 결과

 

로그 확인!

 

작성한 댓글이 데이터베이스에도 정상적으로 추가됨

 

 

 7-2-2) 특정 게시물의 댓글 목록 확인

ReplyController에 코드 추가

 

✨ 테스트

 글번호 77846의 1 페이지에 있는 댓글들 요청

 

 

데이터베이스와 똑같은 결과 확인

 

로그 확인

 

 

 7-2-3) 댓글 조회와 삭제

ReplyController에 코드 추가

 

✨ 테스트

 1) 댓글 조회

 댓글번호 25번 댓글 조회

 

 결과

 

데이터 베이스의 동일한 결과 확인

 

2) 댓글 삭제

요청

 

25번 댓글 삭제 확인

 

💡 존재하지 않는 rno 값을 전송하면 500 오류 발생함

 

 

 7-2-3) 댓글 수정

ReplyController에 코드 추가

 

✨ 테스트

9번 댓글 수정 요청

 

결과

 

로그 확인

 

 

 

댓글