이것저것/React.js

[React] 반응형으로 항상 화면에 꽉 찬 컴포넌트 만들기

Im_Hayden 2024. 7. 26. 15:53

01. 문제 상황

현재 진행중인 프로젝트에서, 꽉 찬 컴포넌트를 만들어야 할 일이 생겼다.
그를 위해 찾아보니 가장 많이 보이는 해결책이 vw, vh 단위를 사용하는 것이다.
그러나 이 방법을 프로젝트에 적용시켜보니 그리 좋은 해결책은 아닌것 같다는 생각이 들었다.
이유는 아래와 같다.

    1. vw, vh 단위는 브라우저의 스크롤 영역까지를 포함시킨 뷰포트 크기를 반환한다.
    • 이런 이유로 언제 브라우저에 스크롤바가 생겨서 사이트가 깨질지 알 수 없다.
    1. 1번과 같은 맥락으로, 모바일에서 사용하기 난처하다.
    • 모바일에는 기본적으로 네비게이션바, 노치 등이 포함되어 있으므로 100vh 등을 적용하면 페이지가 넘친다.

02. 해결 방법

해결방법은 간단했다.
바로 innerHeight(innerWidth)와 props, 이벤트 리스너를 사용하는 방법이다.

  1. props로 width 크기와 height 크기 변수, 해당 값을 제어할 훅을 만든다.
  2. 브라우저의 크기가 변경되는 resize 동작이 발생할 경우 실행할 이벤트 핸들러를 정의한다.
    • 이때 이벤트 핸들러에서 훅을 사용하여컴포넌트의 사이즈를 innerHeight로 변경한다.
  3. 이벤트리스너에서 resize가 감지되면 위에서 정의한 핸들러를 호출한다.
  4. 한번 위의 과정을 코드로 구현해보자.

03. 코드

const Background = ({child})=>{

    const [width, setWidth] = useState(window.innerWidth)
    const [height, setHeight] = useState(window.innerHeight)

    const resizeHandler = (()=>{
        setWidth(window.innerWidth)
        setHeight(window.innerHeight)
    })

    useEffect(()=>{
        window.addEventListener('resize', resizeHandler)
        return ()=>window.removeEventListener('resize', resizeHandler)
    }, [])

    return (
        <div style={{width:`${width}px`, height:`${height}px`, backgroundColor:'red'}}>
            {width}, {height} <br></br>
            {child}
        </div>
    )
}

 

  1. window.innerWidth(innerHeight) 를 통해 스크롤바 등의 영역을 뺀 이너 뷰포트의 크기를 얻을 수 있다.
  2. width, height에 관한 훅을 설정한다.
  3. 브라우저의 크기가 변경되면 실행될 핸들러를 정의한다.
  4. 이벤트 핸들러를 등록한다.
    • 여기서 useEffect()는 컴포넌트가 렌더링 될때 실행되는 함수이다.
      • useEffect() 밖에서 이벤트를 등록해도 정상적으로 동작하지만, 이런 경우에는 컴포넌트가 등록되어있지 않아도 계속해서 이벤트를 감지한다.
      • 이를 위해 실제 화면에 컴포넌트가 있을 경우에만 이벤트를 감지하도록 useEffect() 안에서 이벤트를 등록시켰다.

04. 실행 결과

전체 화면

 

축소 화면

이처럼 브라우저의 크기가 변경되어도 컴포넌트가 항상 꽉 찬 상태를 유지한다.