RecyclerView 올바른 사용 방법

컴퓨터공부/안드로이드 2020. 7. 22. 19:38 Posted by 아는 개발자

 

사진첩 내용이랑 리뷰 처럼 동일한 형태의 아이템을 리스트로 띄우고 있다

전화번호부, 구글 편지함, 사진첩 등등 요즘 출시되는 대부분의 앱에선 전화번호 정보나 사진과 같은 동일한 유형의 아이템을 리스트로 보여주는 뷰를 가지고 있다. 하나의 아이템은 간단하게 텍스트 정보만 가지는 것부터 사진, 동영상처럼 파일 크기를 많이 차지하는 미디어까지 서비스마다 다양한 방식으로 효과를 준다. 이 아이템 효과를 개발적인 측면에서 고려해보면 화면에 보여주려는 아이템이 차지하는 메모리 크기가 얼마 되지 않는다면 리스트에 붙인 모든 아이템을 바로 화면에 렌딩해도 크게 문제가 되진 않지만 파일 크기가 큰 미디어를 포함하는 아이템을 한번에 렌딩한다면 프로그램에서 순식간에 대량의 메모리를 차지하게되는 문제가 생긴다. 스크롤이 버벅거리다가 Out of Memory 가 발생해서 앱이 죽는 경우가 이런 경우다.

 

이런 경우를 위해 만들어진 라이브러리가 RecyclerView 클래스다. RecyclerView 클래스는 대량의 아이템을 리스트로 보여줄때 실제로 화면에 비춰지는 아이템만 렌딩하도록 만들어 앱에서 사용하는 메모리의 양을 최소화 했다. 실제로 구현해보면 100개의 아이템을 RecyclerView에 붙여도 화면에 바인딩 되는 아이템은 화면에 비춰지는 것과 캐싱용으로 그 근처에 있는 아이템인 7~8개 남짓이다. 나머지 아이템은 스크롤해서 가까이 이동할 때 읽어와 화면에 띄워줘서 메모리 공간을 절약하는 방식이다. RecyclerView가 대신 메모리 관리를 해주기 때문에 개발자는 화면에 뿌려줄 아이템만 찾아주는데 집중하면 된다.

 

RecyclerView를 잘못 사용하는 경우는 RecyclerView의 장점인 메모리 관리 기능을 살리지 않고 사용할 때다. 화면에 비춰지는 것들만 화면에 렌딩해야하는데 잘못 사용하다보면 화면에 비춰지지 않는 아이템들도 바인딩 시켜버려서 메모리를 급격하게 잡아 먹게돼 폰이 갑자기 느려지는 경우가 생긴다. 물론 이런 유형의 버그를 만드는 것도 쉽진 않다. 하지만 화면에 다양한 유형의 아이템을 넣으려고 하다 보면 아래의 같은 구조로 코드를 짜게 되는데 이런 구조가 대표적으로 recyclerview를 잘못 쓸 수도 있게 되는 예다 (무조건 잘못하는 건 아니고)

 

 

위 그림에서 Parent RecyclerView는 Child RecyclerView 하나씩 나눠서 하게 된다. 그런데 Parent RecyclerView의 입장에서는 Child Recycler View가 가지고 있는 아이템이 얼마나 되는지는 모른다. 단지 첫번째 Child RecyclerView가 화면에 비치기만 한다면 각각이 갖고 있는 아이템의 개수와 상관 없이 화면에 바로 렌딩을 하게 된다. 여기서 만약 Child RecyclerView가 렌딩해야하는 총 크기가 화면 뷰를 벗어나지 않는다면 크게 문제가 되진 않는데 이를 벗어나 갖고 있는 모든 아이템을 렌딩하면 문제가 될 수도 있게 된다

 

 

윗 사진의 화면 페이지와 로그를 비교해보면 문제가 되는 것을 확인 할 수 있다. 실제로 화면에서는 0 ~ 7번까지만 화면에 보이고 있는데 로그에서는 불과 200ms 만에 21번까지 화면에 바인딩이 되버린다. 화면에서는 스트링 정보만 있기 때문에 스크롤 할 때 큰 문제가 되진 않는데 만약 리스트에 사진파일이나 동영상이 있으면 심각하게 스크롤이 잘 되지 않는 문제가 생긴다 (심지어 고성능 폰에서도 말이다) 

 

렉걸리는 문제에 대한 스택 오버플로우 답변으로는 각 아이템이 Constraint Layout을 없애서 아이템 하나가 차지하는 메모리의 크기를 줄이라고 하는데, 요새 폰들은 뷰의 부하 정도는 거뜬히 이겨낼 수 있을 정도로 좋아서 이부분이 그렇게까지 문제가 되는 것 같지는 않고 마지막에 최적화 할 부분이 없을 때 사용할 만한 팁인 정도다. 예상외로 심각하게 렉이 발생한다면 위 사례처럼 화면에 보이지 않는 아이템까지 바인딩하면서 메모리를 잡아먹고 있는것은 아닌지 확인하는게 좋을 것 같다.