KeyBoard 이벤트 활용해보기

KeyBoard 이벤트
홍윤's avatar
Sep 10, 2024
KeyBoard 이벤트 활용해보기

나의 코드

1. BoardController

// localhost:8080?title=제목 @GetMapping("/board") public ResponseEntity<?> boardList(@RequestParam(name = "title", required = false) String title) { List<BoardResponse.DTO> boardList = boardService.게시글목록보기(title); return ResponseEntity.ok(Resp.ok(boardList)); } @GetMapping("/") public String list(@RequestParam(name = "title", required = false) String title, HttpServletRequest request) { // HttpServletRequest request 얘는 가방같은 역할 화면에 뿌리기 위해 담아둠 List<BoardResponse.DTO> boardList = boardService.게시글목록보기(title); request.setAttribute("models", boardList); return "board/list"; }
  • 코드설명
💡
이 코드는 Spring 프레임워크를 사용하여 게시글 목록을 조회하고, 그 결과를 반환하는 두 가지 방식의 엔드포인트를 정의한 것입니다. 첫 번째 메서드는 API 응답으로 JSON 형식의 데이터를 반환하고, 두 번째 메서드는 JSP 또는 다른 템플릿 엔진을 통해 HTML 페이지를 렌더링하는 방식입니다. 두 메서드 모두 게시글을 검색하거나 목록을 반환하는 기능을 담당하지만, 그 방식이 다릅니다.

@GetMapping("/board") 코드

public ResponseEntity<?> boardList(@RequestParam(name = "title", required = false) String title)

  • 설명: 이 메서드는 ResponseEntity<?>를 반환하는데, 이는 API 응답으로 HTTP 상태 코드와 함께 데이터를 반환하는 객체입니다.
  • @RequestParam(name = "title", required = false): 클라이언트가 **title*이라는 쿼리 파라미터를 전달할 수 있으며, 이 값은 게시글 목록을 필터링하는 데 사용됩니다. **required = false*는 title이 선택사항임을 의미하며, 없을 경우 전체 게시글을 조회할 수 있게 합니다.

List<BoardResponse.DTO> boardList = boardService.게시글목록보기(title);

  • 설명: boardService.게시글목록보기(title)게시글 목록을 조회하는 서비스 메서드를 호출하여, 그 결과를 boardList에 담습니다. 여기서 반환되는 데이터는 DTO(Data Transfer Object) 형식으로, 게시글의 정보를 담고 있는 객체 리스트입니다.
  • *title*이 제공된 경우, 제목을 기준으로 필터링된 게시글 목록을 반환하고, 그렇지 않으면 전체 게시글을 반환할 것입니다.

return ResponseEntity.ok(Resp.ok(boardList));

  • 설명: 이 부분은 HTTP 응답으로 게시글 목록을 클라이언트에게 반환하는 역할을 합니다.
    • ResponseEntity.ok()HTTP 200 OK 상태 코드를 반환하며, 이와 함께 데이터를 담아 보냅니다.
    • Resp.ok(boardList)는 응답 데이터를 감싸는 커스텀 객체일 가능성이 있습니다. 주로 응답의 구조를 통일하고, 성공 여부나 추가 메타 데이터를 포함하는 데 사용됩니다.
      1. API 방식 (/board):
          • 사용자가 /board 경로로 GET 요청을 보내면, 서버는 게시글 목록을 JSON 형식으로 반환합니다. 만약 title이라는 쿼리 파라미터가 있으면 해당 값을 기반으로 게시글 목록을 필터링합니다.
          • 이 방식은 주로 REST API로 데이터를 제공할 때 사용됩니다.
      1. HTML 렌더링 방식 (/):
          • 사용자가 / 경로로 GET 요청을 보내면, 서버는 게시글 목록을 가져와 뷰에 전달하고, 이를 사용해 HTML 페이지를 생성합니다.
          • request.setAttribute로 데이터를 뷰에 전달한 후, "board/list"라는 뷰 파일을 사용해 최종 HTML을 클라이언트에게 반환합니다.
      따라서 이 코드는 같은 게시글 목록을 두 가지 방식으로 처리하는데, 하나는 API 응답으로 데이터를 제공하고, 다른 하나는 웹 페이지를 렌더링하는 방식으로 작동합니다.
      4o
       

