해당 프로젝트에서 겪었던 가장 크리티컬 했던 이슈는 강의를 다 들었는지에 대한 기준을 어떻게 잡을 것인가에 대한 것이었습니다
초기에 클라이언트 측에서 제시한 요구사항은 플레이어바가 마지막에 도달하는 트리거(onPlayerEnd)를 기반으로 완료 처리를 하자는 의견이 나왔지만, 이는 강의를 실제로 다 듣지 않고 플레이어바를 끝으로 넘기는 인원이 있을 수 있기 때문에 다른 방식을 고안해야 했습니다.
첫 번째로 떠올린 방법은 setInterval() 을 통해 1초마다 상태를 업데이트하다가 영상의 길이와 똑같아 졌을 때 완료 처리를 하는 API를 보내는 방식으로 진행을 하기로 했습니다.
실제로 이 방식으로 몇 주간 사용을 했었는데 사용자들의 불만이 몇 가지가 존재하였습니다.
“강의를 끝까지 들었는데 체크가 되지 않아 다음 강의를 수강하지 못한다.”
(페이지에 현재 어느 정도 들었는지 진행률이 표시가 되었는데) “진행률이 잘 일치하지 않는 것 같다. 100%가 되어도 완료 표시가 되지 않는다.”
이러한 문제를 해결하기 위해 며칠간 고민을 했었고 내린 결론을 클라이언트 측에 공유드린 결과 모두가 만족하여 해당 방식으로 전환하기로 결정했습니다.
세웠던 가설
강의를 끝까지 들었음에도 강의 완료 체크가 되지 않은 이유는 명료합니다.
기존 방식에서는 만약 영상의 길이가 50초라면 영상을 시작함과 동시에 setInterval을 통해 시간을 측정하는데 useEffect 안에서 이 둘 값이 같아지는 경우에 완료를 나타내는 API를 보내는 방식이었습니다.
그러나 이 경우 네트워크 환경에 따라 영상의 현재 시간과 측정되고 있는 시간 간의 완벽한 동기화가 어렵기 때문에 딱 영상 길이가 되기 전에 영상이 끝나버리는 경우가 많기 때문에 발생하는 문제라고 판단하였습니다.
그래서 생각해 볼 수 있는 솔루션은 1~2초 정도의 margin을 두어서 반드시 영상이 끝나기 전에 영상을 다 봤다고 판단하도록 조작하는 것이었습니다.
하지만 이 역시도 네트워크에 따라서 혹은 나갔다 다시 들어온 경우 문제가 생길 여지가 있었고 실제로 테스트해 본 결과 그러한 문제가 빈번하게 발생했습니다.
이러한 문제는 setInterval이 사실 delay 시간을 100% 보장하지 못하는 문제가 존재하기 때문에 발생하는 것입니다. setInterval은 함수를 실행하는 와중에도 delay가 흘러가기 때문에, 만약 함수의 실행이 종료될 때까지 기다렸다가 함수의 실행이 종료되면 다음 함수를 즉시 실행하게 됩니다.
즉, 1초마다 한 번씩 함수가 호출되어야 하는 것인데 함수의 실행이 약간의 시간이 걸린다면 함수의 실행이 끝난 후에 1초를 기다리지 않고 다음 함수를 바로 실행해버린다는 의미입니다.
그렇기 때문에 아래와 같은 방법을 고려해보았습니다.
시도한 방법
영상 길이의 80%가 지났으면서 && 플레이어가 끝까지 도달하는 경우
이 방식으로 진행하는 경우 어떠한 경우에도 영상이 끝났어도 완료가 되지 않는 문제가 일어나지 않으며, 사용자의 부정행위까지도 방지할 수 있게 됩니다.
이는 내부적인 로직으로 만약 사용자가 이를 어떻게 알아냈다고 하더라도 80% 정도 들었다는 것은 사실상 다 들은 것으로 인정을 해주어야 마땅한 것이기 때문에 클라이언트 쪽에서도 상당히 만족한 방식이었습니다.
배속으로 강의를 듣는 경우 등을 고려해야 하기 때문.
추가적으로 완료 체킹 API를 보냄과 동시에 팝업 컴포넌트를 띄우도록 구현을 리팩토링하였는데, 이 방식이 사용되면 사용자 입장에서는 ‘아 이 팝업이 뜨면 강의를 완료했다는 것이구나’가 인지되기 때문에 플레이어바가 마지막까지 갔음에도 이 팝업이 뜨지 않은 경우에는 본인의 진행률이 부족했음을 인지하고 다시 재생하여 80%를 채우도록 유도가 됩니다.
개선된 지표
이렇듯 문제 해결을 위한 다양한 방식의 도입을 통해 사용자 경험을 개선시켰고 특히, 실제로 사용자들로부터 완료 팝업 컴포넌트에 대해 긍정적인 피드백을 많이 받을 수 있었습니다.
이번 트러블 슈팅을 계기로 사용자의 입장에서 조금 더 생각해보게 된 계기가 되었으며, 그 뿐만 아니라 관리자 측면에서도 어떤 방식이 타당할지를 고려해야 했기에 양측의 의견을 모두 수용할 수 있는 방식을 유연하게 찾아낼 수 있는 실력을 키울 수 있었습니다.