부트스트랩에서는 d-flex 하면 flex됨 문법이다
mb 마진 바텀 주는 것
list 이동


- 코드
<div class="d-flex justify-content-end mb-2">
<form class="d-flex col-md-3">
<input class="form-control me-2" type="text" placeholder="Search">
<button class="btn btn-primary" type="button">Search</button>
</form>
</div>
보드 레파지토리(쿼리짜러)
검색은 간단한 쿼리라 보드레파지토리에서 가능
//9.10일 검색한다고 추가
@Query("select b from Board b where b.title like %:title% order by b.id desc")
List<Board> mFindAll(@Param("title") String title);
보드 레파지토리 테스트
@Test
public void mFindAll_test(){
//given
String title ="1";
//when
List<Board> boardList = boardRepository.mFindAll(title);
//then
System.out.println(boardList.size());
System.out.println(boardList.get(0).getTitle());
}
보드 컨트롤러
전
@GetMapping("/")
public String list(HttpServletRequest request) {
List<Board> boardList = boardService.게시글목록보기();
request.setAttribute("models", boardList);
return "board/list";
}
변경 후
//localhost:8080?title=제목 이러면? requestParam 생략 가능
// 이유는 적어주면 requestParam에서(defaultValue ="", name="title") 이렇게 쓸 수 있다 쿼리 안에 title이 없으면 터지는데 (파싱 못하니까) 그래서 공백으로 넣어라 할 수 있다.!
@GetMapping("/")
public String list(@RequestParam(value = "title", required = false) String title, HttpServletRequest request) {
List<Board> boardList = boardService.게시글목록보기(title);
request.setAttribute("models", boardList);
return "board/list";
}
required = false하면 localhost:8080 했을 때 null이 뜬다! 문법이다 확인해보자 연습 하자
보드 서비스
public List<Board> 게시글목록보기(String title) {
if(title == null){
//Pageable pg = PageRequest.of(0, 3, Sort.Direction.DESC, "id");
// 게시글 순서 거꾸로 만드려고
Sort sort = Sort.by(Sort.Direction.DESC, "id");
List<Board> boardList = boardRepository.findAll(sort);
return boardList;
}else {
List<Board> boardList = boardRepository.mFindAll(title);
return boardList;
}
}
동적 쿼리는 아니다
- 동적 쿼리는
mFindAll했을 때 쿼리 변하는 것
보드 쿼리리포지토리에서 만들어야 한다!
동적 쿼리 예시
public void 쿼리(String title){
if(title==null){
em.createQuery("");
}else{
em.createQuery("");
}
}
list 머스테치
<div class="d-flex justify-content-end mb-2">
<form action="/" method="get" class="d-flex col-md-3">
<input class="form-control me-2" type="text" placeholder="Search" name="title">
<button class="btn btn-primary" type="button">Search</button>
</form>
</div>
action, method추가 name추가
중요
구체적 질의 get요청의 where절에 걸린다!!
쿼리 스트링의 키 값은 where절에 걸린다!!
질문
list화면에 색터 2개로나누고 왼쪽에는 게시글목록, 오른쪽에는 인기게시글목록이 있다면
검색해서 게시글만 바꾸려면 ajax써야 한다 전체 리로딩해도 되기는 한다 하지만
트래픽이 증가한다!
상황2
회원가입 화면에서 ID중복체크 버튼 만든다 하면
중복체크 만들면 ID 있는지 없는지 하려면 반드시 ajax써야 한다 안 쓰면 이미 적은 것들 날라간다!
검색
List머스태치에서
type="button" 이거 지우기
<div class="d-flex justify-content-end mb-2">
<form action="/" method="get" class="d-flex col-md-3">
<input class="form-control me-2" type="text" placeholder="Search" name="title">
<button class="btn btn-primary">Search</button>
</form>
</div>
ajax요청으로 바로바로 검색할 수 있게 만들자
- 키보드 입력
- 이벤트 캐치
- 그 이벤트로 통신
- 정보 가지고 박스 찾아내서 내부 append해줘야 한다!
우리가 모르는 것
- 키보드 이벤트 내가 할 수 없는 것 샘플링 해봐야 한다!
- 통신 빼고는 다 샘플링할 수 있다
유니티로 누가 샘플링한 결과가 있어 회사에서 그거를 보여줘야 한다
- 내가 모름
- 웹에다 3D안뿌려봄
- 유니티도 모른다
근데 이거를 화면에 보여주려면 미친 짓이다
먼저 스프링 웹 페이지에 통신없이 랜더링 먼저 해봐야 한다!
어떤 비지니스가 있다면 abcdefg
초보자들은 하나의 트랜잭션( 즉 하나의 기능)이라고 본다(메인페이지만들기 - 웹화면3D렌더링)
이거를 기존 프로잭트에 한번에 만드려고 한다
a하고 b하고 c하고 쪼개서 해야한다!
1. 샘플링하자 (VS코드로) 키보드 이밴트부터
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
</head>
<body>
<input type="text" id="keyword">
<script>
</script>
</body>
</html>
이벤트 모르니까 검색으로
자바스크립트 keyboard 이벤트 해보자
블로그도 만들자!
쿼리샐랙터로 찾아서 어떤거를 할지 function에 넣는다!
복붙
눈으로 계속 보고있는중
해당 돔을 찾아서 돔에 기능 넣는다
돔은 태그들이고
돔을 찾아서 이밴트리스너를 달아야겠다가 중요함
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
</head>
<body>
<input type="text" id="keyword">
<script>
let keyword = document.querySelector("#keyword");
keyword.addEventListener("keyup", function(){console.log("g");});
</script>
</body>
</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>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
</head>
<body>
<input type="text" id="keyword">
<script>
let keyword = document.querySelector("#keyword");
keyword.addEventListener("keyup", function (e) { console.log(e); });
</script>
</body>
</html>


