Flutter setState() 자세히 알아보기

여러분들이 Flutter를 이용해 애플리케이션을 개발하다 보면 상태(변경하고자 하는 데이터)가 변경되어 화면을 업데이트해야 할 상황이 생깁니다. 이때 setState()를 호출하게 됩니다. setState()는 가장 쉬운 화면 업데이트 방법입니다. setState()를 자세히 알아보도록 하겠습니다.


    setState() 사용 예제

    setState()는 Widget이 참조하고 있는 상태가 변경되었을 때 호출합니다.
     setState(() { _myState = newValue; });

    setState() 동작 원리

    호출 즉시 콜백 함수가 호출된다.

    setState()는 VoidCallback 함수를 Parameter로 갖습니다. VoidCallback에서 변경하고자 하는 상태를 변경합니다. 참고로 VoidCallback 함수는 setState()가 호출된 즉시 호출하게 됩니다. 따라서 Future 타입을 설정하면 안 됩니다. async callback이 호출될 경우 상태를 업데이트하고자 하는 시점이 명확하지 않기 때문입니다. 그리고 VoidCallback이 null 일 경우 에러가 발생합니다.

    build() 함수가 예약된다.

    setState()를 호출하게 되면 Flutter 프레임워크가 build() 함수를 예약하도록 합니다. 이때 build() 함수는 비동기로 동작하게 됩니다. setState()를 호출하지 않으면 build() 함수가 예약되지 않을 수 있기 때문에 화면 갱신을 보장하지 못합니다.

    하위 트리의 Widget이 모두 빌드된다.

    해당 Widget과 그 하위 트리에 있는 모든 Widget의 build() 함수가 호출됩니다.

    setState() 사용 시 주의할 점

    남용하면 Flutter 버벅임의 원인이 된다.

    setState()는 Widget 트리의 하위 트리까지 모두 갱신하기 때문에 자식 Widget이 많을 경우 화면이 버벅거리는 현상이 심해질 수 있습니다. 많은 커뮤니티 사이트에서 Flutter의 렌더링 퍼포먼스를 많이 지적하는데, 렌더링 퍼포먼스를 극복하기 위해서라도 이 부분을 고려하여 남용하지 않아야 합니다.

    mounted property를 확인하고 사용해야 한다.

    setState()는 buildContext가 활성화되어있을 때만 사용할 수 있습니다. buildContext는 Widget이 화면에 연결되어 있을 때만 활성화되어 있으며, mounted property를 통해 확인할 수 있습니다. 그래서 setState()를 사용할 땐 mounted property가 true인지 확인하고 사용해야 합니다.

    setState() 단점과 한계

    부모 Widget에 상태 변경이 어렵다.

    트리 노드에서 부모 Widget의 상태 변경이 어렵습니다. 트리의 depth가 낮으면 VoidCallback을 자식 Widget에게 넘겨줄 수도 있지만, 트리가 깊어질수록 이 방법 또한 힘듭니다. 

    렌더링 퍼포먼스 이슈로 최하위 Widget에서만 사용해야한다.

    프로젝트의 크기가 커질수록 Flutter의 버벅거림 이슈는 수면 위로 올라오게 됩니다. 하위 트리를 모두 렌더링 하는 setState()의 무분별한 사용은 지양되고 있습니다. 이런 이유로 트리의 최하단인 리프 노드에서 간단하게 사용해야만 합니다. 

    상태관리를 위한 다른 솔루션과 병행해서 사용되어야 한다.

    결국, setState()는 Widget 간의 상태 관리, 데이터 전달이 어렵고 렌더링 퍼포먼스 저하를 발생시킵니다. setState()만을 이용하여 상태를 관리할 수 없다는 결론이 나오고, 다른 솔루션을 찾아 개발해야만 합니다. 

    setState()를 대체할 솔루션

    setState()를 대체할 상태관리 솔루션은 다음과 같습니다.

    댓글