최근 회사에서 채팅UI의 구조 개선에 대한 이슈가 발생하여 만들어두었던 채팅창을 모두 갈아엎게 되었다.
기존의 채팅 UI구조는 채팅메세지가 들어올 때마다 Instantiate ( ) 가 수행되어 말풍선 UI가 계속해서 쌓이는 구조였다.
물론 처음 개발 당시엔 채팅메세지가 엄청나게 쏟아지는 경우를 고려하여 말풍선이 쌓이는 갯수를 최대 200개 까지로 제한하여 그 이상 메세지가 쌓일 시엔 가장 오래 된 메세지를 삭제하고 새로 생성하는 형태로 구현했었다.
워낙 게임이 채팅이 많이 오가는 게임이 아니라서 (개인적으론 그렇게 생각한다..) 딱히 위 설계대로 구현한 당시엔 큰 문제나 이슈는 없었다.
그러나 오랫동안 접속상태를 유지한 채, 채팅창을 한번도 키지않고 있다가 새로운 메세지가 많이 쌓인 상태에서 채팅창을 킬 시 200개의 메세지를 모두 갱신하느라 하드웨어에 따라 다르지만 약 3~10초 이상의 딜레이가 걸리는 문제로 결국 인해 최적화 이슈가 발생했다.
이 문제를 어떻게 해결할까 하다가 결국 Infinite ScrollView의 필요성을 느끼게 되었고, 여러가지 InfiniteScrollView에 대한 Reference를 찾아보고 적용해보았지만 가장 큰 문제가 있었다.
구글, 스택오버플로우 등 다양한 곳에서 찾아본 Infinite ScrollView는 100% Grid 형태의 모든 스크롤 항목이 동일한 크기임을 전제로 하여 만들어져 있었다. 그러나 필자가 필요로 하는 Infinite ScrollView의 경우 채팅창의 말풍선들이 내용에 따라 가변적으로 크기가 변하는 조건이 있어서 사람들이 흔히 쓰는 방식으로는 구현할 수가 없었다.
결국...NGUI의 UITable 의 Reposition 기능과 더불어 ScrollView의 기능을 자동으로 수행해줄 수 있는 Infinite ScrollView
를 따로 만들게 되었다.
혹시나 필자가 만들어둔 ScrollView를 사용할 사람들을 위해 주의사항을 몇가지 작성해둔다.
1. 각 스크롤 되는 아이템 항목은 가변적으로 늘어나되, 가변으로 아이템의 크기가 변경되는 사항은 NGUI Anchor를 이용한다는 전제로 구현되어 있다.
2. Prefab으로 연결 시킬 Item의 크기에 따라 자동으로 내부의 Pooling이 결정 된다.
3. 여러개의 Column을 지원하지만, 1 Column 체제로 사용하는 것을 추천한다.
4. 필자는 Vertical 기능만 있으면 되서 Horizontal 은 구현하지 않았다. (Horizontal 부분은 구조만 잡혀있다)
5. SetFocus 기능을 이용하면 해당 아이템을 기준으로 Refresh 된다. (Panel 이 Spring 되는 것이 아니다)
6. Position 계산의 Pivot은 Top이 기준이다.
7. Default 설정 값은 가급적 그대로 두고 사용하길 추천한다 (One Direction, Flat, Horizontal 등. 미완성 내용이 많다)
8. Prepare Size 는 Pool에서 미리 잡아두는 예비 Item 사이즈이다. (2~4정도면 적절, Column 갯수가 늘어난다면 문제가 발생할 수 있다)
결국 Pooling 형태의 Infinite ScrollView로 변경한 결과, 오래 된 내용이 있을지라도 Instantiate ( ) 를 하지 않고 현재 보여질 내용만 갱신하게 되어 속도와 메모리 측면에서 상당히 좋은 결과를 얻을 수 있었다.
다만 단점은 갱신 되는 Item의크기와 예비 갯수에 따라 스크롤이 매끄럽게 계속해서 이어가다가 끊기는 현상이 다분히 발생할 수 있다.