본문 바로가기
개발개발/LifeGraph_인생그래프

[인생 그래프] 반응형 버그 해결

by yelimu 2025. 2. 20.

 

푸터 추가할 겸 사이트 보다가 버그를 발견했다.

아래 두 개 gif의 차이점이 보이나요?

before
after

 

그래프 영역의 너비가 줄어들지 않아도 윈도우 너비가 변하면 그래프가 같이 축소되고있다.

윈도우 너비에 반응하도록 구현해두었기 때문에 발생한 문제이다.

파란 테두리 안쪽 영역(.border)의 최대 너비를 1200px에서 900px로 줄이면서 이 문제를 알아채게 되었다. 

이전에 반응형 테스트할때 최대 너비 이상으로는 늘려보지 않았던게 패착이었다. 

즉 1200px 이내에서만 너비를 늘리고, 줄이는 테스트를 했기때문에 항상 그래프 영역의 너비도 줄어들었던 것이다. 

 

//기존 코드
const [width, setWidth] = useState(window.innerWidth);
const [prevWidth, setPrevWidth] = useState(window.innerWidth);

기존에는 width와 prevWidth를 window.innerWidth 를 초기값으로 했는데 이를 0 으로 하고, 

 

(컴포넌트가 마운트 될때)

useEffect 내부에서 ResizeObserver 를 사용하여, ref로 관찰하고 있는 DOM 요소 의 크기 변화를 감지한다.

-> 이를 setWidth 로 설정한다.

 

(컴포넌트 언마운트 될때) 

Observer 해제 

import { useEffect, useRef, useState } from "react";
import { useGraphStore } from "../store/useGraphStore";
import { PointData } from "../types/pointType";
import debounce from "../util/debounce";

const useMovePointByWidth = () => {
  const containerRef = useRef<HTMLDivElement | null>(null); // 기준이 될 DOM 요소

  const [width, setWidth] = useState(0);
  const [prevWidth, setPrevWidth] = useState(0);
  const { points, setPoints } = useGraphStore();

  // 특정 DOM 리사이즈 감지

  useEffect(() => {
    if (!containerRef.current) return; 

    const updateWidth = () => {
      if (containerRef.current) {
        setWidth(containerRef.current.clientWidth);
      }
    };

    // 디바운스 적용
    const debouncedUpdateWidth = debounce(updateWidth, 200);

    // ResizeObserver로 감지
    const observer = new ResizeObserver(debouncedUpdateWidth);
    observer.observe(containerRef.current);

    // 초기 값 설정
    updateWidth();

    return () => observer.disconnect();
  }, []);

  useEffect(() => {
    // 이미 저장된 points x좌표 조정
    if (width !== prevWidth && prevWidth !== 0) {
      const newPoints: PointData[] = points.map((point) => ({ ...point, x: point.x * (width / prevWidth) }));
      setPoints(newPoints);
    }
    setPrevWidth(width);
  }, [width, points, prevWidth]);

  return { width, points, containerRef };
};

export default useMovePointByWidth;

 

그리고 나머지 코드는 동일하게 초기값 width가 prevWidth와 달라지면 전체 point의 x 값을 재조정하여 setPoints에 넘겨준다.

containerRef 를 함께 return한다

 

const GraphContainer = ({
  children,
  onClick,
}: Props) => {
  const { containerRef } = useMovePointByWidth();

  return (
    <div className="graph-wrapper" ref={containerRef}>
      <div className="graph-container" onClick={onClick}>
        {children}
      </div>
    </div>
  );
};

export default GraphContainer;

가장 바깥쪽 div 인 graph-wrapper에 ref를 추가한다. => 해당 DOM 을 관찰하게 된다


ResizeObserver 라는 걸 제공하고 있었다니!

이번 프로젝트에서 사용한 것처럼 window 너비가 아니라 특정 DOM 요소 크기 변화를 감지할때 유용하다

 

완성샷은 뿌듯하니까 한번 더 ! ㅎㅎㅎ

그래프 바깥쪽 여백의 너비가 변할때는 Point가 조정되지 않고, 내부 div가 변할때만 조정 된다 ㅎㅎ 

아우 깜빡임 눈아파

after
이미지를 클릭하면 사이트로 이동합니다.