[JavaScript] 6. Ajax (Asynchronous JavaScript and XML)

김미숙's avatar
Apr 03, 2025
[JavaScript] 6. Ajax (Asynchronous JavaScript and XML)
‼️
JavaScript와 XML을 이용한 비동기적 정보 교환 기법
브라우저의 XMLHttpRequest를 이용해 전체 페이지를 새로 가져오지 않고도 페이지 일부만을 변경할 수 있도록 javascript를 실행해 서버에 데이터만을 별도로 요청하는 기법
 

1. AJAX의 핵심 개념

비동기 통신 (Asynchronous)
  • AJAX는 요청을 보내고 응답을 기다리지 않고, 다른 작업을 계속 수행할 수 있도록 합니다.
  • 동기 방식(Synchronous)에서는 요청을 보낸 후 응답이 올 때까지 기다려야 하지만, AJAX는 기다릴 필요 없이 응답이 오면 특정 이벤트를 통해 처리합니다.
XML 대신 JSON 사용
  • 초기에는 XML을 데이터 형식으로 많이 사용했지만, 현재는 더 가볍고 효율적인 JSON을 주로 사용합니다.
새로고침 없이 데이터 갱신
  • 페이지 전체를 다시 로드하지 않고 필요한 부분만 업데이트할 수 있어 사용자 경험(UX)이 개선됩니다.
notion image
 
3. 서버의 다양성
3. 서버의 다양성

Session 인증의 단점

  • 인증방식
    • → 1. 사용자(클라이언트)가 서버에 로그인 요청
      → 2. 서버는 인증절차를 수행하고, 인증이 유효하면 세션 객체를 생성하고 서버에 저장
      → 3. 서버는 요청에 대한 응답으로 응답 헤더의 set -cookie를 통해 세션 ID를 클라이어트에게 전달
      → 4. 이후부터는 클라이언트가 서버에 요청할 때마다 전달받은 쿠기를 요청헤더아 추가하여 요청 (쿠키를 요청헤더에 추가해주는 것은 브라우저가 처리)
  • Session 방식의 한계
    • → 1. 서버 부하 증가
      • 세션 정보를 서버에서 관리해야 해서, 사용자가 많아지면 서버 메모리 사용량 증가
      • 특히, 대규모 서비스에서는 세션 저장을 위한 추가적인 관리(ex. Redis, DB 저장)가 필요요
      → 2. 확장성 문제
      • 서버가 여러 대일 경우, 세션 정보 공유 필요
      • 세션을 중앙 저장소에 저장하지 않으면, 사용자가 처음 접속한 서버에서만 인증이 유지되는 문제가 생길 수 있음
      → 3. 보안 문제
      • 세션 하이재킹(Session Hijacking): 세션 ID가 탈취되면 공격자가 사용자로 위장할 수 있음
      • 세션 고정 공격(Session Fixation): 공격자가 미리 정해놓은 세션 ID를 사용하도록 유도할 수 있음
      • CSRF(Cross-Site Request Forgery) 공격에 취약할 수도 있다
      → 4. 수동 로그아웃 필요
      • 세션이 만료되지 않으면, 사용자가 직접 로그아웃하지 않는 한 계속 유지될 수 있다
      • 공유 컴퓨터에서는 보안 위험이 클 수 있다
      → 5. 쿠키 의존성
      • 일반적으로 세션 ID는 쿠키를 통해 관리되는데, 브라우저에서 쿠키를 차단하면 인증이 제대로 작동하지 않을 수 있다
      • XSS(크로스 사이트 스크립팅) 공격을 통해 세션 쿠키가 탈취될 가능성도 있다
 

