멀티스레딩 및 콜백 기본 지침서
컬렉션을 사용해 정리하기
내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요.
Kotlin으로 Android 앱 개발 과정에서는 멀티스레딩 개념 및 용어를 잘 알고 있다고 가정합니다. 따라서 여기서는 복습 차원에서 개념을 개략적으로 살펴봅니다.
휴대기기에는 프로세서가 있습니다. 오늘날 대부분의 기기에는 각기 프로세스를 동시에 실행하는 여러 하드웨어 프로세서가 있습니다. 이를 다중 처리라고 합니다.
운영체제는 프로세서를 더 효율적으로 사용하기 위해 애플리케이션이 프로세스 내에서 둘 이상의 실행 스레드를 만들도록 할 수 있습니다. 이를 멀티스레딩이라고 합니다.

동시에 여러 권의 책을 읽을 때 각 챕터 단위로 책을 번갈아 가며 읽다 보면 결국에는 모든 책을 다 읽을 수 있지만 정확히 동시에 두 권 이상의 책을 읽을 수 없는 것과 같다고 생각할 수 있습니다.
이러한 모든 스레드를 관리하려면 약간의 인프라가 필요합니다.

스케줄러는 우선순위와 같은 사항을 고려하며 모든 스레드가 실행되고 완료되도록 합니다. 책이 영원히 선반에 놓인 상태로 먼지가 쌓이지는 않지만 책이 너무 길거나 여유가 있는 경우 전달되기까지 시간이 걸릴 수 있습니다.
디스패처는 스레드를 설정합니다. 즉, 읽어야 하는 책을 보내고 독서가 진행될 컨텍스트를 지정합니다. 컨텍스트는 별도의 전문적인 독서실로 생각할 수 있습니다. 일부 컨텍스트는 사용자 인터페이스 작업에 가장 적합하고 일부는 입력/출력 작업을 처리하는 데 특화되어 있습니다.
사용자 대상 애플리케이션은 일반적으로 포그라운드에서 실행되는 기본 스레드를 가지고 있으며 백그라운드에서 실행될 수 있는 다른 스레드를 전달할 수 있다는 점만 알아두면 됩니다.
Android에서 기본 스레드는 UI에 관한 모든 업데이트를 처리하는 단일 스레드입니다. UI 스레드라고도 하는 이 기본 스레드는 모든 클릭 핸들러, 기타 UI, 수명 주기 콜백을 호출하는 스레드이기도 합니다. UI 스레드는 기본적인 스레드입니다. 앱이 명시적으로 스레드를 전환하거나 다른 스레드에서 실행되는 클래스를 사용하는 경우를 제외하고 앱이 하는 모든 작업은 기본 스레드에 있습니다.
이로 인해 어려움이 생길 수 있습니다. 즉, 뛰어난 사용자 환경을 보장하려면 UI 스레드가 원활하게 실행되어야 합니다. 앱이 눈에 띄는 일시중지 없이 사용자에게 표시되도록 하려면 기본 스레드가 16ms마다 또는 더 자주 화면을 업데이트하거나 초당 약 60프레임으로 화면을 업데이트해야 합니다. 이 속도에서 인간은 프레임 변경이 완벽히 원활하다고 인식합니다. 즉, 적은 시간에 많은 프레임을 렌더링해야 합니다.
따라서 Android에서는 UI 스레드 차단을 방지하는 것이 중요합니다. 이 컨텍스트에서 차단은 예를 들어 데이터베이스가 업데이트를 완료할 때까지 기다리는 동안 UI 스레드가 아무 작업도 하지 않는 것을 의미합니다.

