Flutter Row Column 차이
Flutter에서 화면을 만들다 보면 가장 자주 만나는 위젯이 Row와 Column입니다. 둘 다 여러 위젯을 한 줄로 정렬할 때 쓰지만, Row는 가로 방향, Column은 세로 방향이라는 차이가 있습니다. 두 위젯 모두 children 목록을 받아서 여러 자식을 배치하고, 정렬 방식도 비슷한 속성으로 맞춥니다.
기본 개념 정리
Row는 위젯들을 왼쪽에서 오른쪽으로 놓습니다.
예를 들어 아이콘 옆에 텍스트를 붙이거나, 버튼 2개를 한 줄에 나란히 보여줄 때 Row를 씁니다. Flutter 공식 API도 Row를 가로 배열로 자식 위젯을 보여주는 위젯으로 설명합니다.
Column은 위젯들을 위에서 아래로 놓습니다.
제목 아래 설명문을 넣거나, 로그인 화면에서 입력창과 버튼을 위아래로 쌓을 때 Column을 씁니다. Flutter 공식 API도 Column을 세로 배열로 자식 위젯을 보여주는 위젯으로 설명합니다.
한 줄 요약 비교
- Row: 가로로 나란히 배치
- Column: 세로로 차례대로 배치
이 둘은 방향만 다를 뿐, 사용하는 방식은 꽤 비슷합니다. 그래서 하나를 이해하면 다른 하나도 금방 익힐 수 있습니다. Flutter 레이아웃 문서도 Row와 Column을 가장 많이 쓰는 배치 위젯으로 다루고 있습니다.
화면 배치 예시
Row 사용 예시
Row(
children: [
Icon(Icons.star),
Text('인기 글'),
ElevatedButton(
onPressed: () {},
child: Text('확인'),
),
],
)
위 코드는 아이콘, 텍스트, 버튼이 한 줄에 가로로 보입니다.
Column 사용 예시
Column(
children: [
Text('로그인'),
TextField(),
TextField(),
ElevatedButton(
onPressed: () {},
child: Text('로그인하기'),
),
],
)
위 코드는 제목, 입력창, 입력창, 버튼이 위에서 아래로 보입니다.
실제 화면에서 생각하면 더 쉽다
가로 메뉴바, 아이콘 묶음, 버튼 묶음은 Row가 잘 맞습니다.
회원가입 화면, 게시글 상세 화면, 설정 화면처럼 내용이 위아래로 이어질 때는 Column이 잘 맞습니다.
즉, 옆으로 놓고 싶으면 Row, 아래로 쌓고 싶으면 Column이라고 생각하면 됩니다.
정렬 속성 이해
Row와 Column은 방향만 다르고, 정렬할 때 쓰는 핵심 속성은 같습니다. 가장 먼저 알아둘 것은 mainAxisAlignment와 crossAxisAlignment입니다. Flutter 레이아웃 문서는 Row와 Column 모두 자식 위젯을 가로와 세로 기준으로 정렬할 수 있다고 설명합니다.
mainAxisAlignment 뜻
mainAxisAlignment는 현재 위젯이 놓이는 기본 방향 기준 정렬입니다.
- Row에서 main axis는 가로
- Column에서 main axis는 세로
즉 Row에서는 왼쪽, 가운데, 오른쪽처럼 가로 기준으로 움직이고, Column에서는 위, 가운데, 아래처럼 세로 기준으로 움직입니다.
예를 들어:
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('A'),
Text('B'),
Text('C'),
],
)
이 코드는 A, B, C를 가로줄 가운데로 모읍니다.
crossAxisAlignment 뜻
crossAxisAlignment는 기본 방향과 반대쪽 기준 정렬입니다.
- Row에서는 세로 기준 정렬
- Column에서는 가로 기준 정렬
예를 들어 Row에서 crossAxisAlignment: CrossAxisAlignment.end를 주면, 자식들이 아래쪽 기준으로 맞춰질 수 있습니다. Column에서는 왼쪽 정렬, 가운데 정렬, 오른쪽 정렬 느낌으로 이해하면 쉽습니다. 관련 제약 조건 문서도 Row와 Column의 반대 방향 크기 제약이 중요하다고 설명합니다.
예제로 같이 보기
Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('제목'),
Text('설명'),
Text('버튼'),
],
)
이 경우:
mainAxisAlignment.center→ 세로 가운데로 모임crossAxisAlignment.start→ 가로는 왼쪽부터 시작
처음엔 이름이 낯설지만,
main은 현재 방향, cross는 반대 방향이라고 기억하면 금방 익숙해집니다.
Expanded 함께 이해하기
Row와 Column을 쓰다 보면 Expanded를 자주 같이 씁니다. Flutter 공식 API는 Expanded를 Row, Column, Flex 안에서 남는 공간을 채우도록 확장하는 위젯이라고 설명합니다. 특히 Row에서는 가로 방향, Column에서는 세로 방향의 남는 공간을 채우는 데 사용됩니다.
Row에서 Expanded
Row(
children: [
Icon(Icons.search),
Expanded(
child: TextField(),
),
Icon(Icons.close),
],
)
이 코드는 가운데 TextField가 남는 가로 공간을 넓게 차지합니다.
Column에서 Expanded
Column(
children: [
Text('상단 영역'),
Expanded(
child: Container(
color: Colors.blue,
),
),
Text('하단 영역'),
],
)
이 코드는 가운데 파란 박스가 남는 세로 공간을 채웁니다.
초보자 입장에서는 이렇게 기억하면 쉽습니다.
- Row + Expanded = 가로 남는 자리 채우기
- Column + Expanded = 세로 남는 자리 채우기
자주 헷갈리는 부분
Row에서 글자가 넘치는 경우
Row는 자식들을 한 줄에 가로로 놓기 때문에, 내용이 너무 길면 화면을 넘길 수 있습니다. Flutter Row 문서도 Row는 스크롤하지 않으며, 자식이 공간보다 많으면 문제가 될 수 있다고 안내합니다. 이런 경우에는 Expanded로 남는 공간을 나누거나, 필요하면 ListView 같은 스크롤 위젯을 써야 합니다.
예를 들어 긴 텍스트가 있을 때:
Row(
children: [
Icon(Icons.info),
Expanded(
child: Text(
'이 문장은 길어질 수 있어서 Expanded로 감싸는 편이 안전합니다.',
),
),
],
)
텍스트를 그냥 넣으면 넘칠 수 있지만, Expanded로 감싸면 사용할 수 있는 가로 공간 안에서 맞춰집니다.
Column에서 아래쪽이 넘치는 경우
Column도 스크롤하지 않습니다. 그래서 자식이 너무 많아 화면 높이를 넘어가면 아래쪽 overflow가 날 수 있습니다. Flutter Column 문서도 Column은 스크롤하지 않으며, 필요한 경우 ListView를 고려하라고 설명합니다.
예를 들어 입력창이 아주 많은 화면이라면:
SingleChildScrollView(
child: Column(
children: [
TextField(),
TextField(),
TextField(),
TextField(),
TextField(),
TextField(),
],
),
)
이런 식으로 감싸야 작은 화면에서도 안전합니다.
Column 안에 또 Column 넣을 때 주의할 점
Flutter의 제약 조건 문서에 따르면, Flex 계열 위젯인 Row와 Column은 사용 위치에 따라 크기 제한 문제를 만날 수 있고, 특히 스크롤 영역이나 또 다른 Flex 안에서 Expanded를 섞을 때 예외가 발생할 수 있습니다. 초보자가 많이 보는 오류 중 하나가 바로 이 부분입니다.
처음에는 이렇게만 기억해도 충분합니다.
- Row, Column 안에서
Expanded는 아주 자주 씀 - 그런데 스크롤 위젯 안이나 크기 제한이 애매한 곳에서는 오류가 날 수 있음
- 에러가 나면 부모 위젯이 어느 정도 크기를 주는지 먼저 확인해야 함
언제 Row를 쓰고 언제 Column을 쓸까
Row가 잘 맞는 경우
- 아이콘 + 텍스트를 한 줄에 보여줄 때
- 버튼 2개 이상을 나란히 놓을 때
- 프로필 사진 옆에 이름과 소개를 붙일 때
- 상단 메뉴나 태그 목록을 가로로 놓을 때
Column이 잘 맞는 경우
- 제목, 설명, 버튼을 위아래로 쌓을 때
- 로그인, 회원가입, 설정 화면을 만들 때
- 카드 안에 여러 정보를 세로로 넣을 때
- 게시글 상세처럼 내용이 아래로 이어질 때
실무에서는 둘 중 하나만 단독으로 쓰는 경우보다, Column 안에 Row, Row 안에 Column처럼 섞어서 쓰는 경우가 훨씬 많습니다. Flutter 레이아웃 문서도 Row와 Column은 서로 중첩해서 쓸 수 있다고 설명합니다.
같이 쓰면 좋은 위젯
SizedBox
간격 줄 때 가장 편합니다.
Row(
children: [
Icon(Icons.star),
SizedBox(width: 8),
Text('즐겨찾기'),
],
)
Row에서는 width, Column에서는 height를 많이 씁니다.
Spacer
남는 공간을 띄우고 싶을 때 좋습니다.
Row(
children: [
Text('왼쪽'),
Spacer(),
Text('오른쪽'),
],
)
Center
전체를 가운데에 놓고 싶을 때 간단합니다.
Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.login),
Text('로그인'),
],
),
)
실전 화면 예시
로그인 화면 생각하기
로그인 화면을 만든다고 가정해보겠습니다.
- 페이지 전체는 위에서 아래로 쌓이니 Column
- 이메일 입력창과 비밀번호 입력창도 세로로 놓이니 Column
- 비밀번호 입력창 오른쪽에 눈 아이콘을 붙이면 그 줄은 Row
- 버튼은 한 개면 굳이 Row 없이 단독 사용 가능
즉 실제 앱 화면은 보통 이렇게 됩니다.
Column(
children: [
Text('로그인'),
SizedBox(height: 16),
TextField(),
SizedBox(height: 12),
Row(
children: [
Expanded(child: TextField()),
Icon(Icons.visibility),
],
),
SizedBox(height: 16),
ElevatedButton(
onPressed: () {},
child: Text('로그인하기'),
),
],
)
이 예시 하나만 잘 이해해도 Row와 Column의 차이를 꽤 분명하게 잡을 수 있습니다.
결론
Flutter에서 Row와 Column의 차이는 생각보다 단순합니다. Row는 위젯을 가로로 배치할 때 쓰고, Column은 세로로 쌓을 때 씁니다. 처음에는 속성 이름이 낯설 수 있지만, 옆으로 놓을지 아래로 놓을지만 먼저 정하면 훨씬 쉽게 이해됩니다.
실제로 화면을 만들다 보면 둘 중 하나만 쓰는 경우보다 함께 섞어 쓰는 경우가 더 많습니다. 예를 들어 페이지 전체는 Column으로 만들고, 그 안의 아이콘과 텍스트 한 줄은 Row로 넣는 식입니다. 여기에 mainAxisAlignment, crossAxisAlignment, Expanded까지 익혀두면 기본 화면은 충분히 만들 수 있습니다.
처음부터 모든 옵션을 외우려 하기보다, 간단한 예제를 직접 바꿔보면서 차이를 눈으로 확인하는 편이 더 빠릅니다. Flutter 입문 단계에서는 Row와 Column만 제대로 익혀도 화면 배치가 한결 편해집니다.
FAQ
Flutter Row와 Column은 가장 큰 차이가 무엇인가요?
가장 큰 차이는 배치 방향입니다. Row는 자식 위젯을 가로로 나란히 놓고, Column은 세로로 아래쪽으로 쌓습니다. 그래서 버튼 여러 개를 한 줄에 보여주려면 Row를, 로그인 입력창처럼 위아래로 놓으려면 Column을 쓰는 경우가 많습니다.
Flutter 초보자는 Row와 Column 중 무엇부터 익히면 좋나요?
둘 다 같이 익히는 게 좋습니다. 두 위젯은 쓰는 방식이 거의 비슷하고 방향만 다르기 때문입니다. 하나만 따로 배우기보다, 같은 예제를 Row로도 만들어보고 Column으로도 바꿔보면 차이가 훨씬 빨리 익숙해집니다.
Row 안에서 글자가 넘치는 이유는 무엇인가요?
Row는 자식들을 한 줄에 계속 놓기 때문에, 텍스트가 길거나 자식 위젯이 많으면 화면 너비를 넘길 수 있습니다. 이럴 때는 Expanded를 함께 써서 남는 공간 안에서 글자가 표시되게 하거나, 화면 구성을 다시 나누는 것이 좋습니다.
Column에서 아래쪽 overflow 오류가 나는 이유는 무엇인가요?
Column은 자식 위젯을 아래로 계속 쌓는데, 화면 높이보다 내용이 많아지면 아래쪽이 넘칠 수 있습니다. 입력창이 많거나 설명이 긴 화면에서 자주 생깁니다. 이런 경우에는 SingleChildScrollView 같은 스크롤 위젯을 함께 쓰는 것이 일반적입니다.
mainAxisAlignment와 crossAxisAlignment는 어떻게 구분하면 되나요?
mainAxisAlignment는 현재 배치 방향 기준 정렬이고, crossAxisAlignment는 그 반대 방향 기준 정렬입니다. Row에서는 main이 가로, Column에서는 main이 세로입니다. 처음에는 헷갈릴 수 있지만, Row는 좌우 기준, Column은 상하 기준이라고 떠올리면 이해하기 쉽습니다.
Expanded는 언제 사용하나요?
Expanded는 남는 공간을 채우고 싶을 때 사용합니다. Row 안에서는 가로 공간을 넓게 차지하게 만들고, Column 안에서는 세로 공간을 더 많이 차지하게 만듭니다. 예를 들어 검색창을 한 줄에서 넓게 보여주고 싶을 때 자주 씁니다.
Row와 Column은 함께 써도 되나요?
네, 함께 쓰는 경우가 훨씬 많습니다. 예를 들어 전체 페이지는 Column으로 만들고, 그 안의 프로필 사진과 이름은 Row로 넣을 수 있습니다. 실제 앱 화면은 이런 식으로 여러 위젯을 섞어서 만드는 경우가 대부분입니다.
버튼 여러 개를 배치할 때는 Row가 무조건 맞나요?
한 줄에 나란히 보여주고 싶다면 Row가 잘 맞습니다. 하지만 버튼이 많거나 작은 화면에서도 보기 좋게 만들고 싶다면 Column이 더 나을 수 있습니다. 어떤 위젯이 더 맞는지는 버튼 개수와 화면 크기에 따라 달라집니다.
Row와 Column만 알아도 Flutter 화면을 만들 수 있나요?
기본 화면을 만드는 데는 큰 도움이 됩니다. 물론 실제 앱에서는 Container, SizedBox, Expanded, ListView 같은 위젯도 함께 쓰게 되지만, Row와 Column을 제대로 이해하면 대부분의 화면 배치에서 훨씬 수월하게 작업할 수 있습니다.
Row와 Column을 쉽게 익히는 방법이 있나요?
가장 좋은 방법은 같은 위젯 묶음을 Row와 Column으로 각각 바꿔보는 것입니다. 아이콘, 텍스트, 버튼 3개 정도를 놓고 방향만 바꿔보면 차이가 바로 보입니다. 여기에 정렬 속성을 조금씩 추가해보면 어느 순간 자연스럽게 익숙해집니다.