Flutter에서 API 호출 시 꼭 알아야 할 것들
Flutter로 앱을 개발하면서 서버 API를 호출하는 작업은 거의 모든 프로젝트에서 기본적으로 들어가는 요소다. 하지만 간단해 보이는 API 호출도 실제 운영 환경에서는 다양한 예외 상황과 문제를 발생시킬 수 있다. 이번 글에서는 Flutter에서 API를 호출할 때 반드시 고려해야 할 사항들을 정리해본다.
1. 적절한 예외 처리와 에러 메시지 제공
API 호출은 항상 성공한다는 보장이 없다. 네트워크 단절, 서버 다운, 인증 만료, 데이터 포맷 오류 등 다양한 이유로 실패할 수 있다. 이런 상황을 고려하지 않고 try-catch 없이 호출만 한다면 앱이 크래시나 무반응 상태로 이어질 수 있다.
- 예외는 반드시 잡아야 한다 (try-catch)
- 사용자에게 의미 있는 에러 메시지를 보여주자 (예: "인터넷 연결을 확인해주세요")
- 디버깅을 위한 로깅도 중요하다 (예: logger 패키지 활용 -> 블로그 참고 : https://developer0524.tistory.com/140)
2. 재시도 로직과 서킷 브레이커 개념 도입
서버가 일시적으로 불안정하거나, 통신 환경이 나쁠 때 여러 번 시도하면 성공할 수 있다. 하지만 무한 재시도는 또 다른 문제를 낳는다. 최대 횟수나 시간 제한을 두고 재시도를 구현하고, 일정 횟수 이상 실패 시 일정 시간 동안 요청을 차단하는 서킷 브레이커 방식도 고려할 수 있다.
- dio + retry_interceptor 활용
- 직접 서킷 브레이커 유사 로직 작성도 가능
3. debounce / throttle 적용
검색어 자동완성, 실시간 필터링 등에서 사용자가 타이핑할 때마다 API를 호출하면 서버 부하가 심해지고 UX도 나빠질 수 있다. 이럴 때는 debounce나 throttle을 적용해 호출 빈도를 제어하자.
- debounce: 마지막 입력 이후 일정 시간 동안 입력이 없을 때만 호출
- throttle: 일정 주기마다 한 번만 호출
4. API 호출 시점 명확히 하기
initState, build, onTap, onChanged 등 다양한 곳에서 API를 호출할 수 있지만, 잘못된 위치에서 호출하면 중복 요청, 과도한 요청, UI 깜빡임 등의 문제가 발생할 수 있다.
- FutureBuilder 또는 FutureProvider로 의도된 시점에만 호출
- mounted 여부 체크 후 호출 (if (!mounted) return;)
- 필요한 경우 한 번만 호출되도록 메모이제이션 사용
5. 로딩 상태 관리
API 호출이 오래 걸리는 경우, 아무런 피드백이 없다면 사용자는 앱이 멈췄다고 느낀다. 로딩 상태를 UI에 반영해 사용자에게 피드백을 주는 것이 중요하다.
- CircularProgressIndicator, Shimmer 등으로 로딩 상태 표시
- riverpod, bloc 등을 활용한 로딩 상태 분리 관리
- 로딩 중 버튼 중복 클릭 방지 처리도 함께 고려
6. 데이터 캐싱 전략
매번 API를 호출하면 네트워크 사용량이 증가하고 속도도 느려진다. 자주 변경되지 않는 데이터는 캐싱 전략을 통해 효율적으로 관리할 수 있다.
- shared_preferences, hive 등을 이용한 로컬 캐싱
- Stale-While-Revalidate 패턴처럼 먼저 캐시 보여주고 백그라운드에서 갱신
- 무조건 캐싱이 아니라 갱신 주기나 갱신 조건에 따라 유연하게 적용
7. 백그라운드 상태 및 라이프사이클 관리
앱이 백그라운드에 있을 때 API 호출이 중단되거나, 다시 돌아왔을 때 데이터를 새로고침해야 할 때가 있다. Flutter는 라이프사이클을 감지할 수 있는 방법을 제공하므로 이를 적절히 활용해야 한다.
- WidgetsBindingObserver를 활용한 앱 상태 감지
- 앱 포그라운드 복귀 시 데이터 리프레시 처리
8. 인증 토큰 자동 갱신 처리
많은 API는 access token 기반 인증을 사용하며, 토큰은 만료될 수 있다. 이럴 경우 401 응답을 감지하고 자동으로 갱신하거나 로그인 화면으로 유도해야 한다.
- dio interceptor로 access token 갱신 처리
- refresh token 사용 시 무한 루프 방지 필요
- 토큰 갱신 실패 시 로그아웃 처리도 고려
9. 디버깅용 로그와 릴리즈용 필터링
개발 중에는 API 요청/응답 로그를 모두 보고 싶지만, 릴리즈 버전에서는 민감 정보가 노출되지 않도록 조심해야 한다. 로그 필터링이나 조건부 출력이 필요하다.
- Logger 또는 PrettyDioLogger 등 활용
- kReleaseMode 여부에 따라 출력 다르게 설정
10. 네트워크 상태 감지와 사용자 피드백
API 호출 전에 네트워크가 연결되어 있는지 미리 확인하는 습관이 필요하다. 연결이 안 되어 있다면 무작정 호출하는 대신 사용자에게 알려주는 것이 UX에 더 낫다.
- connectivity_plus로 네트워크 상태 체크
- 상태별 분기 처리 (연결 안 됨 → 토스트 메시지, 연결됨 → API 호출)
Flutter 앱에서 API 호출은 단순한 작업처럼 보이지만, 세심하게 다뤄야 할 요소들이 많다. 위의 내용을 잘 정리하고 적용한다면, 훨씬 더 안정적이고 사용자 친화적인 앱을 만들 수 있을 것이다 그럼 오늘도 즐코 빡코 !