전자서명 인증

  • 전자서명 인증의 개념
    • → 전자서명 인증은 공개 키 암호화(PKI, Public Key Infrastructure) 를 기반으로 사용자의 신원을 검증하는 인증 방식
      → 전자서명은 문서나 데이터의 무결성을 보장하고, 송신자의 신원을 확인할 수 있다.
  • 전자서명의 작동 원리
    • 전자서명 인증은 개인 키(Private Key)와 공개 키(Public Key) 를 활용하여 다음과 같은 방식으로 작동한다
    • → 1. 서명생성 (Signing)
      • 사용자가 개인 키(Private Key)로 문서 또는 데이터를 암호화하여 서명을 생성함
      → 2. 서명 전송
      • 서명된 문서와 함께 전자서명(Signature)을 상대방에게 보냄
      → 3. 서명 검증 (Verification)
      • 수신자는 송신자의 공개 키(Public Key)를 사용하여 서명의 유효성을 검증
      • 복호화된 데이터가 원본과 일치하면 무결성(Integrity) 및 신원(Authenticity)이 확인됨
notion image
 

ex06/test05.html

<!DOCTYPE html> <html lang="ko"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> </head> <body> <h1>fetch get, post, put, delete</h1> <hr /> <button onclick="get1()">get</button> <button onclick="post1()">post</button> <button onclick="put1()">put</button> <button onclick="delete1()">delete</button> <form> <input type="text" id="title" placeholder="title" /><br /> <input type="text" id="content" placeholder="content" /><br /> <input type="text" id="author" placeholder="author" /><br /> <button type="button" onclick="write1()">게시글쓰기</button> </form> <script> async function write1() { let requestBody = { title: document.querySelector("#title").value, content: document.querySelector("#content").value, author: document.querySelector("#author").value, }; let response = await fetch("http://localhost:8080/api/boards", { method: "post", body: JSON.stringify(requestBody), headers: { "Content-Type": "application/json" }, }); let responseBody = await response.json(); console.log(responseBody); } async function get1() { let response = await fetch("http://localhost:8080/api/boards/1", { method: "get", }); let responseBody = await response.json(); console.log(responseBody); } async function post1() { let requestBody = { title: "제목9", content: "내용9", author: "ssar", }; let response = await fetch("http://localhost:8080/api/boards", { method: "post", body: JSON.stringify(requestBody), headers: { "Content-Type": "application/json" }, }); let responseBody = await response.json(); console.log(responseBody); } async function put1() { let requestBody = { title: "제목11", content: "내용11", author: "ssar", }; let response = await fetch("http://localhost:8080/api/boards/1", { method: "put", body: JSON.stringify(requestBody), headers: { "Content-Type": "application/json" }, }); let responseBody = await response.json(); console.log(responseBody); } async function delete1() { let response = await fetch("http://localhost:8080/api/boards/1", { method: "delete", }); let responseBody = await response.json(); console.log(responseBody); } </script> </body> </html>
 
Blog

Blog

localhost:8080/

index

