Wanna be Brilliant Full-Stack Developer

2/16 SpringBoot 포토리스트 뷰 렌더링하기 본문

Back-End/Spring Boot

2/16 SpringBoot 포토리스트 뷰 렌더링하기

Flashpacker 2022. 2. 16. 12:11


목표 

화면에 뿌리는 AJAX 호출을 해볼것이다!

 

스토리 로드하기 부분 story.js를 구현을 해보려고한다!

/**
	2. 스토리 페이지
	(1) 스토리 로드하기
	(2) 스토리 스크롤 페이징하기
	(3) 좋아요, 안좋아요
	(4) 댓글쓰기
	(5) 댓글삭제
 */

// (1) 스토리 로드하기
function storyLoad() {
	$ajax({
		url: `/api/image`,
		dataType: "json"
	}).done(res=> {
		console.log(res);
	}).fail(error=>{
		console.log("오류",error);
	});
}

storyLoad();

function getStoryItem() {

}

// (2) 스토리 스크롤 페이징하기
$(window).scroll(() => {

});


// (3) 좋아요, 안좋아요
function toggleLike() {
	let likeIcon = $("#storyLikeIcon-1");
	if (likeIcon.hasClass("far")) {
		likeIcon.addClass("fas");
		likeIcon.addClass("active");
		likeIcon.removeClass("far");
	} else {
		likeIcon.removeClass("fas");
		likeIcon.removeClass("active");
		likeIcon.addClass("far");
	}
}

// (4) 댓글쓰기
function addComment() {

	let commentInput = $("#storyCommentInput-1");
	let commentList = $("#storyCommentList-1");

	let data = {
		content: commentInput.val()
	}

	if (data.content === "") {
		alert("댓글을 작성해주세요!");
		return;
	}

	let content = `
			  <div class="sl__item__contents__comment" id="storyCommentItem-2""> 
			    <p>
			      <b>GilDong :</b>
			      댓글 샘플입니다.
			    </p>
			    <button><i class="fas fa-times"></i></button>
			  </div>
	`;
	commentList.prepend(content);
	commentInput.val("");
}

// (5) 댓글 삭제
function deleteComment() {

}

애를 기반으로 스토리에 이미지를 뿌려야하는데! 

 

/**
	2. 스토리 페이지
	(1) 스토리 로드하기
	(2) 스토리 스크롤 페이징하기
	(3) 좋아요, 안좋아요
	(4) 댓글쓰기
	(5) 댓글삭제
 */

// (1) 스토리 로드하기
function storyLoad() {
	$.ajax({
		url: `/api/image`,
		dataType: "json"
	}).done(res=> {
		console.log(res);
		res.data.forEach((image)=>{
			let storyItem = getStoryItem();
			$("#storyList").append(storyItem);
		});
	}).fail(error=>{
		console.log("오류",error);
	});
}

storyLoad();

function getStoryItem() {
	let item =`<div class="story-list__item">
	<div class="sl__item__header">
		<div>
			<img class="profile-image" src="#"
				onerror="this.src='/images/person.jpeg'" />
		</div>
		<div>TherePrograming</div>
	</div>

	<div class="sl__item__img">
		<img src="/images/home.jpg" />
	</div>

	<div class="sl__item__contents">
		<div class="sl__item__contents__icon">

			<button>
				<i class="fas fa-heart active" id="storyLikeIcon-1" onclick="toggleLike()"></i>
	</button>
</div>

<span class="like"><b id="storyLikeCount-1">3 </b>likes</span>

<div class="sl__item__contents__content">
	<p>등산하는 것이 너무 재밌네요</p>
</div>

<div id="storyCommentList-1">

	<div class="sl__item__contents__comment" id="storyCommentItem-1"">
		<p>
			<b>Lovely :</b> 부럽습니다.
		</p>

		<button>
			<i class="fas fa-times"></i>
		</button>

	</div>

</div>

<div class="sl__item__input">
	<input type="text" placeholder="댓글 달기..." id="storyCommentInput-1" />
	<button type="button" onClick="addComment()">게시</button>
		</div>

	</div>
</div>`;
	return item;
}

// (2) 스토리 스크롤 페이징하기
$(window).scroll(() => {

});


// (3) 좋아요, 안좋아요
function toggleLike() {
	let likeIcon = $("#storyLikeIcon-1");
	if (likeIcon.hasClass("far")) {
		likeIcon.addClass("fas");
		likeIcon.addClass("active");
		likeIcon.removeClass("far");
	} else {
		likeIcon.removeClass("fas");
		likeIcon.removeClass("active");
		likeIcon.addClass("far");
	}
}

