APK를 빌드하고 나서 Analyze APK를 클릭하면 위처럼 dex 파일과 디렉터리로 구성된 빌드 결과물을 확인할 수 있습니다.그런데, 프로가드 적용 유무에 따라 이 분석 결과가 달라집니다. 무슨 연관이 있을까요?DEX (Dalvik Executable) 파일이란?DEX 파일은 안드로이드 애플리케이션의 바이트코드를 담고 있는 파일입니다.안드로이드는 Dalvik/ART(안드로이드 런타임)를 사용해 DEX 파일을 실행합니다.모든 자바 클래스 파일(.class)들은 하나 이상의 DEX 파일로 변환되어 안드로이드 패키지(APK)에 포함됩니다.DEX 파일은 메모리와 성능 최적화를 위해 설계되었으며, 앱의 크기와 성능에 중요한 영향을 미칩니다.DEX와 ProGuard의 연관성- ProGuard가 DEX 파일 생성..
Android
MVI 패턴이란?Model - View - Intent의 약자로, 단방향 데이터 흐름을 가지는 패턴입니다.State를 중심으로 UI에 전달하는 방식으로서 여기서 Intent는 기존에 알고 있는 Intent와는 다른 개념입니다. Model: 상태(State)로, UI에서 보일 데이터 또는 상태입니다.View: 화면(UI)을 구성하는 요소로, Model의 상태 변화를 관찰하여 이를 반영합니다.Intent: 사용자의 액션이나 이벤트를 정의한 것으로, 이를 통해 Model이 업데이트됩니다. 상태가 중심인 MVI에서는 데이터는 불변의 구조로 구성되며, 그로 인해 상태가 변할 때 필요한 부분만 갱신되면서 효율성이 증가합니다. MVI 패턴 장점1. 단방향 데이터 흐름 (Unidirectional Data Flow)상..
Bottom Sheet 내부에 EditText를 넣으면 상황에 따라 상하 컴포넌트나 BottomSheet 윗부분이 화면 영역을 넘어가버려 사용에 불편한 경우가 있습니다.이럴 경우 Bottom Sheet Style에 아래 item을 설정해 주면 됩니다.falseadjustResize 그리고 BottomSheet의 onCreate()에서 아래와 같이 선언해줍니다.setStyle(BottomSheetDialogFragment.STYLE_NORMAL, R.style.CustomBottomSheetDialogTheme)android:windowIsFloating의미: 이 속성은 창이 플로팅(floating) 창인지 여부를 설정합니다. 플로팅 창은 일반적인 Activity 창과는 다르게, 독립된 팝업처럼 동작하며,..
앱 자체의 잠금 기능을 구현할 때, 비밀번호 말고도 사용자가 더욱더 빠르게 보안 접근을 해제할 수 있도록 지문 인증 처리를 제공할 수도 있습니다.private var biometricPrompt: BiometricPrompt? = nullprivate var promptInfo: BiometricPrompt.PromptInfo? = null먼저 위 두 개 변수를 선언해 줍니다. BiometricPrompt사용자가 지문, 얼굴 인식 등을 통해 인증을 수행할 때 해당 프롬프트를 표시하고, 인증이 성공하거나 실패했을 때의 콜백을 처리합니다. BiometricPrompt.PromptInfoBiometricPrompt.PromptInfo는 BiometricPrompt에 표시할 다이얼로그의 정보를 구성하는 데 사용..
RxJava 라이브러리를 통해 검색 기능을 구현하는 부분에 대해 다뤄보겠습니다.RxJava를 통해 검색 중에 Reactive Steam으로 사용자가 입력 중인 검색어에 따라 debounce로 실시간 검색 처리가 가능합니다. 먼저 RxJava에 대한 개념 몇 가지를 살펴보자면.. Reactive Programming: 데이터를 비동기 스트림으로 처리하는 프로그래밍 패러다임입니다. 데이터의 흐름을 관찰하면서 이벤트가 발생하면 이를 구독자에게 전달하여 처리하는 방식입니다.Observable: 스트림에서 발생하는 이벤트나 데이터를 발행하는 주체입니다. TextView의 텍스트 변화처럼 연속적인 이벤트를 관찰하고, 이에 대해 구독자에게 이벤트를 전달합니다.Observer: Observable이 발행하는 이벤트나..
기존 프로젝트는 Retrofit을 매번 모든 Api 통신 클래스 하위에 가지고 있었습니다. 또한 통신 과정에서 예외 처리하는 부분까지 반환되는 타입이 매번 다를 뿐 거의 유사했기 때문에코드 관리 및 낭비를 줄이기 위한 정리가 필요했습니다. API 통신 클래스들이 추상 클래스를 상속받는 형태로 처리를 진행했습니다.먼저 각각의 API 통신 결과 타입은 항상 상이할 수 있기에 제네릭을 활용하여 값을 받을 Result Class를 만들어줍니다.sealed class Result { data class Success(val data: T) : Result() data class Error(val message: String? = "ERROR", val code: Int) : Result()}매번 다른 ..
하단 탭 바를 통해 탭을 이동하는 것뿐 아니라 간혹 내부 컴포넌트 onClick을 통해 탭을 이동해야 하는 경우가 있습니다.이때는 NavController를 통해 원하는 탭을 지정할 수 있습니다.FloatingActionButton( onClick = { navController.navigate(Screen.Notes.route) } ...navigate 함수에 탭 key 값을 인자로 넣어줌으로써 지정한 탭으로 이동이 가능합니다. 하지만? 여기서 문제가 한 가지 발생합니다.1번 탭에 있다가 2번 탭으로 navigate -> 이후 다시 하단 탭바로 1번 탭으로 이동하려 하면 1번 탭으로 이동되지 않습니다.이 현상은 NavController가 경로(Route)와 백 스택(Back..
컴포즈에서 하단에 4칸짜리 탭을 구현해 보겠습니다.먼저 gradle에 아래 navigation 의존성 추가가 필요합니다.implementation("androidx.navigation:navigation-compose:2.8.1")implementation("androidx.compose.material3:material3:1.2.1") 탭을 구성하기 위해서는 NavigationBar, NavigationGraph, 각 탭 별 Screen Class가 필요합니다.그리고 화면에서 NavController를 통해 등록된 화면 간의 이동을 제어하게 됩니다. 먼저 필요한 화면에 대한 기본 데이터(route, title, icon....)들을 sealed class로 정의해 줍니다.sealed class Scre..
자사 서비스를 개발하던 중, 대량 데이터를 가지고 있는 특정 사용자의 CS에서 화면에 보여야 할 데이터의 렌더링이 느리다는 보고를 받았습니다.화면을 넘기다가 멈추면 일정이 늦게 그려져요. 서비스의 데이터(일정)를 보여주는 화면의 구조는 ViewPager로 구성되어 있었고, 각 페이지가 Selected 될 때마다 매번 전체 데이터 중 현재 화면에 보여줘야 할 데이터들을 쿼리 하는 작업이 수행되는 구조였습니다.문제점은 빠르게 스크롤을 하면 대량의 쿼리 요청이 축적되고, 데이터 DB는 작업의 부하가 걸리면서 최종적으로 보이는 마지막 페이지의 쿼리 후 데이터 렌더링이 지연되는 것이었습니다. 해결 방안DB 작업을 취소하던지, 순서 제어를 하던지 둘 중 하나의 방법이 필요했습니다.하지만 안드로이드 SQLite에서..
리스트를 구성하다 보면 각종 기능을 위해 상단 또는 하단에 여백을 주고 싶은 경우가 있습니다.이럴 때, 처음 또는 마지막 뷰 홀더에 margin을 넣는 것이 아니라 RecyclerView 자체에 padding Top 또는 Bottom을 넣어주면 됩니다.하지만 바로 넣은 이후에는 그만큼 margin 값이 스크롤 영역을 잡아먹게 되는데요.이런 경우를 고려히여 clipToPadding을 false로 지정해 주면 됩니다.RecyclerView의 clipToPadding 속성은 RecyclerView가 자신의 패딩(padding) 영역에 있는 항목을 표시할지 여부를 결정하는 속성입니다.기본 값: truetrue로 설정되어 있을 경우, RecyclerView는 패딩 영역에 있는 항목을 잘라내고 표시하지 않습니다. ..