Android ExifInterface를 활용해 촬영한 사진이 회전하는 문제 해결하기
·
Android
현재 개발 중인 앱에서 사진을 촬영하고 서버에 업로드하는 과정에서 사진이 회전되는 문제가 발생했다. 함께 개발 중인 페어께서 이 문제를 발견하셨고 "회전 메타 데이터 활용해서 사진 안 돌아가게 수정해 주세요"라는 요구 사항을 전달받았다. 이와 관련된 내용을 조사하던 중 Exif 태그라는 것의 존재를 알게 되었고 이를 활용해 문제를 해결한 방법을 소개하고자 한다.기존 코드촬영된 이미지를 서버에 업로드하기 위해 Uri 형태의 이미지를 ByteArray로 변환하는 방식을 사용했다. UI Layer에서 사용의 편의를 위해 Context의 확장함수로 선언했으며 이 함수는 Android 시스템이 제공하는 Uri를 실제 이미지 데이터로 읽어 들인 뒤 ByteArray로 압축 변환하여 반환한다. 동작 과정은 다음과 같..
Compose 디자인 시스템 설계하기
·
Android
서론디자이너와 협업 시 가장 중요한 것은 디자이너가 의도한 디자인을 정확하게 구현하는 것이다. 특정 텍스트가 어떤 폰트를 사용해야 하는지, 글자 크기는 얼마인지, 자간과 행간은 어떻게 적용되어야 하는지까지 세세하게 정해져 있다. 같은 스타일의 텍스트를 구현하면서도 매번 폰트나 크기, 행간이나 자간을 다시 설정해야 하고 화면이 많아질수록 이러한 작업은 반복되어 개발 생산성이 점점 저해된다. 이러한 불편함을 줄이기 위해 디자이너가 설계한 디자인을 기준으로 재사용할 수 있는 시스템을 만드는 것이 바로 디자인 시스템이다. 디자인 시스템을 도입하면 디자이너의 요구사항을 일관된 방식으로 반영할 수 있고 이미 정의된 시스템을 활용해 보다 안정적으로 화면을 구현할 수 있다. 오늘은 실제 프로젝트에서 사용한 디자인 ..
HiltViewModel 의존성 주입 원리
·
Android
갑자기 새로운 버전을 배포한 앱이 크래시 되는 일이 발생했습니다. Firebase Crashlytics를 확인한 결과 다음과 같은 에러가 발생하고 있었습니다. 원인은 단순했습니다. ViewModel에 @HiltViewModel을 Activity에 @AndroidEntryPoint를 추가하지 않았기 때문이었죠. 하지만 여기서 의문이 생겼습니다. "Hilt는 컴파일 타임에 의존성 주입 코드를 생성해서 런타임 에러를 방지한다고 알고 있는데 왜 컴파일은 성공하고 런타임에 크래시가 발생한 걸까?" 이 의문을 해결하기 위해 ViewModel의 기본 작동 원리부터 Hilt가 어떻게 ViewModel을 주입하는지 차근차근 알아보겠습니다.Hilt 의존성 주입"Hilt는 컴파일 타임에 의존성 관계를 분석하여 의존성 주입..
아주 쉽게 알아보는 뷰가 그려지기까지의 여정
·
Android
Activity의 생명주기, Fragment의 생명주기, ViewModel의 생명주기까지 안드로이드를 조금이라도 공부해 본 사람들이라면 이 내용에 대해 당연히 들어봤고 한 번쯤은 공부해 봤을 것입니다. 하지만 View의 생명주기는 어떨까요? 필자는 다른 컴포넌트들의 생명주기에 비해 유독 View의 생명주기가 어렵게 느껴졌기 때문에 이를 조금이라도 쉽게 풀어 소개해보고자 합니다. 먼저 View의 생명주기에 대해 알아보겠습니다. View가 화면에 보이기까지는 크게 4단계를 거칩니다onAttachedToWindow() : 화면 준비 완료 !onMeasure() : 내 크기는 얼마나 필요해 ?onLayout() : 내 자리는 어디야 ?onDraw() : 이제 그린다 !onAttachedToWindow( ) 뷰가..
운영체제 메모리
·
Android
공식문서에 따르면 안드로이드 플랫폼은 사용 가능한 메모리가 있다는 것은 메모리를 낭비라는 전제 하에 작동하기 때문에 항상 사용 가능한 모든 메모리를 사용하기 때문에 Android 기기는 사용 가능한 메모리가 거의 없는 상태로 실행되는 경우가 많습니다. ART(Android Run Time)과 Dalvik VM은 페이징(paging)과 메모리 매핑 기법을 사용해 메모리를 관리합니다. 이를 이해하기 위해선 프로세스가 메모리(RAM)에 할당되는 방식에 대해서 알아보겠습니다.모든 실행되는 명령어와 데이터들은 CPU가 직접적으로 접근할 수 있는 메인 메모리와 레지스터에 있어야 합니다. 또한 각각의 프로세스는 독립된 메모리 공간을 가집니다. 이 공간은 일반적으로 다음과 같이 구분됩니다.코드 영역 (Text Seg..
안드로이드에서 네트워크 상태에 따라 API를 재호출해보자
·
Android
모바일 환경에서는 네트워크 연결이 끊기는 상황이 매우 빈번하게 발생합니다. 만약 이에 대한 적절한 대응이 없다면, 사용자는 네트워크를 연결한 뒤 화면을 다시 열거나 앱을 재시작하는 것 외에는 앱을 계속 사용할 수 없습니다. 이러한 경험은 UX 측면에서 매우 불친절하며, 장기적으로 사용자 이탈로 이어질 수 있습니다.목표API 호출 시 네트워크가 연결되어 있지 않으면 ConnectException이 발생합니다. 이를 방지하기 위해 API 호출 전 네트워크 연결 상태를 확인하여 네트워크가 연결이 되어 있을 때만 API를 호출하며, 실패한 API 요청을 적절히 재시도하는 방법을 소개합니다.ConnectivityConnectivity는 기기의 네트워크의 다양한 연결 상태를 추적할 수 있는 API로, 단순한 네트워..
Retrofit Internals - Retrofit In Coroutine
·
Android
이전 글에서는 Retrofit이 동적 프록시와 리플렉션을 활용해 서비스 인터페이스의 구현체를 생성하는 과정을 살펴보았습니다. 이를 통해 Retrofit이 어떻게 인터페이스 메서드 호출을 가로채고, 내부에서 HTTP 요청 처리를 위한 준비를 하는지 이해할 수 있었습니다. 이번 글에서는 코루틴을 지원하는 Retrofit의 동작 방식을 자세히 들여다보며, HttpServiceMethod가 어떻게 다양한 호출 방식(suspend 함수, 일반 함수, Response, Call)을 처리하는지, 그리고 네트워크 요청을 어떻게 수행하는지 알아보겠습니다.# ContinuationRetrofit이 코루틴을 다루는 방법을 이해하기 위해선 먼저 suspend 함수에 대한 지식이 필요합니다. 이를 위해 간단한 예시 코드를 한..
Retrofit Internals - Retrofit은 어떻게 인터페이스의 구현체를 만들까 ?
·
Android
서론Retrofit을 사용해 네트워크 요청을 만들 때 서비스 인터페이스를 구현하는 것 만드로 API 요청을 구현할 수 있습니다. 어떻게 구현체가 없는 인터페이스를 실행 가능한 형태로 만드는 걸까요? 이 글에서는 Retrofit이 내부적으로 서비스 인터페이스의 구현체를 생성하는 과정과 이를 통해 API 요청을 수행하는지를 단계별로 살펴보겠습니다.create( ) 메서드는 두 단계를 걸쳐 서비스 인터페이스의 구현체를 생성합니다. 이를 단계별로 분석해 보겠습니다.Step1. 서비스 인터페이스 검증 (validServiceInterface())Retrofit은. create()를 통해 전달된 클래스가 정상적인 인터페이스인지 먼저 확인하고 아닐 시 예외를 던집니다.private void validateServi..