플렉스 박스를 활용한 레이아웃
컴포넌트는 플렉스 박스 알고리즘을 사용해 자식 엘리먼트의 레이아웃을 지정할 수 있다. 플렉스 박스는 다양한 화면 크기에서 일관된 레이아웃을 제공하도록 설계됐다.
일반적으로 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-around
를 사용하면 첫 번째 자식 요소의 시작 부분과 마지막 자식 요소의 끝 부분에도 공간이 분배된다. -
space-evenly
: 컨테이너의 메인 축을 따라 자식 요소들을 균등하게 배치한다. 각 인접한 요소 쌍 사이의 간격, 메인 축 시작 부분과 첫 번째 요소 사이의 간격, 메인 축 끝 부분과 마지막 요소 사이의 간격이 모두 동일하다.
더 자세한 내용은 여기에서 확인할 수 있다.
- TypeScript
- JavaScript
Align Items
alignItems
는 컨테이너의 교차 축을 기준으로 자식 요소들을 어떻게 정렬할지 정의한다. justifyContent
와 매우 유사하지만, 주축이 아닌 교차 축에 적용된다는 점이 다르다.
-
stretch
(기본값) 컨테이너의 교차 축 높이에 맞게 자식 요소를 늘린다. -
flex-start
컨테이너의 교차 축 시작점에 자식 요소를 정렬한다. -
flex-end
컨테이너의 교차 축 끝점에 자식 요소를 정렬한다. -
center
컨테이너의 교차 축 중앙에 자식 요소를 정렬한다. -
baseline
컨테이너의 자식 요소들을 공통 기준선에 맞춰 정렬한다. 각 자식 요소는 부모 요소의 기준선이 될 수 있다.
stretch
가 효과를 발휘하려면, 자식 요소가 교차 축 방향으로 고정된 크기를 가지고 있지 않아야 한다. 아래 예제에서 alignItems: stretch
를 설정해도 width: 50
이 자식 요소에 설정되어 있으면 아무런 효과가 없다.
더 자세한 내용은 여기에서 확인할 수 있다.
- 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
플렉스 박스의 Basis, Grow, Shrink 이해
-
flexBasis
는 주축을 따라 아이템의 기본 크기를 설정하는 축 독립적인 방법이다. 부모 컨테이너가flexDirection: row
로 설정된 경우, 자식의flexBasis
를 설정하는 것은 자식의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
을 한 번에 지정하는 단축 속성이다.
gap
과 함께 flexWrap
과 alignContent
를 사용하면 아이템 간 일관된 간격을 추가할 수 있다.
- 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에서 포함 블록의 동작 방식은 웹에서의 동작 방식과 매우 유사하지만, 일부 웹 기능이 없기 때문에 단순화된 형태로 구현된다.
절대 위치로 지정된 엘리먼트의 top
, right
, bottom
, left
값은 포함 블록을 기준으로 상대적으로 결정된다.
절대 위치로 지정된 엘리먼트에 적용된 백분율 길이(예: width: '50%'
또는 padding: '10%'
)는 포함 블록의 크기를 기준으로 계산된다. 예를 들어, 포함 블록의 너비가 100포인트라면, 절대 위치로 지정된 엘리먼트에 width: 50%
를 적용하면 해당 엘리먼트의 너비는 50포인트가 된다.
다음 목록은 특정 엘리먼트의 포함 블록을 결정하는 데 도움을 준다:
- 엘리먼트의
position
타입이relative
또는static
이라면, 포함 블록은 부모 엘리먼트이다. - 엘리먼트의
position
타입이absolute
라면, 포함 블록은 다음 조건 중 하나를 만족하는 가장 가까운 상위 엘리먼트이다:static
이 아닌position
타입을 가진 경우transform
속성을 가진 경우
더 깊이 알아보기
플렉스 박스를 더 잘 이해하기 위해 Yoga Playground를 활용해 보자. 이 인터랙티브 도구를 사용하면 개념을 더 명확히 이해할 수 있다.
기본적인 내용을 다뤘지만, 레이아웃을 구성할 때 필요한 다양한 스타일이 더 있다. 레이아웃을 제어하는 전체 속성 목록은 여기에서 확인할 수 있다.
또한, Wix 엔지니어들이 작성한 예제도 참고하면 도움이 될 것이다.