Navigator와 페이지 전환: 앱의 흐름을 설계하는 법
최근 바이브코딩 프로젝트를 진행하면서 느끼는 점은, 앱의 완성도는 결국 '매끄러운 사용자 경험'에서 나온다는 것입니다. 사용자가 버튼을 눌렀을 때 자연스럽게 상세 페이지로 이동하고, 다시 원래 자리로 돌아오는 기능은 앱의 가장 기본이자 핵심이죠. 오늘은 플러터에서 화면을 관리하는 거대한 관제탑, Navigator의 원리와 실전 사용법을 상세히 알아보겠습니다.
1. Navigator의 원리: Stack(스택) 구조
플러터의 화면 관리는 '종이 쌓기(Stack)'와 똑같습니다. 새로운 화면이 나타날 때 기존 화면을 지우는 것이 아니라, 그 위에 새로운 화면이라는 종이를 한 장 더 얹는 방식입니다.
- 📥 Push (밀어 넣기): 새로운 페이지를 스택의 가장 위에 올립니다. (화면 이동)
- 📤 Pop (꺼내기): 맨 위에 있는 종이를 치워 바로 아래에 있던 페이지를 보여줍니다. (뒤로 가기)
이러한 구조 덕분에 사용자가 '뒤로 가기'를 눌렀을 때 이전 화면의 상태(스크롤 위치 등)가 그대로 유지될 수 있는 것입니다.
2. 핵심 함수 상세 분석
① Navigator.push()
새로운 화면을 스택에 추가합니다. 이때 Route(경로)라는 개념이 필요합니다.
- MaterialPageRoute: 플러터가 제공하는 기본 경로 생성기입니다. 안드로이드는 아래에서 위로, iOS는 옆에서 밀려오는 플랫폼별 특유의 애니메이션을 자동으로 적용해 줍니다.
- builder: 이동할 새 페이지 위젯을 반환하는 함수를 작성합니다.
② Navigator.pop()
현재 화면을 닫고 이전 화면으로 돌아갑니다. 물리적인 뒤로 가기 버튼뿐만 아니라, 앱 내 '닫기' 버튼 등을 직접 구현할 때 사용합니다.
3. 여기서 다시 만나는 BuildContext
이전에 공부한 내용 중 BuildContext가 위젯의 '신분증'이자 '주소'라고 배웠습니다. 네비게이터를 쓸 때 왜 context를 인자로 넘겨줄까요?
Navigator 위젯은 보통 위젯 트리의 최상단에 살고 있습니다. 현재 위젯이 자신의 위치 정보(context)를 알려줘야 네비게이터가 "아, 너 지금 여기 있구나! 그럼 네 위에 새로운 화면을 쌓아줄게"라고 정확히 판단할 수 있기 때문입니다.
4. 실전 코드로 익히기
바이브코딩에서 활용할 수 있는 가장 기본적인 화면 전환 예제입니다.
// 1번 화면: 메인 페이지 class FirstPage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('메인')), body: Center( child: ElevatedButton( onPressed: () { // 상세 페이지로 이동 (Push) Navigator.push( context, MaterialPageRoute(builder: (context) => const SecondPage()), ); }, child: const Text('상세 보기'), ), ), ); } } // 2번 화면: 상세 페이지 class SecondPage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('상세 페이지')), body: Center( child: ElevatedButton( onPressed: () => Navigator.pop(context), // 현재 화면 닫기 (Pop) child: const Text('닫기'), ), ), ); } }
스택의 가장 마지막 페이지(홈 화면)에서
Navigator.pop(context)를 호출하면 앱이 꺼지거나 검은 화면이 나올 수 있습니다. Navigator.canPop(context)로 돌아갈 페이지가 있는지 먼저 확인하는 습관을 들이면 더욱 견고한 앱을 만들 수 있습니다.
💡 퀴즈 (Check-point)
Q. 새로운 화면으로 이동하여 스택에 '종이를 쌓을 때' 사용하는 함수는 무엇일까요?
(정답: Navigator.push()입니다! 반대로 현재 화면을 치울 때는 pop을 사용합니다.)