RxSwift

[RxSwift] Single

yujaehui 2024. 6. 3. 20:43

1. Single

Single은 Observable의 한 종류로, 오직 하나의 값 또는 에러를 방출하고 완료되는 시퀀스를 처리.

성공적으로 값을 방출할 경우 success 이벤트, 실패할 경우 error 이벤트를 전달하며, 그 이후에는 더 이상 이벤트가 발생하지 않음.

주로 네트워크 요청, 파일 읽기/쓰기와 같은 단일 결과를 반환하는 작업에서 많이 사용.

(이때 작업이 성공하면 하나의 값을 방출하고 완료, 실패하면 에러를 방출하는 구조.)


2. Single의 특징

  1. 하나의 값 또는 에러 방출
    • Single은 성공하면 하나의 값을 방출하고 완료되며, 실패할 경우 에러를 방출.
    • 즉, next 이벤트가 없고, success 또는 error 이벤트만 발생.
  2. 단일 결과에 적합
    • Single은 오직 하나의 값을 방출하고 완료되기 때문에, 단일 결과를 반환하는 비동기 작업에 적합.
    • 예를 들어, 네트워크 요청의 결과나 파일 읽기 작업의 결과를 처리하는 데 유용.
  3. 완료 후 추가 이벤트 없음
    • Single은 성공이나 실패 후 더 이상 이벤트를 방출하지 않음.
    • 즉, 한 번 완료된 후에는 구독이 자동으로 종료.

3. Single의 생성 및 사용

Single은 주로 create 연산자를 통해 직접 생성하거나, Observable을 변환하여 생성 가능.

Single을 사용한 비동기 작업 처리

import RxSwift

let disposeBag = DisposeBag()

// Single 생성
let single = Single<String>.create { single in
    let success = true

    if success {
        // 성공 시, 성공 이벤트 방출
        single(.success("Data loaded successfully"))
    } else {
        // 실패 시, 에러 이벤트 방출
        single(.error(NSError(domain: "TestError", code: -1, userInfo: nil)))
    }

    // 리소스 정리를 위한 Disposable 반환
    return Disposables.create()
}

// Single 구독
single.subscribe { event in
    switch event {
    case .success(let data):
        print("Success with data: \\\\(data)")
    case .error(let error):
        print("Error: \\\\(error)")
    }
}.disposed(by: disposeBag)
Success with data: Data loaded successfully
  • Single을 생성하고, 성공 시 success 이벤트로 데이터를 방출.
  • Single은 한 번의 성공 또는 에러를 방출하고 자동으로 구독을 종료.
  • Disposable을 반환하여 리소스를 정리.

4. Single의 주요 특징 비교

  Single Observable
이벤트 타입 success 또는 error 이벤트 발생 next, error, completed 이벤트 발생
방출 값 하나의 값 또는 에러만 방출 여러 값을 방출할 수 있음
에러 발생 시 에러 발생 시 구독 종료, 더 이상 이벤트 발생하지 않음 에러 발생 시 구독 종료
주요 사용 사례 단일 결과를 반환하는 작업 (네트워크 요청, 파일 읽기 등) 여러 값을 반환하는 시퀀스 작업 (타이머, 스트림 처리 등)

5. Single의 주요 장점

  1. 단일 결과 처리에 최적화
    • 오직 하나의 값 또는 에러를 방출하고 완료되기 때문에, 단일 결과를 처리하는 비동기 작업에 최적화.
  2. 간단한 구조
    • 여러 이벤트를 처리할 필요 없이, 성공 또는 에러 이벤트만 처리하면 되므로 코드가 간결.
  3. 리소스 관리
    • 한 번 완료되면 더 이상 추가적인 이벤트가 발생하지 않으므로, 리소스 관리가 용이.
    • 비동기 작업이 끝나면 자동으로 구독이 종료.

6. Single 선택 가이드

  • 단일 작업의 결과 처리가 필요한 경우
    • Single은 한 번에 하나의 결과를 반환하는 비동기 작업에 적합.
    • 예를 들어, 네트워크 요청이나 파일 읽기 작업의 결과를 처리할 때 사용.
  • 성공/실패 이벤트만 필요할 때
    • 단순히 성공 여부 또는 실패를 처리해야 할 때 Single을 사용하는 것이 좋음.
    • 여러 값을 처리할 필요가 없는 작업에서 효과적.
  • 에러가 발생해도 스트림을 유지할 필요가 없을 때
    • Single은 에러가 발생하면 즉시 구독을 종료.
    • 따라서, 에러가 발생해도 스트림을 유지할 필요가 없는 작업에 적합.

7. Single의 예시 사용

네트워크 요청에서 Single 사용

import RxSwift

func fetchData() -> Single<String> {
    return Single<String>.create { single in
        let success = true

        // 네트워크 요청의 결과를 가정
        if success {
            single(.success("Data fetched from server"))
        } else {
            single(.error(NSError(domain: "NetworkError", code: -1, userInfo: nil)))
        }

        return Disposables.create()
    }
}

let disposeBag = DisposeBag()

fetchData().subscribe { event in
    switch event {
    case .success(let data):
        print("Success with data: \\\\(data)")
    case .error(let error):
        print("Error: \\\\(error)")
    }
}.disposed(by: disposeBag)
  • Single을 사용하여 네트워크 요청의 결과를 처리 → 성공하면 데이터 반환, 실패하면 에러 반환.
  • 구독은 한 번의 성공 또는 에러 후 자동으로 종료.

파일 읽기 작업에서 Single 사용

import RxSwift

func readFile() -> Single<String> {
    return Single<String>.create { single in
        let fileExists = true

        // 파일 읽기 작업의 결과를 가정
        if fileExists {
            single(.success("File content"))
        } else {
            single(.error(NSError(domain: "FileError", code: -1, userInfo: nil)))
        }

        return Disposables.create()
    }
}

let disposeBag = DisposeBag()

readFile().subscribe { event in
    switch event {
    case .success(let content):
        print("File content: \\\\(content)")
    case .error(let error):
        print("Error: \\\\(error)")
    }
}.disposed(by: disposeBag)
  • Single을 사용하여 파일 읽기 작업의 결과를 처리 → 파일이 존재하면 내용 반환, 파일이 없으면 에러 반환

8. 정리

Single은 Observable의 특수한 형태로, 하나의 값 또는 에러를 방출하고 완료되는 비동기 작업에 적합.

  • 네트워크 요청, 파일 읽기와 같은 단일 작업에서 Single을 사용하면 한 번에 하나의 결과를 처리할 수 있음.
  • Single은 success 또는 error 이벤트만을 처리하므로, 간단한 결과 처리를 할 때 적합.
  • 에러가 발생하면 자동으로 스트림이 종료되어, 추가적인 에러 처리 로직을 줄일 수 있음.