Flexible은 Flex 컨테이너에서 자식 요소가 사용 가능한 공간을 차지하는 방식을 제어하는 Flutter 위젯입니다. Expanded와 달리 Flexible은 자식이 할당된 전체 영역을 채우도록 강제하지 않습니다 — 자식 위젯은 더 작을 수 있으며 나머지 공간은 비어 있습니다. 공식 Flutter 문서(2026)에 따르면 Flexible은 강제적인 늘임 없이 유연한 공간 분배가 필요한 시나리오(최소 너비의 버튼, 자연스러운 크기의 텍스트 블록, intrinsic constraints가 있는 요소)에서 필요합니다.
주요 포인트
Flexible은 Flex 컨테이너에서 자식 요소에 유연한 공간을 제공하는 래퍼 위젯입니다. Flexible은 Expanded와 마찬가지로 여유 공간 분배에 참여하지만, 한 가지 중요한 차이점이 있습니다: Flexible의 자식은 자체 크기가 사용 가능한 공간보다 작은 경우 할당된 공간보다 적게 차지할 수 있습니다.
Flexible은 Flutter의 Flex 알고리즘을 사용하여 사용 가능한 공간을 계산합니다. 먼저 프레임워크는 유연하지 않은 모든 자식(Flexible/Expanded가 없는 위젯)을 쿼리하고 해당 고유 크기를 계산합니다. 나머지 공간은 flex 계수에 비례하여 유연한 자식들 사이에 분배됩니다. 공간 할당 후 Flexible은 fit을 확인합니다 — loose인 경우 자식은 “할당된 것보다 크지 않음”이라는 제약을 받아 작게 유지될 수 있습니다.
Flexible의 특징: 자식 위젯에 자체 최소 크기가 있는 경우(예: 긴 문자열이 있는 Text), Flexible은 강제적인 늘임 없이 요청된 공간을 할당합니다. 이로 인해 Flexible은 컨테이너가 아닌 콘텐츠에 의해 크기가 결정되어야 하는 요소에 필수적입니다.
요약: 요소의 공간을 예약해야 하지만 늘어나도록 강제하고 싶지 않은 경우 Flexible을 사용하세요. 이렇게 하면 유연한 레이아웃 분배를 유지하면서 콘텐츠의 자연스러운 크기가 보존됩니다.
FlexFit은 tight와 loose 두 가지 값의 열거형입니다. fit의 선택에 따라 자식 위젯이 할당된 공간의 크기로 강제로 늘어날지 여부가 결정됩니다.
FlexFit.tight: 자식 요소가 tight constraints를 받습니다 — 최소 및 최대 크기가 할당된 공간과 동일합니다. 자식은 Flex 알고리즘이 할당한 정확한 공간을 차지해야 합니다. 자식이 더 작으면 늘어나고, 더 크면 줄어듭니다. 동작은 Expanded와 동일합니다.
FlexFit.loose: 자식 요소가 loose constraints를 받습니다 — 최소 크기는 0이고 최대 크기는 할당된 공간과 같습니다. 자식은 0에서 최대까지 모든 크기가 될 수 있습니다. 자식이 작은 경우(예: 짧은 문자열이 있는 Text) 자연스러운 너비를 차지하고 나머지 공간은 비어 있습니다.
요약: FlexFit.loose는 텍스트 블록과 자연스러운 크기의 요소에 적합합니다. FlexFit.tight는 모든 요소가 동일한 너비 또는 높이를 가져야 하는 엄격한 컬럼 레이아웃에 적합합니다.
Flexible과 Expanded는 비슷해 보이지만 다른 작업을 해결합니다. Expanded는 항상 자식을 늘려 사용 가능한 모든 공간을 채웁니다. Flexible은 콘텐츠 크기가 할당된 비율보다 작은 경우 자식 주위에 빈 공간을 남길 수 있습니다.
Flexible 시나리오: Row 안에 두 개의 버튼이 있습니다. 첫 번째는 “구매”(짧은 텍스트), 두 번째는 “장바구니에 추가”(긴 텍스트)입니다. Expanded를 사용하면 두 버튼이 동일한 너비로 늘어나고 짧은 텍스트에 큰 패딩이 생깁니다. Flexible을 사용하면 각 버튼이 텍스트의 너비를 차지하고 여유 공간은 버튼 사이 또는 가장자리에 남습니다.
Expanded 시나리오: Column 안에 콘텐츠에 관계없이 동일한 높이를 차지해야 하는 세 개의 카드가 있습니다. Expanded는 사용 가능한 높이를 균등하게 나누고 각 카드는 동일한 크기로 늘어납니다. loose가 있는 Flexible은 여기서 작동하지 않습니다 — 작은 카드는 작게 유지되어 균일한 디자인이 깨집니다.
요약: 콘텐츠가 요소 크기를 결정하고 주변에 빈 공간이 허용되는 경우 Flexible을 선택하세요. 콘텐츠에 관계없이 모든 요소가 동일한 크기여야 하는 경우 Expanded를 선택하세요.
예제 1은 Row에서 FlexFit.loose를 사용한 Flexible의 기본 사용법을 보여줍니다.
Row(
children: [
Flexible(
fit: FlexFit.loose,
child: Container(
color: Colors.amber,
child: const Text('짧은'),
),
),
Flexible(
fit: FlexFit.loose,
child: Container(
color: Colors.cyan,
child: const Text('데모용 긴 텍스트'),
),
),
],
)
예제에서 두 Flexible 모두 loose fit을 사용합니다. 짧은 텍스트가 있는 첫 번째 컨테이너는 자연스러운 너비를 차지합니다. 긴 텍스트가 있는 두 번째 컨테이너는 자체 너비를 차지합니다. Row는 각각 사용 가능한 너비의 절반을 할당하지만 loose fit을 통해 컨테이너가 더 작아질 수 있으며 여유 공간은 그 사이에 비어 있습니다.
예제 2 — Column에서 Tight 및 Loose fit을 사용한 Flexible 비교.
Column(
children: [
Flexible(
fit: FlexFit.tight,
child: const Card(
child: ListTile(
title: Text('Tight — 전체 높이로 늘림'),
),
),
),
const SizedBox(
height: 8,
),
Flexible(
fit: FlexFit.loose,
child: const Card(
child: ListTile(
title: Text('Loose — 자연스러운 높이'),
),
),
),
],
)
Column에서 첫 번째 Flexible(tight)은 Card를 사용 가능한 높이의 절반으로 늘입니다. 두 번째 Flexible(loose) — Card는 콘텐츠에 따라 높이를 차지하고 나머지 공간은 비어 있습니다. 시각적으로 tight가 강제로 영역을 채우는 반면 loose는 컴팩트한 크기를 유지하는 것을 볼 수 있습니다.
요약: 프로덕션 코드에서 Flexible with loose는 양식 필드, 버튼 및 텍스트 블록에 사용됩니다. Flexible with tight는 Expanded와 동일하며 균일한 분배에 사용됩니다.
실수 1: Flex 컨테이너 외부에서 Flexible 사용. Expanded와 마찬가지로 Flexible은 Row, Column 또는 Flex 내부에 없으면 LayoutException을 발생시킵니다. 해결책: 항상 부모 위젯 체인을 확인하세요.
실수 2: Flexible과 Expanded 혼동. 개발자는 loose fit의 Flexible이 필요할 때 Expanded를 자주 사용하며 그 반대의 경우도 마찬가지입니다. 결과: Expanded가 짧은 텍스트가 있는 요소를 늘려 큰 빈 여백을 만듭니다. 해결책: 요소 크기가 할당된 것보다 작을 수 있는 경우 Flexible(fit: FlexFit.loose)를 사용하세요.
실수 3: 0의 flex 계수. flex=0인 Flexible은 유연하지 않은 위젯처럼 작동하여 직관적이지 않을 수 있습니다. 개발자는 유연한 동작을 기대하지만 요소는 최소 크기를 차지합니다. 해결책: 활성 공간 분배를 위해 flex는 ≥1이어야 합니다.
실수 4: 크기 제약 없이 ScrollView 내부에 Flexible 배치. SingleChildScrollView 내부의 Column에 Flexible이 있으면 스크롤 컨테이너가 무한 공간을 제공하고 flex 분배가 작동하지 않습니다. 해결책: SizedBox 또는 ConstrainedBox를 사용하여 스크롤 컨테이너 크기를 제한하세요.
요약: Flexible은 Expanded와 마찬가지로 부모 컨텍스트에 대한 동일한 주의가 필요합니다. 유일한 차이점은 fit입니다 — 작업에 따라 의도적으로 선택하세요.
자주 묻는 질문
Expanded는 고정된 fit=tight를 가진 Flexible입니다. 차이점은 Expanded가 사용 가능한 모든 공간을 채우기 위한 엄격한 바인딩을 가지고 있는 반면, Flexible은 자식의 자연스러운 크기를 유지하기 위해 loose fit을 사용할 수 있다는 것입니다.
다른 텍스트 길이의 버튼에는 Flexible(fit: FlexFit.loose)를 사용하세요. 각 버튼은 콘텐츠의 너비를 차지하며 버튼 간에 불균형이 없습니다. Expanded는 모든 버튼을 동일한 너비로 만듭니다.
fit: FlexFit.tight를 설정하세요 — Flexible이 자식이 할당된 모든 공간을 채우도록 강제합니다. 이 모드에서 Flexible은 동작이 Expanded와 완전히 동일합니다.
네, 자식이 할당된 공간보다 큰 경우입니다. Flexible은 Flex 컨테이너의 비율과 동일한 최대 크기로 제약 조건을 전달합니다. 자식이 이 크기를 초과하면 제약 조건 내에서 줄어듭니다.
네, Flexible은 Row, Column 및 임의 방향의 기본 Flex 위젯을 포함한 모든 Flex 컨테이너와 작동합니다. Flex는 mainAxisAlignment 및 crossAxisAlignment를 통해 비표준 방향을 설정할 수 있습니다.
요약
턴키 방식의 모바일 애플리케이션을 개발해 드립니다
IT Sectr는 2017년부터 스타트업과 기업을 위한 iOS 및 Android 애플리케이션을 만듭니다. 저희가 상담해 드리고 최적의 솔루션을 제안하겠습니다.