[Spring] 자바스크립트 - AJAX 통신을 활용한 CSR(Client Side Rendering)

Feb 29, 2024
[Spring] 자바스크립트 - AJAX 통신을 활용한 CSR(Client Side Rendering)
 
💡
CSR(Client Side Rendering)은 사용자의 브라우저 측에서 모든 렌더링 작업을 처리하는 방식을 의미한다. 서버에서 렌더링을 처리해서 전송하는 SSR 방식과는 달리, CSR 방식은 최소한의 HTML 틀만을 클라이언트에게 보내고, 나머지 데이터를 비동기적으로 받아와 렌더링한다. CSR은 필요한 부분만을 업데이트하므로 서버 부하가 줄어들고 UX가 증가한다.
 
 

1. HTML 틀 출력

 
더미데이터
insert into board_tb(title, content, author) values('제목1', '내용1', '홍길동'); insert into board_tb(title, content, author) values('제목2', '내용2', '홍길동'); insert into board_tb(title, content, author) values('제목3', '내용3', '장보고'); insert into board_tb(title, content, author) values('제목4', '내용4', '장보고'); insert into board_tb(title, content, author) values('제목5', '내용5', '장보고'); insert into board_tb(title, content, author) values('제목6', '내용6', '장보고'); insert into board_tb(title, content, author) values('제목7', '내용7', '임꺽정'); insert into board_tb(title, content, author) values('제목8', '내용8', '임꺽정');
 
 
HTML 기본 틀
<div class="container p-5"> <table class="table table-striped"> <thead> <tr> <th>번호</th> <th>제목</th> <th>내용</th> <th>작성자</th> <th></th> </tr> </thead> <tbody> </tbody> </table> </div>
 
페이지가 시작되면 아래의 화면만 뜸. 데이터는 자바스크립트로 받아서 브라우저에서 표시한다.
실제 데이터는 서버와의 통신을 통해 받는다.
 
 
<tr> <td>1</td> <td>제목1</td> <td>내용1</td> <td>홍길동</td> <td> <div class="d-flex"> <form action="#"> <button class="btn btn-danger">삭제</button> </form> <form action="/board/1/updateForm" method="get"> <button class="btn btn-warning">수정</button> </form> </div> </td> </tr>
 
서버를 통해 받을 데이터이다. 추후에 자바스크립트 내부로 넣는다.
 
 
notion image
 
서버에서 그림만 받아 그린다. 실제 데이터는 서버와 한 번 더 통신 후 받는다.
 
 

2. AJAX 통신으로 데이터 받아오기

 
💡
데이터를 받기 위한 통신을 한 번 더 수행한다. HTTP 통신과의 구분을 위해 Api 통신이라고 정한다.
 
ApiUtil<T>
package shop.mtcoding.blog.board; import lombok.AllArgsConstructor; import lombok.Data; // 응답받은 상태와 데이터를 받음 @Data public class ApiUtil<T> { private Integer status ; //200,400,404,405 private String msg ; // 성공, 실패 -> 메세지 성공시에는 메세지 필요없음 private T body ; // 타입이 정해져있지 않아 new 때 타입을 정하는 T로 정함 //통신이 성공했을 때 public ApiUtil(T body) { this.status = 200; this.msg ="성공"; this.body = body; } //통신이 실패했을 때 public ApiUtil(Integer status, String msg) { this.status = status; this.msg = msg; this.body=null; // 실패 시에는 메세지와 상태코드만 필요하기 때문에 바디 데이터는 필요없다. } }
 
ApiUtil 클래스를 생성한다. ApiUtil은 api 통신의 성공 실패 여부를 받는다. 성공 시에는 상태 코드 200을 응답해주면 되고, 실패 시에는 바디에 상태 코드와 메세지를 담아주어야 한다.
 
💡
<T> 는 제네릭 타입으로 바디 데이터에 어떤 데이터가 모를 때 사용한다. 제네릭은 타입을 컴파일 시에 동적으로 정할 수 있다.
 
BoardApiController
@RequiredArgsConstructor @RestController public class BoardApiController { private final BoardRepository boardRepository; @GetMapping("/api/boards") public ApiUtil<?> findAll(HttpServletResponse response) { //response.setStatus(200); List<Board> boardList = boardRepository.selectAll(); return new ApiUtil<>(boardList); // MessageConverter }
notion image
 
접속 시 통신 성공과 함께 데이터가
 
http://localhost:8080/api/boards 입력
notion image
 
💡
상태 코드가 헤더에 있더라도, 실패 시 실패 사유를 알아야 하기 때문에 바디 데이터에 상태와 메세지를 담아야 한다.
 

3. 데이터 화면에 출력하기

 
제이쿼리를 이용한 AJAX 통신 요청 기본 문법
$.ajax({ }).done((res)=>{ }).fail((res)=>{ });
 
 
{{> layout/header}} <div class="container p-5"> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css"> <table class="table table-striped"> <thead> <tr> <th>번호</th> <th>제목</th> <th>내용</th> <th>작성자</th> <th></th> </tr> </thead> <tbody id="board-box"> </tbody> </table> </div> <script> $.ajax({ url: "/api/boards", type: "get" }).done((res) => { console.log("통신 성공"); console.log(res); // 통신이 성공하면 res에 있는 값을 화면에 뿌려야 해. let boardList = res.body; // 통신 성공했을 때 바디 값을 받아서 boardList.forEach((board) => { $("#board-box").append(render(board)); }) // 반복문 돌림 }).fail((res) => { // console.log("통신 실패"); // console.log(res); // 콘솔.로그를 찍어서 res에 뭐가 들어있는지 확인해보자. alert(res.responseJSON.msg); // 로그인이 되지 않았다면? 로그인폼을 보여줘야 하잖아. location.href = "/loginForm"; }); // 200 떨어지면 done, 200이 아니면 fail로 감. 첫 번째 res는 바디데이터, 두 번째 res는 에러메시지 function render(board) { return `<tr id="board-${board.id}"> <td>${board.id}</td> <td>${board.title}</td> <td>${board.content}</td> <td>${board.author}</td> <td> <div class="d-flex"> <button onclick = "del(${board.id})" class="btn btn-danger">삭제</button> <form action="/board/${board.id}/updateForm" method="get"> <button class="btn btn-warning">수정</button> </form> </div> </td> </tr> `; } </script> {{> layout/footer}}
 
notion image
Share article

{CODE-RYU};