<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Appisode</title><link>https://appisode.me/</link><description>Recent content on Appisode</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><lastBuildDate>Mon, 16 Mar 2026 00:00:00 +0900</lastBuildDate><atom:link href="https://appisode.me/index.xml" rel="self" type="application/rss+xml"/><item><title>Looper, MessageQueue, Handler</title><link>https://appisode.me/posts/looper-handler/</link><pubDate>Mon, 16 Mar 2026 00:00:00 +0900</pubDate><guid>https://appisode.me/posts/looper-handler/</guid><description>&lt;p&gt;기본적으로 JVM 프로그램은 &lt;code&gt;main&lt;/code&gt; 함수가 끝나는 즉시 애플리케이션이 종료된다. 하지만 안드로이드는 명시적으로 종료를 선언하기 전까지 실행 상태를 유지하는데, 이는 메인 스레드 내에서 끊임없이 돌아가는 &lt;code&gt;Looper&lt;/code&gt; 덕분이다.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Looper&lt;/code&gt; 는 안드로이드 애플리케이션의 실행 상태를 유지하는 것 외에도, 안드로이드의 UI 요소를 안정적으로 그리는 데에도 핵심적인 역할을 수행한다. 이번 포스팅에서는 &lt;code&gt;Looper&lt;/code&gt; 를 중심으로, 이와 밀접하게 연관된 &lt;code&gt;Handler&lt;/code&gt; 와 &lt;code&gt;MessageQueue&lt;/code&gt; 에 대해서도 알아본다.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="안드로이드-시스템-구조"&gt;안드로이드 시스템 구조&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;Looper&lt;/code&gt; 를 이해하기 위해, 먼저 안드로이드의 시스템 구조부터 간략하게 파악해보자.&lt;/p&gt;</description></item><item><title>About</title><link>https://appisode.me/about/</link><pubDate>Wed, 11 Mar 2026 13:00:00 +0900</pubDate><guid>https://appisode.me/about/</guid><description/></item><item><title>Binder 동작 원리 - 통신 준비</title><link>https://appisode.me/posts/binder-ipc-communication-prep/</link><pubDate>Sun, 01 Feb 2026 00:00:00 +0900</pubDate><guid>https://appisode.me/posts/binder-ipc-communication-prep/</guid><description>&lt;p&gt;&lt;a href="https://appisode.me/posts/binder-ipc/"&gt;지난 포스팅&lt;/a&gt;에서는 &lt;code&gt;Binder&lt;/code&gt; 가 왜 등장했는지, 어떤 특징이 있는지 알아봤다. 이 과정에서 &lt;code&gt;Binder&lt;/code&gt; 가 안드로이드 시스템에서 핵심 역할을 수행한다는 사실도 알 수 있었다.&lt;/p&gt;
&lt;p&gt;이제 더 나아가, 이번 포스팅을 시작으로 &lt;code&gt;Binder&lt;/code&gt; 가 내부에서 어떻게 동작하는지 상세히 알아볼 것이다. 우선 전체적인 동작 흐름을 가볍게 훑어보고, 본격적인 통신에 앞서 선행되어야 하는 &lt;strong&gt;준비 과정&lt;/strong&gt;을 다이어그램과 함께 상세히 살펴보자.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="전체-동작-흐름"&gt;전체 동작 흐름&lt;/h2&gt;
&lt;p&gt;&lt;img src="binder-ipc-communication-prep-01.png" alt="Full Binder IPC"&gt;&lt;/p&gt;
&lt;p&gt;위 이미지는 &lt;code&gt;Binder&lt;/code&gt; 통신 과정에서 발생하는 흐름을 시각적으로 표현한 것이다. 처음엔 생소한 용어들이 많아 복잡해 보일 수 있지만, 단계별로 개념을 알아가다 보면 자연스럽게 이해할 수 있을 것이다.&lt;/p&gt;</description></item><item><title>Binder 란?</title><link>https://appisode.me/posts/binder-ipc/</link><pubDate>Fri, 05 Sep 2025 00:00:00 +0900</pubDate><guid>https://appisode.me/posts/binder-ipc/</guid><description>&lt;p&gt;앱을 사용하다 보면, 갤러리에서 프로필 사진을 고르거나 카메라로 사진을 찍는 경우가 있다. 사용자 입장에서는 마치 하나의 앱에서 모든 일이 자연스럽게 처리되는 것처럼 보인다. 하지만 실제로는 ‘갤러리’를 담당하는 앱과 ‘카메라’를 담당하는 앱이 &lt;strong&gt;서로 다른 프로세스에서 독립적으로 실행되고 있다&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;그렇다면 안드로이드는 어떻게 독립된 앱들을 하나로 이어주는걸까? 이것을 가능하게 해주는 것이 바로 안드로이드의 핵심 &lt;code&gt;IPC&lt;/code&gt; 메커니즘인 &lt;strong&gt;&lt;code&gt;Binder&lt;/code&gt;&lt;/strong&gt; 이다. 이번 포스팅에서는 &lt;code&gt;Binder IPC&lt;/code&gt; 가 어떤 역할을 하고, 왜 필요한지 그 개념을 차근차근 살펴본다.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="안드로이드와-linux"&gt;안드로이드와 Linux&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;Binder&lt;/code&gt;를 이해하려면, 먼저 안드로이드가 어떤 기반 위에서 동작하는지 알아야 한다.&lt;/p&gt;</description></item><item><title>코루틴 내부 구조, 쉽게 뜯어보기</title><link>https://appisode.me/posts/kotlin-coroutine-internal-structure/</link><pubDate>Tue, 01 Jul 2025 00:00:00 +0000</pubDate><guid>https://appisode.me/posts/kotlin-coroutine-internal-structure/</guid><description>&lt;p&gt;코틀린을 주력 언어로 사용하는 개발자라면, 비동기 처리 시에 코루틴을 습관처럼 사용하고 있을 것이다. 복잡한 설정 없이 &lt;strong&gt;&lt;code&gt;suspend&lt;/code&gt;&lt;/strong&gt; 키워드만 붙여주면, &lt;strong&gt;함수가 중단되었다가 작업이 완료되는 신기한 비동기 흐름&lt;/strong&gt;을 간단하게 만들 수 있기 때문이다.&lt;/p&gt;
&lt;p&gt;물론 단순히 &lt;code&gt;suspend&lt;/code&gt; 키워드의 역할만 알아도 코루틴을 사용하는 데에는 아무런 문제가 없지만, 어느 순간 이런 궁금증이 들 수 있다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;🤔 &lt;code&gt;suspend&lt;/code&gt; 가 붙은 함수는 내부에서 어떻게 동작하는걸까?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;오늘은 이러한 개발자스러운 궁금증을 해결하기 위해, 코루틴의 내부 동작을 이해하는 데 핵심이 되는 아래 &lt;strong&gt;세 가지 키워드&lt;/strong&gt;를 중심으로 차근차근 뜯어보려 한다.&lt;/p&gt;</description></item><item><title>Sequence</title><link>https://appisode.me/posts/sequence/</link><pubDate>Sun, 03 Mar 2024 00:00:00 +0000</pubDate><guid>https://appisode.me/posts/sequence/</guid><description>&lt;p&gt;프로그램을 개발하며 &lt;code&gt;Collection&lt;/code&gt; 을 사용해보지 않은 개발자는 한 명도 없을 것이다. 특히 코틀린 개발자는 어떠한 리스트가 필요할 때 &lt;code&gt;Collection&lt;/code&gt; 을 습관적으로 사용하는 경우가 대부분일 것이다. 하지만, 대량의 데이터를 다룰 때에도 &lt;code&gt;Collection&lt;/code&gt; 을 사용한다면, 애플리케이션의 성능을 저하시킬 우려가 있다. &lt;strong&gt;코틀린에서는 대량의 데이터를 처리해야 하는 경우 빠른 연산을 자랑하는 &lt;code&gt;Sequence&lt;/code&gt; 의 사용을 권장&lt;/strong&gt;한다.&lt;/p&gt;
&lt;h2 id="collection-을-사용하면-성능이-저하되는-이유"&gt;&lt;code&gt;Collection&lt;/code&gt; 을 사용하면 성능이 저하되는 이유&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;Collection&lt;/code&gt; 을 사용하면 왜 애플리케이션의 성능이 저하될까?&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-kotlin"&gt;val file = File(&amp;quot;Hoyahozz.csv&amp;quot;).readLines()
file
.filter { it.startsWith(&amp;quot;ho&amp;quot;) } // new List
.drop(5) // new List
.mapNotNull { it.split(&amp;quot;,&amp;quot;).getOrNull(6) } // new List
.count()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;코틀린으로 개발을 하다보면 많이 볼 수 있는 형태의 코드 전개이다. 하나의 리스트에 대해 여러 처리 함수를 사용하고 있는데, &lt;strong&gt;문제는 각 함수를 호출할 때마다 새로운 &lt;code&gt;Collection&lt;/code&gt; 이 반환된다는 점&lt;/strong&gt;이다. 하지만 당연하게도 중간에 사용된 &lt;code&gt;Collection&lt;/code&gt; 은 결국 사용되지 않고, 오로지 마지막에 있는 &lt;code&gt;Collection&lt;/code&gt; 만 사용하므로 오버헤드가 발생한다.&lt;/p&gt;</description></item><item><title>예제로 살펴보는 Jetpack Compose 의 장점</title><link>https://appisode.me/posts/jetpack-compose-benefits-by-example/</link><pubDate>Sun, 18 Feb 2024 00:00:00 +0000</pubDate><guid>https://appisode.me/posts/jetpack-compose-benefits-by-example/</guid><description>&lt;p&gt;벌써 &lt;code&gt;Jetpack Compose&lt;/code&gt; 가 스테이징으로 출시된지 2년이 훌쩍 넘어가고 있는 시점입니다. 그 사이 &lt;code&gt;Jetpack Compose&lt;/code&gt; 는 불안정했던 초기 버전을 지나 구글의 적극적인 지원으로 안드로이드 생태계에 빠르게 자리를 잡았는데요, 현재는 많은 프로젝트에서 안드로이드 UI 툴킷으로 &lt;code&gt;Jetpack Compose&lt;/code&gt; 를 적극적으로 채택하고 있는 추세입니다.&lt;/p&gt;
&lt;p&gt;이러한 흐름에 맞게 이제는 &lt;code&gt;Jetpack Compose&lt;/code&gt; 를 프로젝트에 도입해볼까 하는 안드로이드 개발자분들이 많으실 것 같아요. 이 고민에 작은 도움이 되고자 이번 포스팅에서는 &lt;strong&gt;안드로이드 주니어 개발자인 제가 2개의 사이드 프로젝트와 1개의 사내 프로젝트를 개발하고 출시하며 느꼈던 &lt;code&gt;Jetpack Compose&lt;/code&gt; 의 장점&lt;/strong&gt;에 대해 간략하게 이야기 해보려고 해요!&lt;/p&gt;</description></item><item><title>Kotlin Generic in, out</title><link>https://appisode.me/posts/kotlin-generic-in-out/</link><pubDate>Sun, 07 Jan 2024 00:00:00 +0000</pubDate><guid>https://appisode.me/posts/kotlin-generic-in-out/</guid><description>&lt;p&gt;&lt;a href="https://appisode.me/posts/kotlin-generic/"&gt;지난 포스팅&lt;/a&gt;에서는 제네릭의 기초적인 내용들을 알아보았다. 이번 포스팅에서는 한 발 더 나아가 심화적인 내용들을 알아보도록 하자.&lt;/p&gt;
&lt;h2 id="제네릭은-기본적으로-불변invaraint하다"&gt;제네릭은 기본적으로 불변(invaraint)하다&lt;/h2&gt;
&lt;pre&gt;&lt;code class="language-kotlin"&gt;fun main() {
val any: Any = 5 // 업캐스팅
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;위의 코드가 컴파일 오류 없이 잘 동작하는 이유는 무엇일까?&lt;/p&gt;
&lt;p&gt;&lt;code&gt;5&lt;/code&gt; 라는 값은 기본적으로 &lt;code&gt;Int&lt;/code&gt; 타입이다. 그리고 &lt;strong&gt;&lt;code&gt;Int&lt;/code&gt; 는 &lt;code&gt;Any&lt;/code&gt; 의 서브 타입&lt;/strong&gt;이기 때문에 값이 할당되는 과정에서 &lt;strong&gt;&lt;code&gt;5&lt;/code&gt; 는 자동적으로 &lt;code&gt;Any&lt;/code&gt; 타입으로 변환&lt;/strong&gt;된다. 즉, &lt;strong&gt;&lt;code&gt;Any&lt;/code&gt;, &lt;code&gt;Int&lt;/code&gt; 는 부모-자식 간의 관계&lt;/strong&gt;를 지니고 있기 때문에 코틀린 타입 변환에 의해 자동으로 업캐스팅되어 정상적으로 작동한다.&lt;/p&gt;</description></item><item><title>Kotlin Generic</title><link>https://appisode.me/posts/kotlin-generic/</link><pubDate>Sun, 10 Dec 2023 00:00:00 +0000</pubDate><guid>https://appisode.me/posts/kotlin-generic/</guid><description>&lt;h2 id="generic-"&gt;Generic ?&lt;/h2&gt;
&lt;p&gt;제네릭은 함수에 파라미터를 전달하는 것과 유사하게 &lt;strong&gt;타입에 파라미터를 전달&lt;/strong&gt;해 &lt;strong&gt;컴파일 시에 적합한 타입을 사용할 수 있게 지정하는&lt;/strong&gt; 것을 의미한다. 이로 인해 &lt;strong&gt;타입 안정성을 강화&lt;/strong&gt;할 수 있는 것은 물론, &lt;strong&gt;코드 재사용성&lt;/strong&gt;을 높이는 효과를 누릴 수 있다. 아래 코드를 보며 제네릭에 대해 가볍게 이해해보자.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-kotlin"&gt;fun printStringList(list: List&amp;lt;String&amp;gt;) {
list.forEach { item -&amp;gt;
println(item)
}
}
fun printIntList(list: List&amp;lt;Int&amp;gt;) {
list.forEach { item -&amp;gt;
println(item)
}
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;아주 간단하게 &lt;strong&gt;&lt;code&gt;List&lt;/code&gt; 의 타입을 파라미터로 받아 콘솔로 출력하는 함수&lt;/strong&gt;이다. 크게 문제는 없지만, 만약 여기서 &lt;code&gt;Float&lt;/code&gt;, &lt;code&gt;Double&lt;/code&gt; 타입의 &lt;code&gt;List&lt;/code&gt; 를 출력하고 싶다면, &lt;strong&gt;새로운 함수를 작성&lt;/strong&gt;해야 한다.&lt;/p&gt;</description></item></channel></rss>