Flutter에서의 Layout Widget은 앱의 UI를 구성하는 데 있어 핵심적인 역할을 합니다.
이들은 다양한 방식으로 Widget을 배치하고, 조정하여 원하는 디자인과 구조를 만들 수 있게 해줍니다.
주요 Layout Widget에 대하여 간단한 예시 코드와 함께 소개하겠습니다.
아래 예제의 전체 소스는 GitHub Repository 에 있습니다.
Container
소개
여백, 정렬, 크기 등을 설정할 수 있는 범용 Widget입니다.
속성
- padding: 자식과 컨테이너의 가장자리 사이의 여백.
 - color: 컨테이너의 색상.
 - decoration: 자식 뒤에 그려질 장식.
 - margin: 컨테이너를 둘러싼 여백.
 - width, height: 컨테이너의 크기.
 - alignment: 컨테이너 내에서의 자식의 정렬.
 
예시 코드
200px x200px 의 배경이 파란 사각형 컨테이너를 생성하고, 안에 상하좌우 padding 20px을 주고 자식 widget으로 Text widget을 추가합니다.
      Container(
        padding: const EdgeInsets.all(20.0),
        color: Colors.blue,
        width: 200,
        height: 200,
        child: const Text(
          'Hello World',
          style: TextStyle(
            color: Colors.white,
            fontSize: 20,
          ),
        ),
      ),결과

Row
소개
세로 방향으로 자식 Widget을 정렬합니다.
속성
- mainAxisAlignment: 주 축(로우의 경우 수평)을 따라 자식들이 배치되는 방식.
 - crossAxisAlignment: 교차 축(로우의 경우 수직)을 따라 자식들이 배치되는 방식.
 - mainAxisSize: 주 축이 차지해야 하는 공간의 양.
 
예시 코드
3개의 다른 색의 container를 수평 방향으로 나열합니다.
주축(main axis)는 균등한 간격으로 배치되고, 교차 축(cross axis)은 시작 부분에 맞추어 정렬됩니다.
      Row(
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Container(
            color: Colors.red,
            width: 100,
            height: 100,
          ),
          Container(
            color: Colors.green,
            width: 100,
            height: 100,
          ),
          Container(
            color: Colors.blue,
            width: 100,
            height: 100,
          ),
        ],
      ),결과

Column
소개
가로 방향으로 자식 Widget을 정렬합니다.
속성
- mainAxisAlignment: 주 축(컬럼의 경우 수직)을 따라 자식들이 배치되는 방식.
 - crossAxisAlignment: 교차 축(컬럼의 경우 수평)을 따라 자식들이 배치되는 방식.
 - mainAxisSize: 주 축이 차지해야 하는 공간의 양.
 
예시 코드
3개의 다른 색의 container를 수직 방향으로 나열합니다.
주축(main axis)는 균등한 간격으로 배치되고, 교차 축(cross axis)은 시작 부분에 맞추어 정렬됩니다.
      Column(
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Container(
            color: Colors.red,
            width: 100,
            height: 100,
          ),
          Container(
            color: Colors.green,
            width: 100,
            height: 100,
          ),
          Container(
            color: Colors.blue,
            width: 100,
            height: 100,
          ),
        ],
      ),결과

Stack & Positioned
소개
Stack
Widget을 겹쳐서 배치합니다.
Positioned
Stack 내에서 Widget의 위치를 조정합니다.
속성
- alignment (Stack): 자식들이 서로 대비하여 어떻게 정렬될지.
 - top, right, bottom, left (Positioned): 스택 내에서 자식의 정확한 위치.
 
예시 코드
하단으로 부터 10px 우측에서 부터 10px 떨어져서 Widget을 위치시켰습니다.
      Stack(
        children: <Widget>[
          Container(
            color: Colors.red,
            width: 200,
            height: 200,
          ),
          const Positioned(
            bottom: 10.0,
            right: 10.0,
            child: Text(
              'On top of image',
              style: TextStyle(fontSize: 20, color: Colors.white),
            ),
          ),
        ],
      ),결과

