[JS] 11. CSR(Client-Side-Rendering)

최재원's avatar
Apr 03, 2025
[JS] 11. CSR(Client-Side-Rendering)

1. 메인 페이지 렌더링

notion image
코드
{{> layout/header}} <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 id="board-box"> </tbody> </table> </div> <script> // 책임: 컴포넌트 생성 function makeBoard(board) { let tr = document.createElement("tr"); tr.innerHTML = ` <td>${board.id}</td> <td>${board.title}</td> <td>${board.content}</td> <td>${board.author}</td> <td> <div class="d-flex"> <form action="#"> <button class="btn btn-danger" onclick="delBoard(${board.id})">삭제</button> </form> <form action="/board/${board.id}/updateForm" method="get"> <button class="btn btn-warning">수정</button> </form> </div> </td> `; return tr; } // 책임: 통신 async function init() { let response = await fetch("/api/boards"); let responseBody = await response.json(); let boardList = responseBody.body; // console.log(boardList); let boardBox = document.querySelector("#board-box"); boardList.forEach((board) => { boardBox.append(makeBoard(board)); }); } init(); </script> {{> layout/footer}}

2. 수정 페이지 렌더링

notion image
notion image
코드
{{> layout/header}} <div class="container p-5"> <div class="card"> <div class="card-header"><b>익명 글수정 화면입니다</b></div> <div class="card-body"> <form action="#"> <input type="hidden" id="boardId" value="{{boardId}}"/> <div class="mb-3"> <input type="text" class="form-control" placeholder="Enter author" id="author"> </div> <div class="mb-3"> <input type="text" class="form-control" placeholder="Enter title" id="title"> </div> <div class="mb-3"> <textarea class="form-control" rows="5" id="content"></textarea> </div> <button type="submit" class="btn btn-primary form-control">글수정완료</button> </form> </div> </div> </div> <script> let boardId = document.querySelector("#boardId").value; // html에 있는 id가져오는 방법 let boardId2 = getCookie("boardId"); // 쿠키에서 id가져오는 방법 function getCookie(key) { const cookies = document.cookie.split('; '); for (let cookie of cookies) { const [k, v] = cookie.split('='); if (k === key) { return v; } } return null; // 해당 키가 없으면 null 반환 } // 책임: 통신 async function init() { let response = await fetch("/api/boards/" + boardId); let responseBody = await response.json(); document.querySelector("#author").value = responseBody.body.author; document.querySelector("#title").value = responseBody.body.title; document.querySelector("#content").value = responseBody.body.content; } init(); </script> {{> layout/footer}}
수정 페이지를 렌더링 하기 위해선 이 페이지의 id값이 필요하다
id를 가져오는 방법은 2가지가 있다
  1. HTML 안에 숨은 input 태그를 만들고 거기에 id를 넣어 보내는 것 (서버가 input에 id를 넣어줌)
  1. 쿠키에 있는 값을 읽어서 사용 (서버가 쿠키에 id를 넣어줌)
    1. 자바스크립트로 쿠키의 값을 읽는 방식은 보안에 위험함으로 httpOnly를 사용해 자바스크립트에서 접근하지 못하게 막음
      1. notion image
        httpOnly는 http프로토콜에 의한 쿠키 읽음만 가능함. 브라우저와 서버만 접근 가능

서버에서 쿠키를 주는 방법