인터넷에서 데이터 가져오기, 대용량 파일 읽기, 데이터베이스에 데이터 쓰기와 같은 많은 일반적인 작업은 16밀리초 이상 걸립니다. 따라서 코드를 호출하여 기본 스레드에서 이 같은 작업을 실행하면 앱이 일시중지되거나 끊기거나 멈출 수 있습니다. 그리고 기본 스레드를 너무 오랫동안 차단하면 앱이 비정상 종료될 수 있으며 '애플리케이션 응답 없음'(ANR) 대화상자가 표시될 수도 있습니다.
콜백
기본 스레드에서 작업을 완료하는 방법으로는 몇 가지 옵션이 있습니다.
기본 스레드를 차단하지 않고 장기 실행 작업을 이행하는 한 가지 패턴은 콜백입니다.
콜백을 사용함으로써 백그라운드 스레드에서 장기 실행 작업을 시작할 수 있습니다.
작업이 완료되면 인수로 제공되는 콜백이 호출되어 기본 스레드의 결과를 코드에 알립니다.
콜백은 훌륭한 패턴이지만 몇 가지 단점이 있습니다. 콜백을 매우 많이 사용하는 코드는 읽기 어렵고 추론하기가 더 어려워질 수 있습니다. 코드는 순차적으로 보이지만 콜백 코드는 나중에 비동기 시간에 실행되기 때문입니다. 또한 콜백은 예외와 같은 일부 언어 기능의 사용을 허용하지 않습니다.
코루틴
Kotlin에서 코루틴은 장기 실행 작업을 원활하고 효율적으로 처리하기 위한 솔루션입니다.
Kotlin 코루틴을 사용하면 콜백 기반 코드를 순차 코드로 변환할 수 있습니다. 순차적으로 작성된 코드는 일반적으로 읽기가 더 쉬우며 예외와 같은 언어 기능을 사용할 수도 있습니다. 결국 코루틴과 콜백은 정확히 동일한 작업을 합니다. 즉, 장기 실행 작업에서 결과를 사용할 수 있을 때까지 기다렸다가 실행을 계속합니다.
이 페이지에 나와 있는 콘텐츠와 코드 샘플에는 콘텐츠 라이선스에서 설명하는 라이선스가 적용됩니다. 자바 및 OpenJDK는 Oracle 및 Oracle 계열사의 상표 또는 등록 상표입니다.
최종 업데이트: 2025-08-19(UTC)
[[["이해하기 쉬움","easyToUnderstand","thumb-up"],["문제가 해결됨","solvedMyProblem","thumb-up"],["기타","otherUp","thumb-up"]],[["필요한 정보가 없음","missingTheInformationINeed","thumb-down"],["너무 복잡함/단계 수가 너무 많음","tooComplicatedTooManySteps","thumb-down"],["오래됨","outOfDate","thumb-down"],["번역 문제","translationIssue","thumb-down"],["샘플/코드 문제","samplesCodeIssue","thumb-down"],["기타","otherDown","thumb-down"]],["최종 업데이트: 2025-08-19(UTC)"],[],[],null,["# Multi-threading & callbacks primer\n\nThe\n[Developing Android Apps in Kotlin course](https://codelabs.developers.google.com/codelabs/kotlin-android-training-welcome/index.html?index=..%2F..index#0)\nassumes that you are familiar with the concept and terminology of\nmulti-threading. This page is a high-level introduction and refresher.\n\nMobile devices have processors, and these days, most devices have multiple\nhardware processors that each run processes concurrently. This is called\n*multiprocessing*.\n\nTo use processors more efficiently, the operating system can enable an\napplication to create more than one thread of execution within a process. This\nis called *multi-threading*.\n\nYou can think of it as reading multiple books at the same time, switching\nbetween books after each chapter, eventually finishing all books, but you can't\nread more than one book at the exact same time.\n\nIt takes a bit of infrastructure to manage all those threads.\n\nThe *scheduler* takes into account things such as priorities, and makes sure all\nthe threads get to run and finish. No book is allowed to sit in the shelf\nforever and gather dust, but if a book is very long, or can wait, it may take a\nwhile before it gets sent your way.\n\nThe *Dispatcher* sets up threads, that is, it sends you books that you need to\nread, and specifies a **context** for that to happen in. You can think of the\ncontext as a separate, specialized reading room. Some contexts are best for user\ninterface operations, and some are specialized to deal with input/output\noperations.\n\nThe only other thing to know is that a user-facing application usually has a\n*main thread* that runs in the foreground and can dispatch other threads that\nmay run in the background.\n\nOn Android, the main thread is a single thread that handles all updates to the\nUI. This main thread, also called the *UI thread*, is also the thread that calls\nall click handlers and other UI and lifecycle callbacks. The UI thread is the\ndefault thread. Unless your app explicitly switch threads or uses a class that\nruns on a different thread, everything your app does is on the main thread.\n\nThis creates a potential challenge. The UI thread has to run smoothly to\nguarantee a great user experience. For your app to display to the user without\nany visible pauses, the main thread has to update the screen every 16 ms or more\noften, or at about 60 frames per second. At this speed, humans perceive the\nchange of frames as completely smooth. That's a lot of frames and little time.\nTherefore, on Android it's essential to avoid blocking the UI thread. *Blocking*\nin this context means the UI thread is not doing anything at all while it waits\nfor something like a database to finish updating.\n\nMany common tasks take longer than 16 milliseconds, such as fetching data from\nthe internet, reading a large file, or writing data to a database. Therefore,\ncalling code to perform tasks like those from the main thread can cause the app\nto pause, stutter, or even freeze. And if you block the main thread for too\nlong, the app may even crash and present an \"application not responding\" (ANR)\ndialog.\n\nCallbacks\n---------\n\nYou have several options for how to get work done off of from the main thread.\n\nOne pattern for performing long-running tasks without blocking the main thread\nis *[callbacks](https://en.wikipedia.org/wiki/Callback_(computer_programming))*.\nBy using callbacks, you can start long-running tasks on a background thread.\nWhen the task completes, the callback, supplied as an argument, is called to\ninform your code of the result on the main thread.\n\nCallbacks are a great pattern, but they have a few drawbacks. Code that heavily\nuses callbacks can become hard to read and harder to reason about. Because while\nthe code looks sequential, the callback code will run at some asynchronous time\nin the future. In addition, callbacks don't allow the use of some language\nfeatures, such as exceptions.\n\nCoroutines\n----------\n\nIn Kotlin,\n*[coroutines](https://kotlinlang.org/docs/reference/coroutines-overview.html)*\nare the solution for handling long-running tasks elegantly and efficiently.\nKotlin coroutines let you convert callback-based code to sequential code. Code\nwritten sequentially is typically easier to read, and can even use language\nfeatures such as exceptions. In the end, coroutines and callbacks do exactly the\nsame thing: wait until a result is available from a long-running task and\ncontinue execution."]]