선생님, 개발을 잘하고 싶어요.

[Android] Custom Font 적용 시 OutOfMemory 발생 및 해결 본문

개발/android 개발

[Android] Custom Font 적용 시 OutOfMemory 발생 및 해결

알고싶은 승민 2021. 8. 26. 21:00

상황

개인 프로젝트를 개발하고 있는데 잘만 동작하던 앱이 갑자기 죽기 시작했습니다.

내가 최근 작업에서 건드린 부분이 아닌데 왜 이러나 한참 헤매었습니다.

CustomFont로드 시점에 OutOfMemory가 나면서 죽는 경우였습니다.

코드는 다음과 같았습니다.

fun getSLightTypefaceSpan(context: Context): CustomTypefaceSpan {
    return CustomTypefaceSpan(
        Typeface.create(
            ResourcesCompat.getFont(
                context,
                R.font.s_light
            ),
            Typeface.NORMAL
        )
    )
}

 

 

이 코드를 모든 화면에서 사용하고 있었습니다.

TLDR

  • Resource를 접근하는 코드는 캐시 하자.
  • 폰트 사이즈가 너무 크면 Memory 제한에 걸리고 죽고, 느려진다.

Typeface를 캐시 안 한 게 문제

첫 문제는 이 함수가 호출될 때마다 계속 Typeface를 만들고 Span객체를 만든다는 점입니다. 이는 memory leaks을 야기하며 성능을 엄청나게 저하시킵니다.

https://stackoverflow.com/questions/16901930/memory-leaks-with-custom-font-for-set-custom-font

따라서 코드를 다음과 같이 변경했습니다.

object CustomFontCache {
    lateinit var sLightSpanTypeface: CustomTypefaceSpan

    fun init(context: Context) {
        sLightSpanTypeface = CustomTypefaceSpan(
            Typeface.create(
                ResourcesCompat.getFont(
                    context,
                    R.font.s_light
                ),
                Typeface.NORMAL
            )
        )
    }
}

// App 클래스, onCreate 함수에 다음을 추가합니다.
// 앱 초기화 시점에 앱 전체에서 쓰이는 폰트는 미리 만들고 케시합니다.
CustomFontCache.init(this)

하지만 여전히 죽었습니다. 이것도 문제지만, 이것 때문만은 아녔습니다.

폰트 사이즈가 문제

폰트의 크기가 너무 컸습니다.

https://spoqa.github.io/spoqa-han-sans/ko-KR/#download

스포카 폰트를 다운로드하고 사용했는데 오리지널을 사용한 게 문제가 되었습니다.

가볍게? 얼마나 가볍겠지? 무거우면 얼마나 무겁겠어?

실제로는 29MB가 넘었는데, 당연히 죽을 수밖에 없죠?

서브셋을 다운로드하고 교체했습니다. 500KB 정도의 크기입니다. 엄청 작죠?

결론

개발 초기 단계부터 앱이 묘하게 느리다는 느낌을 받았습니다만, 대수롭지 않게 넘겼었습니다. 사전에 주의를 좀 해야 할 것 같아요.

Comments