◉ 타임리프와 바닐라(순수) 자바스크립트를 활용한 Ajax 구현
▪︎ AjaxExamController.java
- 세 번째 'member 목록 요청' 클릭 시, 요청 처리 메서드 작성
// * /index.html에서 member 목록 요청 누를 경우
@GetMapping("ajax/member/all")
public String getMemberList() {
log.info("{}", "ajax/member/all 요청 중");
return "ajax/member/list";
}
▪︎ templates/member 에 list.html 생성
① 타임리프 네임스페이스 선언
<html xmlns:th="http://www.thymeleaf.org">
② body 태그 안에 Ajax 호출 버튼 및 호출 후 받아온 데이터를 이용해 테이블을 그려 줄 memberTable 작성
- <table> 태그 안에 th:fragment 속성 추가 ( 아래 개념 설명 참고 )
<body>
<h1>Member List</h1>
<button id="btnMemberList">멤버 리스트 요청</button>
<table id="memberTable" th:fragment="memberTable">
<tr>
<th>아이디</th>
<th>이름</th>
</tr>
<!-- tr 태그 사이 루프 반복 -->
<tr th:each="member : ${ memberList }">
<td th:text="${ member.key }">여기에 아이디</td>
<td th:text="${ member.value }">여기에 이름</td>
</tr>
</table>
</body>
③ script 태그 코드 → <header> 태그 안에 위치시키고, window.onload 이용
▪︎ DOM(Document Object Model)은 반드시 body 태그를 모두 읽어오고 나서 작동해야 함
- 다음 두 방식은 같은 원리로 작동함 ( 태그와 스크립트를 분리하는 2번째 방식 권장 )
1. </body> 위에 <script> 태그 위치시키기
2. window.onload 이용 - body 태그 안의 내용을 모두 읽어오면 'load' 이벤트 작동함
<script type="text/javascript">
window.onload = function(){
// * 로그 확인 - alert 이용해서 실행 여부 확인하기
//alert('window.onload 이벤트 등록')
// 바닐라 자바스크립트 순수 ajax 라이브러리인 XMLHttpRequest 이용
// ① ajax 객체 선언
let xhr;
// ② id = btnMemberList 찾아 변수 button에 저장
let button = document.getElementById("btnMemberList")
// ③ 버튼 객체 클릭 시, ajax 요청 : button의 'click' 이벤트리스너 등록
button.addEventListener('click', () => {
// ❶ xhr(ajax 객체 생성)
xhr = new XMLHttpRequest();
// ❷ ajax 객체에 상태변화이벤트(readystatechange) 등록
xhr.onreadystatechange = () => {
// xhr 객체의 준비가 모두 마쳤는지
if( xhr.readyState === xhr.DONE ){
// 서버로부터 응답이 오면
if( xhr.status === 200 ){
let table = document.getElementById('memberTable')
table.innerHTML = xhr.response;
} else {
alert('Ajax Request 에러!')
}
}
} // ❷ 상태변화 이벤트 핸들러 등록 끝 -
// ④ xhr 객체 상태변화를 위해 서버에 연결 (xhr 객체의 연결 이벤트)
xhr.open('GET', '/ajax/member/list')
// ⑤ xhr 객체 상태변화 (xhr 객체가 서버에 응답을 요청하는 이벤트)을 위해
// 서버가 응답에 필요한 요청데이터 전송
xhr.send()
}) // ③ 버튼 객체 클릭 시, ajax 요청 끝 -
}
</script>
◎ list.html 전체 코드
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script type="text/javascript">
// * DOM(Document Object Model)은 반드시 body 태그를 모두 읽어오고 나서 작동해야 함
// 다음 두 방식은 같은 원리로 작동함 ( 태그와 스크립트를 분리하는 2번째 방식 권장 )
// 1. </body> 위에 <script> 태그 위치시키기
// 2. window.onload 이용 - body 태그 안의 내용을 모두 읽어오면 'load' 이벤트 작동함
window.onload = function(){
// * 로그 확인 - alert 이용해서 실행 여부 확인하기
//alert('window.onload 이벤트 등록')
// 바닐라 자바스크립트 순수 ajax 라이브러리인 XMLHttpRequest 이용
// ① ajax 객체 선언
let xhr;
// ② id = btnMemberList 찾아 변수 button에 저장
let button = document.getElementById("btnMemberList")
// ③ 버튼 객체 클릭 시, ajax 요청 : button의 'click' 이벤트리스너 등록
button.addEventListener('click', () => {
// ❶ xhr(ajax 객체 생성)
xhr = new XMLHttpRequest();
// ❷ ajax 객체에 상태변화이벤트(readystatechange) 등록
xhr.onreadystatechange = () => {
// xhr 객체의 준비가 모두 마쳤는지
if( xhr.readyState === xhr.DONE ){
// 서버로부터 응답이 오면
if( xhr.status === 200 ){
let table = document.getElementById('memberTable')
table.innerHTML = xhr.response;
//alert(xhr.response)
} else {
alert('Ajax Request 에러!')
}
}
} // ❷ 상태변화 이벤트 핸들러 등록 끝 -
// ④ xhr 객체 상태변화를 위해 서버에 연결 (xhr 객체의 연결 이벤트)
xhr.open('GET', '/ajax/member/list')
// ⑤ xhr 객체 상태변화 (xhr 객체가 서버에 응답을 요청하는 이벤트)을 위해
// 서버가 응답에 필요한 요청데이터 전송
xhr.send()
}) // ③ 버튼 객체 클릭 시, ajax 요청 끝 -
}
</script>
</head>
<body>
<h1>Member List</h1>
<button id="btnMemberList">멤버 리스트 요청</button>
<table id="memberTable" th:fragment="memberTable">
<!-- th붙지 않았으므로, 정적인 영역 -->
<tr>
<th>아이디</th>
<th>이름</th>
</tr>
<!-- tr 태그 사이 루프 반복 -->
<tr th:each="member : ${ memberList }">
<td th:text="${ member.key }">여기에 아이디</td>
<td th:text="${ member.value }">여기에 이름</td>
</tr>
</table>
</body>
</html>
▪︎ AjaxExamController.java
: XMLHttpRequest 객체가 '/ajax/member/list'로 GET 요청 시, 처리할 메서드 작성
// * xhr.open('GET', '/ajax/member/list')
// xhr 객체가 위의 url 주소로 GET 요청했으므로, 이 요청을 처리할 메서드 작성
@GetMapping("/ajax/member/list")
public String getMembers(Model model) {
log.info("{}", "/ajax/member/list 요청 중");
// * 가상의 멤버 테이블 생성
// : Map<회원번호, 회원이름>으로 구성된 가상의 멤버리스트 생성
// → 나중에 리포지토리를 이용해 대체
Map<Integer, String> memberList = new HashMap<>();
// * 테스트용 가상의 회원 추가
memberList.put(1, "하늘");
memberList.put(10, "구름");
memberList.put(20, "바다");
memberList.put(200, "태양");
model.addAttribute("memberList", memberList);
// * 템플릿 조각에 데이터 넘기기
// 뷰템플릿 타임리프에서 html파일의 일부 영역에 접근해 그 내용을 바꾸는 방법
// → templates 파일 이름 + '::' + 데이터가 변경될 fragment id
return "ajax/member/list :: memberTable";
}
◎ 요청 흐름 및 결과
1. 홈에서 세번째 'member 목록 요청' 클릭 → AjaxExamController에서 매핑된 "ajax/member/all"로 이동
2. 이동 시, 아직 memberList 생성되지 않았기 때문에, 현재 테이블에 나올 데이터 없음
3. '멤버 리스트 요청' 버튼 클릭 → list.html의 <script> 태그 : 버튼 클릭 시 등록된 함수 실행 → 서버로 요청 데이터 전송
AjaxExamController에 의해 템플릿 조각의 데이터가 바뀐 상태의 뷰를 반환 → 아래와 같이 데이터 출력됨
◎ 타임리프 템플릿 조각
▪︎ 웹 페이지 개발 시, 여러 페이지에서 공통으로 사용하는 영역들이 존재
→ 이런 공통 영역 페이지마다 코드를 작성하게 될 경우, 코드 중복 뿐만 아니라 수정하게 될 경우, 모든 페이지를 각각 수정해주어야 한다는 불편함이 있음
∴ 이러한 문제를 해결하기 위해 템플릿 조각과 레이아웃 기능 지원함
▪︎ 타임리프 템플릿 조각
- HTML 파일에서 특정 태그의 속성에 th:fragment로 이름 지정해주면 끝
- 컨트롤러에 의해 뷰 파일 반환 시, 아래와 같이 경로만 지정해주면 됨
" 템플릿_조각_경로 :: 조각명 "
'프론트엔드 > Ajax' 카테고리의 다른 글
AJAX 실습 - POST 방식 구현 (0) | 2023.08.18 |
---|---|
AJAX 실습 - GET 방식 구현 (0) | 2023.08.18 |
AJAX (0) | 2023.08.18 |