GitHub
스크린 캡쳐 무반응 오류 해결하기

스크린 캡쳐 무반응 오류 해결하기

저는 AI 기반 채팅 애플리케이션을 만드는 스타트업에서 일하고 있습니다. 현재는 사내 개발에 대한 요청 지원을 하거나 앱 내 버그를 해결하여 유저들의 사용성을 향상시키는 팀에 속하여 유저들의 목소리를 듣고 앱을 개선하는 일을 하고 있습니다. 언젠가부터 서비스에서 대화 내용을 캡쳐할 수 있는 기능이 정상적으로 동작되지 않아 불편함을 호소하는 유저들의 제보가 많아져 해당 버그를 파악하고 해결한 것에 대한 기록을 남깁니다.

원인을 찾으러

해당 문제는 앱 내의 채팅 기록을 이미지로 저장할 수 있도록 하는 대화 캡쳐 기능에 대한 버그로 캡쳐시 완료 메세지가 뜨고 캡쳐된 이미지가 사용자의 기기에 저장되는 식으로 구현되어 있습니다. 해당 기능은 react-native-view-shot이라는 라이브러리를 이용, useViewShot이라는 커스텀 훅으로 작성하여 앱 내에서 사용하고 있습니다. 먼저 원인을 찾기 위해 커스텀 훅의 동작부터 점검하기로 했습니다.

유저가 자세하게 작성해준 리포트와 캡쳐 기능이 동작하기 위한 조건들을 바탕으로 어느 부분에서 문제가 발생할 수 있는지 정리 후 버그를 재현해보기로 했습니다. 단순히 캡쳐하는 것에는 문제가 없었기 때문에 이 조건은 제외하기로 했습니다. 그렇다면 유력한 부분은 이미지로 저장될 메세지의 갯수(e.g. messagesLength)에 따른 문제 발생 가능성이었습니다. 해당 기능은 최대 20개의 메세지를 하나의 이미지로 저장할 수 있는만큼 먼저 메세지의 길이에 따라 버그가 발생하진 않는지 확인했습니다. 간헐적으로 해당 버그가 재현되는 것을 확인했으나 재현된 케이스들의 메세지 갯수가 고정되어 있지 않아 해당 조건도 정확한 원인이 아니었습니다.

매몰되기 전에

명확하게 원인이 파악되지 않아 해결이 지지부진 했고 오전 내내 해당 문제에만 매달려 있다보니 매몰되어 가는 듯 했습니다. 경험상 이럴 때마다 유연해지지 않았기 때문에 다른 업무들을 해결하면서 머리 속을 환기시킨 뒤 다시 보기로 했습니다.

밀린 업무들을 처리한 뒤 다시 이 문제를 바라보니 제보된 버그들에 하나의 공통점이 있었습니다. 우리 앱은 영어를 포함한 7개 언어를 서비스하고 있었는데, 유독 대만지역의 유저들에게서 보고가 많았습니다. 해당 언어를 사용하는 유저들은 각각의 메세지의 길이가 굉장히 길었고 캡쳐했을 때 해당 버그가 발생했다는 점입니다.

해당 공통점에서 착안하여 개발 서버에서 동일한 환경을 설정하여 버그 재현해보니 10번을 시도하면 10번 모두 버그가 재현됐습니다. 메세지의 갯수가 문제가 아닌 캡쳐를 하는 과정에서 발생하는 문제라 판단, 이는 라이브러리에 문제가 있을 거라는 생각으로 이어졌습니다.

더 깊은 곳으로

하지만 라이브러리의 어떤 부분에 문제가 있는지 정확하게 알아야 할 필요가 있었습니다. 그래야 확정짓고 해결할 수 있으니까요. 그래서 원인으로 추정되는 부분이 보이니 해당 시나리오의 단계마다 콘솔을 추가하여 로그를 확인했습니다. 일반적인 캡쳐와 다르게 위에서 발생한 특정 조건에서 캡쳐시 [Error: The view cannot be captured. drawViewHierarchyInRect was not successful. This is a potential technical or security limitation.]라는 에러가 뜨면서 기능이 정상적으로 동작하지 않았습니다. 잠재적인 기술이나 보안 문제로 인하여 캡쳐가 불가능하다니… 영원히 해결할 수 없는 문제가 된건가 싶었지만 많은 개발자들이 사용하고 있던 라이브러리인만큼 제보된 이슈는 없는지 찾아보기로 했습니다.

천만다행으로 이미 알려져 있던 이슈였습니다! 여러 사용자가 iOS 환경에서 해당 버그에 대한 불편함을 제보했고 이를 해결할 수 있는 방법까지 남겨두고 있었습니다.

그래서 문제는

발생 원인에 대해 정리해보자면 제보된 버그들의 경우 모두 이미지의 길이가 굉장히 길었고, 이때문에 드로잉 문제가 발생하여 기능이 정상적으로 동작하지 않았던 것입니다. 구글링을 통해 원인을 더 자세히 알아보니 iOS에서는 CPU 기반의 캡쳐링 방식을 사용하고 있는데 이 방식은 보안 제한이 걸리거나, 특정 뷰에서 캡쳐 자체가 차단될 수 있다고 합니다. 그래서 해당 라이브러리의 useRenderInContext 옵션을 true로 설정하여 다른 방식(GPU 방식)으로 캡쳐를 할 수 있도록 도와주는 옵션으로 해결할 수 있다고 합니다. 해당 옵션을 추가하고 버그를 다시 구현해보니 정상적으로 캡쳐 기능이 동작하는 것을 확인했습니다!

여러 테스트 기기에서 QA를 진행했고 정상적으로 기능이 동작하는 것을 확인한 뒤에 빠르게 배포를 진행하여 버그는 해결되었습니다.

아쉬운 점이라면

처음 개발을 배울 때 코치분들께서 항상 하셨던 말은 뭔가 되지 않는다면 콘솔을 확인해라였습니다. 프론트엔드 영역에서 대부분의 문제는 콘솔을 통해 확인하거나 유추할 수 있기 때문에 제일 먼저 콘솔을 확인하라는 것이었습니다. 저도 제일 먼저 확인했다면 보다 빠르게 문제를 해결할 수 있었을 것입니다. 스타트업의 특성상 기민한 움직임과 실행이 필수적이기 때문입니다. 다만 빠르게 쳐내는 식보다는 문제를 정확하게 파악하고 해결하는 것이 중요하다고 생각했기에 잘못했다고는 생각하지 않습니다. 그렇지만 앞으로 문제에 대한 해결 방식을 좀 더 기민하게 해결될 수 있는지도 고려해야겠다는 생각이 들었습니다.