// (4) 댓글쓰기
function addComment() {

	let commentInput = $("#storyCommentInput-1");
	let commentList = $("#storyCommentList-1");

	let data = {
		content: commentInput.val()
	}

	if (data.content === "") {
		alert("댓글을 작성해주세요!");
		return;
	}

	let content = `
			  <div class="sl__item__contents__comment" id="storyCommentItem-2""> 
			    <p>
			      <b>GilDong :</b>
			      댓글 샘플입니다.
			    </p>
			    <button><i class="fas fa-times"></i></button>
			  </div>
	`;
	commentList.prepend(content);
	commentInput.val("");
}

// (5) 댓글 삭제
function deleteComment() {

}

이제 이미지랑 데이터만 바꿔주면된다! 

/**
	2. 스토리 페이지
	(1) 스토리 로드하기
	(2) 스토리 스크롤 페이징하기
	(3) 좋아요, 안좋아요
	(4) 댓글쓰기
	(5) 댓글삭제
 */

// (1) 스토리 로드하기
function storyLoad() {
	$.ajax({
		url: `/api/image`,
		dataType: "json"
	}).done(res=> {
		console.log(res);
		res.data.forEach((image)=>{
			let storyItem = getStoryItem(image);
			$("#storyList").append(storyItem);
		});
	}).fail(error=>{
		console.log("오류",error);
	});
}

storyLoad();

function getStoryItem(image) {
	let item =`<div class="story-list__item">
	<div class="sl__item__header">
		<div>
			<img class="profile-image" src="/upload/${image.user.profileImageUrl}"
				onerror="this.src='/images/person.jpeg'" />
		</div>
		<div>${image.user.username}</div>
	</div>

	<div class="sl__item__img">
		<img src="/upload/${image.postImageUrl}" />
	</div>

	<div class="sl__item__contents">
		<div class="sl__item__contents__icon">

			<button>
				<i class="fas fa-heart active" id="storyLikeIcon-1" onclick="toggleLike()"></i>
	</button>
</div>

<span class="like"><b id="storyLikeCount-1">3 </b>likes</span>

<div class="sl__item__contents__content">
	<p>${image.caption}</p>
</div>

<div id="storyCommentList-1">

	<div class="sl__item__contents__comment" id="storyCommentItem-1"">
		<p>
			<b>Lovely :</b> 부럽습니다.
		</p>

		<button>
			<i class="fas fa-times"></i>
		</button>

	</div>

</div>

<div class="sl__item__input">
	<input type="text" placeholder="댓글 달기..." id="storyCommentInput-1" />
	<button type="button" onClick="addComment()">게시</button>
		</div>

	</div>
</div>`;
	return item;
}

// (2) 스토리 스크롤 페이징하기
$(window).scroll(() => {

});


// (3) 좋아요, 안좋아요
function toggleLike() {
	let likeIcon = $("#storyLikeIcon-1");
	if (likeIcon.hasClass("far")) {
		likeIcon.addClass("fas");
		likeIcon.addClass("active");
		likeIcon.removeClass("far");
	} else {
		likeIcon.removeClass("fas");
		likeIcon.removeClass("active");
		likeIcon.addClass("far");
	}
}

// (4) 댓글쓰기
function addComment() {

	let commentInput = $("#storyCommentInput-1");
	let commentList = $("#storyCommentList-1");

	let data = {
		content: commentInput.val()
	}

	if (data.content === "") {
		alert("댓글을 작성해주세요!");
		return;
	}

	let content = `
			  <div class="sl__item__contents__comment" id="storyCommentItem-2""> 
			    <p>
			      <b>GilDong :</b>
			      댓글 샘플입니다.
			    </p>
			    <button><i class="fas fa-times"></i></button>
			  </div>
	`;
	commentList.prepend(content);
	commentInput.val("");
}

// (5) 댓글 삭제
function deleteComment() {

}

페이징을 할것이다!  너무 사진이 많아서 3개씩만 보고싶다? 하면 페이징이라는것을 해야하는데! 

첫번쨰로 페이징 하려면 이미지API컨트롤러에서 

package com.cos.photogramstart.web.api;

import java.util.List;

import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.web.PageableDefault;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import com.cos.photogramstart.config.auth.PrincipalDetails;
import com.cos.photogramstart.domain.image.Image;
import com.cos.photogramstart.service.ImageService;
import com.cos.photogramstart.web.dto.CMRespDto;

import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor
@RestController
public class ImageApiController {

	private final ImageService imageService;
	
