Starbucks Caramel Frappuccino
본문 바로가기
  • 그래 그렇게 조금씩
SwiftUI/SwiftUI(Basic)

46. [SwiftUI] .onAppear/disappear & DispatchQueue, 동시성 프로그래밍/ 비동기적 실행

by Toughie 2023. 5. 2.

뷰가 화면에 나타나거나 사라질 때 원하는 동작을 실행할 수 있는 .onAppear() / .onDisappear() 메소드에 대해 알아보자.

관련 예시 코드를 보기 전에 필요한 개념들을 먼저 정리해 보자.

.onAppear()

사실 정확하게 말하면 뷰가 로드되어 화면에 배치되고, 화면에서 표시될 준비가 된 후에 실행된다. 

즉 유저 눈에 보이고 나서 실행되는 것이 아니라, 뷰가 화면에 나타나기 직전, 즉 화면에 나타날 예정인 시점에 실행되는 것이다.

뷰가 처음으로 나타날 때만 호출되고, 이후 뷰가 갱신될 때에는 호출되지 않는다. 

 

.onDisappear()

뷰가 화면에서 사라질 예정인 시점에 실행된다. (다른 뷰로 넘어갈 때 등)

ex. 화면에서 노래가 나오다가 다른 화면으로 넘어가면 노래가 멈추는 등

 

Concurrency Programming (동시성프로그래밍)

여러개의 스레드나 프로세스를 사용해 한 번에 여러 가지 일을 처리하는 것을 의미함

이를 통해 시스템의 성능 향상 및 대기 시간 최소화라는 이점이 있음.

 

⭐️비동기적 실행

작업을 효율적으로 처리하고 *블로킹을 방지하기 위해

현재 실행되고 있는 스레드나 프로세스를 사용하지 않고, 다른 스레드나 프로세스를 사용해 작업을 처리.

*블로킹 - 어떤 작업이 수행될 때 해당 작업이 완료될 때까지 다른 작업을 수행할 수 없는 상태

 

+동기적 실행 - 코드 실행이 완료될 때까지 다음 코드가 실행되지 않음 (기다림)

-> 다음 코드를 실행하는 스레드는 블로킹 상태에 놓임

 

비동기적으로 실행되는 코드는 해당 코드를 실행하는 스레드와 메인스레드가 다를 때 

해당 스레드에서 작업을 수행하고, 작업이 완료되면 메인스레드에서 결과를 처리함.(UI 업데이트)

 

ex. 사용자의 입력에 따라 UI를 업데이트 하는 코드가 있다고 가정하자.

이 작업이 매우 오래 걸린다면? 메인스레드가 블로킹되어 UI가 먹통이 될 것이다. (화면 버벅버벅)

-> 이 작업을 비동기적으로 실행해서 메인 스레드를 자유롭게 동작하도록 하기.

DispatchQueue

Swift에서 비동기 코드 실행을 다루기 위한 클래스.

DispatchQueue.main.async

메인 스레드에서 비동기적으로 실행될 작업을 지정.

- iOS 앱에서 UI를 업데이트 해야 하는 경우 자주 사용함.

 

프로세스와 스레드

프로세스(Process)

운영체제 상에서 실행 중인 하나의 프로그램 단위(ex. iOS의 경우 앱)

각각의 프로세스는 운영체제에서 독립적인 메모리 영역을 할당받으며,

각각의 프로세스는 독자적인 실행 공간을 가지며 다른 프로세스와 독립적으로 실행됨.

 

스레드(Thread)

프로세스 내부에서 실행되는 작은 실행 단위.

하나의 프로세스에는 여러 스레드가 존재할 수 있으며, 스레드들은 프로세스가 가진 자원들을 공유함.

각각의 스레드는 프로세스 내부에서 동시에 실행될 수 있고, 각각의 스레드는 자신의 실행 순서를 가지고 실행됨.

 

프로세스는 각각 독립적인 실행 공간을 가짐.

스레드는 프로세스 내부에서 공유되는 실행 단위임.

-> 스레드는 프로세스보다 경량화 되어있고, 스레드를 사용하면 프로그램의 성능을 향상시킬 수 있음.

but 스레드간 동기화 문제, 경합 상태나 데드락 문제를 주의해야함.

 

경합상태(Race Condition)

둘 이상의 스레드가 공유 자원에 접근하며 발생하는 문제.

ex. 두 스레드가 같은 변수를 동시에 읽거나 쓰면 예기치 않은 결과가 발생할 수 있음.

 

데드락(DeadLock)

둘 이상의 작업이 서로 상대방의 작업이 끝나기를 기다리며 무한정 대기하는 상황

데드락이 발생하면 둘 이상의 작업이 멈추게 되고, 이후에 다른 작업도 실행할 수 없음.

메인 스레드

UI와 관련된 작업을 수행하는 스레드. (UI업데이트 관련 코드가 실행되어야함.)

메인 스레드에서 UI 업데이트가 이루어지지 않으면 앱이 크래시될 수도 있음.

 

 

예시를 보면 텍스트가 잠시 뒤에 변하는 것을 알 수 있다. -> DispatchQueue 활용

또한 스크롤을 할 때 Rectangle 카운트가 올라가는 것을 볼 수 있는데,

LazyVStack 안에 ForEach를 통해 50개의 RoundedRectangle을 찍어내는 구조이다.

즉 처음부터 50개가 한번에 생성되는 것이 아니라, LazyVStack 안에 있기 때문에 스크롤을 할 때마다 생성되고,

생성될 때마다 .onAppear()가 실행되는 것이다.

//  Created by Toughie on 2023/05/02.
//

import SwiftUI

struct OnAppearDisapper: View {
    
    @State var myText: String = "Start"
    @State var count: Int = 0
    
    var body: some View {
        NavigationView {
            
            ScrollView {
                Text(myText)
                LazyVStack {
                    ForEach(0..<50) { _ in
                        RoundedRectangle(cornerRadius: 25.0)
                            .frame(height: 200)
                            .padding()
                            //onAppear each roundedRectangle
                            .onAppear {
                                count += 1
                            }
                    }
                }
            }
            .onAppear(perform: {
                DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
                    myText = "New Text"
                }
            })
            .onDisappear(perform: {
                myText = "End"
            })
            .navigationTitle("Rectangle : \(count)")
        }
    }
}