기획자의 앱 도전기 #4 - 화면 이동

2025. 8. 17. 23:18·개발/[Flutter]

앱 첫 난관 : 앱 화면 이동

웹처럼 앱 또한 화면 이동이 된다.

하지만 기획을 하면서 웹의 화면 이동 방식과 앱의 화면 이동 방식에 다른 부분이 생겼다.

 

웹(Web)에서의 화면 이동

웹은 URL과 브라우저 히스토리를 기반으로 화면을 이동합니다.

  • URL 기반: 각 페이지는 고유한 URL을 가지며, 주소를 통해 직접 접근할 수 있다.
  • 히스토리 관리: 브라우저는 방문 기록을 저장하고, 사용자는 앞/뒤로 가기 버튼으로 쉽게 이동할 수 있다.
  • SPA(Single Page Application): 화면 전체를 새로고침하지 않고, 특정 부분만 교체합니다. 하지만 여전히 내부적으로는 **라우터(router)**가 URL을 바꾸고 화면을 관리한다.

즉, 웹은 "페이지 단위 이동"보다는 URL이 우선이고, 브라우저가 이동과 히스토리를 주도한다고 볼 수 있다.


앱(App)에서의 화면 이동

앱은 브라우저처럼 URL을 사용하지 않고, Navigator(네비게이터)라는 개념을 기반으로 이동한다.

  • 스택(Stack) 구조: 새로운 화면을 띄우면 스택에 push, 뒤로 가면 pop으로 관리한다.
  • 앞/뒤로 가기: 브라우저의 히스토리와 달리, 앱에서는 스택에서 쌓인 화면을 하나씩 꺼내면서 이동한다.
  • 탭 전환: 앱 하단의 탭 메뉴는 스택 이동이 아니라 동등한 sibling 화면 간의 전환으로 처리한다.

즉, 앱은 "화면 단위 이동"이고, Navigator가 이동과 히스토리를 주도한다고 할 수 있다.

 

 

보기 편하게 표로 만들면 다음과 같다.

구분 웹 앱
이동 기준 URL Navigator(스택)
기록 관리 브라우저 히스토리 스택 push/pop
앞/뒤로 가기 브라우저가 처리 스택에서 화면 제거
특별한 구조 SPA → 라우터가 화면만 교체 탭 전환 → sibling 이동

 


앱 이동 방식을 알아보자.

 

앱의 화면 이동방식은 스택을 이용한 이동, 탭 전환으로 크게 두 가지로 하나씩 구현해 보면서 알아가자.

 

1. 스택을 이용한 이동

스택으로 이동 시 Navigator라는 클래스를 사용한다.

Navigator는 화면 전환을 관리하는 위젯으로 스택 구조로 관리하여 이동하며, push와 pop을 이용한다.

 

- push : 새로운 화면으로 이동하면서 스택을 쌓는다.

//기존 위치 : Home
Navigator.push(
  context,
  MaterialPageRoute(builder: (context) => const SecondScreen()),
); //이동 위치 : [Home, SecondScreen]

 

- pop : 이전 화면으로 이동하면서 스택을 제거한다.

//현재 위치 : [Home, SecondScreen]
Navigator.pop(context);
//이동 위치 : [Home]

 

아래는 Navigator의 push와 pop을 이용하여 구현한 화면이다.

직접 구현을 해보니 확실히 웹과는 다른 매력이 느껴진다...(재밌당)

스택 이동 구현 예시

 

위의 Navigator를 이용하여 만든 스터디용 코드가 필요하다면 댓글을 남겨주면 보내드릴 수 있는데,

그냥 GPT한테 한번 구현해달라고 하고 그걸로 써보는 것이 더 빠를 것이다.

 

2. 탭 전환 이동

탭 전환 이동은 Sibling Navigation이라 불리며, 스택을 쌓는게 아니라 같은 레벨의 화면들을 옆으로 바꿔치기하는 방식으로, 보통 메인 화면에서 sibling 전환을 사용하고 각 탭 안에서 Navigator로 뎁스를 파고 든다.

스택 방식과는 다르게 뒤로가기와는 무관하여, 안드로이드의 경우 탭 전환 후 뒤로가기를 클릭했을 경우 앱을 이탈할 수 있다.

 

탭 전환은 크게 두 가지 방식이 있다.

 

BottomNavigationBar를 이용한 화면 전환

바텀 네비게이션 바를 이용하는 경우는 보통, 메인 화면 간 탭을 변경하는 구조에서 많이 사용한다.

왼쪽 사람인 바텀네비게이션 / 오른쪽 카카오톡 바텀네비게이션

 

구현 방식은 여러가지가 있다는데 나는 가장 기본적인 BottomNavigationBar와 IndexedStack으로 구현을 해보았다.

 

IndexedStack이란, 플러터에서 여러 개의 화면(위젯)을 Index에 쌓아놓고 그 중 하나를 보여주도록 하는 클래스이다.

옛날에 많이 썼던 투명 파일철과 비슷하게 투명한 파일철 안에 여러장의 파일을 끼워넣고 내가 원하는 파일을 꺼내서 보는 것이다.

 

