
Flutter에서 위젯을 만들다 보면 습관처럼 Container를 쓰는 경우가 많다.
그런데 정말 필요한 상황이 아니면 Container는 피하는 게 좋다.
그 이유는 간단하다.
Container는 내부적으로 너무 많은 기능을 포함하고 있어서, 렌더링 시 더 많은 비용이 발생하기 때문이다.
Container는 내부적으로 다음과 같은 기능들을 모두 지원한다:
이 말은 곧, 내가 단순히 크기만 설정하고 싶은데 Container를 쓰면, 필요 없는 렌더링 비용까지 지불하게 된다는 뜻이다.
간단하게 크기만 주고 싶다면 SizedBox를 사용하고, 스타일이 필요하면 DecoratedBox를 조합하면 된다.
// 불필요하게 무거운 방식
Container(
width: 100,
height: 100,
color: Colors.blue,
child: Text('Hello'),
);
// 더 가벼운 방식
DecoratedBox(
decoration: BoxDecoration(color: Colors.blue),
child: SizedBox(
width: 100,
height: 100,
child: Text('Hello'),
),
);
Container는 내부적으로 여러 위젯이 결합된 형태다.
다음은 Container 하나가 만들어내는 위젯 트리 구조 예시다:
→ Padding
→ Align
→ ConstrainedBox
→ DecoratedBox
→ SizedBox
→ Child
즉, 단순히 하나의 위젯처럼 보여도 실제 렌더링에서는 복수의 위젯이 트리에 생성된다.
반면 SizedBox + DecoratedBox 조합은 꼭 필요한 위젯만 사용하므로 렌더링 비용이 낮다.
→ DecoratedBox
→ SizedBox
→ Child
필요한 만큼만 쓰는 게 핵심이다.
class TestContainer extends StatelessWidget {
Widget build(BuildContext context) {
return Container(
width: 100,
height: 100,
color: Colors.blue,
child: Text('Container'),
);
}
}
class TestLightContainer extends StatelessWidget {
Widget build(BuildContext context) {
return DecoratedBox(
decoration: BoxDecoration(color: Colors.blue),
child: SizedBox(
width: 100,
height: 100,
child: Text('DecoratedBox'),
),
);
}
}
자주 쓰는 구조 중 하나가 이런 식이다:
Expanded(child: Container())
사실 이건 대부분의 경우 그냥 Spacer()로 대체 가능하다.
Spacer()
필요한 건 빈 공간을 차지하는 역할이지, 스타일링은 아니니까.
본문 내용과는 별개지만, 단순 여백을 위해 SizedBox(height: x) 같은 코드 쓰는 게 지겹다면,
Gap 패키지를 사용하는 것도 방법이다.
Gap(16)
가독성도 좋고, 의미도 명확하다.
Container는 기능이 많아서 무거운 위젯이다.SizedBox, DecoratedBox, Spacer 등을 조합해서 더 가볍게 만들 수 있다.Container 쓰지 말고, 정말 필요한 경우에만 쓰자."가벼운 UI가 결국 더 부드러운 앱을 만든다.