목적 : 회원정보 페이지에 CSR 하기
1. API 컨트롤러 Json 리턴
@GetMapping("/s/api/user/{id}")
public ResponseDto<?> userInfo(@PathVariable Integer id) {
User userEntity = userService.회원정보(id);
return new ResponseDto<>(1, "성공", userEntity);
}
2. API 문서
(1) GET 요청
(2) /s/api/user/아이디
(3) 인증되어있어야 함
(4) 응답 : json
데이터를 프론트에 뿌리는 것
CSR, SSR을 모두 퍼블리싱이라고 한다.
3. 자바스크립트 ajax 요청 => fetch 요청
해당 페이지가 오픈될 때 fetch가 호출되어야 하네?
4. fetch 결과를 자바스크립트로 랜더링
<script>
async function loading() {
let userId = $("#userId").val();
let response = await fetch(`/s/api/user/${userId}`);
let responseParse = await response.json();
if (responseParse.code == 1) {
// CSR 시작
$("#username").val(responseParse.data.username);
$("#password").val(responseParse.data.password);
$("#email").val(responseParse.data.email);
$("#address").val(responseParse.data.address);
} else {
alert("잘못된 요청입니다.");
history.back(); // 뒤로가기
}
}
loading();
</script>
CSR 방식으로 글 목록 페이지를 만들어보자.
1. list.mustache 이동 시 -> 순수한 디자인만 주기
<!-- 컨테이너 시작 -->
<div class="container mt-3">
<!-- 게시글 아이템 시작 -->
<div id="post-box">
</div>
<!-- 게시글 아이템 끝 -->
<!-- 페이지 시작 -->
<ul class="pagination justify-content-center">
<li class="page-item disabled"><a class="page-link" href="?page=1">이전</a></li>
<li class="page-item"><a class="page-link" href="?page=1">다음</a></li>
</ul>
<!-- 페이지 시작 -->
</div>
<!-- 컨테이너 끝 -->
2. 해당 페이지 내부에서 fetch로 게시글 목록 다운로드하기
3 CSR
* 검색, 페이징, 오더 바이 신경 X findAll 사용 *
{{> /layout/header}}
<script>
async function list() {
let response = await fetch("/api/list");
let responseParse = await response.json();
if (responseParse.code == 1) {
for (post of responseParse.data) {
$("#post-box").append(render(post));
}
} else {
alert("실패");
}
}
function render(post) {
return `<div class="card mb-3">
<div class="card-body">
<h4 class="card-title">${post.title}</h4>
<a href="/post/${post.id}" class="btn btn-secondary">상세보기</a>
</div>
</div>`
}
list();
</script>
{{> /layout/footer}}
// PostApiController.java
@GetMapping("/api/list")
public ResponseDto<?> list() {
List<Post> postEntity = postService.글목록();
return new ResponseDto<>(1, "성공", postEntity);
}
// PostService.java
public List<Post> 글목록() {
return postRepository.findAll();
}
이제 for of 쓰지 말고 다른 메서드 쓰자.
responseParse.data.forEach((element) => { });
if (responseParse.code == 1) {
responseParse.data.forEach((post) => {
$("#post-box").append(postItemRender(post));
});
} else {
alert("잘못된 요청입니다.");
}
4. findAll(pageable); // 3건만 들고 오기
- 더미 데이터 5건 정도 만들고
- 3건만 select 되는지 브라우저로 테스트
- 안에 내용이 json이 어떻게 생겼는지 확인
- CSR 렌더링 할 때 post.content.title인가 content.post.title인가 다름
- 3건 뿌려봐
// PostService.java 페이징한거 아님 3개만 뿌리기 실습
public Page<Post> 글목록() {
PageRequest pq = PageRequest.of(0, 3);
return postRepository.findAll(pq);
}
@GetMapping("/api/post")
public ResponseDto<?> list() {
Page<Post> pagePosts = postService.글목록();
// 응답의 DTO를 만들어서 <- posts를 옮김 (라이브러리 있음)
return new ResponseDto<>(1, "성공", pagePosts);
}
json 생긴 거 확인
if (responseParse.code == 1) {
responseParse.data.content.forEach((post) => {
$("#post-box").append(postItemRender(post));
});
} else {
alert("잘못된 요청입니다.");
}
하이퍼링크를 클릭할 때마다 아래 리스트가 부분 리로드 되어야 한다.
하이퍼링크는 원래 페이지 새로고침 되어 데이터들이 날아가는데
ajax를 사용하기 때문에 부분 리로드 되어 변수가 계속 유지된다.
하이퍼링크 무효화 기억나지요?
{{> /layout/header}}
<!-- 컨테이너 시작 -->
<div class="container mt-3">
<!-- 게시글 아이템 시작 -->
<div id="post-box">
</div>
<!-- 게시글 아이템 끝 -->
<!-- 페이지 시작 -->
<ul class="pagination justify-content-center">
<li id="li-prev" class="page-item"><a id="btn-prev" class="page-link" href="javascript:;">이전</a></li>
<li id="li-next" class="page-item"><a id="btn-next" class="page-link" href="javascript:;">다음</a></li>
</ul>
<!-- 페이지 시작 -->
</div>
<!-- 컨테이너 끝 -->
<script>
let page = 0;
$("#btn-prev").click(() => {
page--;
console.log("현재 페이지 : " + page);
$("#post-box").empty();
list();
});
$("#btn-next").click(() => {
page++;
console.log("현재 페이지 : " + page);
$("#post-box").empty();
list();
});
function pagingDisabled(responseParse) {
if (responseParse.data.first == true) {
$("#li-prev").addClass("disabled");
$("#li-next").removeClass("disabled");
} else if (responseParse.data.last == true) {
$("#li-prev").removeClass("disabled");
$("#li-next").addClass("disabled");
} else {
$("#li-prev").removeClass("disabled");
$("#li-next").removeClass("disabled");
}
}
async function list() {
let response = await fetch(`/api/post?page=${page}`);
let responseParse = await response.json();
console.log(responseParse.data);
console.log(responseParse.data.content);
if (responseParse.code == 1) {
pagingDisabled(responseParse);
responseParse.data.content.forEach((post) => {
$("#post-box").append(postItemRender(post));
});
} else {
alert("잘못된 요청입니다.");
}
}
function postItemRender(post) {
return `<div class="card mb-3">
<div class="card-body">
<h4 class="card-title">${post.title}</h4>
<a href="/post/${post.id}" class="btn btn-secondary">상세보기</a>
</div>
</div>`;
}
list();
</script>
{{> /layout/footer}}
[출처]
https://cafe.naver.com/metacoding
메타코딩 : 네이버 카페
코린이들의 궁금증
cafe.naver.com
메타 코딩 유튜브
https://www.youtube.com/c/%EB%A9%94%ED%83%80%EC%BD%94%EB%94%A9
메타코딩
문의사항 : getinthere@naver.com 인스타그램 : https://www.instagram.com/meta4pm 깃헙 : https://github.com/codingspecialist 유료강좌 : https://www.easyupclass.com
www.youtube.com