React native layout with flexbox

Dev-Yuns
Cross-Platform Korea
6 min readSep 26, 2021
Photo by Halacious on Unsplash

리액트 네이티브를 약 1년간 사용해오면서 flexbox 에 대해 잘 안다고 생각했는데, 최근 UI 컴포넌트를 만들다가 생각한대로 컴포넌트가 그려지지 않는 고통을 겪었습니다. 그래서 이번 기회에 flexbox 에 대해 다시 한번 정리해보는 시간을 가졌습니다.

What is flex

Flex란 컴포넌트가 축에 따라 차지할 공간과 위치를 결정해주는 디자인 시스템입니다. Flexbox 시스템을 이해하기 위해서는 메인 축(main axis)과 교차 축(cross axis)에 대한 개념을 잘 인지하고 있어야 합니다. 축의 방향에 따라 자기 자신이 공간을 차지하는 방법과 자식 컴포넌트를 정렬하거나 공간을 차지할 방법을 결정해줍니다. 만약 컴포넌트에 width나 height 값이 있다면, 해당 값이 우선 적용됩니다.

Main axis & Cross axis

axis (축)은 컴포넌트가 정렬되는 방향입니다. 기본적으로 부모 컴포넌트에서 자식 컴포넌트가 정렬되는 방향을 결정할 수 있습니다. 이를 flexDirection 이라고 합니다.

flexDirection의 값이 column 인 경우 main axis 는 y축이 됩니다. column 의 의미가 기둥인 것을 생각하면 세로로 블록이 쌓이는 것을 생각해볼 수 있습니다. 따라서 cross axis 의 방향은 x축이 됩니다.

반대로 값이 row 라면 main axis 는 x축이 되겠죠. 가로 방향으로 아이템이 정렬됩니다. cross axis 의 방향은 y축이 됩니다.

Flexbox in React native

리액트 네이티브의 레이아웃 시스템은 기본적으로 flexbox를 지원합니다. flexbox가 동작하는 방식은 web과 동일하지만, 몇 가지 예외가 있습니다. 예를 들어 기본 flexDirectioncolumn 이고, alignContentflex-start , justifyContentstretch 가 기본입니다.

JustifyContent와 AlignItems

JustifyContentAlignItems 는 축의 방향에 따라 자식 컴포넌트를 정렬하는 방법입니다. JustifyContent 는 메인 축 방향에 따라 자식들을 정렬하고, AlignItems 는 교차 축 방향에 따라 자식들을 정렬합니다.

리액트 네이티브에서 기본 flexDirection은 column이므로, 메인 축은 세로, 즉 y축이 되고 교차 축은 x축이 됩니다. 따라서 justfyContent는 세로 방향으로 자식을 정렬하고, alignItems는 가로 방향으로 자식들을 정렬합니다.

이때 동작 방식이 약간 헷갈릴 수 있는데, justifyContent는 기본 값이 flex-start로, 자식들을 세로 방향으로 위에서 아래로 정렬시킵니다.flex-start는 자식에게 width 값이 없다면 자식이 가질 수 있는 최소한의 공간만 가지도록 합니다. 만약 자식이 Text를 가지고 있는 View라면 Text 크기만큼만 공간을 차지하게 됩니다.

반면 alignItem의 기본값은 stretch이기 때문에, 교차축 방향으로 가질 수 있는 최대한의 공간을 가질 수 있도록 해줍니다. 따라서 가로 방향으로는 왼쪽에서 오른쪽까지 공간을 차지할 수 있습니다.

한 가지 주의할 점은 AlignItemsstretch 값을 주지 않고, flex-start 혹은 flex-start 등의 값을 준다면 자식 컴포넌트는 자신이 가질 수 있는 최소한의 값만 가지게 될 것입니다. 앞서 언급했듯이 컴포넌트가 아무 설정 없이도 공간을 넓게 차지하는 것은 기본적으로 alignItems 의 값이 stretch 이기 때문입니다. 물론 main axis의 방향이 flexDirection에 따라 바뀐다면 공간을 차지하는 방향 역시 바뀌게 될 것 입니다. 또한 여기서 설정한 값은 다음에 살펴볼 flex 값 혹은 alignSelf 값에 의해 override 될 수 있습니다.

Flex와 AlignSelf

JustifyContentAlignItems 가 자식 컴포넌트에 대한 정렬 방향과 차지할 공간 값을 조절했다면, Flex와 alignSelf 값은 자신에 대한 정렬 값을 결정할 수 있습니다. flex:1을 준다면 메인 축에 따라 자신이 차지할 수 있는 최대한의 공간을 차지하게 되고, alignSelf:stretch 값을 준다면 교차축을 따라 자신이 차지할 수 있는 최대한의 공간을 차지하게 됩니다. flex와 alignSelf 값은 부모 컴포넌트에서 결정한 justifyContent와 alignItems의 값을 override 합니다.

만약 부모 컴포넌트에서 alignItems: flex-start 를 통해 자식이 가질 수 있는 최소한의 값을 가지도록 값을 설정해도, 자식 컴포넌트에서 alignSelf:stretch 를 통해 형제 컴포넌트가 차지하고 있는 공간을 제외한 남은 공간을 모두 차지하도록 값을 override 할 수 있습니다.

min-width, min-height, max-width, max-height

Flex 값으로 전체적인 레이아웃을 잡을 수 있지만, 때로는 컴포넌트가 원하는 크기를 잡도록 하기 위해서 width 혹은 height 값을 줘야할 때가 있습니다. 기본적으로 리액트 네이티브에서 컴포넌트의 크기는 가지고 있는 content의 크기만큼만 차지합니다. 만약 width, height 값을 설정한다면, flex로 설정한 값과 다르게 동작할 수 있습니다. 특히 widthalignSelf 등을 함께 사용한다면 코드를 이해하기 어려워질 수 있어 피하는 것이 좋습니다.

min-height와 max-height는 flex-grow와 flex-shrink에 따라 컴포넌트 크기가 늘어나거나 줄어들 때, 줄어들 최소한 값과 늘어날 최대한의 값을 설정할 수 있습니다. flex와 width, height를 함께 사용할 때, 크기를 조절하기 쉬워집니다.

예제

앞서 살펴본 기본 개념을 가지고 몇 가지 예제를 만들어보았습니다. 스크롤을 천천히 내리면서 코드만 보고 어떤 화면이 그려질지 예측해보시고 결과를 보시면 좋을 것 같습니다.

예제 1

예제 1
예제1의 실행 결과

예제 2

두 번째 예제는 살짝 복잡하게 만들어 보았습니다. 아래 코드가 정확하게 예측이 된다면 flexbox에 대한 기본 개념을 이해하고 있다고 볼 수 있을 것 같습니다.

예제2
예제2의 결과

예제3

flex에 width 혹은 height 값을 섞어보았습니다.

예제3
예제3의 결과

위 예제가 만약 이해가 잘 안가신다면 playground에서 값을 바꿔가면서 연습해보시는 것을 추천드립니다.

--

--