Flutter Row 위젯 완벽 가이드

개발/Flutter1 2026. 2. 10. 10:04

Flutter에서 위젯을 가로로 배치할 때 사용하는 필수 레이아웃 위젯이 바로 Row입니다. 이 글에서는 Row 위젯의 모든 것을 상세히 알아보겠습니다.

Row란?

Row는 자식 위젯들을 가로(수평) 방향으로 배치하는 레이아웃 위젯입니다. 여러 위젯을 왼쪽에서 오른쪽으로 나란히 배치할 때 사용합니다.

기본 사용법

Row(
  children: [
    Icon(Icons.star, color: Colors.yellow),
    Icon(Icons.star, color: Colors.yellow),
    Icon(Icons.star, color: Colors.yellow),
  ],
)

주요 속성

1. mainAxisAlignment

가로축(주축)에서 자식 위젯들을 어떻게 배치할지 결정합니다.

Row(
  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
  children: [
    Icon(Icons.home),
    Icon(Icons.search),
    Icon(Icons.person),
  ],
)

사용 가능한 값들은 다음과 같습니다.

  • start: 왼쪽에 배치 (기본값)
  • end: 오른쪽에 배치
  • center: 중앙에 배치
  • spaceBetween: 양 끝에 배치하고 사이 공간을 균등 분배
  • spaceAround: 각 위젯 주변에 동일한 공간 배치
  • spaceEvenly: 모든 공간을 균등하게 분배

2. crossAxisAlignment

세로축(교차축)에서 자식 위젯들을 어떻게 배치할지 결정합니다.

Row(
  crossAxisAlignment: CrossAxisAlignment.center,
  children: [
    Text('작은 텍스트'),
    Text(
      '큰 텍스트',
      style: TextStyle(fontSize: 32),
    ),
  ],
)

사용 가능한 값들입니다.

  • start: 위쪽 정렬
  • end: 아래쪽 정렬
  • center: 세로 중앙 정렬 (기본값)
  • stretch: 세로 전체를 채움
  • baseline: 텍스트 기준선에 맞춤

3. mainAxisSize

Row가 가로 방향으로 차지할 공간의 크기를 결정합니다.

Row(
  mainAxisSize: MainAxisSize.min,
  children: [
    Text('최소'),
    Text('크기'),
  ],
)
  • max: 사용 가능한 최대 너비를 차지 (기본값)
  • min: 자식 위젯들을 담을 수 있는 최소 너비만 차지

실전 예제

1. 소셜 미디어 좋아요 버튼

Row(
  mainAxisSize: MainAxisSize.min,
  children: [
    Icon(
      Icons.favorite,
      color: Colors.red,
      size: 20,
    ),
    SizedBox(width: 4),
    Text('1,234'),
    SizedBox(width: 16),
    Icon(
      Icons.comment,
      color: Colors.grey,
      size: 20,
    ),
    SizedBox(width: 4),
    Text('56'),
    SizedBox(width: 16),
    Icon(
      Icons.share,
      color: Colors.grey,
      size: 20,
    ),
  ],
)

2. 프로필 헤더

Row(
  children: [
    CircleAvatar(
      radius: 30,
      backgroundImage: NetworkImage('https://example.com/avatar.jpg'),
    ),
    SizedBox(width: 16),
    Expanded(
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text(
            '홍길동',
            style: TextStyle(
              fontSize: 18,
              fontWeight: FontWeight.bold,
            ),
          ),
          SizedBox(height: 4),
          Text(
            '온라인',
            style: TextStyle(
              color: Colors.green,
              fontSize: 14,
            ),
          ),
        ],
      ),
    ),
    IconButton(
      icon: Icon(Icons.more_vert),
      onPressed: () {},
    ),
  ],
)

3. 버튼 그룹

Row(
  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
  children: [
    ElevatedButton(
      onPressed: () {},
      child: Text('취소'),
      style: ElevatedButton.styleFrom(
        backgroundColor: Colors.grey,
      ),
    ),
    ElevatedButton(
      onPressed: () {},
      child: Text('확인'),
    ),
  ],
)

4. 별점 표시

Row(
  mainAxisSize: MainAxisSize.min,
  children: [
    ...List.generate(5, (index) {
      return Icon(
        index < 4 ? Icons.star : Icons.star_border,
        color: Colors.amber,
        size: 24,
      );
    }),
    SizedBox(width: 8),
    Text('4.0'),
  ],
)

5. 카드 하단 액션 버튼

Row(
  mainAxisAlignment: MainAxisAlignment.end,
  children: [
    TextButton(
      onPressed: () {},
      child: Text('취소'),
    ),
    SizedBox(width: 8),
    TextButton(
      onPressed: () {},
      child: Text('저장'),
    ),
  ],
)

주의사항

1. 오버플로 방지

Row의 자식 위젯들이 화면 너비를 넘어가면 오버플로 에러가 발생합니다.

문제 상황:

Row(
  children: [
    Text('이것은 매우 긴 텍스트입니다. ' * 10),
  ],
)

해결 방법 1: Expanded 사용

Row(
  children: [
    Expanded(
      child: Text('이것은 매우 긴 텍스트입니다. ' * 10),
    ),
  ],
)

해결 방법 2: Flexible 사용

Row(
  children: [
    Flexible(
      child: Text(
        '이것은 매우 긴 텍스트입니다. ' * 10,
        overflow: TextOverflow.ellipsis,
      ),
    ),
  ],
)

2. Expanded와 Flexible 활용

여러 위젯의 공간 비율을 조절할 때 사용합니다.

Row(
  children: [
    Expanded(
      flex: 2,
      child: Container(
        color: Colors.blue,
        height: 50,
        child: Center(child: Text('2')),
      ),
    ),
    Expanded(
      flex: 1,
      child: Container(
        color: Colors.red,
        height: 50,
        child: Center(child: Text('1')),
      ),
    ),
  ],
)

3. Spacer 위젯 활용

위젯 사이에 빈 공간을 만들 때 유용합니다.

Row(
  children: [
    Text('왼쪽'),
    Spacer(),
    Text('오른쪽'),
  ],
)

 

Row vs Column 비교

특징 Row Column
배치 방향 가로(수평) 세로(수직)
주축 가로축 세로축
교차축 세로축 가로축
오버플로 화면 너비 초과 시 화면 높이 초과 시

 

실무 팁

1. 반응형 디자인

LayoutBuilder(
  builder: (context, constraints) {
    if (constraints.maxWidth < 600) {
      // 모바일: Column 사용
      return Column(children: widgets);
    } else {
      // 태블릿/데스크톱: Row 사용
      return Row(children: widgets);
    }
  },
)

2. 조건부 위젯 추가

Row(
  children: [
    Icon(Icons.home),
    SizedBox(width: 8),
    Text('홈'),
    if (isAdmin) ...[
      SizedBox(width: 16),
      Icon(Icons.admin_panel_settings),
    ],
  ],
)

3. 리스트를 Row로 변환

final items = ['사과', '바나나', '오렌지'];

Row(
  children: items.map((item) => 
    Padding(
      padding: EdgeInsets.symmetric(horizontal: 8),
      child: Chip(label: Text(item)),
    )
  ).toList(),
)

마무리

Row는 Column과 함께 Flutter에서 가장 기본적이면서도 강력한 레이아웃 위젯입니다.
mainAxisAlignment와 crossAxisAlignment를 적절히 조합하고, Expanded와 Flexible을 활용하면 다양한 가로 배치 레이아웃을 자유롭게 구현할 수 있습니다.
실제 프로젝트에서 다양하게 활용해보시기 바랍니다!

반응형
admin