똑같은 기능을 가진 페이지이지만 그 구성이 다른 것을 확인할 수 있습니다.
이러한 차이는 OS가 다르기 때문입니다. 좌측은 iOS 기기에서 네이버 검색을 들어갔을 때 노출되는 페이지이고, 우측은 aOS 기기에서 네이버 검색을 들어갔을 때 노출되는 페이지입니다.
클라이언트에서 페이지 개발을 진행할 때는 이런 키패드 유무에 대한 파악과 대응이 크게 어렵지 않습니다. 기본적으로 이러한 기능들을 제공하기 때문이죠. 하지만 웹뷰를 개발하는 상황이라면 이야기가 다릅니다. 따로 키패드의 유무를 파악할 수 있는 메서드가 존재하지 않기 떄문에 다른 방법으로 이를 파악하고 대응해야 합니다.
window.innerHeight
해당 값을 통해 화면 전체의 높이값을 파악할 수 있다. (이 값은 OS별로 크기가 다른데 그에 대한 상세한 정보는 실제 사례와 함께 설명할 예정입니다.)
window.visualViewport.height
눈에 보이는 화면에 대한 높이값을 파악할 수 있다.
aOS의 경우 window.innerHeight
값과 window.visualViewport.height
값은 키패드를 제외한 푸른색 영역으로 동일합니다.
window.innerHeight
값이 키패드를 제외한 영역으로 잡히기 때문에 기존에 아래에 위치했던 요소들도 당연히 키패드 위쪽으로 자연스럽게 이동하게 됩니다.
키패드가 노출되지 않은 상태에서의 window.innerHeight
값을 기억해두었다가 window.innerHeight
혹은 window.visualViewport.height
값이 변화했을 때 두 값을 비교해서 키패드의 유무를 파악할 수 있습니다.
const App = () => {
const fullHeight = useRef(0);
useEffect(() => {
const handleVisualViewportResize = () => {
// aOS에서 키패드가 노출된 경우
if (fullHeight.current > window.innerHeight) {}
}
fullHeight.current = window.innerHeight;
visualViewport.addEventListener('resize', handleVisualViewportResize);
return () => visualViewport.removeEventListener('resize', handleVisualViewportResize);
}, [])
}
iOS의 경우는 aOS의 동작과는 다른 형태를 보여줍니다. window.innerHeight
값은 키패드 유무와 관계없이 항상 화면 전체(푸른색 영역)의 높이값을 가지게 됩니다.
window.visualViewport.height
값은 aOS와 동일하게 키패드 영역을 제외한 영역의 높이값이 됩니다.
해당 동작이 가능한 이유는 iOS에서는 키패드가 노출되었을 때 키패드 뒤쪽에 가상의 영역이 생기기 때문입니다. 이로 인해 버튼은 키패드 뒤쪽에 가려진 상태로 노출되게 됩니다. (보다 쉬운 이해를 위해 사진에서는 버튼을 앞쪽에 배치하였습니다.)
이러한 특징을 통해 우리는 window.innerHeight
값이 window.visualViewport.height
값보다 더 큰 순간이 iOS에서 키패드가 노출된 순간이라는 것을 알 수 있습니다.
const App = () => {
useEffect(() => {
const handleVisualViewportResize = () => {
// iOS에서 키패드가 노출된 순간
if (window.innerHeight > window.visualViewport.height) {}
}
}, [])
visualViewport.addEventListener('resize', handleVisualViewportResize);
return () => visualViewport.removeEventListener('resize', handleVisualViewportResize);
}