개요

SizedBox는 특정 너비와 높이를 가진 박스를 생성하는 간단한 위젯입니다.

SizedBox는 크기 지정만을 목적으로 하는 단일 기능 위젯으로, Container보다 가볍고 효율적입니다. 주로 위젯 간 간격을 만들거나, 자식 위젯의 크기를 제한하거나, 조건부 렌더링에서 빈 공간을 만들 때 사용됩니다. 내부적으로는 ConstrainedBox를 사용하여 tight constraints를 적용합니다.

참고: https://api.flutter.dev/flutter/widgets/SizedBox-class.html

언제 사용하나요?

  • 위젯 간 고정된 간격을 만들 때
  • 자식 위젯에 고정된 크기를 강제할 때
  • 조건부 렌더링에서 빈 공간이 필요할 때
  • Container의 다른 기능(색상, 패딩, 장식 등)이 필요 없을 때
  • 성능이 중요한 곳에서 단순히 크기만 지정할 때

기본 사용법

// 고정 크기 박스
SizedBox({
  width: 200,
  height: 100,
  child: Text('고정 크기')
})

// 간격 만들기 (가장 일반적인 사용)
Column({
  children: [
    Text(''),
    SizedBox({ height: 20 }), // 20픽셀 세로 간격
    Text('아래')
  ]
})

// 가로 간격
Row({
  children: [
    Icon({ icon: Icons.star }),
    SizedBox({ width: 8 }), // 8픽셀 가로 간격
    Text('별표')
  ]
})

Props

width

값: number | undefined

박스의 너비를 픽셀 단위로 지정합니다. 지정하지 않으면 자식의 너비에 따라 결정됩니다.

SizedBox({
  width: 100,
  child: Text('너비 100px')
})

height

값: number | undefined

박스의 높이를 픽셀 단위로 지정합니다. 지정하지 않으면 자식의 높이에 따라 결정됩니다.

SizedBox({
  height: 50,
  child: Text('높이 50px')
})

child

값: Widget | undefined

SizedBox 안에 배치할 자식 위젯입니다. 자식이 없으면 빈 공간이 생성됩니다.

SizedBox({
  width: 200,
  height: 200,
  child: Container({ color: 'blue' })
})

정적 메서드

SizedBox.shrink()

크기가 0인 SizedBox를 생성합니다. 조건부 렌더링에서 아무것도 표시하지 않을 때 유용합니다.

// 조건부 렌더링
const widget = showButton 
  ? ElevatedButton({ child: Text('클릭') })
  : SizedBox.shrink();

// 기본 사용
SizedBox.shrink() // width: 0, height: 0

// 자식과 함께 사용
SizedBox.shrink({
  child: Text('보이지 않음') // 크기가 0이므로 표시되지 않음
})

SizedBox.expand()

가능한 모든 공간을 차지하는 SizedBox를 생성합니다.

// 전체 공간 차지
SizedBox.expand({
  child: Container({ color: 'red' })
})

// 특정 방향만 확장
SizedBox.expand({
  width: 100, // 너비는 100으로 고정
  child: Container({ color: 'blue' }) // 높이만 확장
})

SizedBox.fromSize()

Size 객체로부터 SizedBox를 생성합니다.

const size = Size({ width: 150, height: 75 });

SizedBox.fromSize({
  size: size,
  child: Text('Size 객체 사용')
})

SizedBox.square()

정사각형 SizedBox를 생성합니다.

// 100x100 정사각형
SizedBox.square({
  dimension: 100,
  child: Container({ color: 'green' })
})

실제 사용 예제

예제 1: 리스트 아이템 간격

const listWithSpacing = Column({
  children: [
    ListTile({ title: Text('항목 1') }),
    SizedBox({ height: 8 }),
    ListTile({ title: Text('항목 2') }),
    SizedBox({ height: 8 }),
    ListTile({ title: Text('항목 3') })
  ]
});

예제 2: 버튼 그룹

const buttonGroup = Row({
  mainAxisAlignment: MainAxisAlignment.center,
  children: [
    ElevatedButton({
      onPressed: () => {},
      child: Text('이전')
    }),
    SizedBox({ width: 16 }), // 버튼 간 간격
    ElevatedButton({
      onPressed: () => {},
      child: Text('다음')
    })
  ]
});

예제 3: 조건부 간격

const conditionalSpacing = Column({
  children: [
    Text('제목'),
    hasSubtitle ? SizedBox({ height: 8 }) : SizedBox.shrink(),
    hasSubtitle ? Text('부제목') : SizedBox.shrink(),
    SizedBox({ height: 16 }),
    Text('본문')
  ]
});

예제 4: 고정 크기 이미지 컨테이너

const imageGrid = GridView({
  gridDelegate: SliverGridDelegateWithFixedCrossAxisCount({
    crossAxisCount: 3,
    spacing: 8
  }),
  children: images.map(img => 
    SizedBox.square({
      dimension: 100,
      child: Image({
        src: img,
        fit: 'cover'
      })
    })
  )
});

예제 5: 로딩 표시기 크기 제한

const loadingIndicator = Center({
  child: SizedBox({
    width: 50,
    height: 50,
    child: CircularProgressIndicator()
  })
});

Container와의 차이점

SizedBox 사용

// 단순히 크기만 필요할 때
SizedBox({ 
  width: 100, 
  height: 50,
  child: widget 
})

Container 사용

// 크기 외에 다른 스타일이 필요할 때
Container({ 
  width: 100, 
  height: 50,
  padding: EdgeInsets.all(8),
  color: 'blue',
  child: widget 
})

성능 차이: SizedBox는 단일 ConstrainedBox만 생성하지만, Container는 여러 위젯을 조합하므로 SizedBox가 더 효율적입니다.

주의사항

  • width와 height 중 하나만 지정하면 다른 축은 자식의 크기를 따릅니다.
  • SizedBox.expand()는 부모가 무한 크기를 허용하면 오류가 발생할 수 있습니다.
  • 자식이 없는 SizedBox는 지정된 크기의 빈 공간을 만듭니다.
  • 음수 크기는 허용되지 않습니다.

관련 위젯

  • Container: 크기 외에 다양한 스타일링이 필요할 때
  • ConstrainedBox: 최소/최대 크기 제약이 필요할 때
  • AspectRatio: 가로세로 비율을 유지해야 할 때
  • FractionallySizedBox: 부모 크기의 비율로 크기를 정할 때
  • Spacer: Row/Column에서 유연한 공간을 만들 때