240613~240614 TIL

나고수·2024년 6월 14일

2024 TIL

목록 보기
21/94
post-thumbnail

① 배운 것

Flutter 에러 늪 탈출기: _lifecycleState != _ElementLifecycle.defunct 그리고 addPostFrameCallback

Flutter 개발을 하다 보면 가끔씩 알 수 없는 에러 메시지와 마주치게 됩니다. 특히 위젯의 생명주기와 관련된 에러는 디버깅하기 까다롭기로 악명이 높습니다.

오늘은 그중에서도 악몽 같은 _lifecycleState != _ElementLifecycle.defunct 에러를 만났을 때, 어떻게 해결하고 예방할 수 있는지, 그리고 WidgetsBinding.instance.addPostFrameCallback이 어떤 역할을 하는지 알아보겠습니다!

'죽은' 위젯을 건드리려고 했어요!

_lifecycleState != _ElementLifecycle.defunct 에러는 Flutter 위젯이 이미 dispose된 상태, 즉 생명주기가 끝난 상태에서 해당 위젯에 접근하려고 할 때 발생합니다. 쉽게 말해, 이미 '죽은' 위젯을 건드리려고 해서 Flutter가 화를 내는 겁니다.

제가 겪었던 에러 상황을 예로 들어볼게요.

이름 입력 후 다음 화면으로 이동하는 로직을 구현했는데, 이ㅁ을 Provider를 통해 업데이트하고 바로 다음 페이지로 이동하는 코드를 작성했습니다.

void goNextScreen() {
  ref.read(nameProvider.notifier).update((state) => '한모'); // 이름 업데이트
  context.pushNamed(RouterName.nextScreen); // 다음 페이지로 이동
}

이 코드에서 _lifecycleState != _ElementLifecycle.defunct 에러가 발생했습니다.

왜 그럴까요?

Provider는 비동기적으로 동작하기 때문입니다!

Provider를 사용하여 상태를 업데이트하면, 변경된 상태가 즉시 반영되지 않고 비동기 작업이 완료된 후에 반영될 수 있습니다.

제 코드에서는 이름 업데이트가 완료되기 전에 페이지 이동을 시도했기 때문에, 이전 페이지의 컨텍스트가 유효하지 않은 상태에서 위젯에 접근하려고 하면서 에러가 발생한 것입니다.

구조대 등장: addPostFrameCallback

이런 문제를 해결하는 데 유용한 도구가 바로 WidgetsBinding.instance.addPostFrameCallback입니다.

addPostFrameCallback은 현재 프레임이 완전히 렌더링된 직후에 특정 작업을 실행할 수 있도록 해줍니다. 즉, 모든 위젯이 화면에 그려진 후에 안전하게 작업을 수행할 수 있도록 도와주는 거죠!

수정된 코드:

void goNextScreen() {
  ref.read(nameProvider.notifier).update((state) => '한모');
  WidgetsBinding.instance.addPostFrameCallback((_) {
    context.pushNamed(RouterName.nextScreen); // 화면 전환
  });
}

꿀팁: 에러 예방하기

  • await 키워드 활용: 비동기 작업 후 위젯에 접근해야 하는 경우, await 키워드를 사용하여 작업이 완료될 때까지 기다립니다.
  • 컨텍스트 관리: BuildContext를 신중하게 사용하고, 필요하다면 GlobalKey를 활용하여 위젯에 접근합니다.
  • 생명주기 이해: Flutter 위젯의 생명주기를 이해하고, 각 단계에서 어떤 작업을 수행해야 하는지 파악합니다.

마무리

Flutter 에러는 때로는 좌절감을 주지만, 원인을 파악하고 해결하는 과정을 통해 Flutter에 대한 이해를 높일 수 있습니다.

_lifecycleState != _ElementLifecycle.defunct 에러를 만났을 때 당황하지 말고, addPostFrameCallback과 위젯 생명주기에 대한 이해를 바탕으로 문제를 해결해 보세요!

토스트 디자인이 제각각이여서 개발하기 힘들었다. 그래서 디자이너분께 토스트 디자인(패딩, 넓이, 높이 등)을 통일해 달라고하고 위치도 다 제각가이었는데 통일해다라고했다 굿

② 회고 (restropective)
버그를 수정할때 최대한 덕지덕지 테이프 붙이는 형식말고 정말 설계를 제대로 해서 수정하는걸 목표로하자.

③ 개선을 위한 방법
이번에 화면이 비슷한데 시나리오별로 로직과 디자인이 약간씩 다른 것을 프로바이더를 통해 구현했는데 이랬더니 뒤로가기 같은걸 했을 때 state 관리가 어려워 고라우터 path를 통해 구현하면 훨씬 좋을 것 같다.
고라우터를 통해 구현을 시도했다가 잘안되서 포기했는데 고라우터를 공부해서 다시 도전해봐야겠다. (부모 라우터로 go를하니까 부모 페이지도 고라우터야 한다 이런 에러가 났었음)

profile
되고싶다

0개의 댓글