이 안에 value때리면 된다
e.target.value 하면된다
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
</head>
<body>
<input type="text" id="keyword">
<script>
let keyword = document.querySelector("#keyword");
keyword.addEventListener("keyup", function (e) { console.log(e.target.value); });
</script>
</body>
</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>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
</head>
<body>
<input type="text" id="keyword">
<script>
let keyword = document.querySelector("#keyword");
keyword.addEventListener("keyup", function (e) {
//1. 입력한 값 가지고 오기
let value = e.target.value;
//2. fetch 요청
//3. 결과 csr
});
</script>
</body>
</html>
이제 다시 스프링으로 돌아감
list머스테치 이동
<div class="d-flex justify-content-end mb-2">
<form>
<input class="form-control me-2" type="text" placeholder="Search" id="title">
</form>
</div>
jquery로 한다
{{>layout/header}}
<form action="/text/form" method="post">
<input type="text" name="username">
<button>고고</button>
</form>
<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>
{{#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>
<script>
$("#title").on("keyup", function(e){
let title = e.target.value;
console.log(title);
});
</script>
{{>layout/footer}}
확인 잘 되는지

통신 날리기
보드 컨트롤러
2가지
@ResponseBody Resp<?>해도 됨
아니면 ResponseEntity를 거는게 좋다
// 보드 데이터만 받아오는 데이터 return board/list하면 안됨 responseEntity 받아야함 원래는 boardDTO를 받아야함
//가방에 담을 필요 없음 담았다가 뿌리는게 아니니까
//세션없고 board에 있는것 getter때림 json이니까 근데 getUser할 때 no Session뜰거다! user안에는 담는 데이터가 없고 이미 세션 끝나고 끝남
//그래서 boardDTO로 바꿔야 한다!!
@GetMapping("/board")
public ResponseEntity<?> boardList(@RequestParam(value = "title", required = false) String title) {
List<Board> boardList = boardService.게시글목록보기(title);
return ResponseEntity.ok(Resp.ok(boardList));
}
깊은 복사 하러 간다
boardResponse 이동
원래는 content이런거 다 빼고 만들어야 한다
보드 서비드 이동
public List<BoardResponse.DTO> 게시글목록보기(String title) {
List<BoardResponse.DTO> dtos = new ArrayList<>();
List<Board> boardList = null;
//전체 결과
if(title == null){
//Pageable pg = PageRequest.of(0, 3, Sort.Direction.DESC, "id");
// 게시글 순서 거꾸로 만드려고
Sort sort = Sort.by(Sort.Direction.DESC, "id");
boardList = boardRepository.findAll(sort);
// 검색된 결과
}else {
boardList = boardRepository.mFindAll(title);
}
//엔티티를 dto로 이동
for(Board board : boardList){
BoardResponse.DTO dto = new BoardResponse.DTO(board);
dtos.add(dto);
}
return dtos;
// return boardList.stream().map(BaordResponse.DTO::new).toList();
}
스트림으로는 이런 방법이 있다
return boardList.stream().map(BaordResponse.DTO::new).toList();
ajax로 요청하면 ajax로 응답한다!!

패치 때리자 list이동
{{>layout/header}}
<form action="/text/form" method="post">
<input type="text" name="username">
<button>고고</button>
</form>
<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;
console.log(title);
//2. fetch 요청 이거는 따로 빼자
getBoardList(title);
});
</script>
{{>layout/footer}}
네모 틀을 잡아서 csr하는 것!!
실무에서는 한가지 더 해줘야 한다
글자 적을 때 마다 통신이 계속 일어난다
→ 엄청 많이 걸려서 서버 부하가 크다
제목5를 검색하고 싶은데 적으면 중간중간 검색되는 거 원치 않는다
그래서 시간 바운싱을 한다
1초로 잡으면 1초 지나면 바운싱 된다
바운싱 할 때 키보드 땔 때 발동할 수 도 있고 0.5초 뒤에 할 수 도 있다.
디바운스라 한다!
스로틀 과 디바운스가 있다
jquery에 발동한다!! 무조건 쓴다! 개념을 알고 있어야 한다!!
디바운스 → 마지막 것 만 때린다
스로틀 → 설정 시간으로 주는 것
처음에는 스로틀로 연습해보는게 좋다!
면접 질문 디바운스, 스로틀 설명
Share article