@GetMapping("/board/{id}/updateForm") public String updateForm( @PathVariable int id, HttpServletRequest request, HttpServletResponse response) { request.setAttribute("boardId", id); Cookie cookie = new Cookie("boardId", id + ""); cookie.setHttpOnly(true); // http프로토콜 전용으로 사용해라 js가 접근 불가, 브라우저의 통신에서만 접근 허용 response.addCookie(cookie); return "board/updateForm"; }

3. post로 데이터 insert하기

notion image
notion image
코드
{{> layout/header}} <div class="container p-5"> <div class="card"> <div class="card-header"><b>익명 글쓰기 화면입니다</b></div> <div class="card-body"> <form action="#"> <div class="mb-3"> <input type="text" class="form-control" placeholder="Enter author" id="author"> </div> <div class="mb-3"> <input type="text" class="form-control" placeholder="Enter title" id="title"> </div> <div class="mb-3"> <textarea class="form-control" rows="5" id="content"></textarea> </div> <button type="button" onclick="writeBoard()" class="btn btn-primary form-control">글쓰기완료</button> </form> </div> </div> </div> <script> // 아래 함수 작성하기 전에, // 1. button -> type button으로!! // 2. input name을 id로 변경하기 async function writeBoard() { // 1. id 값 찾아서 requestBody 오브젝트에 넣기 let requestBody = { title: document.querySelector("#title").value, content: document.querySelector("#content").value, author: document.querySelector("#author").value } // 2. fetch post 요청하기 let response = await fetch("/api/boards", { method: "post", headers: { "Content-Type": "application/json" }, body: JSON.stringify(requestBody) }) let responseBody = await response.json(); console.log(responseBody); // 3. 마지막에 아래 코드로 페이지 이동하기 location.href = "/"; } </script> {{> layout/footer}}

4. put으로 update하기

notion image
notion image
notion image
코드
{{> layout/header}} <div class="container p-5"> <div class="card"> <div class="card-header"><b>익명 글수정 화면입니다</b></div> <div class="card-body"> <form action="#"> <input type="hidden" id="boardId" value="{{boardId}}"/> <div class="mb-3"> <input type="text" class="form-control" placeholder="Enter author" id="author"> </div> <div class="mb-3"> <input type="text" class="form-control" placeholder="Enter title" id="title"> </div> <div class="mb-3"> <textarea class="form-control" rows="5" id="content"></textarea> </div> <button type="button" onclick="put1()" class="btn btn-primary form-control">글수정완료</button> </form> </div> </div> </div> <script> let boardId = document.querySelector("#boardId").value; // html에 있는 id가져오는 방법 let boardId2 = getCookie("boardId"); // 쿠키에서 id가져오는 방법 let inputAuthor = document.querySelector("#author"); let inputTitle = document.querySelector("#title"); let inputContent = document.querySelector("#content"); // 책임: 통신 async function put1() { let requestBody = { author: inputAuthor.value, title: inputTitle.value, content: inputContent.value } let response = await fetch("/api/boards/" + boardId, { method: "put", headers: {"Content-Type": "application/json"}, body: JSON.stringify(requestBody) }); let responseBody = await response.json(); location.href = "/" } // 쿠키에서 key에 대한 값 리턴 function getCookie(key) { const cookies = document.cookie.split('; '); for (let cookie of cookies) { const [k, v] = cookie.split('='); if (k === key) { return v; } } return null; // 해당 키가 없으면 null 반환 } // 책임: 통신 async function init() { let response = await fetch("/api/boards/" + boardId); let responseBody = await response.json(); inputAuthor.value = responseBody.body.author; inputTitle.value = responseBody.body.title; inputContent.value = responseBody.body.content; } init(); </script> {{> layout/footer}}

4. delete로 delete하기

notion image
notion image
코드
{{> layout/header}} <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 id="board-box"> </tbody> </table> </div> <script> // 책임: 컴포넌트 생성 function makeBoard(board) { let tr = document.createElement("tr"); tr.setAttribute("id", `board-${board.id}`); tr.innerHTML = ` <td>${board.id}</td> <td>${board.title}</td> <td>${board.content}</td> <td>${board.author}</td> <td> <div class="d-flex"> <form action="#"> <button type="button" class="btn btn-danger" onclick="delBoard(${board.id})">삭제</button> </form> <form action="/board/${board.id}/updateForm" method="get"> <button class="btn btn-warning">수정</button> </form> </div> </td> `; return tr; } // 책임: 통신 async function delBoard(boardId) { let response = await fetch("/api/boards/" + boardId, { method: "delete" }); let responseBody = await response.json(); console.log(responseBody) // location.reload(); // 페이지 새로고침 let tr = document.querySelector(`#board-${boardId}`); tr.remove(); } // 책임: 통신 async function init() { let response = await fetch("/api/boards"); let responseBody = await response.json(); let boardList = responseBody.body; // console.log(boardList); let boardBox = document.querySelector("#board-box"); boardList.forEach((board) => { boardBox.append(makeBoard(board)); }); } init(); </script> {{> layout/footer}}
Share article

jjack1