인프런 커뮤니티 질문&답변

챠챠_님의 프로필 이미지
챠챠_

작성한 질문수

[리뉴얼] React로 NodeBird SNS 만들기

swr 사용해보기

팔로워 3명씩 불러오고 데이터 합쳐주는걸로 바꾸고 서버요청을 무한으로하고있습니다.

작성

·

137

0

안녕하세요 제로초님.

강의중에 말씀해주셨건걸 참고해서

팔로워, 팔로잉을 3명 호출하고, 이후에 다음3명씩 호출하고 불러온 데이터를 합쳐서 리스트를 만드는식으로 바꿔봤습니다.

그런데 이슈가 한번 불러오기, 더보기 다 작동하는데 서버 요청을 무한으로 하고 있습니다.

어떤 부분을 수정해야할지 봐주실 수 있을까요?

limit은 3으로 고정, page를 조절해서 다음 3명씩
/pages/profile.js

import Head from "next/head";
import { useDispatch, useSelector } from "react-redux";
import { useCallback, useEffect, useState } from "react";
import { useRouter } from "next/router";
import axios from "axios";
import useSWR from "swr";

import { loadFollowersRequestAction, loadFollowingsRequestAction, loadMyInfo } from "../reducers/user";
import AppLayout from "../components/AppLayout";
import NicknameEditForm from "../components/NicknameEditForm";
import FollowList from "../components/FollowList";
import wrapper from "../store/configurStore";

const fetcher = (url) =>
	axios.get(url, { widthCredentials: true }).then((result) => {
		console.log("fetcher----------------------");
		return result.data;
	});

const Profile = () => {
	const router = useRouter();
	const dispatch = useDispatch();
	const { me } = useSelector((state) => state.user);
	const [followersLimit, setFollowersLimit] = useState(1);
	const [followingsimit, setFollowingsLimit] = useState(1);
	const [followers, setFollowers] = useState([]);
	const [followings, setFollowings] = useState([]);

	const {
		data: followersData,
		error: followerError,
		isLoading: followerLoading,
	} = useSWR(`http://localhost:3065/user/followers?page=${followersLimit}`, fetcher, {
		onSuccess: (data) => {
			setFollowers((prev) => [...prev, ...data]);
		},
	});
	const {
		data: followingsData,
		error: followingError,
		isLoading: followingLoading,
	} = useSWR(`http://localhost:3065/user/followings?page=${followingsimit}`, fetcher, {
		onSuccess: (data) => {
			setFollowings((prev) => [...prev, ...data]);
		},
	});

	useEffect(() => {
		if (!(me && me.id)) {
			router.push("/");
		}
	}, [me && me.id]);

	const loadMoreFollowings = useCallback(() => {
		setFollowingsLimit((prev) => prev + 1);
	}, []);
	const loadMoreFolloweers = useCallback(() => {
		setFollowersLimit((prev) => prev + 1);
	}, []);

	if (!me) {
		return <div>내정보 로딩중...</div>;
	}

	if (followerError || followingError) {
		console.error(followerError || followingError);
		return <div>팔로잉/팔로워 로딩 중 에러 발생...</div>;
	}
	return (
		<>
			<Head>
				<title>내 프로필 | NodeBird</title>
			</Head>
			<AppLayout>
				<NicknameEditForm />
				<FollowList header='팔로워' data={followers} onClickMore={loadMoreFolloweers} loading={followerLoading} />
				<FollowList header='팔로잉' data={followings} onClickMore={loadMoreFollowings} loading={followingLoading} />
			</AppLayout>
		</>
	);
};

export const getServerSideProps = wrapper.getServerSideProps((store) => async ({ req }) => {
	console.log(req.headers);
	const cookie = req ? req.headers.cookie : "";
	axios.defaults.headers.Cookie = "";
	if (req && cookie) {
		axios.defaults.headers.Cookie = cookie;
	}
	await store.dispatch(loadMyInfo());
});
export default Profile;

 

/routes/userl.js

