내일배움캠프 39일차

임클·2025년 4월 24일

내일배움캠프

목록 보기
40/44
post-thumbnail

동시성 프로그래밍에서 동기와 비동기의 차이, iOS에서 비동기 작업 처리 방법, 세마포어와 뮤텍스의 차이

  1. 동기(Synchronous)와 비동기(Asynchronous)의 정의 및 차이점
    • 동기
      • 호출자가 작업이 끝날 때까지 기다린 뒤에야 다음 코드를 실행
      • 일반적으로 호출 스레드를 블로킹(blocking)
      • 예: 파일을 읽는 함수가 리턴될 때까지 UI 스레드가 멈춰 있을 수 있음
    • 비동기
      • 호출 즉시 제어권을 반환하고, 실제 작업은 백그라운드에서 수행
      • 완료 시점에 콜백, 클로저, 프로미스, async/await 등을 통해 결과를 통지
      • 호출 스레드를 블로킹하지 않으므로 UI나 다른 로직이 계속 실행 가능
    • 비교
      동기비동기
      블로킹예 (blocking)아니오 (non-blocking)
      호출 반환작업 완료 후 반환즉시 반환
      에러 처리예외/리턴값콜백 인자/Task 재시도 등
      사용 예간단한 로직 순차 처리네트워크 통신, 디스크 I/O
  2. iOS에서 비동기 작업 처리 방법
    1. GCD(Grand Central Dispatch)
      • DispatchQueue.global().async { /* 백그라운드 작업 */ }
      • DispatchQueue.main.async { /* UI 업데이트 */ }
      • 장점: 간단하고 가벼움
      • 코드 예
        DispatchQueue.global(qos: .userInitiated).async {
            let image = downloadImage(from: url)
            DispatchQueue.main.async {
                imageView.image = image
            }
        }
        
    2. OperationQueue & Operation
      • Operation을 상속하거나 블록(OperationBlock)을 사용
      • 의존성 설정, 취소, 최대 동시 수행 개수 제어 가능
      • 코드 예
        let queue = OperationQueue()
        let op = BlockOperation {
            let data = fetchData()
            OperationQueue.main.addOperation {
                textView.text = data
            }
        }
        queue.addOperation(op)
        
    3. URLSession
      • 네트워크 요청 자체가 비동기 처리
      • dataTask(with:completionHandler:) 또는 async/await 버전
      • 코드 예 (completion handler)
        URLSession.shared.dataTask(with: url) { data, response, error in
            guard let data = data else { return }
            DispatchQueue.main.async {
                parseAndDisplay(data)
            }
        }.resume()
        
      • 코드 예 (async/await, iOS 15+)
        Task {
            do {
                let (data, _) = try await URLSession.shared.data(from: url)
                let decoded = try JSONDecoder().decode(Model.self, from: data)
                await MainActor.run {
                    updateUI(with: decoded)
                }
            } catch {
                print(error)
            }
        }
        
    4. Swift Concurrency (async/await, Task, Actor)
      • 코드 가독성 향상, 구조적 동시성 지원
      • Task.detached vs Task {}
      • @MainActor 또는 await MainActor.run {} 으로 메인 스레드 보장
      • 예:
        func fetchImage() async throws -> UIImage {
            let (data, _) = try await URLSession.shared.data(from: url)
            guard let img = UIImage(data: data) else { throw URLError(.badServerResponse) }
            return img
        }
        
        Task {
            do {
                let image = try await fetchImage()
                imageView.image = image
            } catch {
                print(error)
            }
        }
        
  3. 세마포어(Semaphore)와 뮤텍스(Mutex)의 차이점
    • 공통점
      • 둘 다 임계 구역(critical section)을 보호하기 위한 동기화 도구
    • 세마포어
      • 내부에 카운터(count)를 가지고, wait() 시 카운터를 하나 줄이고 0보다 작아지면 블록
      • signal() 시 카운터를 하나 늘리고 블록된 스레드를 깨움
      • 카운터 초기값을 1로 주면 이진 세마포어(binary semaphore)가 되어 mutex처럼 동작
      • 카운터를 1보다 크게 줘서 동시에 허용 가능한 리소스 개수를 제한 가능
      • iOS 예:
        let sema = DispatchSemaphore(value: 2) // 최대 2개 동시 진입
        DispatchQueue.global().async {
            sema.wait()
            // 임계 구역
            sema.signal()
        }
        
    • 뮤텍스
      • 상호 배제(mutex)는 오직 하나의 스레드만 임계 구역에 진입하도록 보장
      • 일반적으로 이진 세마포어와 유사하지만, 소유권 개념(owner)이 있어 unlock은 잠금을 건 스레드만 가능
      • 언락(해제)이 반드시 락을 건 스레드에서만 호출되어야 함
      • iOS 예 (NSLock 사용):
        let lock = NSLock()
        DispatchQueue.global().async {
            lock.lock()
            // 임계 구역
            lock.unlock()
        }
        
    • 비교
      세마포어뮤텍스
      카운터0 이상 정수 (동시 진입 수 제어)이진 (1 또는 0)
      소유권없음있음 (소유 스레드)
      용도자원 풀(pool) 제어, 동시성 제한임계 구역 배타적 접근
      unlock 제한어떤 스레드든 signal 가능오직 락 건 스레드만 unlock

정리

  • 동기 방식은 순차적이고 간단하지만, 장시간 작업 시 UI 블로킹 위험
  • 비동기 방식은 콜백, 큐, async/await 등을 통해 논블로킹 처리 가능
  • iOS에서는 GCD, OperationQueue, URLSession, Swift Concurrency를 주로 활용
  • 세마포어는 동시 진입 허용 수 제어에 유리하며, 뮤텍스는 엄격한 임계 구역 보호에 적합

0개의 댓글