평균 10초가 걸렸던 API 응답에 대한 대응
디프만 14기 활동 중 개발했던 프로젝트에서 겪었던 트러블 슈팅 경험을 정리하고자 합니다.
기능 소개
사용자들의 관심사를 입력 후 핸드폰을 흔들면 적절한 대화 주제를 추천해주는 기능입니다.
이때 대화 주제는 GPT를 활용하여 추천해주기로 했습니다.
아래 영상은 흔들기 데모 영상입니다.
자이로센서로 뷰들의 x,y 값을 실시간으로 수집하여 동적으로 뷰의 위치를 갱신하도록 구현했습니다.
트러블 슈팅
사용자에게 5개의 대화 주제를 추천해주어야 했습니다. 그런데 서버에서 만들어준 API에선 한 번에 5개의 data를 내려주고 있었는데 GPT 서버 상태에 따라 응답 시간이 불규칙했고 평균 10초라는 긴 시간이 걸렸습니다.
이렇게 시간이 오래 걸리게 되면 사용성이 매우 떨어진다는 점에서 api 응답 시간을 줄이는 고민이 필요했습니다.
대응 방안
gpt라는 외부 api를 사용하는 만큼 어떠한 요인이 문제가 되는 것인지 온전히 파악이 어려워 서버 개발자와 함께 여러 테스트를 해보았습니다. data를 한 번에 하나씩만 내려주도록 API를 수정하고 클라이언트에서 해당 API를 비동기로 5번 연속 호출을 해보니 평균 6초란 시간으로 단축되었습니다.
나름 많이 개선하였지만 여전히 사용자에게 타협될 수 없는 속도였습니다. 이에 안드로이드에서는 아래와 같은 시도를 하였습니다.
[기존 설계]
흔들기 Activity에서 3초 흔들기 -> 대화 주제 추천 Activity로 이동 -> 대화 주제 API 호출
기존에는 각각의 화면을 모두 Activity로 구현하였고 화면에 필요한 data를 해당 화면에 진입한 시점에 API를 호출하여 받아왔습니다.
[새로운 방안]
흔들기 Fragment에서 대화주제 API 호출 -> (흔드는 동안 data를 하나씩 계속 받아옴) -> 대화 주제 추천 Fragment로 이동 -> 뷰모델에서 관리하고 있던 data를 화면에 바인딩하고 새로 수신된 data는 기존에 관리되고 있던 dataList에 addAll 후 어댑터에 submitList
기존에 2개의 Activity로 구성했던 것을 하나의 Activity 하위에 2개의 Fragment로 구성 되게 변경하였습니다.
화면 구성을 Fragment로 바꾸면 하나의 뷰모델을 공유할 수 있으므로 현재 화면에서는 사용되지 않지만 다음 화면에서 보여줄 data를 미리 받아오게 하는 아이디어입니다. 뷰모델은 뷰와 별개의 생명주기를 가진다는 점을 이용했습니다.
이 방법을 사용해 API 속도는 그대로 6초이지만 다음 화면으로 넘어가기 전에 api 호출을 미리 하였기 때문에 실질적으로 사용자가 다음 페이지에 진입했을 때 data를 받기까지 체감하는 시간은 3초 정도였습니다.
느낀점
- API와 관련된 문제 대응에 서버 개발자만 참여하는 것이 아닌 클라이언트 개발자도 역할을 했다는 점이 새로웠고 재밌었습니다. 엘리베이터에 거울 하나 설치한 것만으로 사용자들의 체감 속도를 빠르게 하여 사용성을 챙겼다는 이야기가 생각이 났습니다.
- 문제를 구체적으로 정의하는 것이 중요하다고 느꼈습니다. 이번 상황에서는 단순히 10초란 시간이 걸린다는 것이 아닌, 사용자가 해당 페이지에 진입 후 10초가 걸린다는 것을 문제로 정의하였습니다. 그렇기 때문에 페이지 진입 전에 API를 미리 호출할 수 있는 방법에 대해 고민했고 Fragment로 화면 구성을 바꾼다음 하나의 뷰모델을 공유하는 방법을 떠올릴 수 있었습니다.
- 하지만 사용자가 다음 화면까지 넘어가지 않고 중간에 페이지를 이탈하면 불필요한 API를 호출한 것이 되므로 낭비가 되는 상황도 있기에 이탈률을 모니터링할 필요성은 있습니다. 만약 이로 인해 비용이 크게 발생하게 됐다면 다른 방법을 찾아야 할 것입니다. trade off를 고려하여 상황에 맞는 적절한 선택을 하는 것이 중요하다고 느꼈습니다.