스크린샷과 에셋8 분 읽기

음수 자간이 아랍어 단어의 마지막 글자를 먹었습니다

스토어 스크린샷을 로케일별로 찍는데 아랍어 컷에서만 화면 제목이 잘렸습니다. 폭 문제로 보였고 근거도 있었습니다. 폭을 넓혀도 그대로였고, 변수를 하나만 바꿔 네 번 그려 보니 범인은 폰트도 굵기도 폭도 아닌 음수 letterSpacing이었습니다. 라틴 밀도를 위한 개선이 다른 문자 체계에서 글자를 지우고 있었습니다.

#screenshots#localization#android#gotchas#debugging
같은 단어를 세 번 겹쳐 쓴 그림. 위 둘(보통 / Bold)은 온전하고, 맨 아래(자간 -0.6)만 마지막 글자가 오른쪽 경계 밖으로 반쯤 밀려 잘려 있다.
음수 자간을 주면 측정된 폭이 실제 그려지는 폭보다 작게 잡히고, 아랍어는 단어 끝 글리프가 넓어 마지막 글자가 레이아웃 밖으로 밀려납니다.

안드로이드 앱의 스토어 스크린샷을 로케일별로 찍고 있었습니다. 한국어·영어·일본어 컷은 멀쩡한데 아랍어 컷에서만 화면 제목이 잘려 나왔습니다. "오늘"에 해당하는 단어의 마지막 글자가 사라진 채 렌더됐습니다.

당신이 어떤 버그를 "레이아웃 폭 문제"로 진단할 때, 그 진단을 뒷받침하는 증거가 사실은 다른 원인도 똑같이 만들어 내는 증상은 아닌지 확인하십니까?

첫 가설이 그럴듯해서 오래 붙잡았습니다

처음엔 레이아웃 폭 문제로 보였습니다. 근거도 있었습니다 — 제목이 두 줄로 쪼개져 있었고, maxLines = 1을 걸자 마지막 글자가 사라졌습니다. 전형적인 넘침입니다.

그런데 폭을 카드 전체로 넓혀도 그대로였습니다.

여기서 추측을 멈추고 진단 화면을 만들었습니다. 같은 문자열을 조건만 바꿔 세 번 그려 한 장으로 찍었습니다.

조건 결과
34sp 보통 온전
34sp Bold 온전
34sp + letterSpacing = (-0.6).sp 잘림

폰트도 굵기도 폭도 아니고 자간이었습니다. 음수 자간을 주면 측정된 폭이 실제로 그려지는 폭보다 작게 잡히고, 아랍어는 단어 끝에서 쓰는 글리프가 넓어서 마지막 글자가 레이아웃 밖으로 밀려납니다.

반전은 이겁니다

그 자간은 디자인 개선이었습니다. 라틴 문자 제목의 밀도를 조금 높이려고 넣은 값이고, 제가 보는 화면에서는 실제로 조금 나아 보였습니다. 개선이 다른 문자 체계에서는 글자를 지우고 있었습니다.

규칙 하나로 접었습니다 — 타이포그래피에 음수 letterSpacing을 쓰지 않는다. 라틴에서 얻는 미세한 밀도보다, 한 로케일에서 글자가 사라지지 않는 쪽이 큽니다.

당신이라면 어떻게 하시겠습니까

두 줄로 쪼개진 화면과 maxLines 실험이 폭 가설을 계속 지지하는 것처럼 보입니다. 여기서 폭 조정을 몇 번 더 시도하겠습니까? 아니면 가설을 잠시 내려놓고, 변수를 하나만 바꿔 나란히 렌더하겠습니까?

가설을 버린 계기는 새 정보가 아니라 "폭을 늘렸는데 안 변한다"는 부정 결과였습니다. 진단 화면을 만드는 비용은 작았고, 그걸 처음부터 했으면 훨씬 빨랐습니다.

코드·명령·수치 — 같은 캡처 작업에서 함께 나온, 같은 성질의 문제들

  • 요일 약자를 앞 두 글자로 자르면 아랍어 일곱 요일이 전부 같은 두 글자가 됩니다. DayOfWeek.getDisplayName(TextStyle.NARROW, locale)을 씁니다.
  • DateFormatSymbols.getInstance()Locale.getDefault()는 JVM 기본 로케일을 봅니다. 화면이 다른 로케일로 그려지고 있으면 그 부분만 영어로 남습니다. 컴포지션의 설정에서 로케일을 꺼내야 합니다.
  • 레이아웃 방향은 액티비티 구성에서 옵니다. 캡처 하네스에서 로케일만 갈아 끼우면 RTL이 안 걸립니다 — 레이아웃 방향도 함께 넘겨야 합니다.
  • 캡션을 이미지로 합성할 때 폰트를 하나로 밀면 아랍어·힌디어가 두부(□□□) 가 됩니다. 문자 체계별 폰트 + 적절한 텍스트 레이아웃 엔진을 쓰고, 글리프가 없으면 실패로 처리합니다.
  • 왜 측정 폭과 렌더 폭이 어긋나는지 내부 구현까지는 확인하지 못했습니다. 관측된 동작과 회피책까지가 이 글의 범위입니다.

자가진단 3개

  • 당신의 타이포그래피에 음수 letterSpacing(또는 음수 tracking)이 있습니까? 그 값을 RTL 로케일과 결합 문자 체계에서 렌더해 본 적이 있습니까?
  • 로케일별 스크린샷을 눈으로 봅니까, 아니면 한국어/영어 컷만 보고 나머지는 자막만 얹습니까? 이 결함은 라틴 로케일만 보면 절대 안 보입니다.
  • 버그 가설을 지지하는 것처럼 보이는 증거가, 다른 원인도 똑같이 만들어 내는 증상은 아닙니까? 변수를 하나만 바꿔 나란히 놓으면 바로 갈립니다.

솔직한 부분

첫 가설이 그럴듯해서 오래 붙잡았습니다. 두 줄로 쪼개진 화면과 maxLines 실험이 폭 가설을 계속 지지하는 것처럼 보였고, 변수를 하나만 바꿔 나란히 렌더하는 방법을 왜 마지막에 꺼냈는지는 변명할 게 없습니다. 라틴 로케일만 보면 절대 안 보이는 결함이라는 점은, 이 버그의 성질이자 로케일별 컷을 눈으로 봐야 하는 이유입니다.

로케일 파이프라인이 조용히 한쪽만 보던 앞선 사례가 일본어 스크린샷은 이미 있었다 — 파이프라인이 물어보지 않았을 뿐입니다.

지금 딱 하나만 해보세요. 당신 앱의 화면 제목 하나를 아랍어(또는 힌디어) 로케일로 렌더해서, 마지막 글자가 온전한지 확인해 보시기 바랍니다.

관련 글