2. BoardService

public List<BoardResponse.DTO> 게시글목록보기(String title) { List<BoardResponse.DTO> dtos = new ArrayList<>(); List<Board> boardList = null; if(title == null){ Sort sort = Sort.by(Sort.Direction.DESC, "id"); boardList = boardRepository.findAll(sort); }else{ boardList = boardRepository.mfindAll(title); } for(Board board : boardList){ BoardResponse.DTO dto = new BoardResponse.DTO(board); dtos.add(dto); } return dtos; }
  • 코드설명
💡
이 코드는 게시글목록보기라는 메서드로, 게시글 목록을 조회한 후, 각 게시글을 DTO(Data Transfer Object) 형태로 변환하여 반환하는 역할을 합니다. 이 과정에서 게시글의 제목을 기준으로 필터링할 수 있으며, 제목이 제공되지 않으면 모든 게시글을 조회합니다. 아래는 각 코드 부분에 대한 자세한 설명입니다.

1. public List<BoardResponse.DTO> 게시글목록보기(String title)

  • 설명: 이 메서드는 **List<BoardResponse.DTO>**를 반환하는데, 이는 게시글 목록을 담은 DTO 객체 리스트입니다.
  • title이라는 문자열을 입력 파라미터로 받아, 이 값에 따라 게시글을 필터링하거나 전체 목록을 가져옵니다.

2. List<BoardResponse.DTO> dtos = new ArrayList<>();

  • 설명: dtos는 반환될 DTO 객체들을 저장하는 리스트입니다. 처음에 빈 리스트로 생성되고, 이후에 게시글 데이터를 각각의 DTO로 변환하여 이 리스트에 추가합니다.

3. List<Board> boardList = null;

  • 설명: boardList는 데이터베이스로부터 가져올 게시글 엔티티(Board)의 리스트입니다. 조건에 따라 이 리스트에 게시글 목록을 할당합니다.

4. if(title == null)

  • 설명: titlenull인지 확인하는 조건문입니다. 즉, 사용자가 title을 입력하지 않았을 때 전체 게시글을 가져오는 로직입니다.

5. Sort sort = Sort.by(Sort.Direction.DESC, "id");

  • 설명: Sort 객체를 생성하여, 게시글을 **id를 기준으로 내림차순(DESC)**으로 정렬합니다. 즉, 최신 게시글이 가장 먼저 오도록 정렬합니다.

6. boardList = boardRepository.findAll(sort);

  • 설명: 게시글을 데이터베이스에서 모두 조회하는 부분입니다. 여기서는 boardRepository.findAll(sort)를 호출하여, id 내림차순으로 정렬된 모든 게시글을 가져옵니다.
  • 이 로직은 title이 null일 때, 즉 제목으로 검색하지 않을 때 실행됩니다.

7. else { boardList = boardRepository.mfindAll(title); }

  • 설명: titlenull이 아닌 경우(즉, 사용자가 제목을 입력한 경우) 실행되는 코드입니다. 이때는 mfindAll(title) 메서드를 통해 title이 포함된 게시글을 가져옵니다.
  • mfindAll은 이전에 설명한 것처럼 제목에 특정 문자열이 포함된 게시글을 검색하는 커스텀 쿼리를 수행합니다.

8. for(Board board : boardList)

  • 설명: 가져온 boardList의 각 Board 객체를 순회하면서, 이 게시글을 DTO로 변환하는 작업을 수행합니다.

9. BoardResponse.DTO dto = new BoardResponse.DTO(board);

  • 설명: 각 Board 엔티티 객체를 BoardResponse.DTO 객체로 변환하는 부분입니다. DTO는 데이터 전송을 위한 객체로, 보통 필요한 정보만 포함하여 클라이언트에게 전달할 때 사용됩니다.
    • new BoardResponse.DTO(board): Board 객체를 이용해 DTO 객체를 생성합니다. 이 생성자는 Board 객체를 받아 그 정보를 DTO로 변환하는 역할을 합니다.