{{> 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="deleteBoard(${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 tBody = document.querySelector("#board-box"); boardList.forEach((board) => { tBody.append(makeBoard(board)); }); } init(); </script> {{> layout/footer}}

BoardApiContoller

package shop.mtcoding.blog.board; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; import java.util.List; @CrossOrigin @RequiredArgsConstructor @RestController public class BoardApiController { private final BoardRepository boardRepository; @PutMapping("/api/boards/{id}") public ApiUtil<?> update(@PathVariable("id") int id, @RequestBody BoardRequest.UpdateDTO requestDTO) { boardRepository.updateById(requestDTO, id); return new ApiUtil<>(null); } @PostMapping("/api/boards") public ApiUtil<?> write(@RequestBody BoardRequest.WriteDTO requestDTO) { boardRepository.insert(requestDTO); return new ApiUtil<>(null); } @DeleteMapping("/api/boards/{id}") public ApiUtil<?> deleteById(@PathVariable Integer id) { Board board = boardRepository.selectOne(id); boardRepository.deleteById(id); return new ApiUtil<>(null); } @GetMapping("/api/boards/{id}") public ApiUtil<?> findById(@PathVariable("id") int id) { Board board = boardRepository.selectOne(id); // try { // Thread.sleep(5000); // } catch (InterruptedException e) { // throw new RuntimeException(e); // } return new ApiUtil<>(board); // MessageConverter } @GetMapping("/api/boards") public ApiUtil<?> findAll() { List<Board> boardList = boardRepository.selectAll(); return new ApiUtil<>(boardList); // MessageConverter } }

BoardController

package shop.mtcoding.blog.board; import jakarta.servlet.http.Cookie; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @RequiredArgsConstructor @Controller public class BoardController { @GetMapping("/") public String index() { return "index"; } @GetMapping("/board/saveForm") public String saveForm() { return "board/saveForm"; } @GetMapping("/board/{id}/updateForm") public String updateForm(@PathVariable("id") int id, HttpServletRequest request, HttpServletResponse response) { Cookie cookie = new Cookie("boardId", id + ""); cookie.setHttpOnly(true); response.addCookie(cookie); request.setAttribute("boardId", id); return "board/updateForm"; } }

BoardRepository

package shop.mtcoding.blog.board; import jakarta.persistence.EntityManager; import jakarta.persistence.Query; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Repository; import org.springframework.transaction.annotation.Transactional; import java.util.List; @RequiredArgsConstructor @Repository public class BoardRepository { private final EntityManager em; public List<Board> selectAll(){ Query query = em.createNativeQuery("select * from board_tb order by id desc", Board.class); List<Board> boardList = query.getResultList(); // 못찾으면 빈 컬렉션을 준다 (크기=0) return boardList; } public Board selectOne(int id){ Query query = em.createNativeQuery("select * from board_tb where id = ?", Board.class); query.setParameter(1, id); try { Board board = (Board) query.getSingleResult(); return board; } catch (Exception e) { return null; } } @Transactional public void insert(BoardRequest.WriteDTO requestDTO){ Query query = em.createNativeQuery("insert into board_tb(title, content, author) values(?, ?, ?)"); query.setParameter(1, requestDTO.getTitle()); query.setParameter(2, requestDTO.getContent()); query.setParameter(3, requestDTO.getAuthor()); query.executeUpdate(); } @Transactional public void deleteById(Integer id) { Query query = em.createNativeQuery("delete from board_tb where id = ?"); query.setParameter(1, id); query.executeUpdate(); } @Transactional public void updateById(BoardRequest.UpdateDTO requestDTO, int id) { Query query = em.createNativeQuery("update board_tb set title=?, content=?, author=? where id=?"); query.setParameter(1, requestDTO.getTitle()); query.setParameter(2, requestDTO.getContent()); query.setParameter(3, requestDTO.getAuthor()); query.setParameter(4, id); query.executeUpdate(); } }
notion image
 

localhost:8080/board/saveForm

saveForm

{{> 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" class="btn btn-primary form-control" onclick="writeBoard()">글쓰기완료</button> </form> </div> </div> </div> <script> // 아래 함수 작성하기 전에, // 1. button -> type button으로!! // 2. input name을 id로 변경하기 async function writeBoard() { // 1. id 값 찾아서 requestBody 오브젝트에 넣기 let requestBody = { author: document.querySelector("#author").value, title: document.querySelector("#title").value, content: document.querySelector("#content").value } // 2. fetch post 요청하기 let response = await fetch("/api/boards", { method: "post", body: JSON.stringify(requestBody), headers: {"Content-Type": "application/json"}, }); let responseBody = await response.json(); console.log(responseBody); // 3. 마지막에 아래 코드로 페이지 이동하기 (console볼땐 주석처리) location.href = "/"; } </script> {{> layout/footer}}

BoardApiController

package shop.mtcoding.blog.board; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; import java.util.List; @CrossOrigin @RequiredArgsConstructor @RestController public class BoardApiController { private final BoardRepository boardRepository; @PutMapping("/api/boards/{id}") public ApiUtil<?> update(@PathVariable("id") int id, @RequestBody BoardRequest.UpdateDTO requestDTO) { boardRepository.updateById(requestDTO, id); return new ApiUtil<>(null); } @PostMapping("/api/boards") public ApiUtil<?> write(@RequestBody BoardRequest.WriteDTO requestDTO) { boardRepository.insert(requestDTO); return new ApiUtil<>(null); } @DeleteMapping("/api/boards/{id}") public ApiUtil<?> deleteById(@PathVariable Integer id) { Board board = boardRepository.selectOne(id); boardRepository.deleteById(id); return new ApiUtil<>(null); } @GetMapping("/api/boards/{id}") public ApiUtil<?> findById(@PathVariable("id") int id) { Board board = boardRepository.selectOne(id); // try { // Thread.sleep(5000); // } catch (InterruptedException e) { // throw new RuntimeException(e); // } return new ApiUtil<>(board); // MessageConverter } @GetMapping("/api/boards") public ApiUtil<?> findAll() { List<Board> boardList = boardRepository.selectAll(); return new ApiUtil<>(boardList); // MessageConverter } }

BoardController

package shop.mtcoding.blog.board; import jakarta.servlet.http.Cookie; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @RequiredArgsConstructor @Controller public class BoardController { @GetMapping("/") public String index() { return "index"; } @GetMapping("/board/saveForm") public String saveForm() { return "board/saveForm"; } @GetMapping("/board/{id}/updateForm") public String updateForm(@PathVariable("id") int id, HttpServletRequest request, HttpServletResponse response) { Cookie cookie = new Cookie("boardId", id + ""); cookie.setHttpOnly(true); response.addCookie(cookie); request.setAttribute("boardId", id); return "board/updateForm"; } }

BoardRepository

package shop.mtcoding.blog.board; import jakarta.persistence.EntityManager; import jakarta.persistence.Query; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Repository; import org.springframework.transaction.annotation.Transactional; import java.util.List; @RequiredArgsConstructor @Repository public class BoardRepository { private final EntityManager em; public List<Board> selectAll(){ Query query = em.createNativeQuery("select * from board_tb order by id desc", Board.class); List<Board> boardList = query.getResultList(); // 못찾으면 빈 컬렉션을 준다 (크기=0) return boardList; } public Board selectOne(int id){ Query query = em.createNativeQuery("select * from board_tb where id = ?", Board.class); query.setParameter(1, id); try { Board board = (Board) query.getSingleResult(); return board; } catch (Exception e) { return null; } } @Transactional public void insert(BoardRequest.WriteDTO requestDTO){ Query query = em.createNativeQuery("insert into board_tb(title, content, author) values(?, ?, ?)"); query.setParameter(1, requestDTO.getTitle()); query.setParameter(2, requestDTO.getContent()); query.setParameter(3, requestDTO.getAuthor()); query.executeUpdate(); } @Transactional public void deleteById(Integer id) { Query query = em.createNativeQuery("delete from board_tb where id = ?"); query.setParameter(1, id); query.executeUpdate(); } @Transactional public void updateById(BoardRequest.UpdateDTO requestDTO, int id) { Query query = em.createNativeQuery("update board_tb set title=?, content=?, author=? where id=?"); query.setParameter(1, requestDTO.getTitle()); query.setParameter(2, requestDTO.getContent()); query.setParameter(3, requestDTO.getAuthor()); query.setParameter(4, id); query.executeUpdate(); } }
notion image
notion image
notion image
 

localhost:8080/board/{id}/updateForm

updateForm

{{> 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" class="btn btn-primary form-control" onclick="updateBoard()">글수정완료</button> </form> </div> </div> </div> <script> async function updateBoard() { // 1. id 값 찾아서 requestBody 오브젝트에 넣기 let requestBody = { author: document.querySelector("#author").value, title: document.querySelector("#title").value, content: document.querySelector("#content").value } // 2. fetch put 요청하기 let response = await fetch(`/api/boards/${boardId}`, { method: "put", body: JSON.stringify(requestBody), headers: {"Content-Type": "application/json"} }) let responseBody = await response.json(); console.log(responseBody); // 3. 마지막에 아래 코드로 페이지 이동하기 (console볼땐 주석처리) location.href = "/"; } let boardId = document.querySelector("#boardId").value; //let boardId2 = getCookie("boardId"); // 책임: 통신 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(); 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 반환 } </script> {{> layout/footer}}

BoardApiController

package shop.mtcoding.blog.board; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; import java.util.List; @CrossOrigin @RequiredArgsConstructor @RestController public class BoardApiController { private final BoardRepository boardRepository; @PutMapping("/api/boards/{id}") public ApiUtil<?> update(@PathVariable("id") int id, @RequestBody BoardRequest.UpdateDTO requestDTO) { boardRepository.updateById(requestDTO, id); return new ApiUtil<>(null); } @PostMapping("/api/boards") public ApiUtil<?> write(@RequestBody BoardRequest.WriteDTO requestDTO) { boardRepository.insert(requestDTO); return new ApiUtil<>(null); } @DeleteMapping("/api/boards/{id}") public ApiUtil<?> deleteById(@PathVariable Integer id) { Board board = boardRepository.selectOne(id); boardRepository.deleteById(id); return new ApiUtil<>(null); } @GetMapping("/api/boards/{id}") public ApiUtil<?> findById(@PathVariable("id") int id) { Board board = boardRepository.selectOne(id); // try { // Thread.sleep(5000); // } catch (InterruptedException e) { // throw new RuntimeException(e); // } return new ApiUtil<>(board); // MessageConverter } @GetMapping("/api/boards") public ApiUtil<?> findAll() { List<Board> boardList = boardRepository.selectAll(); return new ApiUtil<>(boardList); // MessageConverter } }

BoardController

package shop.mtcoding.blog.board; import jakarta.servlet.http.Cookie; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @RequiredArgsConstructor @Controller public class BoardController { @GetMapping("/") public String index() { return "index"; } @GetMapping("/board/saveForm") public String saveForm() { return "board/saveForm"; } @GetMapping("/board/{id}/updateForm") public String updateForm(@PathVariable("id") int id, HttpServletRequest request, HttpServletResponse response) { Cookie cookie = new Cookie("boardId", id + ""); cookie.setHttpOnly(true); response.addCookie(cookie); request.setAttribute("boardId", id); return "board/updateForm"; } }

BoardRepository

package shop.mtcoding.blog.board; import jakarta.persistence.EntityManager; import jakarta.persistence.Query; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Repository; import org.springframework.transaction.annotation.Transactional; import java.util.List; @RequiredArgsConstructor @Repository public class BoardRepository { private final EntityManager em; public List<Board> selectAll(){ Query query = em.createNativeQuery("select * from board_tb order by id desc", Board.class); List<Board> boardList = query.getResultList(); // 못찾으면 빈 컬렉션을 준다 (크기=0) return boardList; } public Board selectOne(int id){ Query query = em.createNativeQuery("select * from board_tb where id = ?", Board.class); query.setParameter(1, id); try { Board board = (Board) query.getSingleResult(); return board; } catch (Exception e) { return null; } } @Transactional public void insert(BoardRequest.WriteDTO requestDTO){ Query query = em.createNativeQuery("insert into board_tb(title, content, author) values(?, ?, ?)"); query.setParameter(1, requestDTO.getTitle()); query.setParameter(2, requestDTO.getContent()); query.setParameter(3, requestDTO.getAuthor()); query.executeUpdate(); } @Transactional public void deleteById(Integer id) { Query query = em.createNativeQuery("delete from board_tb where id = ?"); query.setParameter(1, id); query.executeUpdate(); } @Transactional public void updateById(BoardRequest.UpdateDTO requestDTO, int id) { Query query = em.createNativeQuery("update board_tb set title=?, content=?, author=? where id=?"); query.setParameter(1, requestDTO.getTitle()); query.setParameter(2, requestDTO.getContent()); query.setParameter(3, requestDTO.getAuthor()); query.setParameter(4, id); query.executeUpdate(); } }
notion image
notion image
 

localhost:8080/api/boards/{id}/delete

index

{{> 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> async function deleteBoard(boardId) { let response = await fetch("/api/boards/" + boardId, {method: "delete"}); let responseBody = await response.json(); document.querySelector(`#item-${boardId}`).remove(); } // 책임: 컴퍼넌트 생성 function makeBoard(board) { let tr = document.createElement("tr"); tr.setAttribute("id", `item-${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> <button type="button" class="btn btn-danger" onclick="deleteBoard(${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 tBody = document.querySelector("#board-box"); boardList.forEach((board) => { tBody.append(makeBoard(board)); }); } init(); </script> {{> layout/footer}}

BoardApiController

package shop.mtcoding.blog.board; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; import java.util.List; @CrossOrigin @RequiredArgsConstructor @RestController public class BoardApiController { private final BoardRepository boardRepository; @PutMapping("/api/boards/{id}") public ApiUtil<?> update(@PathVariable("id") int id, @RequestBody BoardRequest.UpdateDTO requestDTO) { boardRepository.updateById(requestDTO, id); return new ApiUtil<>(null); } @PostMapping("/api/boards") public ApiUtil<?> write(@RequestBody BoardRequest.WriteDTO requestDTO) { boardRepository.insert(requestDTO); return new ApiUtil<>(null); } @DeleteMapping("/api/boards/{id}") public ApiUtil<?> deleteById(@PathVariable("id") Integer id) { Board board = boardRepository.selectOne(id); boardRepository.deleteById(id); return new ApiUtil<>(null); } @GetMapping("/api/boards/{id}") public ApiUtil<?> findById(@PathVariable("id") int id) { Board board = boardRepository.selectOne(id); // try { // Thread.sleep(5000); // } catch (InterruptedException e) { // throw new RuntimeException(e); // } return new ApiUtil<>(board); // MessageConverter } @GetMapping("/api/boards") public ApiUtil<?> findAll() { List<Board> boardList = boardRepository.selectAll(); return new ApiUtil<>(boardList); // MessageConverter } }

BoardRepository

package shop.mtcoding.blog.board; import jakarta.persistence.EntityManager; import jakarta.persistence.Query; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Repository; import org.springframework.transaction.annotation.Transactional; import java.util.List; @RequiredArgsConstructor @Repository public class BoardRepository { private final EntityManager em; public List<Board> selectAll(){ Query query = em.createNativeQuery("select * from board_tb order by id desc", Board.class); List<Board> boardList = query.getResultList(); // 못찾으면 빈 컬렉션을 준다 (크기=0) return boardList; } public Board selectOne(int id){ Query query = em.createNativeQuery("select * from board_tb where id = ?", Board.class); query.setParameter(1, id); try { Board board = (Board) query.getSingleResult(); return board; } catch (Exception e) { return null; } } @Transactional public void insert(BoardRequest.WriteDTO requestDTO){ Query query = em.createNativeQuery("insert into board_tb(title, content, author) values(?, ?, ?)"); query.setParameter(1, requestDTO.getTitle()); query.setParameter(2, requestDTO.getContent()); query.setParameter(3, requestDTO.getAuthor()); query.executeUpdate(); } @Transactional public void deleteById(Integer id) { Query query = em.createNativeQuery("delete from board_tb where id = ?"); query.setParameter(1, id); query.executeUpdate(); } @Transactional public void updateById(BoardRequest.UpdateDTO requestDTO, int id) { Query query = em.createNativeQuery("update board_tb set title=?, content=?, author=? where id=?"); query.setParameter(1, requestDTO.getTitle()); query.setParameter(2, requestDTO.getContent()); query.setParameter(3, requestDTO.getAuthor()); query.setParameter(4, id); query.executeUpdate(); } }
notion image
notion image
 
Share article

parangdajavous