TIL) 11/26 디버깅을 제대로 하자

100·2025년 11월 26일

TIL

목록 보기
7/11
  • 한 것
    go router 사용 라우트 관리, cubit provider 주입 시점 조절, repo provider 사용
  • 못 한 것
    provider 내부 동작 살펴보기, sealed class 사용
  • 과제는 아니었지만 이상하게 만들어서 수정이 시급한 것
    레이어 분리 제대로(UI가 레포 호출 바로 못하게 - cubit이 처리)

어찌저찌했는데 머리에 다 들어온 건 아닌 듯


여기서부터 팀장님 피드백


Cubit 분리 전략

Cubit을 따로 만들지 않는 경우

등록 플로우 Cubit과 전역 리스트 Cubit을 분리하지 않고 하나로 운용할 때 두 방식 중 선택

방식 1: 파라미터 + 리프레시 호출

  • 업데이트가 필요한 화면으로 파라미터 전달
  • 변경 시 리프레시 신호를 보내서 해당 화면이 데이터 다시 로드
  • 장점: 구조 단순
  • 단점: 수동 리프레시 필요, 여러 화면 동기화 어렵다
  • 사용 시기: 단순 플로우

방식 2: Repository 스트림 구독

  • Repository에 스트림을 두고 데이터 변경 시 이벤트 발행
  • Cubit 등이 스트림을 구독해 자동으로 상태 갱신
  • 장점: 자동 동기화, 화면 여러 개여도 일관성 유지
  • 단점: 구조 복잡
  • 사용 시기: 데이터 공유가 많고 흐름이 복잡할 때

선택 기준

  • 단순: 방식 1
  • 복잡·다중 화면: 방식 2

디버깅 습관

의식의 흐름을 제대로

  1. 갱신이 필요한 위치 확인
  2. 갱신을 호출하는 코드 위치 확인
  3. 호출은 되었는지, 수신은 되었는지, 수행은 되었는지 로그로 확인

이런게 자연스럽게 이뤄져야 함

로그 활용 잘하기

에러 떴으면 뭐라 떴는 지 좀 잘 보기


go_router 메서드 요약

context.go(path)

  • 스택 전체 대체
  • 뒤로가기 불가
  • 로그인 성공 후 메인 이동 등

context.push(path)

  • 스택에 화면 추가
  • 뒤로가기 가능
  • pop 결과값(Future) 받을 수 있음

context.pop([result])

  • 현재 화면 제거
  • push로 온 화면에서만 가능
  • 이전 화면으로 결과 전달 가능

context.replace(path)

  • 현재 화면만 교체
  • 아래 스택 유지
  • 뒤로가기 가능

context.canPop()

  • pop 가능 여부 확인

context.goNamed(name, …)

  • 라우트 이름 기반 go
  • 동작은 go와 동일

context.pushNamed(name, …)

  • 라우트 이름 기반 push
  • 동작은 push와 동일

context.replaceNamed(name, …)

  • 라우트 이름 기반 replace
  • 동작은 replace와 동일

UI → Repository 직접 호출 금지

레이어는 제대로 짜놓고 왜 ui가 cubit 부르는거랑 repo 부르는 걸 섞어놨니..

잘못된 구조 (UI → Repository 직접 호출)

onPressed: () async {
  await context.read<PetRepository>().registerPet(userId, pet);
}

올바른 구조 (UI → Cubit → Repository)

onPressed: () {
  context.read<PetListCubit>().addPet(userId, pet);
}

class PetListCubit extends Cubit<PetListState> {
  Future<void> addPet(String userId, Pet pet) async {
    await repository.registerPet(userId, pet);
    emit(PetListLoaded([...pets, pet]));
  }
}

이유

  • 비즈니스 로직은 Cubit에 집중
  • UI는 “상태와 이벤트”만 알고 Repository는 Cubit만 알도록 분리
  • 테스트 용이성
  • 상태 흐름 일관성 유지

핵심: UI는 Cubit만 호출, Cubit이 Repository를 호출하는 구조


GoRoute : redirect / builder / pageBuilder 정리

redirect

  • 라우팅 직전에 실행되어 경로만 변경하는 함수
  • UI나 페이지를 만들지 않고 단순히 이동만 처리
  • 인증 체크, 초기 플로우 분기 같은 상황에서 사용
  • 부모 페이지 없이 바로 다른 경로로 이동하는 구조

builder

  • child 라우트를 부모 위젯으로 감싸는 방식
  • 반환값이 Widget이기 때문에 Navigator 스택에는 올라가지 않음
  • 공통 Scaffold, AppBar, BlocProvider 같은 “레이아웃 래핑”에 사용
  • 화면 구조는 부모 위젯이 존재하지만 “페이지 단위”는 아님

pageBuilder

  • Navigator가 사용하는 실제 Page(MaterialPage 등)를 생성
  • 부모 Page가 스택에 올라가고, 그 안에서 child가 보여지는 구조
  • 뒤로가기 히스토리에도 부모 페이지가 포함됨
  • 페이지 단위 공통 레이아웃이 필요할 때 사용

요약

  • redirect: 경로만 변경, UI 없음
  • builder: 부모 위젯 생성, Page는 아님
  • pageBuilder: 부모 Page 생성, 스택에 올라감

  • 레이어 제대로 고치고 디버깅 제대로 해서 내가 못고쳤던 문제 해결해보기
  • go_route에서 리다이렉트말고 페이지 빌더 사용해보기
  • 스트림 구독 vs 리프레시 주기
profile
멋있는 사람이 되는 게 꿈입니다

0개의 댓글