Expanded
소개
주로 Row, Column, 또는 Flex 같은 부모 위젯 내에서 사용됩니다.
자식 위젯을 확장하여 주변 공간을 채우게 하여, 주어진 방향(가로 또는 세로)으로 사용 가능한 공간을 모두 차지하도록 합니다.
속성
- flex: 사용 가능한 공간 내에서 자식 위젯이 차지하는 비율을 결정합니다. 모든 
Expanded위젯의flex값을 합산하여, 각Expanded위젯이 차지하는 공간의 비율을 계산합니다. 
예시 코드
첫 번째와 두 번째 컨테이너는 각각 100px의 너비를 유지하는 반면, 세 번째 Expanded widget으로 감싸진 컨테이너는 나머지 공간을 모두 채우게 됩니다.
      Row(
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Container(
            color: Colors.red,
            width: 100,
            height: 100,
          ),
          Container(
            color: Colors.green,
            width: 100,
            height: 100,
          ),
          Expanded(
            child: Container(
              color: Colors.blue,
              width: 100,
              height: 100,
            ),
          ),
        ],
      ),결과

Flexible
소개
Row, Column, 또는 Flex 같은 부모 위젯 내에서 사용됩니다.
자식 Widget 에게 남은 공간을 어떻게 유연하게 배분합니다.
flex 속성을 사용하여 사용 가능한 공간 내에서 각 자식 Widget이 차지할 공간의 비율을 조정할 수 있으며, fit 속성으로 자식의 크기를 어떻게 조정할지 결정할 수 있습니다.
속성
- flex: 사용 가능한 공간 내에서 자식 Widget이 차지하는 비율을 결정합니다. 모든 
FlexibleWidget의flex값을 합산하여, 각FlexibleWidget이 차지하는 공간의 비율을 계산합니다. - fit: 
FlexFit을 사용하여 자식 Widget이 남은 공간을 어떻게 채울지 결정합니다.FlexFit.tight는 자식이 할당된 공간을 모두 채우도록 합니다(이는Expanded와 유사한 행동입니다), 반면에FlexFit.loose는 자식 Widget이 필요한 만큼의 공간만 차지하도록 허용합니다. 
예시 코드
Row의 자식 위젯들로 배치된 Flexible widget들은 주어진 flex값에 해당하는 비율로 표시됩니다.
      Row(
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Flexible(
            flex: 1,
            fit: FlexFit.tight,
            child: Container(
              color: Colors.red,
              height: 100,
            ),
          ),
          Flexible(
            flex: 2,
            fit: FlexFit.loose,
            child: Container(
              color: Colors.green,
              height: 100,
            ),
          ),
          Flexible(
            flex: 4,
            child: Container(
              color: Colors.blue,
              height: 100,
            ),
          ),
        ],
      ),결과

Padding
소개
자식 Widget 주변에 여백을 추가합니다.
속성
- padding: 자식을 안쪽으로 들여쓸 공간의 양.
 
예시 코드
자식 위젯들을 주어진 값 만큼 띄어서 표시합니다.
      body: Row(
        children: [
          Padding(
            padding: const EdgeInsets.all(50.0),
            child: Container(
              color: Colors.red,
              width: 50,
              height: 50,
            ),
          ),
          Padding(
            padding: const EdgeInsets.all(30.0),
            child: Container(
              color: Colors.green,
              width: 50,
              height: 50,
            ),
          ),
          Padding(
            padding: const EdgeInsets.all(10.0),
            child: Container(
              color: Colors.blue,
              width: 50,
              height: 50,
            ),
          ),
        ],
      ),결과

GridView
소개
격자 형태로 아이템을 배치합니다. 주로 이미지 갤러리, 제품 목록 등에 사용됩니다.
속성
- gridDelegate: 그리드의 레이아웃을 제어합니다.
 - scrollDirection: 스크롤 뷰가 스크롤되는 축.
 
예시 코드
4개의 Container들을 1줄에 2개씩 표시합니다.
      body: GridView.count(
        crossAxisCount: 2,
        children: [
          Container(
            color: Colors.red,
          ),
          Container(
            color: Colors.green,
          ),
          Container(
            color: Colors.blue,
          ),
          Container(
            color: Colors.yellow,
          ),
        ],
      ),결과

