본문 바로가기
웹 프론트/React

React : 모바일 사파리 focus, blur 이벤트 감지 훅 만들어보기 (useWindowFocus)

by 번데기 개발자 2024. 4. 24.
반응형

 

IOS Safari 브라우저에서 window.focus 및 window.blur가 제대로 동작하지 않는 문제

 

`Focus` 이벤트는 브라우저 창, 탭, 팝업이 사용자로부터 포커스를 받았을대 호출되는 이벤트로, 사용자가 브라우저창을 클릭하거나 다른 애플리케이션에서 현재 창으로 들어왔을때 쓰이는 등 여러 상황에서 자주 사용이 되는 이벤트입니다. `Blur` 이벤트는 반대로 사용자가 페이지를 떠나거나 다른 탭으로 이동했을때 발생되는 이벤트입니다.

 

하지만 IOS Safari 브라우저를 개발하다보면 Window의 Focus, Blur 이벤트를 등록을 했는데도 제대로 동작하지 않을때가 있습니다.  (IOS에서는 탭 간 전환시 비활성화/ 활성화가 브라우저처럼 제대로 구분되어 있지 않은것 같다고 합니다.)

 

 

visibilitychange 이벤트


focus blur가 제대로 동작하지 않는 문제의 해결방법으로는 focus와 blur 이벤트의 대안으로  `visibilitychange` 이벤트를 이용할수 있습니다. 해당 이벤트는 브라우저가 탭을 변경하거나 다른 애플리케이션으로 전환할때 발생하는 이벤트로 HTML5의 Visibility API의 일부로 개발되었습니다. 

 

속성은 총 visible, hidden 으로 2개가 존재하며 `visible` 속성은 페이지가 보일때 호출되는 이벤트로 window의 focus 이벤트와 유사하며, `hidden` 속성은 페이지가 보이지 않을때 호출되는 이벤트로 window의 blur 이벤트와 유사합니다. 

 

 

useWindowFocus 훅 만들어보기

 

위와 같은 속성을 이용해서 사용할 수 있는 모바일 IOS Safari에서 동작할 수 있는 Focus 이벤트를 감지하는 React Hooks을 만들어보도록 하겠습니다. 

 

const isIOS = () => {
  return navigator.userAgent.match(/iPhone|iPad|iPod/i)
}

export default function useWindowFocus(onFocusCallback, onBlurCallback) {
  useEffect(() => {
    /** AOS일때 focus 함수 적용 **/
    const onWindowFocus = () => {
      onFocusCallback()
    }

    const onWindowBlur = () => {
      onBlurCallback()
    }

    /** IOS일때 focus 함수 적용 **/
    const onVisibilityChange = () => {
      if (!document.hidden) {
        onFocusCallback()
      } else {
        onBlurCallback()
      }
    }

    if (isIOS) {
      document.addEventListener('visibilitychange', onVisibilityChange)
      document.addEventListener('webkitvisibilitychange', onVisibilityChange)
    } else {
      window.addEventListener('focus', onWindowFocus)
      window.addEventListener('blur', onWindowBlur)
    }

    return () => {
      if (isIOS) {
        document.removeEventListener('visibilitychange', onVisibilityChange)
        document.removeEventListener('webkitvisibilitychange', onVisibilityChange)
      } else {
        window.removeEventListener('focus', onWindowFocus)
        window.addEventListener('blur', onWindowBlur)
      }
    }
  }, [])

  return null
}

 

이후에 React 컴포넌트에서 다음과 같이 등록해서 사용하실 수 있습니다.

 

import useWindowFocus from './hooks/useWindowFocus.jsx'

export default function App() {
  /** 화면에서 나갔을때 **/
  const onWindowBlur = () => {
    // 여기에 원하는 동작 구현
  }

  /** 화면으로 복귀했을때 **/
  const onWindowFocus = () => {
    // 여기에 원하는 동작 구현
  }

  useWindowFocus(onWindowFocus, onWindowBlur)
  
  ...
  ...
}
 
추가적으로 `webkitvisibilitychange` 는 구버전의 브라우저을 지원하기 위한 속성으로 `visibilitychange` 와 동일하게 동작합니다. 
 

 

마무리

 

오늘은 모바일 Safari 에서 Window의 Focus, Blur 이벤트가 제대로 동작하지 않는 문제를 해결하기 위한 방법을 알아보고 이에 대한 custom hook을 만들어보았습니다.

 

앞으로도 유용한 기능들에 대한 Custom hook을 시간이 될때  만들어서 공유해보도록 하겠습니다.

 

반응형