-
[Flutter] 상태 변수 최적화 - late final 하나로 코드가 안정적IT 2025. 4. 22. 10:52
Flutter에서 화면을 구성하다 보면 위젯이나 상태값을 나중에 초기화해야 하는 경우가 많습니다.
저도 앱의 MainScreen을 구현하면서 상태 변수 관리가 자꾸 불편했는데,
이번에 late final 키워드를 도입하면서 코드가 놀랍게 깔끔해졌어요.💡 late, final, late final이 뭔가요?
먼저 Dart의 세 가지 변수 선언 키워드를 간단히 정리해볼게요:
키워드의미final 한 번만 값을 할당할 수 있어요. 선언과 동시에 초기화해야 해요. late 나중에 초기화할 수 있어요. 단, 반드시 한 번은 초기화해야 해요. late final 나중에 단 한 번만 초기화할 수 있어요. 즉, 늦게 주지만 바꾸진 않겠다는 뜻! 😕 기존 코드 – ScheduleScreen을 다룰 때 불편했던 점
ScheduleScreen? _scheduleScreen; @override void initState() { _scheduleScreen = ScheduleScreen(key: scheduleScreenKey); }
- nullable(?) 처리로 인해 사용할 때마다 _scheduleScreen?.doSomething() 이런 식으로 null 체크를 해야 했고,
- final이 아니어서 실수로 재할당할 위험도 있었어요.
✅ 개선 후 – late final로 선언하니 이렇게 좋아졌어요
late final ScheduleScreen _scheduleScreen; @override void initState() { super.initState(); _scheduleScreen = ScheduleScreen(key: scheduleScreenKey); }
이렇게 하면:
- null이 아니기 때문에 ?.가 아니라 .로 바로 접근 가능
- final이라서 딱 한 번만 초기화 가능 → 실수 방지
- 선언과 초기화 시점을 분리하면서도 안전함 유지!
전체 적용된 MainScreenState 일부 예시
class MainScreenState extends State<MainScreen> { int selectedIndex = 0; final scheduleScreenKey = GlobalKey<ScheduleScreenState>(); late final ScheduleScreen _scheduleScreen; // 개선 포인트! @override void initState() { super.initState(); selectedIndex = widget.externalTab ?? 0; _scheduleScreen = ScheduleScreen(key: scheduleScreenKey); // ... } @override Widget build(BuildContext context) { return IndexedStack( index: selectedIndex, children: [ HomeScreen(...), _scheduleScreen, // null 체크 없이 안전하게 사용 ... ], ); } }
🎁 보너스 - 하단 네비게이션도 컴포넌트로 분리했어요
이번 기회에 MainBottomBar와 MainFloatingButton도 따로 분리했는데요,
하단 탭바와 가운데 채팅 버튼을 각각 위젯으로 만들고 나니 UI가 훨씬 읽기 쉬워졌습니다.MainBottomBar( selectedIndex: selectedIndex, onTabSelected: setPage, isGuardian: UserManager.currentUser?.is_guardian == true, ),
MainFloatingButton( isGuardian: UserManager.currentUser?.is_guardian == true, onTapGuardian: () => setPage(1), onTapUser: () async { await Navigator.push( context, MaterialPageRoute(builder: (context) => ChatScreen(category: 0)), ); setState(() {}); }, ),
💥 그런데 late final의 단점도 있어요
단점설명❗ 초기화 전에 접근 시 런타임 에러 초기화 전에 사용하면 LateInitializationError가 발생해요. ❗ 초기화 여부가 IDE에서 보이지 않음 변수 선언만 보고는 언제, 어디서 초기화되는지 한눈에 파악하기 어려울 수 있어요. ❗ 과용하면 혼란 초래 무조건 late를 남용하면 코드가 예측 불가능해질 수 있어요. print(_scheduleScreen); // ❌ 아직 초기화되지 않았다면 런타임 에러!
그래서 사용 시엔 정확한 초기화 흐름을 보장할 수 있을 때만 사용하는 게 중요해요.
🧠 최종 요약
항목개선 전개선 후변수 선언 nullable + 재할당 가능 non-null + 재할당 불가 코드 안정성 null 체크 필수 null 걱정 없음 가독성 흐름 분산 선언 → 초기화 → 사용 흐름 명확 UI 구조 MainScreen에 모두 포함 컴포넌트 분리로 가독성 향상
✨ 후기
처음엔 작은 개선이라고 생각했지만,
late final 하나로 변수의 안전성과 명확성을 동시에 얻을 수 있었습니다.
특히 화면 초기화 타이밍이나 BuildContext가 필요한 위젯을 다룰 때는 꼭 써보시길 추천드려요!'IT' 카테고리의 다른 글
[Flutter] Bottom Navigation Bar 클릭 범위 문제 해결기 – InkWell과 Expanded의 조합 (0) 2025.04.22 [유지보수] 레거시 코드 리팩토링.. (0) 2025.04.22 [flutter] nice 인증 api 호출 시 렌더링 오류 문제 (0) 2025.04.14 [Flutter] 연산자와 기호들 (0) 2025.03.26 앱 스토어 등록 시 인앱 결제는 필수적일까? (1) 2025.03.21