[Thymeleaf] ajax를 이용해 비동기식 화면 수정

Spring + Thymeleaf + Ajax - POST

Posted by ChaelinJ on April 14, 2021

Ajax로 비동기 화면 수정

스프링 부트 프로젝트가 전체 동기식이라 부분 부분 비동기식으로 고치는 중이었습니다.

우선 댓글 작성의 경우입니다. 댓글 작성할 때마다 화면을 reload하면 불편하고 수행 능력이 떨어지기 때문에 이 부분을 수정하고자 했습니다.

  • 댓글 작성: ajax로 POST
  • 댓글 작성 후: 새로 댓글 리스트를 controller에서 받아와 화면 수정

Ajax란?

Asynchronos Javascript And XML의 약자로 비동기식으로 서버와 통신하는 방식을 의미합니다.

환경

  • Spring Boot
  • Thymeleaf
  • ajax

Spring Boot에서 Ajax로 통신하기 (Thymeleaf)

view - 댓글 작성 부분

hidden의 내용과 작성된 내용을 ajax로 보내서 controller 갑니다.

view - 댓글 출력 부분

서버에서 댓글 리스트를 받아와서 th:each로 각각을 출력하는 코드입니다.

  • 저는 commentTable의 내부에서 이용되는 값들을 ajax로 가져올겁니다.
    • commentList
    • userInform
    • 이 부분은 controller에서 넣어줄 겁니다.

ajax

각각의 value를 가져오는 방법은 더 다양하지만 일단은 id로 value를 가져오는 방법으로 했습니다.

  • $.ajax로 url과 data, type을 지정합니다.
    • 여기서 url, type은 연결을 원하는 controller과 동일해야 합니다.
  • .done에서 값을 받아와 replaceWith로 값을 바꿔줄겁니다. 비동기식으로 변환되는 부분입니다.
    • 변환되는 값을 출력할 부분의 id를 가져옵니다.
    • 저의 경우, 위의 view에서 확인할 수 있듯이 commentTable입니다.

Controller

CSS와 기타 멤버 필드는 생략하고 가져왔습니다.

  • RequestMapping: 위에 ajax에서 입력했던 url, type과 같아야 합니다.
  • Model: View로 전달할 데이터를 저장합니다.
    • 위에서 보이듯이 addAttribute로 저장합니다.
    • view에서 사용할 commentList와 userInform을 저장해줍니다.
  • RequestParam: HTTP 요청 파라미터를 메소드 파라미터에 넣어주는 어노테이션
    • $.ajax에서 작성해서 보낸 data를 받습니다.
  • 추가적으로 ResponseBody 어노테이션은 쓰지 않습니다!
    • 저는 썼다가 return 값의 String이 고대로 출력되는 일을 겪었습니다.
@RequestMapping
  • DefaultAnnotationHandlerMapping에서 Controller를 선택할 때 사용되는 어노테이션입니다.
  • 어떤 Controller, 어떤 메소드가 요청을 처리할 지 매핑을 위한 어노테이션 입니다.
  • url당 하나의 Controller에 매핑되던 다른 핸들러 매핑과 달리 메서드 단위까지 세분화하여 적용할 수 있으며, url 뿐 아니라 파라미터, 헤더 등 더욱 넓은 범위를 적용할 수 있습니다.
@RequsetBody

서버에서 클라이언트로 응답 데이터를 전송하기 위해서 @ResponseBody 를 사용하여 자바 객체를 HTTP 응답 본문의 객체로 변환하여 클라이언트로 전송시키는 역할을 합니다.

작동

이제 view에서 버튼을 만들어 onclick으로 ajax 메소드를 호출합니다.

그럼 다음처럼 commentList가 비동기식으로 갱신됩니다.

추가) form value 받아오기

위에선 각각 id로 받아왔는데 serialize로 받아올 수도 있습니다.

var commentBean = $("#commentForm").serialize();

위처럼 form의 id를 이용해 serialize할 수 있습니다.

각각 input에 name를 제대로 지정해야 오류 없이 수행할 수 있습니다.

<input type="hidden" name="EMAIL" th:value="${userInform.userEmail}">
<input type="hidden" name="POST_NUM" th:value="${resultMap.POST_NUM}">
<input type="hidden" name="CATEGORY_NAME" th:value="${resultMap.CATEGORY_NAME}">

위처럼 있다고 할 때, serialize하면 다음처럼 됩니다.

EMAIL=cofls749%40naver.com&POST_NUM=1&CATEGORY_NAME=free

name에 유의해주시고, controller에서도 이대로 보내지니 controller에서도 유의해서 오류 없이 진행하면 됩니다.


참조

감사합니다.

Text by Chaelin. Photographs by Chaelin, Unsplash.