
앱을 만들다 보면 "정말 삭제하시겠습니까?" 같은 질문을 던져야 할 때가 있습니다.
사용자로부터 명확한 응답을 받아야 하는 순간이죠.
Flutter에서는 이럴 때 AlertDialog라는 위젯을 사용합니다.
이 글에서는 AlertDialog의 구조부터 결과 처리,
그리고 실무에서 자주 쓰이는 분리/재사용 방식,
마지막으로 iOS/Android 대응 방식까지 단계별로 정리해보았습니다.
다이얼로그, 왜 쓰는 걸까?
AlertDialog는 모달 다이얼로그입니다.
즉, 사용자의 응답을 기다리는 동안 다른 인터랙션을 막고,
중요한 메시지를 강하게 전달할 수 있게 해줍니다.
Android에서는 Dialog,
iOS에서는 UIAlertController가 각각 대응되며,
Flutter에서는 이 모든 걸
AlertDialog 또는 CupertinoAlertDialog로
통합해서 쓸 수 있습니다.
기본 구조, 두 단계를 기억하자
다이얼로그는 크게 두 단계로 나눠서 구성합니다.
showDialog()→ 다이얼로그를 띄우는 함수AlertDialog→ 다이얼로그 내부 UI를 그리는 위젯
showDialog(
context: context,
builder: (context) => AlertDialog(
title: Text('알림'),
content: Text('정말 삭제하시겠습니까?'),
actions: [
TextButton(
onPressed: () => Navigator.pop(context, false),
child: Text('취소'),
),
TextButton(
onPressed: () => Navigator.pop(context, true),
child: Text('확인'),
),
],
),
);
showDialog()는 내부적으로Navigator.of(context).push(...)를 사용하며Future를 반환합니다.- 사용자가 버튼을 누르면
Navigator.pop(context, true or false)로 다이얼로그를 닫으며 값을 반환할 수 있습니다.
결과값을 어떻게 받을까?
final result = await showDialog<bool>(...);
if (result == true) {
// 확인을 눌렀을 때
} else if (result == false) {
// 취소를 눌렀을 때
} else {
// 다이얼로그 외부 탭 등으로 닫혔을 때
}
await 키워드를 통해 사용자의 응답을 기다렸다가, 조건 분기로 분기 처리를 하면 됩니다.
구조화된 분리 방식 3가지
실무에서는 매번 AlertDialog를 새로 작성하지 않고, 다음 3가지 방식 중 하나로 분리해서 재사용합니다.
1. 위젯 함수 분리
Widget _buildConfirmDialog(BuildContext context) => AlertDialog(...);
ElevatedButton(
onPressed: () => showDialog(context: context, builder: _buildConfirmDialog),
child: Text('삭제하기'),
);
- ✅ 간단하게 분리할 수 있지만, 복잡한 커스터마이징에는 다소 한계가 있습니다.
2. 커스텀 Dialog 클래스 분리
class ConfirmDialog extends StatelessWidget {
final String title;
final String content;
...
@override
Widget build(BuildContext context) => AlertDialog(...);
}
- ✅ 구조적이고 테스트가 쉬우며 재사용성이 좋습니다.
3. 전역 유틸 함수로 분리
3-1. Future 기반
Future<bool?> showConfirmDialog(...) => showDialog(...);
final confirmed = await showConfirmDialog(...);
3-2. 콜백 기반
await showConfirmDialogWithCallbacks(
context: context,
content: '정말 삭제하시겠습니까?',
onConfirm: () => print('삭제됨'),
onCancel: () => print('취소됨'),
);
- ✅ 호출부가 간결하고 어디서든 사용하기 좋습니다.
- ❗ 단점: UI 커스터마이징이 어렵고 로직 분리가 어려울 수 있습니다.
화면 전환 + 다이얼로그 예제
SecondPage에서 다이얼로그를 띄우고 "확인"을 누르면 첫 화면으로 돌아가는 예시입니다.
final confirm = await showDialog(...);
if (confirm == true && context.mounted) {
Navigator.pop(context); // SecondPage 닫기
}
여기서 중요한 점은 context의 위치입니다. builder 안의 context는 다이얼로그 전용 context지만, 여전히 동일한 트리 상에서 동작하기 때문에 Navigator.pop()은 안전하게 작동합니다.
iOS와 Android를 자동으로 구분하기
플랫폼에 따라 CupertinoAlertDialog 또는 AlertDialog를 자동으로 선택해주는 유틸 함수도 만들 수 있습니다.
Future<bool?> showPlatformDialog({ ... }) {
if (Platform.isIOS) {
return showCupertinoDialog(...);
} else {
return showDialog(...);
}
}
이렇게 만들면 어느 플랫폼에서든 한 줄로 다이얼로그를 띄울 수 있습니다.
final result = await showPlatformDialog(...);
✏️ 실습 과제
목표
"정말 홍길동님을 삭제하시겠습니까?" 라는 메시지를 띄우고,
버튼 클릭 결과에 따라 SnackBar를 보여주는 AlertDialog를 만들어보세요.
버튼을 누르면 AlertDialog가 나타나고,
다음과 같은 내용을 보여주세요:
- 제목: “확인 요청”
- 내용: “정말 [사용자 이름]님을 삭제하시겠습니까?”
- 버튼: “취소”, “삭제”
조건
- 이름은 변수 userName으로 미리 선언되어 있어야 함
(예: final userName = '홍길동';)
- 사용자가 “삭제”를 누르면 true,
“취소”를 누르면 false를 반환해야 함
- 결과에 따라 ScaffoldMessenger.of(context).showSnackBar()를 이용해 결과 메시지를 보여주세요
예시 흐름
- 버튼 누름
- 다이얼로그 표시 (이름 포함된 메시지)
- 선택에 따라 다이얼로그 닫힘
- 화면 하단에 결과 메시지 표시
마치며
AlertDialog는 간단해 보이지만,
사용자 경험에 큰 영향을 미치는 요소입니다.
처음에는 기본 형태로 시작하되,
이후에는 함수/클래스/전역 함수 등 상황에 맞게 구조를 분리해보세요.
다음 글부터는 StatefulWidget과 setState를 중심으로
상태 변경의 기본 원리를 하나씩 따라가 보려고 해요.
UI는 그대로인데 내부 데이터만 바뀔 때, 우리는 어떻게 대응해야 할까요?
작은 상태 변화부터 하나씩 예제와 함께 익숙해지는 과정을 통해
Flutter의 상태 시스템을 자연스럽게 체득해봅니다.
이 시리즈는 단 한 편으로 끝나지 않아요.
하나씩 단계별로 익숙해지며, 위젯 시리즈, Navigation 시리즈와 교차해가며 다룰 예정이에요.
처음에는 setState 기반으로 시작해서 이후 Provider, Bloc, Riverpod 등으로 확장해나갈 계획입니다.
'개발(Development) > Flutter' 카테고리의 다른 글
| Flutter 앱은 어떻게 시작될까? (4) | 2025.08.06 |
|---|---|
| 상태관리 시리즈 2 – StatefulWidget 생명주기 완전 정복 (3) | 2025.08.05 |
| 상태관리 시리즈 1 - Stateless와 Stateful 완전 정복 (2) | 2025.08.05 |
| Navigation 시리즈 001 - Navigator 1.0 화면 전환과 데이터 전달의 모든 것 (3) | 2025.08.01 |
| Flutter 위젯 시리즈 007 – Scaffold와 AppBar 완전 이해하기 (0) | 2025.07.14 |
| Flutter 위젯 시리즈 006 – Container 완전 이해하기 (1) | 2025.07.14 |
| Flutter 위젯 시리즈 005 – Row 완전 이해하기 (2) | 2025.07.11 |
| Flutter 위젯 시리즈 004 – ElevatedButton 완전 정복 (1) | 2025.07.09 |