Sadturtleman

토큰 갱신 코드 하나로 레이스 컨디션 두 번, 데드락 한 번

로그인 토큰이 만료되면 알아서 새로 받아 오고 실패한 요청을 다시 보내는 코드를 짜 본 적이 있다면, 처음엔 스무 줄이면 끝난다고 생각했을 것이다. 401이 오면 리프레시 토큰으로 갱신하고, 새 토큰으로 재시도한다. 나도 그렇게 짰다. 그리고 같은 코드에서 석 달 동안 세 번 버그가 났다. 두 번은 레이스 컨디션이었고, 마지막은 앱의 모든 요청이 멈추...

Android APM 만들기 3편: 앱 빌드를 건드리지 않고 화면 목록 뽑아내기

빌드에 분석 도구를 붙여 본 적이 있다면 세 가지 걱정을 해 봤을 것이다. 결과가 프로젝트 전체를 다 본 결과인지, 그 도구 때문에 평소 빌드가 느려지거나 깨지지는 않는지, 도구가 중간에 실패하면 무엇이 남는지. 린트든 테스트 커버리지든 의존성 그래프든 같은 걱정이다. 2편에서는 Kotlin 컴파일러 안에서 화면을 찾는 방법을 설계로만 적었다. 오늘...

Android APM 만들기 2편: 컴파일러 안에서 화면을 찾는 법, 그리고 다 못 찾는 이유

앱에 화면이 몇 개 있는지 코드만 보고 세어 본 적이 있다면, 생각보다 답이 안 나온다는 걸 알 것이다. 프로젝트에서 Screen 으로 끝나는 함수를 검색하면 숫자는 나온다. 그런데 그 안에는 화면이 아닌 것도 섞여 있고, 이름에 Screen 이 없는 화면은 빠진다. 어떤 화면이 실제로 어디에 등록돼 있는지는 함수 이름보다 호출 관계를 따라가야 보인다...

Android APM 만들기 1편: 이 화면은 어떻게 들어가고, 왜 느린가

“이 화면 왜 이렇게 느려요?”라는 질문을 받으면 보통 이렇게 한다. 앱을 켜고, 그 화면까지 손으로 찾아 들어가고, 프로파일러를 붙여서 한 번 녹화하고, 타임라인에서 그 화면이 뜬 구간을 눈으로 찾는다. 다른 경로로 들어오면 느린지, 다른 기기에서는 어떤지는 그 과정을 다시 반복해야 안다. 화면이 스무 개를 넘기면 “이 앱에 화면이 몇 개고 각각 어...

썸네일로 바꿨는데 70ms밖에 안 줄었다

화면에 사진 한 장이 늦게 뜨면 누구나 먼저 “사진이 커서”라고 생각한다. 나도 그랬다. 앱의 마이페이지에서 프로필 사진이 화면이 쓸 수 있게 되기까지 걸린 시간의 78%를 차지했고, 받아 오는 파일은 촬영 원본 1500×2000, 454KB였다. 48dp 동그라미 하나를 그리려고 필요한 픽셀의 100배가 넘는 양을 받고 있었으니 썸네일이 답이라고 확...

모듈을 나눴는데 왜 같이 다시 빌드되나

코드를 여러 모듈로 쪼개 본 적 있다면 이런 기대를 했을 것이다. 기능마다 모듈을 따로 두면 내가 건드린 곳만 다시 빌드되고, 팀원끼리 파일이 덜 겹치고, 나중에 떼어내기도 쉬울 거라고. 그런데 막상 나눠 놓으면 빌드가 생각만큼 안 빨라진다. 화면 하나를 고쳤는데 관계없어 보이는 모듈들이 줄줄이 다시 컴파일된다. 웹 모노레포의 패키지든, 백엔드의 멀...

칸이 5,000개인 화면에서 문자열을 5,000번 만들고 있었다

칸이 잔뜩 있는 화면을 만들어 본 적 있다면 익숙할 것이다. 스프레드시트, 캘린더, 픽셀 에디터, 공연장 좌석 배치도, 지하철 노선의 시간표. 이런 화면은 칸 하나하나가 DOM 요소 하나가 되기 쉽고, 그러면 화면에 요소가 순식간에 수천 개가 된다. 내 경우는 점자 편집기였다. 도메인은 낯설어도 문제의 모양은 흔하다. 32칸 × 26줄짜리 격자에 글...

대용량 파일은 직접 넣어 봐야 안다: 90MB PDF와 125만 셀이 알려준 것

대용량 고화질 파일을 넣으면 기능이 거의 다 깨진다는 제보를 받았다. 재현이 안 됐다. 내가 가진 테스트 파일이 22MB였고 그건 멀쩡하게 돌았기 때문이다. 그래서 90MB짜리 600dpi 스캔본을 직접 만들어 넣어 봤다. 결과는 예상과 달랐다. 기능은 안 깨졌고 대신 다른 게 드러났다. 크다는 말이 세 가지 다른 축을 뭉뚱그린 표현이었다는 것, 그...

느릴 때는 코드보다 네트워크를 먼저 갈라 봐라

점자 점역 데스크톱 앱에 무거운 PDF를 넣으면 렉이 걸린다는 제보가 들어왔다. 나는 곧장 코드를 뜯었고 실제로 병목을 두 개 찾아 고쳤다. 조작 한 번에 200ms씩 멈추던 것이 0ms가 됐다. 그런데 사용자가 체감하는 가장 큰 대기, 파일 하나 여는 데 걸리는 5~10초는 그대로였다. 마지막에 첫 바이트까지의 시간을 계층별로 갈라 보고서야 알았다....

배포 직후 서재가 비었다: DataStore에 남아 있던 구버전 정렬 키

캐시 관련 작업을 끝내고 로컬에서도 QA에서도 이상 없는 걸 확인한 뒤 1.9.0 을 배포했다. 배포 직후부터 내 서재에 작품이 안 보인다는 제보가 들어왔다. 원인은 새로 짠 캐시 코드가 아니라 앱이 예전 버전에 저장해둔 값 하나였다. 이 글은 그 사고의 원인과 임시 조치, 영속 데이터에는 버전을 같이 적어야 한다는 결론까지의 기록이다. 무슨 일이 ...