10. dtos.add(dto);

  • 설명: 변환된 DTO 객체를 dtos 리스트에 추가합니다. 이렇게 하면 최종적으로 모든 게시글을 DTO 형태로 변환한 후, 리스트에 담아 반환할 수 있습니다.

11. return dtos;

  • 설명: 최종적으로 게시글 목록이 담긴 **DTO 리스트(dtos)**를 반환합니다. 이 리스트는 이후 컨트롤러에서 클라이언트로 반환되거나 뷰에 전달됩니다.

전체적인 흐름 요약

  1. title이 null일 경우:
      • 전체 게시글을 데이터베이스에서 id 내림차순으로 정렬하여 가져옵니다.
  1. title이 null이 아닐 경우:
      • title에 해당하는 검색어가 포함된 게시글을 데이터베이스에서 조회합니다.
  1. 가져온 Board 엔티티 객체들을 DTO로 변환하여 리스트에 추가하고, 그 리스트를 반환합니다.
이 코드는 데이터베이스에서 게시글 목록을 가져오고, 이를 클라이언트에게 전달하기 전에 DTO로 변환하여 처리하는 전형적인 패턴입니다. 이를 통해 클라이언트는 필요한 정보만을 받게 되며, 데이터 전송량을 줄이거나 보안을 강화할 수 있습니다.

3. list.mustache

