[Android] 앱을 배포해 봅시다.
·
Android
열심히 Develop 에서 코드를 짜고 QA까지 통과했다면 릴리즈를 위해서 AAB 를 추출해야겠죠?앞으로 CI/CD로 자동화까지 고려하고 있지만, 기본적인 워크 플로우를 알고있어야 자동화에 문제가 생겨도 핸들링이 가능할테니 차근차근 따라옵시다.1. release/version branch1.1 브랜치 만들기먼저 릴리즈를 위한 커밋을 하기 위해서 develop에서 release/버전명 (예: release/1.0.0) 브랜치를 생성해줍시다.이렇게 만들었다면 브랜치를 이동해주세요!1.2 Baseline Profile 생성하기최신 코드에 맞춰서 Baseline Profile도 업데이트 해줘야 앱 성능에 도움이 됩니다.먼저 빌드 변형(Build Variant)을 release로 변경해줍니다. 그 후에 Andro..
[Android Compose] 골치덩어리 EdgeToEdge를 잘 써보자.
·
Android/Compose
시작은 불편함에서..Android 15부터 Edge-to-Edge가 기본으로 적용되면서, 이제 앱의 콘텐츠가 시스템 바 아래까지 확장되는 것이 표준이 되었어요. 덕분에 개발자들은 더 넓은 화면을 자유롭게 사용할 수 있게 되었습니다. 하지만 동시에 디자인에 맞춰 상태 바(Status Bar)의 색상을 화면과 자연스럽게 연결해야 하는 과제가 생겼어요😅저도 이 작업을 진행하면서 고민이 많았어요. 이전에는 systemuicontroller 같은 라이브러리를 사용하면 간단히 해결됐지만 Android 16(Tiramisu)부터 Deprecated 되었고, 더 근본적인 문제가 있었어요.LaunchedEffect나 DisposableEffect 안에서 시스템 바 색상을 변경하는 코드를 호출해야 했는데, 이 방식은 스..
[Android] Baseline Profile 적용기 feat. Fake 주입 실패
·
Android
안녕하세요, 오늘은 UX개선 방법중 하나인 Baseline Profile에 대해서 얘기해보려고합니다. 앱 성능 최적화는 언제나 중요한 과제인것 같아요. Lazy를 사용해서 렌더링 최적화를 하고 메모리 사용을 개선하는 등등 부드러운 UX를 제공하기 위해 저도 안드로이드 개발자로서 노력하고 있습니다.그중에서 특히 사용자가 가장 먼저 마주하는 앱 시작 속도는 전체적인 앱 경험에 큰 영향을 끼치죠. 당장 저도 로딩이 길면 화가납니다그래서 안드로이드 진영에서 성능을 최적화 할 방법중 Baseline Profile 을 도입했어요. 오늘은 Baseline Profile을 적용하면서 있었던 일을 공유해보려 합니다ㅎㅎBaseline Profile이 뭔데?Baseline Profile은 앱 설치 시 또는 백그라운드에서 자..
[Android Compose] AboutLibraries로 오픈소스 라이선스 화면을 만들기
·
Android/Compose
앱을 출시하기 전 꼭 포함해야 하는 화면 중 하나가 바로 '오픈소스 라이선스' 명시입니다. 일반적으로 가장 먼저 떠올리는 방법은 Google에서 제공하는 play-services-oss-licenses-plugin 사용하는 방식이겠죠. 저도 공식 지원인 플러그인을 적용했습니다.하지만 막상 구현하고 보니 화면이 제대로 표시되지 않았어요. 세팅하는 과정에서 뭔가 잘못했나? 싶어서 여러번 봤지만 특별하게 잘못된 부분은 없었습니다..// app/build.gradle.ktsplugins { id("com.google.android.gms.oss-licenses-plugin")}// ... dependencies// Activity 코드startActivity(Intent(this, OssLicensesMe..
[Android] 실용적인 멀티모듈 아키텍처 설계 실전기 (Domain 레이어와 build-logic)
·
Android
안녕하세요! AI가 영어 일기를 첨삭해주는 앱, 'Hilingual' 프로젝트를 진행하고 있는 안드로이드 개발자 한민재입니다."AI가 영어 일기를 첨삭해주는 앱"이라는 아이디어로 시작된 Hilingual 프로젝트는 초기 단계부터 명확한 목표를 가지고 있었어요. 바로 지속 가능한 확장성 확보와 팀 단위 개발 생산성 극대화인데요. 저희는 팀 리더의 명확한 비전과 릴리즈에 대한 강한 의지를 바탕으로, 단순한 사이드 프로젝트를 넘어 '실무에 준하는 프로덕트', '수익을 창출해도 부끄럽지 않을 프로덕트'를 만들자는 높은 목표를 세웠어요. 향후 기능 확장의 가능성이 무궁무진하다고 판단했기에, 프로젝트 규모가 커짐에 따라 발생할 수 있는 코드의 강한 결합, 긴 빌드 시간, 명확한 의존성 분리, 그리고 개발자 간의 코..
[Android Compose] @Composable 종속성을 StateFlow로 바꿔보자
·
Android/Compose
안녕하세요, Android 개발자 한민재입니다.최근 Hilingual 프로젝트의 네비게이션 로직을 리팩토링 했어요. 이번 글에서는 @Composable에 의존하던 내비게이션 상태 로직을 UI와 분리된 상태 홀더(State Holder) 패턴과 StateFlow 를 통해 개선한 과정을 상세히 공유해 보려고 합니다. (해당 작업 PR입니다.)UI와 결합된 로직리팩토링 이전, MainNavigator 클래스는 앱의 메인 화면 탐색을 관리했어요. 이 클래스는 DroidKnightsApp을 레퍼런스로 사용했던 코드에요. 그러나 최근에 해당 작업자 본인이 말하길 “땜빵코드”라 꼭 고쳐서 쓰라고 조언을 받았습니다 😅저는 그 얘기를 듣고 한참을 고민했었어요. 좋은 코드같았는데 뭐가 문제였을까? 하면서 고민한 결과 몇..
[Android Compose] flowWithLifecycle은 언제 쓰면 좋을까?
·
Android/Compose
안녕하세요! Compose로 개발하다 보면 Side Effect를 어떻게 처리할지 항상 고민인데요. 저도 ViewModel에서 발생한 이벤트를 LaunchedEffect로 받아서 스낵바를 보여주거나 화면을 전환하는 코드를 자주 작성했어요. 그런데 문득 앱이 백그라운드로 전환됐을 때 flow 수집이 중단되나? 생각이 들어서 테스트 해보니 LaunchedEffect가 계속 동작하는걸 발견했어요.이번 글에서는 제가 겪었던 문제와 flowWithLifecycle API로 해결한 경험, 그리고 이 과정에서 만든 재사용 가능한 확장 함수까지 공유해보려합니다! (해당 작업 PR 입니다)어떤 문제가 있었나요?보통 ViewModel의 단방향 이벤트(Side Effect)를 처리할 때 LaunchedEffect를 많이 사..
[Android Compose] Effect Handlers 딥다이브
·
Android/Compose
안녕하세요! 최근 개발 실력이 나름 늘어간다고 생각이 들면서, 이전까지 모호하게 알고 있다고 생각이 들었던 것들에 대해 다시 기초부터 다지는 중인데요. 내가 컴포즈로 개발을 하면서 사이드 이펙트에 대해 고민을 하고 코드를 작성하고 있었나?라는 생각이 들어 정리를 해봤습니다. 다른 분들에게도 도움이 됐으면 좋겠네요!사이드 이펙트란?사이드 이펙트는 컴포저블 함수의 범위를 벗어나 외부 상태가 변경되는 작업을 말해요. 네트워크 요청, 데이터베이스 접근, 파일 시스템 조작 등이 대표적인 예시예요.왜 문제가 될까요?컴포저블 함수는 언제든지, 몇 번이든 호출될 수 있어요. 리컴포지션은 상태 변화, 부모 컴포저블의 변화, 시스템 설정 변경 등 다양한 이유로 발생하죠. 만약 컴포저블 함수 내에서 직접 네트워크 요청을 한..
[Android Compose] 상태 읽기 지연(Defer State Reads)으로 리컴포지션 최적화하기
·
Android/Compose
Android Compose에서 성능 최적화는 단순히 "빠르게 만들기"를 넘어서, 사용자 경험을 좌우하는 핵심 요소예요. 특히 리컴포지션(Recomposition)을 얼마나 효율적으로 관리하느냐에 따라 앱의 반응성과 배터리 효율성이 크게 달라져요.오늘은 상태 읽기 지연(Defer State Reads) 패턴을 활용해 리컴포지션을 효과적으로 줄인 사례를 통해 Compose 성능 최적화를 알아볼게요.📊 리컴포지션의 3단계와 성능 비용Compose의 리컴포지션은 다음 3단계로 진행돼요컴포지션(Composition) - UI 구조를 다시 계산레이아웃(Layout) - 각 요소의 위치와 크기를 결정드로우(Draw) - 실제 화면에 그리기각 단계는 모두 연산 비용이 발생하며, 특히 컴포지션 단계에서는 모든 계산을..
[Kotlin Coroutine] runCatching으로 CancellationException을 안전하게 처리해보자
·
Kotlin
안녕하세요! 안드로이드 Compose 앱을 개발하면서 예외 처리에 대해 고민할 일이 종종 생기곤 하는데요. 특히 suspend 환경에서의 예외 처리라면 더욱 주의해야 하는 것 같아요.Sopt Makers에서 합류한 지도 벌써 4개월이 지났는데요, 그 과정에서 다시 관심을 갖게 된 주제가 있어요. 바로 RunCatching 인데요! 그리고 이에 관련된 이슈는 과거에도 굉장히 활발히 논의됐었어요.Provide a runCatching that does not handle a CancellationException but re-throws it instead. #1814이걸 계기로 기존에 구현된 코드들을 살펴보다가 suspendRunCatching을 어떻게 개선하면 좋을까? 라는 고민이 생겨서, 파헤쳐 본 내..