Skip to main content

Command Palette

Search for a command to run...

화면 사이즈가 변화하는 걸 잘 감지하는 방법

브라우저 창 사이즈가 변경되는 걸 더 효율적으로 감지할 수 있는 방법을 기록했습니다.

Updated
2 min read

Resize 이벤트

인터넷에 검색했을 때 화면 사이즈가 변경되는 걸 감지하는 방법은 resize 이벤트를 감지하여 콜백 함수를 실행하게 하는 것이다.

브라우저 창이 최소 1픽셀씩 변경될 때마다 매번 콜백 함수가 실행되므로 비효율적이며 웹 페이지의 성능에 악영향을 줄 수 있다.

창 크기가 변경되었을 때 변경된 엘리먼트의 크기를 구하려면 getBoundingClientRect 메소드를 실행해야 하는데 호출하게 되면 브라우저는 모든 엘리먼트의 스타일과 레이아웃을 재계산하는 Reflow가 발생한다.

useEffect(() => {
  useEffect(() => {
    const onResize = function (event: UIEvent) {
      console.log("Resizing...");
    };
    window.addEventListener("resize", onResize);
    return () => {
      window.removeEventListener("resize", onResize);
    };
  }, []);
}, []);

Resize Observer

Resize Observer로 특정 엘리먼트가 변화할 때 함수를 호출하도록 할 수 있다.

브라우저 창이 변경하면 document.body 엘리먼트가 변화하는 걸 이용하여 옵저버로 body 엘리먼트를 관찰하게 한다.

각 엔트리마다 contentRect로 엘리먼트의 레이아웃 정보를 가져올 수 있다.

React 프로젝트에서는 useEffect에 옵저버를 선언 후 엘리먼트를 관찰하고 관찰을 해제하는 함수를 반환하도록 한다.

const onResize = useCallback(() => {
  console.log("Resizing...");
}, []);
useEffect(() => {
  const observer = new ResizeObserver((entries) => {
    entries.forEach((entry) => {
      if (entry.target.isSameNode(document.body)) {
        console.log(entry.contentRect);
        onResize();
      }
    });
  });

  observer.observe(document.body);
  return () => {
    observer.disconnect();
  };
}, [onResize]);

useMediaQuery

만약 특정 사이즈 이하일 때만 컴포넌트를 렌더링하거나 특정 함수를 실행시키고 싶으면 Window 객체의 matchMedia 메소드를 적용할 수 있다.

메소드가 반환하는 객체에 이벤트 리스너를 설정해서 창 크기가 변할 때마다 인자로 주어진 조건에 해당하는지 알 수 있다.

React 프론트엔드에서는 window 객체의 상태와 동기화하기 위해 useSyncExternalStore를 사용할 수 있다.

  • SSR 환경에서는 서버에서도 렌더링이 발생하기 때문에 getServerSnapshot 인자도 전달해야 한다.
// ./src/hooks/useMediaQuery.ts
import { useCallback, useSyncExternalStore } from "react";

export interface UseMediaQueryProps {
  query?: string;
}

const getServerSnapshot = () => null;

const useMediaQuery = (props: UseMediaQueryProps) => {
  const { query } = props;

  const onSubscribe = useCallback(
    (onStoreChange: () => unknown) => {
      if (!query) {
        return () => {};
      }
      const matchMedia = window.matchMedia(query);
      matchMedia.addEventListener("change", onStoreChange);
      return () => {
        matchMedia.removeEventListener("change", onStoreChange);
      };
    },
    [query]
  );

  const onSnapshot = useCallback(() => {
    if (!query) {
      return false;
    }
    return window.matchMedia(query).matches;
  }, [query]);

  return useSyncExternalStore(onSubscribe, onSnapshot, getServerSnapshot);
};

export default useMediaQuery;

// ./src/Example.tsx
export default function Example() {
  const isMobileSize = useMediaQuery({
    query: "(max-width: 480px)",
  });
  const isTabletSize = useMediaQuery({
    query: "(min-width: 480px) and (max-width: 720px)",
  });

  if (isMobileSize) {
    return <ExampleMobile />;
  }
  if (isTabletSize) {
    return <ExampleTablet />;
  }
  return <Example />;
}

More from this blog

AI 에이전트에서 작업 맥락을 관리하기 위해 사용한 방법

AI 에이전트의 불편함 Codex CLI와 같은 AI 코딩 에이전트를 통해서 프로젝트 개발 속도를 높일 수 있다. 그리고 혼자 작업했을 때는 놓칠 수 있는 부분도 발생할 수 있는데 AI 에이전트를 통해 보완할 수 있었다. 컴포넌트에 대해서 접근성 태그 작성 API 호출하는 비동기 코드 작성할 때 에러 처리 그리고 AI 에이전트를 잘 활용하면 불가능하

Mar 8, 202610 min read

지시사항을 분할하여 Codex로 효율적인 작업하기

이슈 Codex와 같은 AI 기반 코드 에이전트는 출력 토큰의 수가 제한되어 있다. 그래서 다양한 작업을 하나의 프롬프트에 전부 몰아서 작성하면 원하는 결과가 나오지 않을 수 있다. Codex와 같은 LLM 기반 서비스는 출력 토큰 수를 초과하게 되면 일부 단계가 누락되거나 특정 요소를 과하게 요약할 수 있고 이는 전체적인 답변 퀄리티를 낮출 수 있기 때문이다. 그래서 다양한 AI 공식문서는 특정 작업을 더 작은 단위로 분할하는 방식을 강조한다...

Nov 3, 20255 min read

Key를 활용하여 컴포넌트 상태를 초기화하기

개요 컴포넌트의 상태가 업데이트되어도 컴포넌트 내부에 배치된 컴포넌트의 상태는 그대로 유지되는 경우가 있었다. 예전에는 Props 전달 및 내부에서 useEffect를 통해서 상태를 초기 상태로 업데이트하도록 했는데 useEffect를 남용하게 되면 상태 변화 추적이 어려워지는 문제가 있었다. 그런데 useEffect 외에도 Key를 통해서 컴포넌트 상태를 초기화할 수 있다는 사실을 알게 되었다. 리스트 렌더링 React 프론트엔드에서 목록 형...

Sep 21, 20253 min read

내가 AGENTS.md를 작성하는 방법

Codex CLI 요즘 프로젝트 개발에 Codex CLI를 활용하는 이유는 다음과 같다. 특정 프로젝트를 작업할 때 Claude Code는 종종 사용량을 초과한 것과 다르게 Codex CLI는 ChatGPT Plus 요금제만으로도 토큰 사용량 초과 걱정 없이 충분하게 활용할 수 있었다. 타 CLI 기반 AI 개발 도구에 비해서 요구사항을 더 정확하게 구현하고 꼭 필요한 작업만 진행하기 때문에 코드를 검토하는 시간을 줄일 수 있다. 반복적인 코드...

Sep 21, 20254 min read
N

Nowon Lee

22 posts