{{>layout/header}} <div class="container p-5"> <div class="d-flex justify-content-end mb-2"> <form> <input class="form-control me-2" type="text" placeholder="Search" id="title"> </form> </div> <div id="board-box"> {{#models}} <div class="card mb-3"> <div class="card-body"> <h4 class="card-title mb-3">{{title}}</h4> <a href="/board/{{id}}" class="btn btn-primary">상세보기</a> </div> </div> {{/models}} </div> </div> <script> // 1. 디자인에 데이터 렌더링 function boardItem(board){ return `<div class="card mb-3"> <div class="card-body"> <h4 class="card-title mb-3">${board.title}</h4> <a href="/board/${board.id}" class="btn btn-primary">상세보기</a> </div> </div>`; } // 2. 통신+CSR 클라이언트사이드렌더링 async function getBoardList(title){ let response = await fetch(`/board?title=${title}`); let responseBody = await response.json(); if(response.ok){ $("#board-box").empty(); // remove 는 dom을 제거, empty는 안에 있는 내용을 제거 let boardList = responseBody.body; for (board of boardList){ let dom = boardItem(board); $("#board-box").append(dom); } }else{ alert(responseBody.msg); } } // 3. 키보드 이벤트 처리 $("#title").on("keyup", function(e){ // 1. 값 가져오기 let title = e.target.value; // 2. fetch 요청 getBoardList(title); }); </script> {{>layout/footer}}
  • 코드설명
💡
이 코드는 **클라이언트 사이드 렌더링(CSR)**을 통해 게시글 목록을 동적으로 렌더링하는 JavaScript 스크립트입니다. 사용자가 키보드로 검색어를 입력하면, 실시간으로 서버에서 해당 검색어에 맞는 게시글을 가져와 화면에 표시합니다. 코드를 단계별로 설명해 보겠습니다.

1. boardItem(board) - 게시글 카드 디자인

javascript 코드 복사 function boardItem(board){ return `<div class="card mb-3"> <div class="card-body"> <h4 class="card-title mb-3">${board.title}</h4> <a href="/board/${board.id}" class="btn btn-primary">상세보기</a> </div> </div>`; }
  • 설명: 이 함수는 게시글 하나를 화면에 표시할 HTML 코드를 생성합니다.
    • board.title: 게시글의 제목을 동적으로 삽입합니다.
    • board.id: 게시글의 고유 ID를 동적으로 삽입하여, 상세보기 링크를 설정합니다.
    • 이 함수는 템플릿 리터럴을 사용하여 게시글의 데이터를 HTML 카드 형식으로 반환합니다.

2. getBoardList(title) - 서버와 통신 및 클라이언트 사이드 렌더링 (CSR)

javascript 코드 복사 async function getBoardList(title){ let response = await fetch(`/board?title=${title}`); let responseBody = await response.json(); if(response.ok){ $("#board-box").empty(); // remove는 DOM 자체를 제거, empty는 안에 있는 내용만 제거 let boardList = responseBody.body; for (board of boardList){ let dom = boardItem(board); $("#board-box").append(dom); } }else{ alert(responseBody.msg); } }
  • 설명: 이 함수는 서버로부터 게시글 목록을 가져오는 **비동기 통신(Async)**을 처리하는 역할을 합니다.
    • fetch(/board?title=${title}): 서버의 /board 엔드포인트로 GET 요청을 보내, title이라는 검색어에 해당하는 게시글 목록을 가져옵니다.
    • await response.json(): 서버로부터 응답을 JSON 형식으로 받아 파싱합니다.
    • response.ok: 서버 응답이 성공적인지 확인합니다. 응답 코드가 200인 경우에 true가 됩니다.
    • $("#board-box").empty(): 게시글 목록을 렌더링할 HTML 요소인 #board-box 내부를 비웁니다. 기존의 내용을 지우고 새롭게 데이터를 렌더링할 준비를 합니다.
    • boardList: 서버로부터 받은 게시글 데이터를 배열 형태로 추출합니다.
    • boardItem(board): 각 게시글 데이터를 HTML로 변환하고, 그 결과를 DOM에 추가합니다.
    • $("#board-box").append(dom): 변환된 HTML을 #board-box에 동적으로 추가하여 화면에 표시합니다.
    • 실패 시 alert(responseBody.msg): 응답이 실패하면 서버에서 전송된 메시지를 알림으로 띄웁니다.

3. $("#title").on("keyup", function(e)) - 키보드 이벤트 처리

javascript 코드 복사 $("#title").on("keyup", function(e){ // 1. 값 가져오기 let title = e.target.value; // 2. fetch 요청 getBoardList(title); });
  • 설명: 이 부분은 키보드 입력 이벤트를 처리하는 코드입니다.
    • $("#title").on("keyup", function(e)): 사용자가 검색창(#title)에서 키를 입력할 때마다 keyup 이벤트가 발생합니다. 이 이벤트가 발생할 때마다 해당 콜백 함수가 실행됩니다.
    • e.target.value: 사용자가 입력한 값을 가져옵니다. e.target은 키보드 이벤트가 발생한 요소(#title input)를 가리키며, value는 사용자가 입력한 텍스트 값입니다.
    • getBoardList(title): 사용자가 입력한 title을 인자로 넘겨 서버로 검색 요청을 보냅니다. 검색어에 맞는 게시글 목록이 동적으로 화면에 표시됩니다.

코드 전체 흐름

  1. 사용자가 검색창에 키를 입력하면 keyup 이벤트가 발생합니다.
  1. 입력된 텍스트 값을 title 변수에 저장하고, 이 값을 getBoardList 함수에 전달합니다.
  1. getBoardList 함수는 서버에 비동기 요청을 보내서 해당 title에 맞는 게시글 목록을 가져옵니다.
  1. 서버에서 응답이 성공적으로 돌아오면, 기존의 게시글 목록을 지우고 새로 가져온 게시글을 화면에 렌더링합니다.
  1. boardItem 함수는 각 게시글을 HTML 카드 형식으로 만들어 DOM에 추가합니다.

주요 기능

  • 실시간 검색: 사용자가 검색창에 입력할 때마다 자동으로 검색 결과가 갱신되어 화면에 표시됩니다.
  • 클라이언트 사이드 렌더링: 서버에서 받은 데이터를 클라이언트에서 처리하여 페이지 새로고침 없이 콘텐츠가 갱신됩니다.
  • 동적 HTML 생성: 서버로부터 받은 데이터를 기반으로 동적으로 HTML을 생성하고 DOM에 추가하여 사용자 인터페이스를 구성합니다.
Share article

Uni