Spring-Boot,JPA로 질문/답변 게시판 구현(33)
Spring-Boot, JPA로 질문/잡변 게시판 구현 및 배포
자바지기님 유튜브 강의 정리
6-1. AJAX를 활용한 답변 추가 1
-
질문 상세보기에서 답변을 달았을 때, 추가되는 부분을 AJAX를 활용하여 구현 해볼 것이다.
-
실제로 구현해야 하는 부분이 답변하기 버튼을 클릭을 하면, 서버로 데이터가 전송이되는데 이 기능을 막은 다음에 ajax라는 기술을 통해서 서버에 전송하는 식으로 구현을 해야한다.
-
show.html에 보면 댓글부분을 구현할 자바스크립트 영역은 footer.html에 포함되어있다. 그 중 jquery와 bootstrap은 외부 라이브러리고, scripts.js를 가지고 ajax를 구현해볼 것이다.
-
답변하기 버튼을 클릭했을 때 서버로 데이터를 바로 전송하지 않도록 먼저 구현해보자.
$(".answer-write input[type=submit]").click(addAnswer); function addAnswer(e) { console.log("click me"); e.preventDefault(); var queryString = $(".answer-write").serialize(); console.log("query : " + queryString); var url = $(".answer-write").attr("action"); console.log("url : " + url); $.ajax({ type : 'post', url : url, data : queryString, dataType : 'json', error : onError; success : onSuccess}); } function onError() { } function onSuccess() { }
- 기존에 작성되어있는 코드를 삭제하고 다시작성한것이다.
- html의 class는 .으로 표현한다.
answer-write
라는 클래스를 가진 태그의 input type=submit이라는 자식 태그를 클릭 했을때, addAnswer라는 function을 호출한다. - 콘솔의 로그는 크롬 개발자도구의 console에서 확인할 수 있다.
- addAnswer에 대한 function을 만든다.
- 우선 submit을 했을 때 서버로 데이터로 보내는 default기능을 preventDefault()로 막는다.
- serialize()라는 function을 통해
answer-write
의 textarea태그의 name=”contents”데이터를 가져올 수 있다. - jquery의 ajax라는 function을 이용해서 서버에 데이터를 전송한다.
- type - http method에 해당하는데 post방식이므로 post
- url은 html의 form태그의 action에 해당하는 url을 가져갈 것이다. 따라서 url을 따로
$(".answer-write").attr("action")
으로 추출한다. - data타입은 json, xml 등 있는데 json으로 선택한다.
- 응답 결과가 error라면 onError, success라면 onSuccess function을 호출한다.
-
자바스크립트에 대한 show.html도 수정한다.
<!-- show.html --> ... <form class="answer-write" ... action="/api/questions//answers"> </form>
-
자바스크립트에 대한 AnswerController를 수정해보자. 기존에 AnswerController를 사용하지 않고 json을 이용하여 데이터를 전달한다.
@RestController @RequestMapping("/api/questions/{questionId}/answers") public class ApiAnswerController { ... @PostMapping("") public Answer create(@PathVariable Long questionId, String, contents, HttpSession session) { if (!HttpSessionUtils.isLoginUse(session)) { return null; } Uesr loginUser = HttpSessionUtils.getUserFromSession(session); Question question = questionRepository.findOne(questionId); Answer answer = new Answer(loginUser, question, contents); return answerRepository.save(answer); } }
- 우리가 응답할 데이터는 Answer 데이터베이스에추가되어있는 answer정보를 클라이언트에 받고싶은것이다. 데이터베이스에 저장되기전에는 데이터베이스의 id가 null인 상태인데 데이터베이스에 저장되면 id값이 부여가되고 결과물이 생성된다. 그 데이터를 받기위해 String 대신 Answer사용했다.
- save메서드를 보면 리턴값이 인자로 전달한 answer를 그대로 리턴한다.
- Spring MVC가 컨트롤러에 해당하는 메서드를 바로 알아서 json으로 변환을 해주는것은 아니다. 그렇게 하도록 하려면 @Controller대신에 @RestController를 사용해야하한다.
-
테스트
- 테스트 할 때 console을 확인해보면 데이터와 url이 제대로 전달된것을 확인할 수 있다. 여기서 새로고침(F5)를 누르면 실제로 댓글등록도 되어있다.
여기까지 테스트
-
서버작업까지 끝냈으니 클라이언트 작업을 해야한다. 응답(response)로 받은 answer데이터를 추가되는 부분만 다시 html을 만들어 그려줄 필요가있다. 구현해보자.
//scripts.js ... function onSuccess(data, status) { console.log(data); }
-
data는 answer, status는 200 등 http 상태코드
-
콘솔로 확인해 보니, 다른 데이터는 안보이는데 formattedCreateDate field만 가지고있다. 다른 field는 getter메서드가 없어서 그런것이다. getter메서드를 사용하면된다.
-
그건 다음시간에 다음 post에 다룬다..
-
:raising_hand_man:여기 테스트하는데 나는 계속 Error가 나온다 왜그런지 모르겠다.
-
:raising_hand_man: Success대신 Error에 data를 인수로하여
console.log(data)
를 작성하여 크롬 console에서 확인해보았다. Error에대한 메세지가 떴는데 자세히 보니 json형태로 변환은 되었는데 parseerror이 발생하여 error이 발생한것이었다.- responseText가 json형태이고, status도 200인데 parsererror가 발생했다.
- responseText를 더 보니 무한루프가 발생하고 있었다.
-
:raising_hand_man: 구글에
ajax parsererror json
이라고 검색해보니 양방향 매핑을 맺은 필드에 대한 어노테이션을 추가해주어야 한다고 한다. Question 클래스와 Answer 클래스를 보면 서로 one-to-many, many-to-one 어노테이션을 붙여 매핑해주었다. Question 클래스의 Answer 객체에@JsonManagedReference
를 붙여주고, Answer 클래스의 Question 객체에@JsonBackReference
를 붙여준다.public class Question { ... @JsonManagedReference @OneToMany(mappedBy = "question") @OrderBy("id ASC") private List<Answer> answers; ... } //서로 다른 java파일 public class Answer { ... @JsonBackReference @ManyToOne @JoinColumn(foreignKey = @ForeignKey(name = "fk_answer_to_question")) @JsonProperty private Question question; }
@JsonManagedRefernce
는 참조가 되는 앞부분을 의미하며, 정상적으로 직렬화를 수행한다.@JsonBackReference
는 참조가 되는 뒷부분을 의미하며, 직렬화를 수행하지 않는다.- https://www.baeldung.com/jackson-bidirectional-relationships-and-infinite-recursion
-
🙋♂️다시 콘솔로 확인해보니 제대로 출력되었다.
-
댓글남기기