Search

웹뷰 엔지니어를 위한 iOS Webview Input 경험 개선기

URL
생성 일시
2026/02/23 05:06
최종 편집 일시
2026/02/23 05:06
태그
당근
파일과 미디어
|| 안녕하세요. 당근 커뮤니티실에서 Software Engineer로 일하고 있는 Dave예요. 저는 지난 4년간 웹뷰 기반의 커뮤니티 당근모임을 만들어 왔어요. 당근모임 당근의 커뮤니티 서비스인 동네생활에서 이웃들과 일상을 공유하고, 모임에서 같은 관심사를 가진 사람들과 대화하며, 카페에서 특정 주제로 정보를 나누고 이야기하는 등 유저 간 게시글, 댓글, 채팅을 통해 소통하는 순간이 많은데요. 그렇다 보니 커뮤니티 프로덕트에서의 Input은 단순한 폼 요소가 아니라 유저 경험을 좌우하는 핵심 인터랙션이었어요. 문제는 이 입력 경험이 웹뷰 환경에서 이루어진다는 점이었는데요. 웹뷰에서는 가상 키보드, Focus, Viewport 같은 OS 레벨 동작을 완전히 제어하기 어렵고, 특히 iOS에서는 키보드가 올라올 때 화면이 밀리는 문제가 유저의 흐름을 쉽게 끊어버렸어요. 그래서 이번 글에서는 이 문제를 해결하기 위해 겪었던 시행착오들을 기록해 보려고 해요. 문제의 발견 iOS 웹뷰에서 input에 focus가 되면, 화면 하단의 input을 키보드 위로 보이게 하기 위해 페이지 전체가 위로 밀려 올라가요. 이때 상단 콘텐츠가 화면 밖으로 사라지게 되는데, 이 동작은 웹 개발자가 제어할 수 없었어요. iOS input focus 기본 동작 우선 이 현상을 이해하려면 두 가지 Viewport 개념을 알아야 하는데요. Layout Viewport: CSS 레이아웃 기준 영역이에요. 키보드가 올라와도 크기가 변하지 않아요. Visual Viewport: 실제로 사용자 눈에 보이는 영역이에요. 키보드가 올라오면 그만큼 줄어들어요. 키보드가 올라오면 Visual Viewport만 줄어들고, Layout Viewport는 그대로 유지돼요. 이 차이 때문에 iOS는 focus된 input을 보이게 하려고 페이지 전체를 밀어올리는 것이죠. 첫번째 시도 — resize 가장 먼저 떠올린 방법은 단순했어요. iOS가 밀어 올리면, 그냥 다시 내리자. visualViewport의 resize 이벤트를 감지해서 키보드 높이만큼 wrapper를 축소하고, window.scrollTo(0, 0)로 밀린 스크롤을 되돌리는 방식이에요. function Approach1() { const { keyboardHeight, isKeyboardOn } = useVisualViewport(); // visualViewport 변경될 때마다 스크롤을 원점으로 되돌림 useEffect(() => { const handler = () => window.scrollTo(0, 0); window.visualViewport?.addEventListener("resize", handler); window.visualViewport?.addEventListener("scroll", handler); return () => { /* cleanup */ }; }, []); return ( <div style={{ position: "fixed", top: 0, left: 0, right: 0, bottom: isKeyboardOn ? keyboardHeight : 0, // 키보드 높이만큼 축소 }}> <div style={{ flex: 1, overflowY: "auto" }}>{/* 컨텐츠 */}</div> <footer> <input placeholder="댓글을 입력해주세요." /> </footer> </div> ); }한계첫번째 시도의 결과물 문제는 scrollTo가 호출되기 전에 이미 화면이 밀려 올라간다는 거예요. iOS가 페이지를 밀고 → resize 이벤트가 발생하고 → 그제서야 scrollTo로 복구하니까, 사용자 눈에는 화