Glide가 이미지 사이즈를 계산하는 방식

 

Glide는 이미지를 로딩할 때, 내부적으로 View의 getSize()를 이용해 목표 사이즈를 계산합니다.

 

Glide는 무작정 원본 이미지를 가져오는 게 아니라, 뷰에 딱 맞는 사이즈의 이미지를 가져오기 위해 노력합니다.
불필요하게 큰 이미지로 인해 발생하는 메모리 낭비, 깜빡임, 렌더링 지연을 방지한다는 뜻입니다.

 

적절한 URL View 크기에 맞는 해상도의 이미지 URL을 선택해서 불러올 수 있음 (커스텀 구현 시)
적절한 이미지 View 크기에 맞게 원본 이미지를 다운샘플링/크롭/리사이즈한 최적화된 비트맵

 


 

ViewTarget의 역할

 

Glide에서 ViewTarget은 이미지가 로드될 View의 실제 사이즈를 계산하고 추적하는 핵심 클래스

 

ViewTarget은 이미지를 View에 넣기 전에 그 View의 크기를 계산하려고 다양한 방법을 시도함

 

  • View의 layoutParams에 명시된 크기 확인 (ex. xml 단의 고정 dp)
  • View가 이미 레이아웃되어 있으면 getWidth()/getHeight() 사용 (ex. imageView.width, imageView.height)
  • wrap_content일 경우엔 경고만 띄우고 강제 크기 지정 권장
  • 아직 크기를 알 수 없다면 OnPreDrawListener를 등록해 레이아웃이 끝날 때까지 기다림

 

ViewTreeObserver.OnPreDrawListener는 View의 크기(너비·높이)를 정확히 알 수 없을 때해당 View가 실제로 그려지기 직전에 호출되는 리스너입니다.

 


 

레이아웃 패스와 이미지 로딩

 

안드로이드에서 화면은 아래 세 단계로 그려집니다

 

  1. Measure Pass – 뷰의 크기 계산
  2. Layout Pass – 뷰의 위치 결정
  3. Draw Pass – 화면에 그림

 

Glide는 레이아웃 패스 이후에 View 크기를 측정해야 정확한 사이즈로 이미지를 로딩할 수 있습니다.

wrap_content를 사용하면 측정이 반복되어 성능이 나빠지고, 이미지 깜빡임이 생길 수 있습니다.

 

 


 

BitmapPool이란?

 

Glide는 메모리 효율을 위해 Bitmap 재사용(pooling) 을 합니다.

비트맵 재사용이란 건, 이미지 데이터 자체를 재사용한다는 뜻이 아니라 이미지 데이터를 담을 메모리 공간(Bitmap 객체의 버퍼)을 재사용한다는 뜻입니다.

 

ex) 서로 다른 이미지를 로드하더라도 해상도(예: 200x200)와 색상 설정(예: ARGB_8888)이 같다면 예전에 사용한 Bitmap 객체의 메모리 버퍼를 다시 사용합니다.

 

비트맵 재사용 시 아래와 같은 효용이 있습니다.

  • 메모리 할당/GC 비용 절감
  • Bitmap 생성 시간 단축
  • 앱 렉/버벅임 방지

View 크기를 명확하게 설정하면 BitmapPool에서 적절한 크기를 빠르게 가져올 수 있어 (BitmapPool 적중률) 높아져 성능이 좋아집니다

 


 

Transition (전환 효과)

 

Glide에서 이미지가 바뀔 때 나타나는 애니메이션 효과
ex. fade in, crossfade, slide 등

 

Glide v4는 전환 효과를 기본 적용하지 않습니다.
직접 명시해야 하며, 예시는 아래와 같습니다

Glide.with(context)
    .load(url)
    .transition(DrawableTransitionOptions.withCrossFade())
    .into(imageView)

 

Glide는 어디에서 이미지를 불러왔는지에 따라 전환 효과의 작동 여부가 달라집니다.

 

✅  디스크 캐시 O 작동함
✅  로컬 파일/Uri O 작동함
✅  네트워크 URL O 작동함
❌  메모리 캐시 ❌  작동 안 함

 

⚠ 주의 사항

  • 전환 효과는 요청 간 교차(fade between A and B) 는 지원하지 않음
    → 첫 요청과 두 번째 요청 사이에 직접적으로 애니메이션을 넣을 수는 없음
  • 커스텀 전환 효과를 만들려면 TransitionFactory를 구현해야 함
  • crossfade는 기본적으로 점점 알파값을 줄이며 전환하는데 placeholder가 로딩중인 이미지보다 크거나 이미지가 부분적으로 투명한 경우 교차 fade를 비활성화하면 애니메이션이 완료된 후 placeholder가 이미지 뒤에 표시될 수 있다
  • Glide에서는 기본 적으로 새로운 로드를 존재하는 View 또는 Target에 할 때 존재하는 요청들을 취소시킨다. 그렇기 때문에 다른 두개의 이미지를 로드 하고 그 둘을 교차 fade하고 싶다면, Glide로는 직접적으로 처리할 수 없다.

 


 

Glide 전환 애니메이션의 성능 주의사항

 

애니메이션도 연산이다

Glide의 crossfade는 이미지 위에 새 이미지를 덧씌워 알파값을 조절하는 방식입니다.
이 과정은 GPU 리소스를 사용하며, 다수의 이미지에 동시에 적용될 경우 렌더링 성능에 영향을 줄 수 있습니다.

캐시된 이미지는 애니메이션 없이 더 빠르다

Glide는 메모리·디스크 캐시를 통해 이미지를 즉시 표시할 수 있습니다.
이때 애니메이션을 적용하면 오히려 불필요한 지연이 생겨 UX를 해칠 수 있습니다.

RecyclerView에서는 특히 주의

스크롤 시 View가 빠르게 재사용되기 때문에 전환 애니메이션이 깜빡임, 프레임 드롭, 흰 배경 노출을 유발할 수 있습니다.

 

Glide 성능 팁 요약

 

불필요한 애니메이션은 피하기

Glide의 전환 효과(crossfade 등)는 GPU 리소스를 사용합니다.
특히 RecyclerView, GridView처럼 스크롤이 많은 UI에서는 프레임 드롭이나 깜빡임을 유발할 수 있습니다.
→ 목록 UI에서는 .dontAnimate() 또는 withNoTransition() 사용을 권장합니다.

미리 로딩(Preloading) 활용하기

사용자가 스크롤하기 전에 이미지를 미리 메모리에 로드해두면, 화면 진입 시 로딩 지연 없이 자연스럽게 이미지를 표시할 수 있습니다.
→ Glide.with(context).load(url).preload() 형태로 적용할 수 있습니다.