게시글이 늘어날 경우를 대비해서 부분적으로 불러올 수 있는 관련 메서드를 찾아봤습니다.
mongoose에서 제공하는 limit() 메서드를 사용하면 조건을 줘서 일부 doc만 불러올 수 있다고 합니다.
아래 참고 링크의 내용을 간략하게 보자면 find() 메소드를 사용하면 모든 document 들을 출력해주기 때문에
limit() 메소드와 skip() 메소드를 통하여 보이는 출력물의 갯수를 제한 할 수 있다고 합니다.
server 코드
아래처럼 체이닝으로 넣어주고 limit(5)로 설정하여 5개의 doc만 불러올 수 있게 하였습니다.
router.post("/list", (req, res) => {
let sort = {};
if (req.body.sort === "최신글") {
sort.createdAt = -1;
} else {
sort.repleNum = -1;
}
Post.find({
//제목이나 내용 둘중 하나에만 걸려도 return으로 $or사용
$or: [
////$regex = cient에서 search 값이 포함 되는 데이터 찾아줍니다.
{ title: { $regex: req.body.search } },
{ content: { $regex: req.body.search } },
],
})
.populate("author")
.sort(sort)
.limit(5) //한번에 찾을 doc의 숫자
.exec()
.then((doc) => {
res.status(200).json({ success: true, postList: doc });
})
.catch((err) => {
res.status(400).json({ success: false });
console.log(err);
});
});
limit() 관련 참고 https://velopert.com/516
[MongoDB] 강좌 4편 find() 메소드 활용 – sort(), limit(), skip() | VELOPERT.LOG
이번 강좌에선 find() 메소드를 더욱 더 활용하기 위해 필요한 sort(), limit(), skip() 메소드에 대해 배워보겠습니다. 그냥 find() 메소드를 사용하면 criteria 에 일치하는 모든 document 들을 출력해주기
velopert.com
클릭시 게시글을 더 불러올 수 있는 버튼을 만들어줍니다.
버튼은 framer의 motion을 사용해서 만들었습니다.
const [loadMore, setLoadMore] = useState(true);
<FooterDiv>
<motion.button
className="square"
whileHover={{ scaleX: 1.2 }}
>
<img src={more} alt="더보기" />
</motion.button>
</FooterDiv>
버튼 참조 https://www.framer.com/motion/
client 코드
useState로 skip을 0으로 초기 설정하고
setSkip에 postList의 length를 주고
body에 넣어서 server에 보냅니다.
const [skip, setSkip] = useState(0);
const getPostLoadMore = () => {
let body = {
sort: sort,
search: search,
skip: skip,
};
axios
.post("/api/post/list", body)
.then((res) => {
if (res.data.success) {
//0 ~ 4번째 들고옴 5개
setPostList([...res.data.postList]);
setSkip(res.data.postList.length);
}
})
.catch((err) => {
console.log(err);
});
};
server 코드
client에서 body로 보낸 skip(req.body.skip)을 추가해 줍니다.
router.post("/list", (req, res) => {
let sort = {};
if (req.body.sort === "최신글") {
sort.createdAt = -1;
} else {
//인기글
sort.repleNum = -1;
}
Post.find({
$or: [
{ title: { $regex: req.body.search } },
{ content: { $regex: req.body.search } },
],
})
.populate("author")
.sort(sort)
//skip초기값 0이라 0~4까지 게시글을 찾습니다.
.skip(req.body.skip)
.limit(5) //한번에 찾을 doc의 숫자
.exec()
.then((doc) => {
res.status(200).json({ success: true, postList: doc });
})
.catch((err) => {
res.status(400).json({ success: false });
console.log(err);
});
});
버튼에 getPostLoadMore 함수를 만들어 줍니다.
<FooterDiv>
<motion.button
className="square"
whileHover={{ scaleX: 1.2 }}
onClick={getPostLoadMore}
>
<img src={more} alt="더보기" />
</motion.button>
</FooterDiv>
더 불러오기 버튼 클릭시 기존 5개 게시글 뒤로 이어서 불러오는게 아니라
기존 5개글 자리에 대체되어 기존글 사라지는 현상 발생.
getPostLoadMore 함수에서 코드 수정
기존에 들고 있던 postList도 같이 넣어줘서 기존 글이랑 더 불러온 글 대체 현상 해결
setPostList([...postList, ...res.data.postList]);
코드 수정 skip 추가
setSkip(skip + res.data.postList.length);
글 limit 5개로 정했는데 서버에 글이 7개라면 5개 불러오고 나머지 2개를 불러오는 현상 발생시 더 불러오기 버튼 사라지게..
const [loadMore, setLoadMore] = useState(true);
서버 게시글 length 5개 이하일 때 false로 설정
if (res.data.postList.length < 5) {
setLoadMore(false);
}
true 일 때 버튼 보이고 false 일 때 버튼 사라집니다.
{loadMore && (
<FooterDiv>
<motion.button
className="square"
whileHover={{ scaleX: 1.2 }}
onClick={getPostLoadMore}
>
<img src={more} alt="더보기" />
</motion.button>
</FooterDiv>
)}
게시글 검색 기능 함수
const listChange = () => {
setSkip(0);
let body = {
sort: sort,
search: search,
skip: 0,
};
axios
.post("/api/post/list", body)
.then((res) => {
console.log(res);
if (res.data.success) {
//0 ~ 4번째 들고옴 5개
setPostList([...res.data.postList]);
setSkip(res.data.postList.length);
if (res.data.postList.length < 5) {
setLoadMore(false);
}
if (res.data.postList.length === 0) {
setLoadMore(false);
}
setLoading(true);
}
})
.catch((err) => {
console.log(err);
});
};