IndexedStack과 BottomNavigationBar를 함께 쓰면 이렇게 된다.

_index = 0
_pages = [Home(), SearchPage(), Profile()]

Scaffold(
   body: IndexedStack(index: _index, children: _pages),
   bottomNavigationBar: BottomNavigationBar(
     type: BottomNavigationBarType.fixed,
     currentIndex: _index, //현재 인덱스 번호
     selectedItemColor: Theme.of(context).colorScheme.primary,
     unselectedItemColor: Colors.grey,
     onTap: (i) => setState(() => _index = i), //탭 시 현재 인덱스 번호 세팅
     items: const [
       BottomNavigationBarItem(icon: Icon(Icons.home), label: '홈'),
       BottomNavigationBarItem(icon: Icon(Icons.search), label: '검색'),
       BottomNavigationBarItem(icon: Icon(Icons.person), label: '프로필'),
     ],
   ),
);

 

꼭 알아야 할 것은 page 순서와 바텀네비게이션 탭 순서는 동일해야 하게 해야하며, 구현하게 되면 아래와 같은 화면이 된다.

바텀네비게이션바 구현 예시

 

TapBar를 이용한 화면 전환

TapBar를 이용한 화면 전환은 메인화면끼리 전환보다는 1개의 메인 메뉴 내에서 카테고리별로 화면을 전환한다.

 

잡플래닛 뉴스탭 내 화면 / 파랑색 : 탭바 / 빨간색 : 바텀네비게이션바

 

TapBar는 TapBar와 TapBarView라는 클래스를 같이 사용하여 구현한다.

사실, 바텀네비게이션과 크게 다를 것은 없다. 바텀네비게이션은 화면 자체를 바꾸고 탭바는 내용물만 바꾼다는 개념 차이만 있을 뿐이다.

 

TapBar 구현 코드는 다음과 같다.

appBar: AppBar(
       title: const Text("TabBar + TabBarView 예제"),
       bottom: const TabBar(
         tabs: [
           Tab(icon: Icon(Icons.home), text: "홈"),
           Tab(icon: Icon(Icons.search), text: "검색"),
           Tab(icon: Icon(Icons.person), text: "프로필"),
         ],
       ),
     ),
     body: const TabBarView(
       children: [
         HomePage(),
         SearchPage(),
         ProfilePage(),
       ],
     ),

 

탭바는 앱바 자식으로만 구현하는 것은 아니다. 바디나 바텀네비게이션으로도 구현 가능하니 참고하길 바라며, 이대로 구현하게 되면 다음과 같은 화면이 나오게 된다.

탭바 구현 예시

 

마무리

앱을 이동 방식을 알게되었는데, 기획 의도를 개발자에게 좀 더 명확히 전달할 수 있도록 기획서를 보완할 수 있는 계기가 되었다.

앱 공부를 하면서 기획에도 도움이 많이 되는 것 같다. 그러니 앱을 직접 만들고 운영할 수 있는 날이 올 때까지 공부하고 알아가는 것들을 기록할 것이다.

'개발 > [Flutter]' 카테고리의 다른 글

기획자의 앱 도전기 #6 - 바텀시트 만들기  (0) 2025.09.28
기획자의 앱 도전기 #5 - 로컬 저장  (0) 2025.08.31
기획자의 앱 도전기 #3 - Flutter UI 구조 이해하기  (1) 2025.07.20
기획자의 앱 도전기 #2 - Flutter 기본 구성 요소  (0) 2025.07.06
기획자의 앱 도전기 #1 – Flutter 환경 세팅부터 시작!  (0) 2025.06.21
'개발/[Flutter]' 카테고리의 다른 글
  • 기획자의 앱 도전기 #6 - 바텀시트 만들기
  • 기획자의 앱 도전기 #5 - 로컬 저장
  • 기획자의 앱 도전기 #3 - Flutter UI 구조 이해하기
  • 기획자의 앱 도전기 #2 - Flutter 기본 구성 요소
Lee-jam
Lee-jam
나는 분명 기획자인데 왜 개발 공부를 하고 있는걸까...
  • Lee-jam
    JamiUp는 사회생활
    Lee-jam
  • 전체
    오늘
    어제
    • 분류 전체보기 (47)
      • 기획 (17)
        • 개념 (5)
        • 인사이트 (9)
        • Figma (1)
      • 개발 (9)
        • [Python] (3)
        • [Flutter] (6)
      • 데이터 분석 (2)
      • 제로베이스 (11)
        • 스터디노트 (11)
      • 회사에서 살아남기 (2)
      • [정보처리기사] (0)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    기획자
    두번째 걸음
    데이터 분석
    서비스 기획
    기획인사이트
    기획자의 앱 도전기
    5주차
    서비스기획자
    기획
    플러터 공부
    Flutter
    다섯 번째 걸음
    서비스기획
    세균무기가 알려주는 서비스 기획의 모든 것
    서비스 기획자
    제로베이스
    이직
    기획 인사이트
    답답해서 내가 뛴다
    pmf
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
Lee-jam
기획자의 앱 도전기 #4 - 화면 이동
상단으로

티스토리툴바