개요
지난 2024년 9월부터, 2년 간 개발 및 운영되었던 프로덕트인 SOPT 공식 iOS App의 유지보수를 맡게 되었습니다.
SOPT는 국내 최대 규모의 대학생 연합 IT벤처 창업 동아리로써, 약 3,000여명의 구성원이 존재하고 해당 구성원들을 연결하기 위한 프로덕트를 만드는 조직인 SOPT makers가 존재합니다.
SOPT makers 내부에는 프로덕트를 만들어가는 여러 팀들이 존재하는데, 그 중에서도 저는 웹 기반 프로덕트(커뮤니티, 모임, 프로젝트 등) 및 네이티브 자체 기능들을 통합해 제공하는 공식 앱 담당 APP팀으로 합류하게 되었는데요.
SOPT 공식 앱 iOS 레포
그 중에서도 오늘은 특정 화면에서 발생했던, 이유가 불명확한 크래시 문제의 원인을 되짚으며 해결했던 과정들을 기술해보려 합니다.
🚨 문제 발생: 솝탬프만 접속하면, 앱이 꺼져버려요
makers에 합류한 지 얼마 지나지 않았을 즈음인 24년 10월, 몇몇 사용자들에게 특정 기능에 접속하면 앱이 종료되어버린다는 CS 문의를 받게 되었습니다. 크래시가 발생하는 기능은 SOPT 회원들의 친목을 도모하기 위해, "같은 파트원들과 떡볶이 먹기" 등 미션을 수행하고 인증하는 솝탬프였는데요. 그 중에서도, 미션 리스트에서 특정 미션을 누르면 아래와 같이 디테일뷰로 넘어가는데, 디테일뷰에 진입하는 순간 몇몇 사용자들의 앱에서 크래시가 발생했습니다.
당시 솝탬프 기능은 앱의 네이티브 기능들 중에서도 손꼽히게 사용률이 높았던 서비스였기 때문에, 불특정 사용자에게 크래시가 발생하는 문제는 사용자 경험에 크게 해가 될 것이라 생각하여 우선순위를 높게 두고 문제를 해결했습니다.
우선 프로젝트에는 Sentry, Crashlytics와 같이 앱에서 크래시가 발생했을 때 로깅할 수 있는 장치가 없었기 때문에, 처음에는 자세한 리포트를 확인할 수 없어 짐작가는 크래시의 원인들을 나열하고, 하나씩 소거하는 방식으로 유추해보았는데요.
당시 코드를 살펴보기 전, 제가 확인했던 내용들은 다음과 같습니다.
1. 서버 로깅 시스템에 해당 뷰와 관련한 에러가 잡혔는가? -> 발생하지 않음.
2. 특정 기기에서 발생하는 문제인가? -> 아님. 여러 기기에서 해당 문제가 발생함. 또한 문제가 생긴 사용자의 ID를 받아 시뮬레이터에서 확인해보았을 때, 크래시가 발생하지 않았음.
3. 최신 버전 OS의 문제인가? -> 아님. 최신 버전 OS의 15pro에서 문제가 발생하지 않음.
어떠한 외부 요인에 의해서 발생하는 문제라고 보기 어려웠기 때문에, 내부적인 관점에서 원인을 분석해보았는데요.
1. 크래시가 발생할만한 위험 요소가 없는지 확인
해당 기능을 구현하고 있는 코드에는 강제 언랩핑을 하거나, self에 대한 강한 참조로 메모리 누수가 발생할만한 요소들이 다수 있었습니다. 그래서 강제 언랩핑이 진행되는 코드마다 디버깅을 시도해보았지만, 앞서 서술했듯 시뮬레이터에서는 크래시 문제가 발생하지 않았기 때문에 해당 문제가 원인이라고 단정짓기 어려웠습니다.
2. 캐시 문제일까?
불특정 기기에서 발생하는 문제였기에, 메모리 관련 이슈일수도 있다고 짐작되어 사용자에게 앱을 삭제하고 재설치해달라고 요청했습니다. 그러나 크래시 문제는 여전히 발생했습니다.
3. 네트워크를 끄고 시도해보자
해당 화면에서 사용자들마다 다른 점이 있다면, 미션마다 서버로부터 받아오는 데이터가 다르다는 점입니다. 때문에 디테일뷰로 넘어갈 때 네트워크를 끄고 재시도해보았는데요. 이 때 크래시가 발생하지 않았고, 데이터를 서버로부터 받아올 때 발생하는 문제임을 짐작할 수 있었습니다.
받아오는 데이터와 관련한 문제임을 인지한 상태에서, 크래시가 발생하는 사용자로부터 크래시 리포트를 받을 수 있었습니다.
📲 크래시 리포트 분석하기
SOPT makers에서 만들어지는 모든 프로덕트들은 카카오톡 채널을 통해 CS 문의를 받고 있습니다. 해당 이슈 또한, 크래시가 발생하는 사용자와 1:1로 소통하며 사용자로부터 크래시 리포트 파일을 받아볼 수 있었는데요.
(실제 상용 서비스였다면 어려운 상황이었겠지만, 실사용자와 밀접하게 소통할 수 있는 서비스 특성상, 이슈 해결을 위해 사용자와 긴밀하게 소통할 수 있었습니다.)
그 중에서도 ImageDownloader에서 이미지를 다운로드 받아 불러올 때, 잘못된 메모리 참조에 의한 Segmentation fault가 발생하고 있음을 살펴볼 수 있었는데요. 여기에서 또 두 가지 원인을 고려해보았습니다.
1. 크래시가 발생하는 사용자와 일반 사용자가 받는 이미지에 차이가 있을까?
이제 이미지가 문제의 원인임이 좁혀졌기 때문에, 관련되어 "혹시 이미지에 차이가 있을까? 이미지 용량이나, 서버에서 보내주는 이미지 url에 차이가 있을까?"하는 부분도 확인해보았습니다. 결과는 크게 차이가 없었고, 크래시가 발생하는 기기에서 (크래시가) 발생하지 않는 사용자의 미션 사진을 띄워보았을 때, 똑같이 크래시가 발생함을 알 수 있었습니다.
결론은 특정 사진의 문제는 아니었습니다.
2. 이미지 라이브러리의 문제일까?
저희 프로젝트는 이미지 라이브러리로 Kingfisher를 사용하고 있습니다. "해당 라이브러리로 이미지 처리나 캐싱된 데이터를 불러올 때 발생하는 문제일까?" 하는 의문을 갖게 되어, 당시 Kingfisher 레포에서 EXC_BAD_ACCESS 관련 이슈가 열려있는지 확인해 보았습니다.
당시 기준 EXC_BAD_ACCESS 이슈는 근 몇 달간 없었기 때문에, 혹시 이후 버전에서 문제가 해결된 것이 아닌지, 하는 예측을 해보았습니다. 크래시가 발생했던 때에는 Kingfisher 7.6.1 버전을 사용하고 있었는데요.
라이브러리 버전 문제는 시도해보기 전까지 해결 방법을 알 수 없다고 생각해서, 우선 버전을 7.12.0으로 높여 배포해보았습니다. (만약 여기에서 해결이 되지 않는다면 이미지 라이브러리를 다른 것으로 마이그레이션하기로 계획하고 있었습니다.)
🥳 결론은...
그리고 놀랍게도 라이브러리 버전을 높여 재배포하니 크래시 문제가 해결되었습니다.
(해결이 되기까지 약 2주간.. 다양한 방법을 시도해보았습니다.)
깨달은 점 및 그 이후,
레거시 코드에 대한 이해도가 떨어지는 상태에서, CS 문의를 받아 대응하는 과정이 혼란스럽고 제 실력이 부족한 것에 대한 자책도 많이 했던 것 같습니다. 물론 문제가 발생하는 사용자도 소수였고, 사소하다면 사소한 이슈였지만, 누군가는 (제가 유지보수하는) 앱의 기술적 문제로 인해 서비스를 이용하지 못한다는 점이 너무나도 속상하게 다가왔습니다. 그래서 당시 제가 생각할 수 있는 방법들을 최대한 적용해보았습니다.
그 과정에서 실제 상용 서비스였다면 사용자의 피드백을 직접 받을 수 없었을 것이고, 덕분에 이번 경험이 더욱 소중한 기회라고 느껴졌습니다. 에러 로깅 장치의 필요성도 느꼈고, 또 서드파티에 무조건적으로 의존하면 이렇게 관련 이슈가 발생했을 때 원인을 파악하기 너무 어렵겠다는 생각도 했습니다.
그러나 당장 이슈가 해결되었음에도... 정확한 원인을 파악하지 않고 Kingfisher의 버전 문제라고 넘기기에는 미심쩍었습니다. 또한 이슈를 대응하며 해당 뷰에 대한 디버깅을 계속 진행했었는데, 그 과정에서 디테일 뷰에 진입했을 때 메모리가 치솟는 문제를 발견했는데요.
(해결 과정은 다음 글에서 더 자세히 서술하겠습니다 :D)
'Project' 카테고리의 다른 글
[iOS/Tuist 4] Firebase Crashlytics 설정 (1) | 2025.06.15 |
---|---|
[SOPT makers] Coordinator, Router 리팩토링 (2) Router, 안전하게 제거하기 (2) | 2025.05.16 |
[SOPT makers] Coordinator, Router 리팩토링 (1) 왜 화면이 움직이지 않나요? (2) | 2025.05.15 |
[SOPT makers] 솝탬프 이슈 해결하기 (2) 메모리 최적화하기 (0) | 2025.03.08 |
[SOPT makers] 35기 회고 (0) | 2025.02.24 |