나의 코드
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)
는 응답 데이터를 감싸는 커스텀 객체일 가능성이 있습니다. 주로 응답의 구조를 통일하고, 성공 여부나 추가 메타 데이터를 포함하는 데 사용됩니다.- API 방식 (
/board
): - 사용자가
/board
경로로 GET 요청을 보내면, 서버는 게시글 목록을JSON
형식으로 반환합니다. 만약title
이라는 쿼리 파라미터가 있으면 해당 값을 기반으로 게시글 목록을 필터링합니다. - 이 방식은 주로 REST API로 데이터를 제공할 때 사용됩니다.
- 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)
- 설명:
title
이 null인지 확인하는 조건문입니다. 즉, 사용자가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); }
- 설명:
title
이 null이 아닌 경우(즉, 사용자가 제목을 입력한 경우) 실행되는 코드입니다. 이때는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)**를 반환합니다. 이 리스트는 이후 컨트롤러에서 클라이언트로 반환되거나 뷰에 전달됩니다.
전체적인 흐름 요약
- title이 null일 경우:
- 전체 게시글을 데이터베이스에서 id 내림차순으로 정렬하여 가져옵니다.
- title이 null이 아닐 경우:
title
에 해당하는 검색어가 포함된 게시글을 데이터베이스에서 조회합니다.
- 가져온 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
을 인자로 넘겨 서버로 검색 요청을 보냅니다. 검색어에 맞는 게시글 목록이 동적으로 화면에 표시됩니다.
코드 전체 흐름
- 사용자가 검색창에 키를 입력하면
keyup
이벤트가 발생합니다.
- 입력된 텍스트 값을
title
변수에 저장하고, 이 값을getBoardList
함수에 전달합니다.
getBoardList
함수는 서버에 비동기 요청을 보내서 해당title
에 맞는 게시글 목록을 가져옵니다.
- 서버에서 응답이 성공적으로 돌아오면, 기존의 게시글 목록을 지우고 새로 가져온 게시글을 화면에 렌더링합니다.
boardItem
함수는 각 게시글을 HTML 카드 형식으로 만들어 DOM에 추가합니다.
주요 기능
- 실시간 검색: 사용자가 검색창에 입력할 때마다 자동으로 검색 결과가 갱신되어 화면에 표시됩니다.
- 클라이언트 사이드 렌더링: 서버에서 받은 데이터를 클라이언트에서 처리하여 페이지 새로고침 없이 콘텐츠가 갱신됩니다.
- 동적 HTML 생성: 서버로부터 받은 데이터를 기반으로 동적으로 HTML을 생성하고 DOM에 추가하여 사용자 인터페이스를 구성합니다.
Share article