Coding History/Team Project

팀플) 행성데이터 연결 및 로그인 로그아웃 UI 처리

BlackBirdIT 2024. 11. 20. 10:59

이거 컨트롤러랑 서비스 준비는 해둠 사실.

근데 캐싱은 안만져놔서 해놓자고

@Cacheable(value = "planetVisibility", key = "#planetName + '-' + #latitude + '-' + #longitude + '-' + #startDate + '-' + #rangeDays")
@Retryable(value = {RestClientException.class}, maxAttempts = 3, backoff = @Backoff(delay = 1000))

캐싱 설정도 했고, @Retryable은 재시도 로직인데 Spring Retry의존성 주입해서 사용함. 이런게 있길래 넣어둠.

여튼 백엔드 준비는 끝남.

그래서 이제 프론트 작성하고 요청 해봤는데

이게 백엔드 로직이 파라미터가 date인데 start_date로 해놨더라..

여튼 수정하고 해봄.

수정 하고 하니까 백엔드에는 로그가 올바르게 찍힘

근데 에러 로그가 있음.

이걸 이제 살펴보니까

아까 추가한 Redis문제였음

그래서 이게 문젠줄 알고 하루종일 고치다가 로그를 자세히 보니까 요청 들어온 순간에 서버가 꺼졌다 켜져서 로직이 꼬이는 것 같아서 그냥 DevTools설정을 재시작 안하게끔 바꾸니까.

데이터는 가져옴 근데 로그 찍힌 순서 보니까 약간 문제 있는듯.

그니까 로딩 상태던, 위치가 확정이 된 상태건을 확실하게 해줘야될듯.


이것도 수정해서 이제 데이터는 잘 가져옴, 로그인한 유저에 대한 맞춤 데이터도 잘 가져오고

근데 문제는 기존의 화면 랜더링이 제대로 작동하지 않음.

이 화면에서 다음 애니매이션이 동작하면서 넘어가야되는데 안넘어감 ㅠㅠ


화면도 제대로 뜨게 고쳤고,

데이터도 잘 가져옴. 로그인 한 회원 것도 마찬가지. 이제 넘겨주면 될듯.

에러 처리도 404로 리다이렉트하게 처리함.

const PlanetPage = () => {
    const { location, isLoading } = useUserLocation(); // 위치 정보
    const {isAuthenticated, user, isAuthLoading} = useAuth(); // 인증 정보

    const [bodyClass, setBodyClass] = useState("opening hide-UI view-2D zoom-large data-close controls-close");
    const [solarSystemClass, setSolarSystemClass] = useState("earth");
    const [isDataOpen, setIsDataOpen] = useState(false);
    const [previousPlanet, setPreviousPlanet] = useState(null);
    const [isPlanetPopupOpen, setPlanetPopupOpen] = useState(false);
    const [scaleFactor, setScaleFactor] = useState(1);

    const navigate = useNavigate();

    const [locationSaved, setLocationSaved] = useState(false);
    const [saveError, setSaveError] = useState(null);

    const [planetData, setPlanetData] = useState({}); // 모든 행성 데이터를 저장
    const [dataLoading, setDataLoading] = useState(true);
    const [fetchError, setFetchError] = useState(null);

    const today = new Date().toISOString().split("T")[0];
    const rangeDays = "7";

    const planetsApi = ["Mercury", "Venus", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune"];

    useEffect(() => {
        console.log('PlanetPage - useEffect 실행됨. isLoading 상태:', isLoading);
        if (isLoading || !location) {
            console.log('위치 정보가 아직 설정되지 않았거나 로딩 중입니다.');
            return;
        }

        const fetchAllPlanets = async () => {
            setDataLoading(true);
            console.log("Fetching all planet data...");
            try {
                const responses = await Promise.all(
                    planetsApi.map((planet) =>
                        axios
                            .get(`/planet/visibility`, {
                                params: {
                                    planetName: planet,
                                    latitude: location.latitude,
                                    longitude: location.longitude,
                                    date: today,
                                    rangeDays,
                                },
                            })
                            .then((response) => {
                                console.log(`Planet ${planet} response:`, response.data);
                                return { planet, data: response.data };
                            })
                            .catch((error) => {
                                console.error(`Error fetching data for ${planet}:`, error);
                                throw error; // 에러를 상위 try-catch로 전달
                            })
                    )
                );

                const allData = {};
                responses.forEach(({ planet, data }) => {
                    if (data) {
                        allData[planet] = data;
                    }
                });

                setPlanetData(allData);
            } catch (error) {
                console.error("Error fetching all planet data:", error);

                // Toast 메시지와 리다이렉트 처리
                toast.error("행성 데이터를 가져오는 중 오류가 발생했습니다. 404 페이지로 이동합니다...", {
                    position: "top-center",
                    autoClose: 3000,
                });

                setTimeout(() => {
                    navigate('/react/404');
                }, 3000); // 3초 후 리다이렉트
            } finally {
                setDataLoading(false);
                console.log("Finished fetching planet data.");
            }
        };

        fetchAllPlanets();
    }, [location, isLoading]);

// 위치 데이터 서버로 전송
    useEffect(() => {
        const saveLocation = async () => {
            if (!isAuthenticated || !location || locationSaved) return;

            console.log("Saving location to server...");
            try {
                const response = await sendLocationToServer({
                    userId: user.id,
                    latitude: location.latitude,
                    longitude: location.longitude,
                });
                console.log("Location saved successfully:", response);
                setLocationSaved(true);
            } catch (error) {
                console.error("Error saving location:", error);

                // Toast 메시지 출력
                toast.error("위치 데이터를 저장하는 중 오류가 발생했습니다. 나중에 다시 시도해주세요.", {
                    position: "top-center",
                    autoClose: 3000,
                });

                // 에러 코드에 따라 404 또는 다른 페이지로 리다이렉트
                if (error.response && error.response.status === 404) {
                    // 404 에러인 경우 리다이렉트
                    setTimeout(() => {
                        navigate('/react/404');
                    }, 3000); // 3초 후 리다이렉트
                } else {
                    // 기타 에러 처리
                    toast.error("알 수 없는 오류가 발생했습니다.", {
                        position: "top-center",
                        autoClose: 3000,
                    });
                }
            }
        };

        saveLocation();
    }, [isAuthenticated, location, locationSaved, user, navigate]);

해당 부분이 내가 추가한 부분.


아! 여담으로 로그인 처리도 명확하게 toast UI로 처리함.

    const { isAuthenticated } = useAuth();

    useEffect(() => {
        const hasShownToast = sessionStorage.getItem("hasShownLoginToast");

        if (isAuthenticated && !hasShownToast) {
            toast.success("로그인에 성공했습니다!", {
                position: "top-center",
                autoClose: 2000, // 2초 후 닫힘
            });
            sessionStorage.setItem("hasShownLoginToast", "true"); // 메시지가 출력되었음을 기록
        }
    }, [isAuthenticated]);

메인 페이지 안에 이런 함수를 넣음. 처음엔 session을 채택하지 않고 메세지 출력 여부로 했는데 새로고침하니까 계속 메세지가 떠서 이렇게 처리하니까 잘 됨.

하는 김에 로그아웃 처리도 함.

첨에는 비회원이 메인페이지 접근할 때 마다 떠서 난감했는데 useEffect의 의존성 배열의 조건을 조금 더 빡빡하게 줘서 해결함.