
추상화하는 것구성 요소
New: 프로세스가 생성되고 있는 상태Running: 프로세스의 명령어들이 실제로 실행되고 있는 상태Waiting: 프로세스가 어떤 사건(I/O 작업, signal 등)이 발생하기를 기다리고 있는 상태 (예: I/O 작업이 완료되거나, 신호(signal)를 수신하는 경우)Ready: 프로세스가 CPU에 할당되기를 기다리고 있는 상태Terminated: 프로세스의 실행이 종료된 상태커널내에 Ready Queue, Waiting Queue, Running Queue를 두고 프로세스들을 상태에 따라 관리한다.
CPU 1개로 여러 프로그램을 "동시에" 실행하는 것처럼 보이게하는 멀티태스킹 (Multitasking)을 위해서 새로운 프로세스로 전환될 때, 커널은 기존(현재) 프로세스의 상태를 저장하고, 새 프로세스의 저장된 상태를 로드하는 작업인 Context switching이 필요하다.
이 때 가장 중요한 것은 PCB(Process Control Block)이다. 프로세스의 모든 상태 정보를 담은 자료구조인 PCB가 없다면 프로세스는 다시 실행할 수 없다.
IPC(Inter-Process Communication)가 필요– 비용이 많이 듦
Thread ID – Thread 식별자Program Counter – 현재 실행중인 Instruction의 주소Register Set - CPU의 Register 값들StackCode – Program의 Code SectionData – Process의 Data SectionFile – Process에서 Open한 File
iOS 앱은 기본적으로 Main Thread에서 시작됩니다. Main Thread는 UI 업데이트를 담당하는 유일한 스레드로, 모든 UI 관련 작업은 반드시 여기서 실행되어야 합니다.
DispatchQueue.main.async {
recognizedText = ...
}
앱 실행 시 자동으로 생성
UI 렌더링, 사용자 입력 처리 담당
무거운 작업을 실행하면 앱이 버벅이거나 멈춤 (UI Freeze)
기본적으로 작업은 메인 쓰레드에서 실행된다.
UI 업데이트, 사용자 입력, 화면 표시 등 모든 사용자 인터페이스 관련 작업은 이곳에서만 해야합니다.
DispatchQueue.main.async를 쓰는 이유
DispatchQueue.main.async는 Background 클로저 안에서 UI 업데이트가 필요할 때 Main Thread로 전환하기 위해 사용한다. 이미 Main Thread라면 쓸 필요 없다.DispatchQueue.global(qos: .background).async { let data = fetchDataFromServer() DispatchQueue.main.async { self.updateUI(with: data) } }
SwiftUI의 @State, @Binding, View 업데이트 등은 항상 메인 스레드에서 실행해야 한다.
백그라운드에서 이걸 바꾸려고 하면 앱이 충돌이 일어난다.
결과만 메인 스레드로 넘겨서 안전하게 UI에 적용하는 것.
DispatchQueue.global(qos: .userInitiated).async {
try handler.perform([request])
}
네트워크 요청, 파일 I/O, 복잡한 연산 등 시간이 오래 걸리는 작업 수행
Main Thread를 블로킹하지 않아 UI가 부드럽게 유지됨
이미지 처리, OCR, 네트워크 통신, 데이터 저장 등 무거운 연산이나 시간이 걸리는 작업을 담당합니다.
Vision의 OCR 엔진은 이미지 분석이라는 무거운 작업을 한다.
그렇기 때문에 메인 스레드에서 하면 앱이 멈춘 듯 버벅거리기 때문에
다른 스레드(백그라운드 스레드)에서 처리해야 한다.
Quality of Service (서비스 품질)의 줄임말이다.
즉, 이 작업이 얼마나 중요한 작업인가? 를 시스템에게 알려주는 우선순위 등급을 뜻한다.
| QoS | 설명 | 예시 |
|---|---|---|
| .userInteractive | 가장 높은 우선순위, 즉시 완료되어야 하는 UI 반응성 작업 | 드래그, 스크롤 등 |
| .userInitiated | 사용자가 요청한 작업으로, 즉시 필요하지만 약간의 처리 시간은 허용 | OCR 처리, 검색 실행 |
| .default | 기본 우선순위 (명시하지 않으면 사용) | 일반적인 작업 |
| .utility | 오래 걸리지만 급하지 않은 작업 | 다운로드, 파일 처리 |
| .background | 사용자가 직접 보지 않아도 되는 작업 | 백업, 캐시 저장 |
| .unspecified | 특별히 지정하지 않음 (시스템 판단에 맡김) | 잘 쓰지 않음 |
실무에서는 특별한 이유가 없으면 DispatchQueue.global().async로 기본값(.default)을 사용하는 경우가 많다.
멀티코어에서 멀티스레딩이 효율적인 이유
멀티스레딩은 같은 프로세스 내에서 데이터를 공유한다. 멀티코어 CPU에서는 여러 코어가 캐시(L3)를 공유하기 때문에, 공유 데이터에 접근할 때 RAM보다 훨씬 빠른 캐시를 활용할 수 있다. 덕분에 멀티코어 환경에서 멀티스레딩이 더 효율적으로 동작한다.핵심:
캐시 공유→RAM 접근 감소→속도 향상
iOS는 위에서 배운GCD와 Operation Queue를 통해 멀티코어를 자동으로 활용한다.
// 병렬 처리 - 시스템이 알아서 여러 코어에 분배
DispatchQueue.concurrentPerform(iterations: 100) { index in
processItem(at: index)
}
concurrentPerform은 반복문을 여러 코어에서 병렬로 실행하는 함수이다.