brunch

You can make anything
by writing

C.S.Lewis

by 서준수 Oct 08. 2021

Widget build가 두 번 호출되는 현상

Widget build가 두 번 호출되는 현상

비동기로 데이터를 받아와서 화면을 갱신하는 작업을 하던 중에 버그를 발견했다. 코드를 다시 확인해도 별 문제가 없어 보였다. 이럴 때는 언제 해당 문제가 발생하는지 알기 위해 재현 스텝을 찾으려고 노력한다.


재현되는 경우는


1. 앱 최초 실행 시 (정상 동작)

2. 앱을 task 목록에서 kill 한 후 실행 시 (정상 동작)

3. 앱을 back 키로 종료 후 실행 시 (비정상 동작)



문제가 되는 부분에 몇 개 로그를 찍어보니 데이터를 두 번씩 받아오고 있었다. 그래서 확인 결과 Widget build가 두 번 호출되어 request가 두 번 실행되었고 이로 인해 response도 두 번을 받은 것이었다.


AVD에서 실행하여 발생한 것인가 싶어서 실물 기기에서도 확인해봤지만 동일했다.

최근 업데이트한 윈도우11(SDK 2.2.3) 문제인가 싶어서 윈도우10(SDK 1.22.4)에서도 확인해봤지만 동일했다. SDK 버전에 차이가 있지만 오히려 1.22.4에서 발생하던 문제가 2.2.3에서까지 동일하게 발생한다는 사실을 알려준다.


좀 더 테스트를 하다 보니 <2. 앱을 task 목록에서 kill 한 후 실행 시>와 <3. 앱을 back 키로 종료 후 실행 시>에서 문제의 양상이 다르게 나타는 것이 의아했다. 이 둘 사이의 차이점을 확인하려 하니 앱을 task에서 kill 하면 안드로이드 스튜디오에서도 실행 중인 앱 종료로 인식하여 로그 확인이 불가능했다. (Lost connection to device.)


?!

차이점이 있다!! 바로 안드로이드 스튜디오에 디바이스가 연결되었느냐 아니냐의 차이.

그래서 디바이스 연결을 끊고 테스트하니 정상 동작을 했다.


4. 안드로이드 스튜디오와 연결을 끊은 상태(Lost connection to device.) 1,2,3 모든 스텝 (정상 동작)



결론적으로 안드로이드 스튜디오에 디바이스가 연결된 상태에서는 앱을 back 키로 종료 후 다시 실행 시 build가 두 번 호출된다. 일반적인 유저 시나리오에서는 큰 문제가 되지 않을 수도 있겠지만 개발 단계에서는 이걸 모르면 나처럼 삽질의 시간을 소모하게 될지도 모른다.


해당 현상을 확인할 수 있는 간단한 예제를 다음과 같이 만들어봤다.


처음 실행 시 로그는 다음과 같다.

[log] build is called
[log] _counter : 1
[log] build is called

처음 실행되었을 때는 당연히 build가 호출되고 _counter 값이 0이기 때문에 page0()이 화면에 표시된다. page0() 표시 후 Future 메서드인 getData()가 호출되고 3초 후 결괏값을 받으면 _counter 값을 1 증가시키고 setState를 통해 재빌드한다.


따라서 'build is called' 로그가 한 번 더 나오고 다음과 같이 page1()이 표시된다.



코드를 보면 절대로 page2()가 보여서는 안 된다. 하지만 back 키로 앱을 종료 후 다시 실행하면 로그가 다음과 같이 나온다.

[log] build is called
[log] build is called
[log] _counter : 1
[log] build is called
[log] _counter : 2
[log] build is called


이렇게 의도하지 않은 build로 인해 원하지 않은 화면이 보이게 되는 문제가 발생할 수 있다.



구글링 해보니 이미 여러 사람들에게 고통을 주고 있던 문제였다.

https://github.com/flutter/flutter/issues/33566


브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari