플렉스 박스를 활용한 레이아웃
컴포넌트는 플렉스 박스 알고리즘을 사용해 자식 엘리먼트의 레이아웃을 지정할 수 있다. 플렉스 박스는 다양한 화면 크기에서 일관된 레이아웃을 제공하도록 설계되었다.
일반적으로 flexDirection
, alignItems
, justifyContent
를 조합해 원하는 레이아웃을 구현한다.
플렉스 박스는 웹의 CSS와 동일하게 동작하지만 몇 가지 차이점이 있다.
기본값이 다르다. flexDirection
은 기본값이 row
가 아닌 column
이고, alignContent
는 stretch
가 아닌 flex-start
이며, flexShrink
는 1
이 아닌 0
이다. 또한 flex
파라미터는 단일 숫자만 지원한다.
플렉스 박스
flex
는 메인 축을 따라 사용 가능한 공간을 아이템들이 어떻게 "채울지" 정의한다. 각 엘리먼트의 flex 속성에 따라 공간이 나뉜다.
다음 예제에서 빨간색, 주황색, 초록색 뷰는 모두 flex: 1
이 설정된 컨테이너 뷰의 자식 엘리먼트다. 빨간색 뷰는 flex: 1
, 주황색 뷰는 flex: 2
, 초록색 뷰는 flex: 3
을 사용한다. 1+2+3 = 6이므로, 빨간색 뷰는 전체 공간의 1/6
, 주황색 뷰는 2/6
, 초록색 뷰는 3/6
을 차지한다.
플렉스 방향
flexDirection
은 노드의 자식 요소들이 배치되는 방향을 제어한다. 이를 메인 축이라고도 부른다. 크로스 축은 메인 축에 수직인 축으로, 줄바꿈이 발생할 때 요소가 배치되는 방향이다.
-
column
(기본값): 자식 요소를 위에서 아래로 정렬한다. 줄바꿈이 활성화된 경우, 다음 줄은 컨테이너 상단의 첫 번째 아이템 오른쪽에서 시작한다. -
row
: 자식 요소를 왼쪽에서 오른쪽으로 정렬한다. 줄바꿈이 활성화된 경우, 다음 줄은 컨테이너 왼쪽의 첫 번째 아이템 아래에서 시작한다. -
column-reverse
: 자식 요소를 아래에서 위로 정렬한다. 줄바꿈이 활성화된 경우, 다음 줄은 컨테이너 하단의 첫 번째 아이템 오른쪽에서 시작한다. -
row-reverse
: 자식 요소를 오른쪽에서 왼쪽으로 정렬한다. 줄바꿈이 활성화된 경우, 다음 줄은 컨테이너 오른쪽의 첫 번째 아이템 아래에서 시작한다.
더 자세한 내용은 여기에서 확인할 수 있다.
- TypeScript
- JavaScript
레이아웃 방향
레이아웃 direction
은 계층 구조 내에서 자식 요소와 텍스트가 배치되는 방향을 지정한다. 이 속성은 start
와 end
가 가리키는 가장자리에도 영향을 미친다. 기본적으로 React Native는 LTR(왼쪽에서 오른쪽) 레이아웃 방향을 사용한다. 이 모드에서 start
는 왼쪽을, end
는 오른쪽을 의미한다.
-
LTR
(기본값) 텍스트와 자식 요소가 왼쪽에서 오른쪽으로 배치된다. 요소의 시작 부분에 적용된 마진과 패딩은 왼쪽에 적용된다. -
RTL
텍스트와 자식 요소가 오른쪽에서 왼쪽으로 배치된다. 요소의 시작 부분에 적용된 마진과 패딩은 오른쪽에 적용된다.
- TypeScript
- JavaScript
Justify Content
justifyContent
는 컨테이너의 메인 축을 기준으로 자식 요소들을 어떻게 정렬할지 결정한다. 예를 들어, 이 속성을 사용해 flexDirection
이 row
로 설정된 컨테이너 내에서 자식 요소를 수평으로 가운데 정렬하거나, flexDirection
이 column
으로 설정된 컨테이너 내에서 자식 요소를 수직으로 가운데 정렬할 수 있다.
flex-start
(기본값): 컨테이너의 메인 축 시작점에 자식 요소를 정렬한다.flex-end
: 컨테이너의 메인 축 끝점에 자식 요소를 정렬한다.center
: 컨테이너의 메인 축 중앙에 자식 요소를 정렬한다.space-between
: 컨테이너의 메인 축을 따라 자식 요소 사이에 남은 공간을 균등하게 분배한다.space-around
: 컨테이너의 메인 축을 따라 자식 요소 주변에 남은 공간을 균등하게 분배한다.space-between
과 달리, 첫 번째 자식 요소의 시작 부분과 마지막 자식 요소의 끝 부분에도 공간이 분배된다.space-evenly
: 컨테이너의 메인 축을 따라 자식 요소를 균등하게 배치한다. 각 자식 요소 사이의 간격, 첫 번째 자식 요소와 메인 축 시작점 사이의 간격, 마지막 자식 요소와 메인 축 끝점 사이의 간격이 모두 동일하다.
더 자세한 내용은 여기에서 확인할 수 있다.
- TypeScript
- JavaScript
Align Items
alignItems
는 컨테이너의 교차 축(cross axis)을 기준으로 자식 요소를 정렬하는 방법을 정의한다. justifyContent
와 매우 유사하지만, 주축(main axis) 대신 교차 축에 적용된다는 점이 다르다.
-
stretch
(기본값): 컨테이너의 교차 축 높이에 맞게 자식 요소를 늘린다. -
flex-start
: 컨테이너의 교차 축 시작점에 자식 요소를 정렬한다. -
flex-end
: 컨테이너의 교차 축 끝점에 자식 요소를 정렬한다. -
center
: 컨테이너의 교차 축 중앙에 자식 요소를 정렬한다. -
baseline
: 컨테이너의 자식 요소를 공통 기준선(baseline)에 맞춰 정렬한다. 각 자식 요소는 부모의 기준선이 될 수 있다.
stretch
가 효과를 발휘하려면, 자식 요소가 교차 축 방향으로 고정된 크기를 가지면 안 된다. 아래 예제에서 alignItems: stretch
를 설정해도 width: 50
이 자식 요소에 설정되어 있으면 아무런 효과가 없다. width: 50
을 제거해야 stretch
가 적용된다.
더 자세한 내용은 여기에서 확인할 수 있다.
- TypeScript
- JavaScript
Align Self
alignSelf
는 alignItems
와 동일한 옵션과 효과를 가지지만, 컨테이너 내부의 자식들 전체에 영향을 주는 대신, 특정 자식에 이 속성을 적용해 부모 내에서의 정렬을 변경할 수 있다. alignSelf
는 부모가 alignItems
로 설정한 옵션을 덮어쓴다.
- TypeScript
- JavaScript
Align Content
alignContent는 교차 축(cross-axis)을 따라 라인을 배치하는 방식을 정의한다. 이 속성은 flexWrap
을 사용해 여러 줄로 나뉜 아이템에만 적용된다.
flex-start
(기본값): 여러 줄을 컨테이너의 교차 축 시작점에 정렬한다.flex-end
: 여러 줄을 컨테이너의 교차 축 끝점에 정렬한다.stretch
(웹에서 Yoga를 사용할 때의 기본값): 여러 줄을 컨테이너의 교차 축 높이에 맞게 늘린다.center
: 여러 줄을 컨테이너의 교차 축 중앙에 정렬한다.space-between
: 여러 줄을 컨테이너의 교차 축에 균등하게 배치하고, 남은 공간을 줄 사이에 분배한다.space-around
: 여러 줄을 컨테이너의 교차 축에 균등하게 배치하고, 남은 공간을 줄 주위에 분배한다. 컨테이너 양 끝의 공간은 줄 사이의 공간보다 절반 크기다.space-evenly
: 여러 줄을 컨테이너의 교차 축에 균등하게 배치하고, 남은 공간을 줄 주위에 동일한 크기로 분배한다.
더 자세한 내용은 여기에서 확인할 수 있다.
- TypeScript
- JavaScript
플렉스 박스 줄바꿈
flexWrap
속성은 컨테이너에 설정하며, 자식 엘리먼트가 컨테이너의 주축 크기를 초과할 때 어떻게 처리할지 결정한다. 기본적으로 자식 엘리먼트는 한 줄에 강제로 배치되며(이 경우 엘리먼트가 축소될 수 있음), 줄바꿈이 허용되면 필요에 따라 주축을 따라 여러 줄로 나뉜다.
줄바꿈이 발생할 때, alignContent
를 사용해 줄이 컨테이너 내에서 어떻게 배치될지 지정할 수 있다. 자세한 내용은 여기에서 확인할 수 있다.
- TypeScript
- JavaScript
플렉스 박스의 기본 크기, 확장, 축소
-
flexBasis
는 주축을 따라 아이템의 기본 크기를 설정하는 축 독립적인 방법이다. 부모 컨테이너가flexDirection: row
일 때는 아이템의width
를 설정하는 것과 유사하고,flexDirection: column
일 때는height
를 설정하는 것과 유사하다.flexBasis
는 아이템의 기본 크기를 정의하며,flexGrow
와flexShrink
계산이 수행되기 전의 크기를 의미한다. -
flexGrow
는 컨테이너 내에서 남은 공간을 아이템들 간에 어떻게 분배할지 결정한다. 아이템을 배치한 후, 컨테이너는 남은 공간을 아이템의flexGrow
값에 따라 비율적으로 분배한다.flexGrow
는 0 이상의 부동 소수점 값을 받으며, 기본값은 0이다. 컨테이너는 아이템의flexGrow
값에 따라 남은 공간을 분배한다. -
flexShrink
는 아이템의 크기가 컨테이너를 넘칠 때 주축을 따라 아이템을 어떻게 축소할지 결정한다.flexShrink
는flexGrow
와 매우 유사하며, 넘치는 크기를 음수의 남은 공간으로 생각하면 이해하기 쉽다. 이 두 속성은 아이템이 필요에 따라 확장되고 축소될 수 있도록 함께 작동한다.flexShrink
는 0 이상의 부동 소수점 값을 받으며, 기본값은 0이다(웹에서는 기본값이 1이다). 컨테이너는 아이템의flexShrink
값에 따라 아이템을 축소한다.
더 자세한 내용은 여기에서 확인할 수 있다.
- TypeScript
- JavaScript
행 간격, 열 간격, 그리고 간격
rowGap
은 엘리먼트의 행 사이 간격(거터) 크기를 설정한다.columnGap
은 엘리먼트의 열 사이 간격(거터) 크기를 설정한다.gap
은 행과 열 사이의 간격 크기를 설정한다. 이는rowGap
과columnGap
을 한 번에 설정하는 단축 속성이다.
flexWrap
과 alignContent
를 gap
과 함께 사용하면 아이템 간 일관된 간격을 추가할 수 있다.
- TypeScript
- JavaScript
너비와 높이
width
속성은 엘리먼트의 콘텐츠 영역 너비를 지정한다. 마찬가지로 height
속성은 엘리먼트의 콘텐츠 영역 높이를 지정한다.
width
와 height
는 다음과 같은 값을 가질 수 있다:
-
auto
(기본값): React Native가 엘리먼트의 너비/높이를 자식 엘리먼트, 텍스트, 이미지 등의 콘텐츠를 기반으로 계산한다. -
pixels
: 절대적인 픽셀 단위로 너비/높이를 정의한다. 컴포넌트에 설정된 다른 스타일에 따라 최종 노드 크기가 달라질 수 있다. -
percentage
: 부모 엘리먼트의 너비 또는 높이에 대한 백분율로 너비 또는 높이를 정의한다.
- TypeScript
- JavaScript
Position
엘리먼트의 position
타입은 해당 엘리먼트가 자신, 부모, 또는 컨테이닝 블록에 대해 어떻게 위치할지 정의한다.
-
relative
(기본값): 기본적으로 엘리먼트는 상대적으로 위치한다. 이는 엘리먼트가 레이아웃의 일반적인 흐름에 따라 배치된 후,top
,right
,bottom
,left
값에 따라 그 위치에서 상대적으로 오프셋을 적용한다는 의미다. 이 오프셋은 형제나 부모 엘리먼트의 위치에 영향을 미치지 않는다. -
absolute
: 절대적으로 위치할 경우, 엘리먼트는 일반적인 레이아웃 흐름에 참여하지 않는다. 대신 형제 엘리먼트와 독립적으로 배치된다. 위치는top
,right
,bottom
,left
값에 따라 결정되며, 이 값들은 엘리먼트를 컨테이닝 블록에 상대적으로 위치시킨다. -
static
: 정적으로 위치할 경우, 엘리먼트는 레이아웃의 일반적인 흐름에 따라 배치되며,top
,right
,bottom
,left
값을 무시한다. 이position
은 또한 엘리먼트가 절대적으로 위치한 자손 엘리먼트에 대한 컨테이닝 블록을 형성하지 않는다. 단, 다른 우선순위가 높은 스타일 속성(예:transform
)이 있는 경우는 예외다. 이를 통해absolute
엘리먼트가 부모가 아닌 다른 요소에 대해 위치할 수 있다.static
은 New Architecture에서만 사용 가능하다는 점에 유의한다.
- TypeScript
- JavaScript
컨테이닝 블록
컨테이닝 블록은 엘리먼트의 위치와 크기를 제어하는 상위 엘리먼트를 말한다. React Native에서 컨테이닝 블록의 동작 방식은 웹에서의 동작과 매우 유사하지만, 일부 웹 기능이 없기 때문에 단순화된 형태로 구현된다.
절대 위치 지정(absolute positioning)된 엘리먼트의 top
, right
, bottom
, left
값은 해당 엘리먼트의 컨테이닝 블록을 기준으로 계산된다.
절대 위치 지정된 엘리먼트에 적용된 백분율 길이(예: width: '50%'
또는 padding: '10%'
)는 컨테이닝 블록의 크기를 기준으로 계산된다. 예를 들어, 컨테이닝 블록의 너비가 100포인트라면, 절대 위치 지정된 엘리먼트의 width: 50%
는 50포인트 너비로 계산된다.
다음 목록은 주어진 엘리먼트의 컨테이닝 블록을 결정하는 데 도움을 준다:
- 엘리먼트의
position
타입이relative
또는static
인 경우, 컨테이닝 블록은 부모 엘리먼트가 된다. - 엘리먼트의
position
타입이absolute
인 경우, 컨테이닝 블록은 다음 조건 중 하나를 만족하는 가장 가까운 상위 엘리먼트가 된다:position
타입이static
이 아닌 경우transform
속성이 적용된 경우
더 깊이 알아보기
플렉스 박스를 더 잘 이해하려면 Yoga Playground를 활용해 보자. 이 인터랙티브 도구를 사용하면 플렉스 박스의 동작을 직접 실험해 볼 수 있다.
기본 개념을 다뤘지만, 레이아웃을 구성할 때 필요한 다양한 스타일이 더 있다. 레이아웃을 제어하는 모든 속성의 전체 목록은 여기에서 확인할 수 있다.
또한, Wix 엔지니어들이 작성한 예제도 참고하면 도움이 될 것이다. 이 자료는 React Native 레이아웃을 구성하는 데 필요한 다양한 팁과 예제를 제공한다.