Swift TIL (제네릭 , 비동기와 네트워킹 , DispatchQueue )

제네릭

제네릭은 코드의 유연성과 재사용성을 높여주는 도구로서 함수, 메서드, 클래스, 구조체 열거형 등에서 사용할 수 있다.

제네릭을 사용하면 코드의 일부분을 일반화하여 데이터 타입이나 요구사항에 대한 명확한 정의 없이 다양한 종류의 데이터 타입을 처리할 수 있다.

  • 타입 안정성(Type Safety) : 컴파일 시점에 타입 안정성을 보장합니다. 컴파일러는 제네릭 코드를 사용하여 잘못된 데이터 타입이 전달되는 것을 방지하고 실행 시점에서 발생할 수 있는 에러를 사전에 방지할 수 있다.
  • 코드 재사용성(Reusability) : 동일한 로직을 다양한 데이터 타입에 대해 재사용할 수 있다. 제네릭을 사용하면 타입에 의존하지 않는 범용적인 코드를 작성할 수 있다.
  • 유연성과 확장성(Flexibility and Scalability) : 제네릭을 사용하면 다양한 데이터 타입에 대해 일반적인 알고리즘을 작성할 수 있다. 이는 프로그램의 확장성을 향상시키고 새로운 데이터 타입이 추가되더라도 기존 코드를 변경하지 않고 적용할 수 있도록 한다.
  • 추상화(Abstraction) : 제네릭을 사용하면 코드를 더 추상화하여 일반적인 개념을 표현할 수 있다. 이는 코드의 가독성을 향상시키고 의도를 명확하게 전달할 수 있다.
func findIndex<T: Equatable>(of valueToFind: T, in array: [T]) -> Int? {
    for (index, value) in array.enumerated() {
        if value == valueToFind {
            return index
        }
    }
    return nil
}

이 함수는 주어진 배열에서 특정 값을 찾아 해당 값의 인덱스를 반환하는 함수입니다.

제네릭 함수의 형식은 다음과 같습니다.

func functionName<T>(parameters: T) -> ReturnType {
		// 제네릭 로직
}

T 는 제네릭 타입 매개변수로 함수를 호출할 때 실제로 사용될 데이터 타입을 대체하는 역확을 합닌다.

Equatable 은 제네릭 타입 매개변수 T 가 == 연산자를 사용할 수 있도록 요구하는 프로토콜입니다. 따라서 T 가 Equatable 프로토콜을 준수하는 타입이어야만 이 함수를 사용할 수 있습니다.

비동기와 네트워킹

스레드

Swift 에서 스레드는 동시에 실행되는 코드의 실행 흐름을 나타냅니다. 각 스레드는 프로세스 내에서 실행되는 작은 실행 단위로, 프로그램이 동시에 여러 작업을 수행하거나 병렬로 실행해야 할 때 사용됩니다. 스레드를 사용하면 여러 작업을 동시에 수행하거나 작업을 분리하여 효율적으로 실행할 수 있습니다.

  • 메인 스레드(Main Thread) : 대부분의 UI 업데이트 및 사용자 상호 작용은 주로 메인 스레드에서 처리 됩니다. 메인 스레드는 앱의 생명주기와 밀접하게 연관되어 있으며, UI 업데이트는 주로 이 스레드에서 수행됩니다.
  • 백그라운드 스레드(Background Thread) : 긴 작업이나 네트워크 호출과 같은 오래 걸리는 작업은 백그라운드 스레드에서 수행될 수 있습니다. 이렇게 하면 메인 스레드가 차단되거나 UI 의 반응성이 떨어지는 것을 방지할 수 있다.

스레드는 동시성 및 병렬성을 구현하는데 사용될 수 있으며 , Grand Central Dispatch(GCD) 나 Operation Queue와 같은 도구를 사용하여 스레드를 관리하고 제어할 수 있다.

이러한 도구는 병렬 작업을 쉽게 처리할 수 있도록 도와주며, 스레드간 통신과 동기화를 관리합니다.

비동기

동기(Sync)

  • 동기 작업은 순차적으로 진행됩니다. 즉 한 작업이 끝나면 그 다음 작업이 시작됩니다.
  • 작업이 완료될 때 까지 대기하며, 다음 작업은 현재 작업이 완료된 후 시작된다.

비동기(Async)

  • 비동기 작업은 병렬로 또는 독립적으로 실행됩니다. 즉, 한 작업의 완료 여부와 상관없이 다른 작업이 시작됩니다.
  • 작업을 시작하고 완료를 기다리지 않고 계속 진행됩니다.
  • 비동기 작업은 주로 I/O 작업(파일읽기,쓰기,네트워크 호출 등) 이나 장기 실행 작업(긴 계산, 데이터베이스 쿼리 등)에서 사용됩니다.

 

DispatchQueue

Grand Central Dispatch(GCD) 기반의 비동기 작업을 관리하는 클래스

  • 비동기 작업 큐 : Dispatch Queue는 작업을 비동기적으로 실행할 수 있는 큐 입니다. 큐에 추가된 작업은 순차적으로 실행되며, 여러 작업을 동시에 처리할 수 있습니다.
  • 작업 스케쥴링 : Dispatch Queue는 작업을 특정시간 또는 조건에 따라 예약할 수 있습니다. 이를 통해 작업을 효율적으로 관리하고 실행할 수 있다.
  • 작업 실행 제어 : Dispatch Queue를 사용하여 실행 중인 작업을 일시 중지하거나 취소할 수 있다. 또한 작업의 실행 우선순위를 지정하여 중요한 작업에 대한 우선순위를 높일 수 있다.
  • 동기화 : Dispatch Queue는 여러 스레드 간에 데이터를 안전하게 공유할 수 있는 동기화 메커니즘을 제공합니다. 특정 작업이 완료될 때 까지 대기하고 다른 작업을 실행할 수 있습니다.
DispatchQueue.global().async {
    print("비동기 작업")
}       // 백그라운드 스레드에서 비동기 작업 실행

DispatchQueue.main.sync {
    print("동기 작업 실행")
}       // 메인 스레드에서 동기 작업 실행

DispatchQueue.main 은 주로 앱 UI 업데이트와 관련된 작업을 처리하는데 사용된다.

메인 스레드에서 동작하며, 주로 사용자 인터페이스를 업데이트 하거나 사용자와 상호 작용을 처리할 때 사용된다.

DispatchQueue.global() 은 백그라운드 스레드에서 작업을 처리하는데 사용된다.

여러 스레드에서 동시에 실행되는 비동기 작업을 처리할 때 유용하다.