본문 바로가기
개발/플러터(Flutter)

Flutter 위젯 탐방기4 - 오늘의 위젯 정리하기

by 수인분당선 2026. 3. 15.

1. Shared_preferences

https://www.youtube.com/watch?v=sa_U0jffQII&list=PLjxrf2q8roU23XGwz3Km7sQZFTdB996iG&index=55

특징

  • 간단한 key-value 데이터를 로컬에 영구 저장할 수 있는 플러그인
  • 기기에 상관없이 영구 저장장치에 같은 코드로 접속할 수 있음

주의사항

  • 영구 저장 장치의 경우 코드 작성이 디스크로 이어진다는 보장이 없기 때문에 민감한 데이터는 secure storage등을 사용해야합니다..
  • 값이 없으면 null을 반환하기 때문에 기본값에 대한 처리가 필요합니다.

활용 예제

 

SharedPreferences prefs = await SharedPreferences.getinstance();

prefs.setBool("darkMode",val);
bool isDark = prefs.getBool("darkMode");


//실제 디스크의 접근 없이 초깃값을설정함으로써 위젯 테스트 시 유용
Map<String, Object> values = <String,Object>('darkMode', true);
SharedPreferences.setMockInitialValues(values);

 


2. RepaintBoundary

https://www.youtube.com/watch?v=cVAGLDuc2xE&list=PLjxrf2q8roU23XGwz3Km7sQZFTdB996iG&index=57

 

특징

  • 리페인트(다시 그리기) 범위를 명확하게 분리해주는 위젯
  • 기본적으로 부모가 그려질 때 자식도 함께 다시 그려지는 플러터의 특성을 차단하여 불필요한 재렌더링을 막음으로써 성능 최적화를 도움
  • ListView, Drawer등의 일부 위젯은 해당 위젯이 내부적으로 자동 추가됨

주의사항

  • 이 위젯은 소량의 cpu와 메모리 공간을 추가로 차지할 수 있으므로 무조건적인 사용을 지양해야합니다.

활용 예제

void main(){
 //플러터가 렌더를 하는 경계를 구분(각 repaint영역이 무지개 색으로 표시됨!)
	debugRepaintRainbowEnable = true;
    runApp(MyAPP());
}

//근접한 위젯에 페인트를 튀기는 상황을 막아줌
RepaintBoundary(
	child: MyWidget(),
)

 


3. StatefulBuilder

https://www.youtube.com/watch?v=syvT63CosNE&list=PLjxrf2q8roU23XGwz3Km7sQZFTdB996iG&index=58

 

특징

  • 작은 영역을 부분적으로 setState할 수 있도록 도와주는 위젯으로, 별도의 StatefulWidget을 만들지 않고도 일부만 재빌드 가능
  • Dialog내부 상태, BottomSheet등에서 사용

주의사항

  • 상태변수의 위치(예제: isExpanded)가 적절한 스코프에 위치해야 합니다. 
  • 복잡한 상태 관리에는 부적합하여,  StatefulWidget또는 상태관리 라이브러리가 필요합니다.

활용 예제

bool isExpanded = false;

Widget build(context){
	return Column(
    	children: [
        	//빌더 생성
        	StatefulBuilder(
            	//재빌드할 부분 추가 후, 조건넣기
            	builder: (ctx, setState) =>
                	InexpensiveStateful(
                    	isExpanded: isExpanded,
                        onTap: (bool newValue) =>
                        	setState(() => isExpanded = val),
                        ),
                    ),
                    ExpensiveStateless(),
        ],
    );
}

 


4. ScaffoldMessenger

https://www.youtube.com/watch?v=lytQi-slT5Y&list=PLjxrf2q8roU23XGwz3Km7sQZFTdB996iG&index=59

 

특징

  • 내장형 위젯으로 모든 위젯의 상위에서 작동하여 SnackBar와 같은 알림을 관리하는 전역 메시지 관리자
  • 새로운 Scaffold가 실행될 때마다 상위 ScaffoldMessenger을 탐색하여 스낵바 이벤트를 보여주는 구조
  •  MaterialApp이 기본 ScaffoldMessenger을 제공하기 때문에 직접 추가할 필요가 없음

주의사항 

  • ScaffoldMessenger.of(context)는 반드시 MaterialApp하위 context여야합니다.
  • 너무 자주 사용될 경우 UX 저하로 이어질 수 있습니다.
  • 중복 스낵바 및 빠른 연속 호출로 인한 스택쌓임에 주의하여야 합니다.

활용 예제

//기존방식
Scaffold.of(context)
=> 
//이렇게 바뀌었어요
ScaffoldMessenger.of(context)

//-----------------------------------

//BuildContext를 이용할 수 없는 경우
//미리 선언하고 사용해버리기
final _scaffoldKey = GlobalKey<ScaffoldMessengerState>();

MaterialApp(
	scaffoldMessengerKey: _scaffoldKey,
)

//이렇게 불러와요
final ScaffoldMessengerState _scaffold = _scaffoldKey.currentState;

//실제로 사용하기
scaffoldMessengerState.showSnackBar(
	SnackBar(...)
)

 


5. Baseline

https://www.youtube.com/watch?v=8ZaFk0yvNlI&list=PLjxrf2q8roU23XGwz3Km7sQZFTdB996iG&index=62

특징

  • 자식 위젯을 텍스트 기준선에 맞춰 정렬하는 위젯
  • Row에서도 자체적인 baseline 파라미터를 지원하지만, 복잡한 레이아웃에서는 직접 Baseline위젯 사용

주의사항

  • 만약 위젯의 높이가 100인데, 기준선이 150인것처럼 기준선이 위젯의 범위를 초과할 경우, 레이아웃 깨짐 현상이 발생할 수 있으므로 주의해야 합니다.
  • 텍스트가 아닌 위젯에는 baseline개념이 없기 때문에 의미가 약합니다.
  • 사실 성능상 Row, Column등으로 처리되기 때문에 거의 사용하지 않게 된 위젯입니다.ㅋㅋ

활용 예제

기준선의 종류

alphabetic : 영문기준선 / ideographic: 동아시아 문자 기준선 

Baseline(
	baseline: 100,
	baselineType: TextBaseline.alphabetic,
	child: MyText(),
)

 


6. GestureDetector

https://www.youtube.com/watch?v=WhVXkCFPmK4&list=PLjxrf2q8roU23XGwz3Km7sQZFTdB996iG&index=66

특징

  • 모든 유형의 사용자 상호작용을 추적하는 위젯
  • onTap 외에도 수많은 사용자 상호작용 타입을 정의하고 추적할 수 있음
  • 클릭, 더블 클릭, 긴 클릭, 스와이프, 드래그뿐만 아니라 집기, 확대까지 가능

주의사항

  • 클릭해도 시각적 피드백이 없기 떄문에 버튼처럼 보이게 하려면 직접 구현할 필요가 있습니다.

활용 예제

GestureDetector(
	onTap: () {}, //버튼과 비슷한 반응 추적
    child: Text(),
)

//드래그 가능한 위젯 만들기
Positioned(
	top: _top,
    child: GestureDetextor(
    	onPanUpdate: (details){ ... },
        child: MyWidget(),
    )
)