[프로젝트] 중첩 데이터 구조로 인한 State 관리 오류

silver's avatar
Jan 08, 2025
[프로젝트] 중첩 데이터 구조로 인한 State 관리 오류

🔍 문제 상황

notion image
notion image
API 엔드포인트: GET /fitness-list
에러 타입: UnimplementedError 및 State 관리 오류

초기 구현 방식

서버에서 카테고리와 운동 리스트를 함께 중첩된 구조로 반환
notion image
 

🤔 원인 분석

발생한 문제

*// dynamic으로 데이터 받기* List<dynamic> responseList = responseBody["response"]; *// 다운캐스팅 시도* FitnessListModel list = FitnessListModel.fromList(responseList);`

왜 문제가 발생했는가?

  1. 중첩 데이터 구조의 복잡성
      • 카테고리와 운동 리스트가 묶여서 전송됨
      • 데이터 파싱 시 구조가 복잡해져 타입 캐스팅 어려움
  1. State 관리 문제
      • 카테고리 정보를 가져올 때마다 하위 운동 리스트도 함께 로드
      • 카테고리 상태가 변경되면 연관된 모든 운동 리스트의 state도 함께 변경
      • 의도하지 않은 UI 리렌더링 및 상태 동기화 문제 발생
  1. 데이터 독립성 부족
      • 카테고리와 운동 리스트가 강하게 결합되어 있어 개별 관리 불가능
      • 특정 카테고리만 업데이트하거나 운동만 추가/삭제하기 어려움

해결 방법

API 엔드포인트 분리

카테고리와 운동 리스트를 독립적인 API로 분리하여 각각 가져오는 방식으로 변경
class FitnessListRepository { const FitnessListRepository(); // 운동 리스트 받아오기 Future<Map<String, dynamic>> findAllFitness() async { Response response = await dio.get("/fitness-list"); Map<String, dynamic> body = response.data; return body; } // 카테고리 리스트 받아오기 Future<Map<String, dynamic>> findAllCategory() async { Response response = await dio.get("/category-list"); Map<String, dynamic> body = response.data; return body; } }

서버 응답 구조 개선

중첩 → 독립적인 구조로 응답의 구조를 개선

📊 개선 효과

1. 명확한 데이터 구조

  • 타입 캐스팅이 단순해짐
  • UnimplementedError 해결
// 개선 후 - 간단한 다운캐스팅 List<dynamic> categories = categoryBody["response"]; List<CategoryModel> categoryList = categories.map((e) => CategoryModel.fromJson(e)).toList();

2. 독립적인 State 관리

  • 카테고리 상태 변경이 운동 리스트에 영향을 주지 않음
  • 각 데이터를 독립적으로 관리 가능

3. 성능 최적화

  • 필요한 데이터만 선택적으로 로드 가능
  • 불필요한 데이터 전송 감소

4. 유지보수성 향상

  • API 엔드포인트 역할이 명확함
  • 추후 기능 확장 시 영향 범위 최소화
💡

결론!

  • API 엔드포인트는 단일 책임 원칙(SRP)을 따르자
  • 데이터는 가능한 한 평면적(Flat)하게 설계하자
  • 클라이언트에서 필요한 데이터만 조합하여 사용하자
  • State 관리는 독립적으로 유지하자
설계 원칙
  • 서버: 최소 단위의 데이터를 제공
  • 클라이언트: 필요에 따라 데이터를 조합하여 사용
  • State: 각 도메인별로 독립적으로 관리
 
Share article

silver