#Frontend

항공 프론트엔드 구축기 (6/10): 컨테이너를 둘로 쪼개지 않았다

항공 프론트엔드 구축기 (6/10): 컨테이너를 둘로 쪼개지 않았다
01

Summary

웹과 앱 웹뷰를 한 방에 해결하는 기가 막힌 단일 레이아웃 컨테이너 설계법

각종 환경 분기와 복잡한 모바일 웹 브라우저 부작용을 단 한 줄의 조건식으로 잠재운 여기어때 항공의 실무 노하우

다양한 환경에 유연하게 대처하면서도 높은 유지보수성을 가져가는 프론트엔드 공통 레이아웃 설계 아키텍처를 소개합니다. 환경별로 불필요하게 컴포넌트를 쪼개는 대신 공통의 핵심 뼈대만 남기고, 브라우저 주소창, 기기별 회전 대응 여백, 헤더 그림자 제어 등은 전용 훅으로 정교하게 격리하는 실제 구현 전략을 배울 수 있습니다.

  • 01웹 브라우저의 가변적인 주소창 높이에 대응하는 100dvh와 앱 웹뷰 전용 100vh의 최소한의 분기 처리
  • 02디바이스 안전 영역(Safe Area)과 기기 회전 이벤트를 반응형으로 부드럽게 감지하는 전용 훅 적용
  • 03동적으로 높이가 계산되는 하단 영역의 레이아웃 시프트(CLS) 현상을 지연 렌더링 방식으로 우아하게 우회
  • 04헤더를 넘겨주기만 하면 스크롤 상단 진입/이탈 여부에 따라 그림자가 자동 처리되는 무상태 구조
  • 05불필요한 리렌더링을 차단하기 위해 스크롤 조작 기능과 스크롤 상태 구독 기능을 두 종류의 훅으로 이원화

RECOMMENDATION

하이브리드 앱이나 다양한 모바일 뷰포트를 일관되게 지원해야 하는 크로스 플랫폼 프론트엔드 개발자 및 공통 컴포넌트 아키텍처 최적화에 관심이 깊은 시니어 React 개발자에게 적극 추천합니다.

The Problem

웹, 모바일 웹, 앱 웹뷰 등 다양한 플랫폼을 동시에 대응해야 하는 상황에서 환경별로 레이아웃 컨테이너를 쪼개어 구현할 경우, 환경에 대한 개별 지식이 컴포넌트 내부에 중복 저장되어 코드 복잡도가 무한히 증가하는 문제가 있었습니다.

The Solution

컨테이너를 하나로 유지하면서 웹과 웹뷰를 가르는 환경 분기를 '전체 화면일 때의 높이 단위 결정(100dvh vs 100vh)' 단 한 줄로 축소하고, 나머지 환경 의존적 요소(뒤로가기, 세이프 에어리어, 화면 오버레이 등)는 하위 전용 훅과 개별 모듈로 이관하여 격리했습니다.

The Result

레이아웃 컨테이너는 오직 세 가지 속성(mode, header, bottomBar)만 주입받는 극도로 단순하고 재사용성 높은 형태로 정리되었으며, 동적 하단 바 렌더링 시 발생하는 레이아웃 시프트를 해결하고 스크롤 동작과 상태 관리 훅을 분리하여 리렌더링 성능 최적화를 달성했습니다.

Trade-off

모든 세부 환경 분기를 훅과 외부 모듈로 밀어내면서 전체를 통제하는 중앙화된 레이아웃 제어 코드가 사라졌으며, 뷰포트 크기가 실시간으로 동적으로 변할 때는 컴포넌트 외부에서 스크롤 대상 전환 등 일부 구체적인 제어 비용을 함께 감수해야 합니다.

03

Key Concepts

Concept · 01

Dynamic Viewport Height (dvh)

모바일 브라우저 주소창의 등장이나 사라짐에 따라 실시간으로 변하는 실제 뷰포트 높이를 동적으로 계산해 주는 최신 CSS 단위입니다.

  • 모바일 브라우저 환경에서 주소창 높이 변화로 하단 버튼이 잘리거나 화면이 갑자기 튀는 현상을 막기 위해 100dvh 단위를 도입했습니다.
  • 반면 주소창 변화가 없는 인앱 웹뷰 환경에서는 고정 100vh를 적용해 불필요한 높이 갱신 연산을 줄였습니다.
Concept · 02

Layout Shift (레이아웃 시프트)

렌더링 이후 비동기적으로 추가 데이터가 로드되거나 요소의 높이가 재조정되면서 기존 화면 요소들의 레이아웃이 덜컥거리며 순간적으로 밀려나는 현상입니다.

  • 높이를 그리기 전까지는 알 수 없는 가변형 하단 바(Bottom Bar) 때문에 본문 영역 스크롤이 생겼다 사라지는 문제를 진단했습니다.
  • 크기 측정이 완료될 때까지 하단 바를 화면 하단에 일시 고정(Fixed)시켜 초기 렌더링 시 레이아웃 흔들림 현상을 완전 방지했습니다.
Concept · 03

Performance Hook Splitting

React 환경에서 빈번하게 발생하는 상태 변화(State)로 인한 리렌더링 오버헤드를 막기 위해 상태값 전달과 단순 함수/액션(Action) 전달을 별개 훅으로 쪼개는 기법입니다.

  • 단순히 스크롤 이동 함수만 호출하는 컴포넌트가 스크롤이 매 픽셀 움직일 때마다 불필요하게 리렌더링되는 성능 낭비를 감지했습니다.
  • 이 문제를 해결하고자 useLayoutContainerActions()와 useLayoutContainerState() 두 갈래 훅으로 분리 구현하여 렌더링 효율을 극대화했습니다.