글과 댓글이 계속 겹쳐보일때, flex-1을 의심하자

flex-1이 아니라 사실 나를 의심하자..🌀

2025년 4월 17일

React Native 앱 배포 후 레이아웃 깨짐 현상 분석 및 해결

현상 요약

배포된 앱에서 댓글과 본문이 겹쳐 보이는 UI 레이아웃 문제가 발생했습니다.

  • expo go 환경에서는 발생하지 않음
  • development buildeas build 환경에서 간헐적으로 발생
  • 특정 사용자 행동과 관련 없이 불규칙하게 발생
앱 화면
본문과 댓글이 겹쳐 보이는 현상
댓글 앱화면
댓글 영역 레이아웃 깨짐

원인 추정 과정

고려한 가능성:

  1. expo go와 빌드 환경의 차이
  2. 빌드 환경에서 댓글 데이터 응답이 느려지는 현상
  3. FlatList 사용 방식 문제
  4. 댓글 입력 후 본문과 댓글 리스트를 동시에 refetch하면서 발생하는 비동기 타이밍 차이

디버깅 방법

2번과 4번을 고려했을 때, content 영역의 높이 변화가 의심되어 onLayout으로 실제 렌더링 시 높이를 추적했습니다.

확인 결과, 실제 크기(예: height: 355)가 찍힌 후 height: 0으로 변경되는 것을 발견했습니다. 높이가 0이 되는 순간 댓글이 위로 올라와 본문과 겹치는 것이었습니다.


왜 높이가 0이 될까? (feat. flex-1의 오남용)

문제의 본질은 부모 컨테이너의 높이가 명확하지 않은 상황에서 flex-1을 무분별하게 사용한 것이었습니다.

flex: 1은 가능한 공간을 전부 채우려고 시도합니다. 하지만 부모의 높이가 0이면 자신도 height: 0이 됩니다.

ChallengeContainer 내부에 flex-1이 있었고, 부모 높이가 정해지지 않은 상태에서 높이가 0이 되어버렸습니다. 댓글 Item 컴포넌트에도 flex-1을 적용해서 서로 남는 공간을 차지하려다 겹치는 문제가 발생했습니다.

본문 컴포넌트와 댓글 항목 모두에 flex-1을 준 것이 원인이었습니다.


flex 속성 이해하기

flex는 flex-grow, flex-shrink, flex-basis를 한 번에 지정하는 속성입니다.

flex-grow

  • flex-basis보다 늘어날 수 있는지 결정
  • 기본값: 0 (원래 크기 유지)
  • 1 이상이면 나머지 여백을 해당 비율로 나눠 가짐

flex-shrink

  • flex-basis보다 줄어들 수 있는지 결정
  • 기본값: 1
  • 0이면 고정 너비

flex-basis

  • flex item의 기본 크기
  • 기본값: auto
  • flex-direction이 row면 너비, column이면 높이

flex: 1을 풀면 다음과 같습니다:

점유 크기를 0으로 만든 후 화면 비율에 따라 늘어나거나 줄어들 수 있다는 의미입니다.

FlatList와의 관계

FlatList는 내부 항목의 높이를 기준으로 가상화 렌더링을 수행합니다. flex-1이 적용된 항목은 높이가 부모 기준으로 동적으로 바뀌기 때문에, FlatList가 예상하지 못한 방식으로 렌더링합니다.

✅ FlatList 내부 항목에는 flex-1을 지양하고, 콘텐츠 기반 높이를 사용하는 것이 안정적입니다.


expo go 환경에서는 왜 정상 작동했는가?

expo go는 개발용 환경으로 다음과 같은 특성이 있습니다:

  • FlatList virtualization이 완화됨
  • 레이아웃 측정 오류 발생 시 내부적으로 보정(reflow) 수행
  • 실제 배포 환경에서 발생할 오류를 감추는 경향

expo go에서는 문제가 숨겨진 채 정상 작동하는 것처럼 보였던 것입니다.


해결 방법

  • 댓글 항목 및 본문에 사용된 flex-1 속성 제거
  • 레이아웃에 의존하는 컴포넌트는 부모 높이를 명확히 지정하거나 flex-1 사용 자제

마무리

React Native 첫 개발에서 flex-1을 이해하지 않고 사용한 것이 문제였습니다. 이번 경험을 통해 개발/빌드 환경의 차이점, flex: 1의 동작 원리, FlatList의 렌더링 방식을 더 깊이 이해하게 되었습니다.

🌀 급할수록 돌아가자 🌀