본문 바로가기

Projects12

[Android/Kotlin] Jetpack Compose + Paging3로 무한 스크롤 구현하기 사진 리스트처럼 무한히 스크롤되는 데이터를 효율적으로 불러오려면, 모든 데이터를 한 번에 불러오는 것이 아니라 필요할 때 필요한 만큼만 로드하는 방식이 필요합니다.Jetpack Compose에서는 Paging3와 함께 이를 쉽게 구현할 수 있습니다.이 글에서는 Unsplash API를 예시로, PagingSource, Pager, PagingData, 그리고 LazyPagingItems를 어떻게 연결하는지를 공부한 내용을 기반으로 정리해보았습니다.1. 의존성 추가먼저 build.gradle에 아래와 같이 Paging 관련 의존성을 추가합니다.// 필수: Paging 로직의 핵심 구성implementation("androidx.paging:paging-runtime:3.3.2")// 선택: Paging 데.. 2025. 5. 15.
[Android/Kotlin] Jetpack Compose에서 Flow.debounce()로 검색 요청 최적화하기 프로젝트에서 실시간 사진 검색 기능을 구현하던 중, 검색어 입력 시마다 API가 호출되는 문제가 있었습니다.예를 들어 사용자가 "dinosaur"를 입력하면 "d", "di", "din" 등 입력하는 매 글자마다 API 요청이 발생했기 때문에 불필요한 호출이 많아지고 사용자 경험에도 영향을 주고 있었습니다.이 문제를 해결하기 위해 Flow.debounce()를 적용해 검색 흐름을 개선해보았습니다.문제 상황: 과도한 API 호출처음에는 TextField의 onValueChange에서 바로 API를 호출하고 있었기 때문에, 아래와 같이 입력할 때마다 로그가 찍히고 요청이 전송되었습니다. 이처럼 한 글자 입력할 때마다 API 요청이 발생해 사용량이 과도하게 늘고로딩 UI가 계속 깜빡이는 등 UX에도 부정적인 .. 2025. 5. 7.
[Android/Kotlin] Room + Flow 조합으로 즐겨찾기 화면 자동 갱신하기 Jetpack Compose로 마이그레이션을 진행하면서, 기존 LiveData 기반의 ViewModel 코드를StateFlow + Flow 중심 구조로 함께 개선했습니다.특히 즐겨찾기 화면에서는 그동안 LiveData 기반으로 onResume() 시점마다 수동으로 데이터를 다시 불러와야 했는데요,이번에는 StateFlow와 Room + Flow 조합을 통해 자동으로 갱신되는 UI 흐름으로 전환하게 되었습니다.이를 통해 어떤 점이 개선되었고, 실제로 어떤 구조의 차이가 있었는지 정리해보고자 합니다.기존 방식: 수동 갱신이 필요했던 구조기존에는 ViewModel 내부에서 다음과 같이 데이터를 불러오는 방식을 사용하고 있었습니다.private fun loadFavoritePhotos() { viewMod.. 2025. 4. 24.
[Android/Kotlin] BaseViewModel을 걷어내고 원본 비율을 살린 Masonry 레이아웃 개선기 Pinterest 스타일의 UI를 구현하기 위해, 저는 처음에 각 이미지 카드의 높이를 랜덤하게 설정하는 방식으로 StaggeredGrid를 구성했습니다.이때는 ViewModel에 높이 계산 로직을 두고 position을 기준으로 랜덤한 값을 생성해서 캐싱했으며, 이를 여러 Fragment에서 공통으로 사용하기 위해 BaseViewModel을 상속받는 구조를 사용했었습니다.하지만 프로젝트의 주요 UI를 Jetpack Compose로 마이그레이션하면서,사진 콘텐츠를 더 자연스럽고 의미 있게 표현하기 위한 Masonry 스타일의 본질을 다시 생각하게 되었고, 그 결과 ViewModel 기반 구조는 제거하고 확장 함수를 활용한 방향으로 리팩터링하게 되었습니다.문제점: 랜덤한 높이는 시각적 흥미를 줄 수 있지만.. 2025. 4. 14.
[Android/Kotlin] XML 속성으로 조정 가능한 GameListView 커스텀 뷰 구현과 활용 방법 안드로이드에서 사용자 맞춤형 UI를 구현할 때 커스텀 뷰를 사용하는 것이 매우 유용합니다.이번 포스팅에서는 GameListView라는 커스텀 뷰를 만들어, XML에서 속성만으로 쉽게 조정할 수 있는 방법을 소개합니다. 이 뷰는 게임 목록을 RecyclerView로 보여주며, 카드 유형과 레이아웃을 속성에 따라 유연하게 조정할 수 있습니다. 1. 커스텀 뷰 만들기GameListView라는 커스텀 뷰는 LinearLayout을 확장하여 구현했습니다.이 뷰는 게임 데이터를 리스트 형식으로 보여주며, RecyclerView를 통해 레이아웃을 구성합니다. 특히, 이 커스텀 뷰는 XML에서 속성을 정의하여 다양한 레이아웃을 설정할 수 있습니다. 즉, 뷰를 XML에 선언만 하면, 해당 속성을 이용해 간편하게 사용할 .. 2024. 10. 2.
[Android/Kotlin] open 메서드를 활용한 다형성 구현 Kotlin에서 클래스나 메서드를 정의할 때, open 키워드를 사용하면 상속받은 클래스에서 해당 메서드를 오버라이드할 수 있습니다. 이번 포스팅에서는 open fun onBind(profileDetailModel: ProfileDetailModel) {} 메서드를 예로 들어, 이 메서드가 어떤 역할을 하고, 어떻게 활용될 수 있는지에 대해 설명하겠습니다. open 키워드와 메서드 오버라이드Kotlin에서는 기본적으로 모든 클래스와 메서드가 final로 선언됩니다. 이는 서브클래스에서 해당 클래스나 메서드를 상속하거나 오버라이드할 수 없음을 의미합니다. 그러나, 클래스나 메서드를 open으로 선언하면, 이를 서브클래스에서 확장하거나 오버라이드할 수 있게 됩니다.예를 들어, 다음과 같은 ProfileDet.. 2024. 8. 26.
[Android/Kotlin] filterIsInstance와 firstOrNull을 사용한 개선 오늘은 Kotlin 코드를 리팩토링하여 더 간결하고 명확하게 만드는 방법을 공유하고자 합니다. 주제로는 filterIsInstance와 firstOrNull을 사용하여 객체를 찾고 처리하는 방법을 다루겠습니다.변경 전 코드먼저, 기존의 toggleLike 함수 코드는 아래와 같았습니다.fun toggleLike() { val currentItems = _items.value.toMutableList() val profileImagesIndex = currentItems.indexOfFirst { it is ProfileDetailModel.ProfileImages } if (profileImagesIndex != -1) { val profileImages = currentIt.. 2024. 8. 12.
[Android/Kotlin] StaggeredGridLayout 사용시 발생한 화면 재구성문제 수정 최근에 StaggeredGridLayoutManager를 사용한 즐겨찾기 화면에서 다음과 같은 문제가 발생했습니다:즐겨찾기 화면에서 첫 번째 사진을 클릭하여 상세 보기로 이동사진 상세 화면에서 즐겨찾기를 해제뒤로 가기를 눌러 다시 즐겨찾기 화면으로 돌아오면 빈 화면이 보여짐이 문제는 StaggeredGridLayoutManager에서 아이템을 재배치하는 과정에서 발생했습니다. 아이템들을 제대로 불러오지 못하고 화면을 재구성하는 데 실패하여 빈 화면을 보여주게 된 것입니다.이 문제를 해결하기 위해 RecyclerView의 상태를 복원하는 방법을 적용했습니다. 이를 통해 화면이 빈 화면으로 나타나는 현상을 해결할 수 있었습니다. 다음은 해결 방법입니다.해결 방법: RecyclerView 상태 복원Recycl.. 2024. 7. 29.
[Android] AppBarLayout에 그림자가 생기는 문제 해결 방법 AppBarLayout을 사용하면서 배경색을 투명하게 설정하면 그림자가 자동으로 생기는 경우가 있습니다.이 글에서는 AppBarLayout의 배경을 투명하게 설정하면서도 그림자를 없애는 방법에 대해 다뤄보겠습니다.문제 상황다음과 같이 AppBarLayout의 배경색을 투명하게 설정했습니다. 위와 같이 elevation을 0dp로 설정했지만, 여전히 그림자가 남아있습니다.해결 방법그림자를 없애기 위해 AppBarLayout에 outlineProvider 속성을 추가해 줍니다. 이 속성은 뷰의 외곽선을 제공하는데, none으로 설정하면 그림자가 사라집니다. 요약배경색을 투명하게 설정하면서 그림자 제거:android:background="@android:color/transparent"android:eleva.. 2024. 7. 25.
반응형