오늘의 고민: 느린 페이지 로딩, 어떻게 해결할까?

lionloopy·2025년 1월 13일
0

오늘의 고민

목록 보기
4/6
post-thumbnail

상황

챗봇을 관리하는 관리자 사이트에서 한 페이지에 접속할 때 유독 로딩이 느린 페이지가 있었다.
페이지 접속 자체가 느리다보니 당연히 사용하는데엔 불편함이 있었고, 페이지를 넘길 때 또한 느리게 동작했다

인터넷 조금만 느려도 불편한데, 관리자가 관리해야하는 페이지가 느리다면 어떻겠는가!
그래서 어떻게 해결할 수 있을까 고민되었다.

아 참, 그리고 여기서 조건은 Angular를 사용해야 한다는 점 !

원인파악

1. 불필요한 api 호출

일단 개발자 도구 빠르게 키고, api 호출부터 살펴봤다.
그런데 이 때 진짜 불필요한 api가 계속 호출되고 있었다.

⛏️문제:
config.js에서 불필요한 reference_data를 호출하게 되는데, 이 함수에 api 호출이 걸려있었고
config.js에 걸려있어서 검색, 페이지 바뀔 때, 초기 페이지 접속 등 계속 호출이 됐다.
그런데 해당 api는 인텐트와 학습 데이터를 모두 긁어오는 풀스캔 ..
무려 60,000개 정도의 데이터를 긁어오는 무서운 놈이었다..

reference_data: function(ReinforceManagerService, $stateParams) {
                    return ReinforceManagerService.reference_data($stateParams);
                 },

⚒️해결:
재빠르게 불필요한 데이터가 맞는지 확인했고
진짜로 불필요한 데이터였다..
바-로 제거했다

2. 매번 불러오는 1000개의 데이터

두번째로는 모달창 클릭 시 select box가 나오고 거기서 1000개의 데이터 중 1개의 데이터를 선택하는 부분이 있다.

⛏️문제:
이 때 모달창 클릭도 전에 페이지 접속 시 1000개의 데이터를 미리 불러오도록 api를 호출했다.

이 때 이 데이터는 바뀔 가능성이 없는 데이터이다. 계속 동일한 데이터이며
key-value값만 있으면 된다.

그런데 페이지 접속할 때 마다 1000개의 데이터를 불러오고, 우리의 앵귤러는 친절하게
양방향 바인딩
을 하고.. 느려질 수 밖에 없었다.

⚒️해결:
처음 페이지에 접속할 때 1번만 세션 스토리지에 데이터를 key-value로 넣고
세션스토리지에서 꺼내서 해당 데이터 정보를 쓰도록 했다.

    // 처음 입장할 때만 데이터 목록 가져와서 세션스토리지에 담음
	// 일부 코드는 비공개
    function reference_data() {
        default_params = {a_id:$stateParams.a_id,b_id:$stateParams.b_id}
        return $http({
            method: 'GET',
            url: '-',
            params: default_params
        })
        .then(function(response) {
            if (response.data.intent) {
                Object.entries(response.data.intent).forEach(function([key, value]) {
                    sessionStorage.setItem(key, value);
                });
            }

            // 세션스토리지에 담은 후 함수 실행
            return initReinforceItemModel($scope);
        }, function(response) {
            return null;
        });
    }

그러나 난 아직도 아쉬워!

그러나 난 아직도 아쉽다.. 아직도 고민에 배가 고프다..
앵귤러가 아니었다면 더 효율적으로 개선할 수 있지 않았을까?

세션스토리지에 담는 건 사실 효율적인 방법이라고 생각하지 않는다.
페이지 속도가 개선 됐으니 효율적이라고 할 수 있을 뿐.

리액트 쿼리 캐싱

react query는 선언적으로 캐싱을 관리할 수 있다. api 호출 횟수를 줄이고 데이터 재사용성을 높이는데 유용하다.

  • staleTime:
    - 데이터가 '신선한 상태'로 간주되는 시간
    • staletime이 지나지 않으면 리액트 쿼리는 네트워크 요청을 보내지 않고, 캐시 데이터를 반환한다.
      => 불필요한 api 호출을 줄일 수 있음!!
  • cacheTime:
    - 데이터가 메모리에서 캐시로 유지되는 시간
    • cacheTime이 지나면 캐시 데이터를 삭제한다. 이 때 기본값은 5분
  • 자동 재요청:
    - 데이터가 오래된 상태가 되면, 자동으로 새 데이터를 요청한다.
const fetchReferenceData = async () => {
  const response = await fetch('-');
  return response.json();
};

export function useReferenceData() {
  return useQuery('referenceData', fetchReferenceData, {
    staleTime: 15 * 60 * 1000, // 15분 동안 데이터 신선 상태 유지
    cacheTime: 30 * 60 * 1000, // 30분 동안 캐시 유지
    refetchOnWindowFocus: false, // 포커스 변경 시 재요청 방지
  });
}

이렇게 api 한 번 호출하고 데이터를 캐시해서 사용할 수 있다.
무려 리액트 쿼리로 손쉽게 !!

마치며

사실 해당 구현은 꽤 급하게 구현해야 했던 부분이었고,
앵귤러의 한계도 어느정도 있었다고 생각한다.

그러나 어떻게 하면 페이지 로딩 속도를 높일 수 있을지 고민했던 것에 대해
한 번 더 성장한 느낌이 들었다!
오늘도 이렇게 조그마한 성장 성공..!

혹시나 더 효과적인 방법을 아시는 분들이 계신다면 댓글 부탁드립니다! (_ _)

profile
기록은 담백하게, 성장은 빠르게! 🐘

0개의 댓글