// GET /user/followers 팔로워즈 불러오기
router.get("/followers", isLoggedIn, async (req, res, next) => {
	try {
		// 나를 먼저 찾고
		const user = await User.findOne({
			where: { id: req.user.id },
		});
		// 내 팔로워즈 get 하기
		const limit = parseInt(req.query.limit, 10) || 3; // 기본값 3
		const page = parseInt(req.query.page, 10) || 1; // 기본값 1
		const offset = (page - 1) * limit;
		const followers = await user.getFollowers({ limit, offset });
		res.status(200).json(followers);
	} catch (error) {
		console.error(error);
		next(error);
	}
});

// GET /user/followings 팔로잉즈 불러오기
// 미들웨어... (req, res, next) 이 콜백함수도 미들웨어
router.get("/followings", isLoggedIn, async (req, res, next) => {
	try {
		const user = await User.findOne({
			where: { id: req.user.id },
		});
		const limit = parseInt(req.query.limit, 10) || 3; // 기본값 3
		const page = parseInt(req.query.page, 10) || 1; // 기본값 1
		const offset = (page - 1) * limit;
		const followings = await user.getFollowings({ limit, offset });
		res.status(200).json(followings);
	} catch (error) {
		console.error(error);
		next(error);
	}
});

 

 

 

 

 

답변 2

0

챠챠_님의 프로필 이미지
챠챠_
질문자

다시 코드를 봐보니까, 호출하고 onSuccess에 state를 바꿔주면 컴포넌트를 리로드해주기 때문에 무한으로 호출하고 있는것 같습니다. 혹시 다른 좋은 방법이 있다면 추천해주실 수 있을까요? useSWRInfinite를 쓰는게 좋은방법일지 궁금합니다.

제로초(조현영)님의 프로필 이미지
제로초(조현영)
지식공유자

네 useSWRInfinite가 나아보이네요

0

안녕하세요, 인프런 AI 인턴입니다.

챠챠_ 님께서 겪고 계신 문제는 SWR 사용시 데이터를 무한으로 요청하는 이슈와 관련있습니다. 이러한 문제는 복수의 요인에 의해 발생할 수 있으나, 주로 요청의 의존성이나 요청 조건, SWR 구성의 오류로 인해 발생합니다.

챠챠_ 님의 코드를 보았을 때, 질문의 핵심은 SWR을 통해 서버로부터 데이터를 가져오되, 그 과정에서 예상치 않은 반복 요청이 발생하는 것입니다. 말씀하신대로 페이지네이션을 통해 3명씩 데이터를 추가로 불러오는 로직에서 이러한 현상이 나타난 것으로 보입니다.

비슷한 상황에서 해결 방안을 모색했던 다른 수강생의 질문과 답변이 있어 참고할만합니다. 예를 들어, ‘mutate’ 함수 사용 방식을 재검토하거나, SWR의 ‘revalidateOnFocus’ 등의 옵션을 조정하여 문제를 해결할 수 있습니다.

이와 관련하여 특정 부분에서 비슷한 문제를 겪었던 사례로, “팔로워,팔로잉 더보기 버튼시 3명씩 더불러오기가 수행되지 않습니다.” 질문에서 제공된 답변들을 살펴보시면 도움이 될 수 있습니다. 해당 사례는 직접 해당 문제를 해결한 것은 아니지만, 비슷한 문제를 다루면서 사용된 SWR 관련 구성 사항들을 확인하실 수 있습니다.

또한, “mutate 질문입니다!”의 사례에서는 mutate 함수 사용에 대한 질문과 답변이 있습니다. 여기서는 팔로잉, 팔로워 데이터를 업데이트 하는 동작에서 mutate 함수를 활용하는 방법을 논의하고 있습니다. 이러한 접근 방식은 데이터 업데이트 로직에서 발생할 수 있는 이슈를 해결하는 데 도움이 될 수 있습니다.

SWR과 관련된 문제 해결 방법을 찾으실 때는 공식 문서 및 커뮤니티에서 제공되는 다양한 사례들을 참조하시는 것도 좋습니다. SWR의 revalidation 전략, fetcher 함수의 구성, 그리고 콜백 함수들의 사용 방법 등을 면밀히 검토해 보세요.

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

챠챠_님의 프로필 이미지
챠챠_

작성한 질문수

질문하기