Flutter for OpenHarmony에서 BottomNavigationBar 구현하기: 초보자도 쉽게 따라 하는 가이드

Flutter for OpenHarmony 환경에서 하단 탐색 바를 구현할 때, PageView와 BottomNavigationBar의 조합은 강력하면서도 직관적인 선택입니다. 이 글에서는 실제 프로젝트에서 마주칠 수 있는 문제점과 해결 방안을 중점적으로 다루며, 성능 최적화 팁까지 제공합니다.

1. PageView + BottomNavigationBar 구조 선택 이유

PageView를 사용하면 각 탭의 상태(State)를 유지하면서 페이지 전환 애니메이션을 자연스럽게 적용할 수 있습니다. BottomNavigationBar와 결합하면 사용자 인터랙션에 따른 페이지 이동이 일관성 있게 동작합니다.

class _MainScreenState extends State<MainScreen> {
  int _selectedIndex = 0;
  final PageController _pageCtrl = PageController();

  final List<Widget> _pageList = [
    const HomePage(),
    const MessagePage(),
    const WorkPage(),
    const DiscoverPage(),
    const ProfilePage(),
  ];

  void _onTabTapped(int idx) {
    if (_selectedIndex != idx) {
      _pageCtrl.animateToPage(
        idx,
        duration: const Duration(milliseconds: 300),
        curve: Curves.easeInOut,
      );
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: PageView(
        controller: _pageCtrl,
        onPageChanged: (idx) {
          setState(() {
            _selectedIndex = idx;
          });
        },
        children: _pageList,
      ),
      bottomNavigationBar: BottomNavigationBar(
        currentIndex: _selectedIndex,
        onTap: _onTabTapped,
        items: [
          // 각 아이템 정의
        ],
      ),
    );
  }
}

2. 자주 발생하는 문제와 해결책

이슈 1: 슬라이드와 탭 선택 간 상태 불일치

사용자가 PageView를 직접 슬라이드할 때 BottomNavigationBar의 index가 업데이트되지 않는 현상입니다. onPageChanged 콜백에서 setState를 호출하여 현재 인덱스를 동기화하면 해결됩니다.

이슈 2: Controller 미해제로 인한 메모리 누수

PageController는 dispose() 메서드에서 반드시 해제해야 합니다. 그렇지 않으면 앱이 점점 느려지거나 비정상 종료될 수 있습니다.

@override
void dispose() {
  _pageCtrl.dispose();
  super.dispose();
}

이슈 3: 네트워크 요청 타임아웃

OpenHarmony 환경에서 dio 라이브러리 사용 시 연결 타임아웃이 자주 발생합니다. 충분한 타임아웃 값을 설정하고, 네트워크 권한을 명시해야 합니다.

final Dio httpClient = Dio(
  BaseOptions(
    connectTimeout: const Duration(seconds: 30),
    receiveTimeout: const Duration(seconds: 30),
    headers: {
      'Content-Type': 'application/json',
      'Accept': 'application/json',
    },
  ),
);

또한 module.json5에 인터넷 권한이 선언되어 있는지 확인하세요.

{
  "module": {
    "requestPermissions": [
      {"name": "ohos.permission.INTERNET"}
    ]
  }
}

이슈 4: 아이콘 스타일 불일치

선택/비선택 아이콘의 디자인이 다르면 사용자 경험에 부정적 영향을 줍니다. activeIcon 속성을 활용하여 두 상태의 아이콘 스타일을 통일하세요.

BottomNavigationBarItem(
  icon: Icon(Icons.home_outlined),
  activeIcon: Icon(Icons.home),
  label: '홈',
),

3. 성능 최적화 전략

  • 상태 보존: 각 탭을 StatefulWidget으로 구현하여 페이지 전환 시 데이터가 유지되도록 합니다.
  • 애니메이션 지속 시간: 300ms는 자연스러운 전환을 위한 최적의 길이입니다. 너무 빠르면 어색하고, 너무 느리면 지루합니다.
  • 리스트 최적화: 긴 목록을 표시할 때는 ListView.builder를 사용하여 화면에 보이는 항목만 렌더링합니다. 메모리 사용량이 크게 줄어듭니다.

4. 실행 결과

위 코드를 적용하면 다섯 개의 탭이 부드럽게 전환되며, 각 페이지의 상태가 유지됩니다. BottomNavigationBar와 PageView의 인덱스가 항상 일치하여 사용자 혼란을 방지합니다.

5. 핵심 요약

  1. PageController의 onPageChanged로 상태 동기화
  2. Controller는 반드시 dispose()에서 해제
  3. 네트워크 타임아웃 설정과 권한 확인
  4. 선택/비선택 아이콘 스타일 통일
  5. ListView.builder로 렌더링 효율화

이 가이드를 따라 구현하면 Flutter for OpenHarmony에서 안정적이고 반응성 좋은 하단 탐색 바를 만들 수 있습니다. 전체 소스 코드는 AtomGit 저장소(https://atomgit.com)에서 확인할 수 있습니다.

태그: Flutter OpenHarmony BottomNavigationBar PageView Dio

5월 27일 04:04에 게시됨