	@GetMapping("/api/image")
	public ResponseEntity<?> imageStory(@AuthenticationPrincipal PrincipalDetails principalDetails,
			@PageableDefault(size=3, sort ="id", direction =Sort.Direction.DESC) Pageable pageable){
		List<Image>	images = imageService.이미지스토리(principalDetails.getUser().getId(), pageable);
		return new ResponseEntity<>(new CMRespDto<>(1,"성공",images), HttpStatus.OK);
	}
}

@PageableDefault() Pageable pageable 이 어노테이션을 붙이면 무엇을 할 수 있냐면 

pageable를 이용해서 페이징을 할 수 있다! 

그리고 pageable을 서비스에 보내면 이미지스토리에서 애가 받게 될텐데

	@Transactional(readOnly = true) // 영속성 컨텍스트 변경 감지를 해서, 더티체킹, flush(반영) 
	public List<Image> 이미지스토리(int principalId, Pageable pageable) {
		List<Image> images = imageRepository.mStory(principalId, pageable);
		return images;
	}
package com.cos.photogramstart.domain.image;

import java.util.List;

import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;

public interface ImageRepository extends JpaRepository<Image, Integer> {

	@Query(value = "SELECT * FROM image WHERE userId IN (SELECT toUserId FROM subscribe WHERE fromUserId = :principalId);", nativeQuery = true)
	List<Image> mStory(int principalId, Pageable pageable);
}

 

mStory를 가져올때 pageable을 통해서 세건씩 정렬해서 최신순해서 id로 가져온다! 

/**
	2. 스토리 페이지
	(1) 스토리 로드하기
	(2) 스토리 스크롤 페이징하기
	(3) 좋아요, 안좋아요
	(4) 댓글쓰기
	(5) 댓글삭제
 */

// (1) 스토리 로드하기
function storyLoad() {
	$.ajax({
		url: `/api/image`,
		dataType: "json"
	}).done(res=> {
		console.log(res);
		res.data.content.forEach((image)=>{
			let storyItem = getStoryItem(image);
			$("#storyList").append(storyItem);
		});
	}).fail(error=>{
		console.log("오류",error);
	});
}

storyLoad();

function getStoryItem(image) {
	let item =`<div class="story-list__item">
	<div class="sl__item__header">
		<div>
			<img class="profile-image" src="/upload/${image.user.profileImageUrl}"
				onerror="this.src='/images/person.jpeg'" />
		</div>
		<div>${image.user.username}</div>
	</div>

	<div class="sl__item__img">
		<img src="/upload/${image.postImageUrl}" />
	</div>

	<div class="sl__item__contents">
		<div class="sl__item__contents__icon">

			<button>
				<i class="fas fa-heart active" id="storyLikeIcon-1" onclick="toggleLike()"></i>
	</button>
</div>

<span class="like"><b id="storyLikeCount-1">3 </b>likes</span>

<div class="sl__item__contents__content">
	<p>${image.caption}</p>
</div>

<div id="storyCommentList-1">

	<div class="sl__item__contents__comment" id="storyCommentItem-1"">
		<p>
			<b>Lovely :</b> 부럽습니다.
		</p>

		<button>
			<i class="fas fa-times"></i>
		</button>

	</div>

</div>

<div class="sl__item__input">
	<input type="text" placeholder="댓글 달기..." id="storyCommentInput-1" />
	<button type="button" onClick="addComment()">게시</button>
		</div>

	</div>
</div>`;
	return item;
}

// (2) 스토리 스크롤 페이징하기
$(window).scroll(() => {

});


// (3) 좋아요, 안좋아요
function toggleLike() {
	let likeIcon = $("#storyLikeIcon-1");
	if (likeIcon.hasClass("far")) {
		likeIcon.addClass("fas");
		likeIcon.addClass("active");
		likeIcon.removeClass("far");
	} else {
		likeIcon.removeClass("fas");
		likeIcon.removeClass("active");
		likeIcon.addClass("far");
	}
}

// (4) 댓글쓰기
function addComment() {

	let commentInput = $("#storyCommentInput-1");
	let commentList = $("#storyCommentList-1");

	let data = {
		content: commentInput.val()
	}

	if (data.content === "") {
		alert("댓글을 작성해주세요!");
		return;
	}

	let content = `
			  <div class="sl__item__contents__comment" id="storyCommentItem-2""> 
			    <p>
			      <b>GilDong :</b>
			      댓글 샘플입니다.
			    </p>
			    <button><i class="fas fa-times"></i></button>
			  </div>
	`;
	commentList.prepend(content);
	commentInput.val("");
}

// (5) 댓글 삭제
function deleteComment() {

}

페이징은 완료가 되었는데 우리가 스크롤이 끝났을떄 스크롤 로딩이라는것을 할것이다!