
Flutter에서 레이아웃을 처음 배울 때 가장 많이 쓰는 위젯이 Column과 Row다.
이 둘을 잘 이해하면 대부분의 화면 배치를 해결할 수 있다.
그런데 mainAxisAlignment와 crossAxisAlignment가 등장하는 순간 헷갈리기 시작한다.
이번 글에서는 이 두 개념을 축(axis)의 관점에서 명확하게 정리한다.
1. Column과 Row의 차이
Column과 Row는 자식 위젯 여러 개를 받아 나란히 배치하는 위젯이다. 차이는 방향뿐이다.
Column: 자식들을 **세로(위에서 아래)**로 배치Row: 자식들을 **가로(왼쪽에서 오른쪽)**로 배치
// 세로 배치
Column(
children: [
Text('첫 번째'),
Text('두 번째'),
Text('세 번째'),
],
)
// 가로 배치
Row(
children: [
Icon(Icons.star),
SizedBox(width: 8),
Text('즐겨찾기'),
],
)
children(복수)을 받는다는 점도 기억해두자. Container나 Center처럼 위젯 하나만 받는 경우는 child(단수)를 사용한다.
2. 두 개의 축 — mainAxis와 crossAxis
Column과 Row 각각에는 두 개의 축이 존재한다.
| ㅤ | Column | Row |
|---|---|---|
| 주축(mainAxis) | 세로 방향 (↕) | 가로 방향 (↔) |
| 교차축(crossAxis) | 가로 방향 (↔) | 세로 방향 (↕) |
즉, 주축(mainAxis)은 배치가 이루어지는 방향이고, 교차축(crossAxis)은 그에 수직인 방향이다. Column의 주축은 세로, Row의 주축은 가로다.
이 개념이 중요한 이유는, 정렬 속성 이름이 "주축/교차축 기준"으로 붙어있기 때문이다. mainAxisAlignment는 주축 방향 정렬이고, crossAxisAlignment는 교차축 방향 정렬이다.
3. mainAxisAlignment — 주축 정렬
자식 위젯들을 주축 방향으로 어떻게 배치할지 결정한다.
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [Text('A'), Text('B'), Text('C')],
)
| 값 | 동작 |
|---|---|
| start | 시작점(Column이면 위, Row면 왼쪽)에 붙여서 배치. 기본값 |
| end | 끝점에 붙여서 배치 |
| center | 중앙에 모아서 배치 |
| spaceBetween | 첫 번째와 마지막은 가장자리에 붙이고, 나머지 간격을 균등하게 |
| spaceAround | 각 위젯 양쪽에 동일한 여백. 가장자리는 그 절반 |
| spaceEvenly | 모든 간격(가장자리 포함)을 동일하게 |
spaceBetween은 AppBar처럼 양쪽 끝에 위젯을 붙이고 가운데를 비울 때 자주 쓴다.
4. crossAxisAlignment — 교차축 정렬
교차축 방향으로 자식들을 정렬한다. Column 기준이면 가로 방향 정렬이다.
Column(
crossAxisAlignment: CrossAxisAlignment.start, // 왼쪽 정렬
children: [
Text('이 텍스트는'),
Text('전부 왼쪽에 붙어있다'),
],
)
| 값 | 동작 |
|---|---|
| start | 교차축의 시작점. Column이면 왼쪽, Row이면 위쪽 |
| center | 교차축 중앙. 기본값 |
| end | 교차축 끝. Column이면 오른쪽, Row이면 아래쪽 |
| stretch | 교차축을 꽉 채우도록 늘림 |
crossAxisAlignment.stretch는 Column 안의 버튼이나 카드를 화면 너비 전체로 늘릴 때 유용하다.
5. mainAxisSize — 주축 크기
Column과 Row는 기본적으로 주축 방향으로 가능한 최대 크기를 차지한다. 이 동작을 바꾸고 싶으면 mainAxisSize를 사용한다.
Column(
mainAxisSize: MainAxisSize.min, // 자식들의 합계 크기만큼만 차지
children: [Text('A'), Text('B')],
)
MainAxisSize.min은 다이얼로그나 바텀시트처럼 내용물 크기에 딱 맞게 줄어들어야 하는 경우에 쓴다.
6. 자주 쓰는 패턴
화면 가운데 배치
Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Icon(Icons.check_circle, size: 64),
SizedBox(height: 16),
Text('완료되었습니다'),
],
)
AppBar 스타일 좌우 분리
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('제목'),
Icon(Icons.more_vert),
],
)
리스트 아이템 가로 배치
Row(
children: [
CircleAvatar(child: Text('김')),
SizedBox(width: 12),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('김철수', style: TextStyle(fontWeight: FontWeight.bold)),
Text('안녕하세요', style: TextStyle(color: Colors.grey)),
],
),
),
Text('오후 3:42'),
],
)
정리
Column은 세로,Row는 가로로 위젯을 배치한다.mainAxisAlignment는 배치 방향 정렬,crossAxisAlignment는 그에 수직인 방향 정렬이다. 이 두 속성을 조합하면 대부분의 레이아웃을 만들 수 있다.
'Flutter&Dart' 카테고리의 다른 글
| Dart abstract class와 callback으로 동작 조합하기 (0) | 2026.09.09 |
|---|---|
| Flutter 위젯 트리와 build() 동작 원리 (0) | 2026.09.09 |
| Dart 콜백과 named parameter로 버튼 클래스 만들기 (0) | 2026.09.08 |
| Dart DTO와 JSON 변환 방법 정리 (0) | 2026.09.07 |
| Dart DTO와 JSON 변환 방법 정리 (0) | 2026.09.07 |