본문 바로가기
스파르타코딩 클럽/사전 캠프

14. 스파르타 코딩클럽 [사전캠프 - 비동기 프로그래밍 / 제네릭]

by UDDT 2025. 2. 20.

기본

 비동기 프로그래밍(Asynchronous Programming)

    - 비동기 프로그래밍 : 작업을 동시에 실행하거나, 완료 여부를 기다리지 않고 다음 작업을 수행할 수 있는 프로그래밍 방식

       * iOS에서는 주로 GCD(Grand Central Dispatch)와 비동기 메서드를 사용

    - 동기 / 비동기

       동기(Synchronous) : 작업이 완료될 때까지 대기

       비동기(Asynchronous) : 작업 완료를 기다리지 않고 바로 다음 작업 실행

 

    - GCD(Grand Central Dispatch)의 주요 큐 :

       Main Queue(모든 UI작업 처리)

       Global Queue(BackGround 작업 처리 - 데이터 처리나 네트워트 요청 같은 시간이 오래 걸리는 작업)

       Custom Queue(사용자 정의 작업 처리 - 큐의 우선순위를 설정하거나 병렬로 처리하고자 할 때)

DispatchQueue.global().async {
    print("비동기 작업 실행")
    DispatchQueue.main.async {
        print("UI 업데이트")
    }
}

 

 제네릭(Generic)

    - 제네릭 : 코드의 유연성과 재사용성을 높이기 위해, 타입에 의존하지 않는 코드를 작성하는 방법

       * 같은 로직을 다양한 타입에서 사용할 수 있도록 함

    - 제네릭 함수 : 하나의 함수로 여러 타입을 처리

func swapValues<T>(_ a: inout T, _ b: inout T) {
    let temp = a
    a = b
    b = temp
}

var x = 10
var y = 20

swapValue(&x, &y)

print(x)  // 20
print(y)  // 10

 

   - 제네릭 타입 : 구조체, 클래스, 열거형에서 제네릭 활용 가능

// 스택에서 제네릭을 활용한 예

struct Stack<T> {
    private var elements: [T] = []
    mutating func push(_ element: T) {
        elements.append(element)
    }
    mutating func pop() -> T? {
        return elements.popLast()
    }
}

 

실습

비동기 데이터 처리하기

DispatchQueue.global()을 사용하여 백그라운드에서 숫자를 1부터 5까지 출력한 후, Main Queue 에서 "UI 업데이트 완료"를
출력하세요.
DispatchQueue.global().async {
    for i in 1 ... 5 {
        print(i)
    }
    DispatchQueue.main.async {
        print("UI 업데이트 완료")
    }
}

 

 비동기 네트워크 시뮬레이션

DispatchQueue를 사용해 다음을 구현하세요.
- 3초간 데이터를 로드하는 작업을 비동기로 수행.
- 작업 완료 후, "데이터 로드 완료" 메시지를 메인 큐에서 출력.
DispatchQueue.global().async {
    for i in 1 ... 3 {
       	sleep(3)
    }
    DispatchQueue.main.async {
        print("데이터 로드 완료")
    }
}

 

 제네릭 함수 작성하기

두 값을 교환하는 제네릭 함수 swapValues<T> 를 작성하세요.
// 매개변수에 inout을 작성해줌으로써 값 변경이 가능해짐

func swapValues<T>(_ a: inout T, _ b: inout T) {
    let temp = a
    a = b
    b = temp
}

var a = 10
var b = 20
swapValues(&a, &b)
print(a, b) 
// 20, 10

 

 제네릭 스택 구현하기

Stack<T> 구조체를 작성하고 다음 기능을 구현하세요:
- push(_:): 스택에 요소 추가.
- pop(): 스택에서 요소 제거.
- 스택의 현재 상태를 출력하는 메서드.
struct Stack<T> {
    var elements: [T] = []

    mutating func push(_ element: T) {
        elements.append(element)
    }

    mutating func pop() -> T? {
        elements.isEmpty ? nil : elements.popLast()
    }
}

var intStack = Stack<Int>()
intStack.push(1)
intStack.push(2)
if let poppedItem = intStack.pop() {
    print(poppedItem) 
}
// 2

 

* 매개변수에서의 inout

     원래 매개변수로 받는 값은 변경할 수 없지만, inout을 포함해주면 값을 변경할 수 있음.

// 원래 함수의 형태
func sayName(_ name: String){
    print("Hello, I'm \(name)")
}
 
sayName("uddt")
// Hello, I'm uddt
 
// 원래 매개변수로 받는 값은 변경할 수 없음 (Cannot assign to value: 'name' is a 'let' constant)
func sayHi(_ name: String){
    name = "new" + name
    print("Hello, I'm \(name)")
}
// 위 코드는 실행 불가
 
// inout을 포함해주면, 값을 변경할 수 있음
func sayHi(_ name: inout String){
    name = "new" + name
    print("Hello, I'm \(name)")
}
 
// sayHi("uddt") 이것처럼 바로 실행해줄 수는 없고, 변수에 값을 담고 넣어줘야함
var name = "uddt"
sayHi(&name)
// Hello, I'm newuddt

 

최근댓글

최근글

skin by © 2024 ttuttak