Wrap
소개
자식들을 수평 또는 수직 방향으로 배치하고, 공간이 부족하면 다음 줄로 넘깁니다.
속성
- direction: 주 축으로 사용할 방향.
 - alignment: 한 줄 안에서 어떻게 자식들을 주 축에 배치할지.
 - spacing: 각 자식 사이의 공간.
 - runSpacing: 자식들의 각 실행(run) 사이의 공간입니다. 수평 
Wrap의 경우, 감싸기가 발생할 때 수직 공간을 제어합니다. 
예시 코드
8px씩 사이를 주고 자식 widget들을 끝에 맞추어 배치하고 마지막 줄에 걸치면 자동 줄바꿈하여 다음 자식 Widget을 표시합니다.
      const Wrap(
        spacing: 8.0,
        alignment: WrapAlignment.end,
        children: [
          Chip(
            avatar: CircleAvatar(
              backgroundColor: Colors.orange,
              child: Text('AH', style: TextStyle(fontSize: 10)),
            ),
            label: Text('Hamilton'),
          ),
          Chip(
            avatar: CircleAvatar(
              backgroundColor: Colors.pink,
              child: Text('ML', style: TextStyle(fontSize: 10)),
            ),
            label: Text('Lafayette'),
          ),
          Chip(
            avatar: CircleAvatar(
              backgroundColor: Colors.lightBlue,
              child: Text('HM', style: TextStyle(fontSize: 10)),
            ),
            label: Text('Mulligan'),
          ),
          Chip(
            avatar: CircleAvatar(
              backgroundColor: Colors.green,
              child: Text('JL', style: TextStyle(fontSize: 10)),
            ),
            label: Text('Laurens'),
          ),
        ],
      ),결과

ListView
소개
스크롤 가능한 세로 목록을 생성합니다.
속성
- scrollDirection: 리스트가 스크롤되는 축.
 - padding: 자식들을 들여쓸 공간의 양.
 
예시 코드
자식 위젯들을 세로 방향으로 리스트 형식으로 표시합니다.
      ListView(
        scrollDirection: Axis.vertical,
        padding: const EdgeInsets.all(16),
        children: <Widget>[
          Container(
            color: Colors.red,
            width: 100,
            height: 100,
          ),
          Container(
            color: Colors.green,
            width: 100,
            height: 100,
          ),
          Container(
            color: Colors.blue,
            width: 100,
            height: 100,
          ),
          Container(
            color: Colors.yellow,
            width: 100,
            height: 100,
          ),
          Container(
            color: Colors.orange,
            width: 100,
            height: 100,
          ),
          Container(
            color: Colors.purple,
            width: 100,
            height: 100,
          ),
        ],
      ),결과

SizedBox
소개
특정 크기의 공간을 만들 때 사용합니다.
주로 Widget 간의 간격을 조절할 때 사용하거나, 자식 Widget들의 크기를 제한할 수 있습니다.
속성
- width: 박스의 가로 너비
 - height: 박스의 세로 길이
 
예시 코드
Width: 100px, Height: 100px 고정크기로 제한하는 Box를 생성합니다.
      SizedBox(
        width: 100,
        height: 100,
        child: Container(
          width: 1000,
          height: 1000,
          color: Colors.red,
        ),
      ),결과

SingleChildScrollView
소개
단일 자식을 스크롤 가능하게 만듭니다. 주로 긴 내용을 스크롤하여 볼 수 있게 할 때 사용됩니다.
속성
- scrollDirection: 스크롤 뷰가 스크롤되는 축.
 
예시 코드
50개 Container를 자식 Widget으로 갖는 Column을 세로 축으로 스크롤이 가능하게 합니다.
      body: SingleChildScrollView(
        // scroll's direction is vertical (default)
        scrollDirection: Axis.vertical,
        child: Column(
          children: List.generate(
            50,
            (index) => Container(
              height: 50,
              color: index % 2 == 0 ? Colors.yellow : Colors.pink,
              child: Center(
                child: Text('Item $index'),
              ),
            ),
          ),
        ),
      ),결과

결론
위와 같이 다양하게 Widget들을 배치할 수 있는 Layout Widget들이 존재합니다.
각 Widget들만의 다양한 특성과 속성값들을 이용하여 원하는 Layout을 꾸며 볼 수 있습니다.










