Neoself의 기술 블로그

기초 CS 본문

개발지식 정리/Swift

기초 CS

Neoself 2025. 3. 6. 15:33

객체

데이터나 데이터를 조작하는 동작을 묶어 놓은 소프트웨어 단위. 주로 구조체나 클래스에 사용됨.

 

모듈

코드 배포의 단일 단위. 프레임워크나 애플리케이션은 개별 모듈로 빌드되고 배포되며, Swift의 import 키워드를 사용하여 다른 모듈에서 임포트될 수 있습니다

"Swift 패키지는 Swift 소스 파일과 매니페스트 파일(Package.swift)을 포함하는 디렉토리입니다. 매니페스트 파일은 패키지의 이름과 그 내용을 정의합니다. 패키지는 라이브러리, 실행 파일 및 Swift 코드로 작성된 다른 모듈의 배포 단위로 사용됩니다."

패키지는 하나 이상의 Swift 모듈을 포함할 수 있으며, 각 모듈은 targets에 정의됩니다. 패키지는 모듈보다 상위 개념으로, 모듈들을 그룹화하고 관리하는 메커니즘을 제공합니다.

 

모듈과 타겟의 관계

Swift Package Manager 문서에 따르면:

"타겟(target)은 빌드할 제품을 정의하며, 자체 소스 파일과 이 소스 파일을 컴파일하는 방법을 위한 설정이 포함되어 있습니다. 패키지에는 여러 타겟이 포함될 수 있으며, 하나의 타겟이 다른 타겟에 의존할 수 있습니다."

 

일반적으로 하나의 타겟은 하나의 모듈을 생성합니다. 타겟은 모듈의 구현 단위라고 볼 수 있습니다.

 

typealias

기존 타입에 새로운 이름을 부여하는 기능. 이를 통해 코드의 가독성을 높이고, 복잡한 타입을 간결하게 표현할 수 있음

 

@discardableResult

Swift에서 함수나 메서드의 반환 값을 무시할 수 있도록 허용하는 속성(attribute)

기본적으로 Swift는 함수나 메서드의 반환 값을 사용하지 않을 경우 컴파일러 경고를 발생시킴.@discardableResult를 사용하면 이러한 경고를 무시하고 반환 값을 사용하지 않아도 되도록 할 수 있음.

@discardableResult
func appendElement(_ element: Int, to array: inout [Int]) -> Int {
    array.append(element)
    return element
}

var numbers = [1, 2, 3]
appendElement(4, to: &numbers) // 반환 값을 사용하지 않아도 경고 없음
let newElement = appendElement(5, to: &numbers) // 반환 값을 사용할 수도 있음

 

Kingfisher에서 URLSessionDataTask를 래핑하고 있는 SessionDataTask 내부 코드를 보면 이미지 다운로드 간에 발생하는 이벤트들에 대한 콜백들을 일괄 제거하는 메서드에 @discardableReult 속성이 적용되어있습니다.

/// 모든 콜백을 제거하고 제거된 콜백 목록을 반환합니다.
@discardableResult
func removeAllCallbacks() -> [TaskCallback] {
    lock.lock()
    defer { lock.unlock() }
    let callbacks = callbacksStore.values // 모든 콜백을 가져옴
    callbacksStore.removeAll() // 딕셔너리 비우기
    return Array(callbacks) // 제거된 콜백 목록 반환
}

 

이로 인해, URLSessionDataDelegate 이벤트를 처리하는 SessionDelegate 클래스에서 콜백을 제거하는 remove 메서드에서 이를 사용할 때에는, 반환값 핸들링 없이 호출만 하고있는 것에 반해, onCompleted 메서드에서는 반환값을 callbacks 변수에 저장하여 활용하는 것을 볼 수 있습니다.

private func remove(_ task: SessionDataTask) {
    ...
    task.removeAllCallbacks() // 반환값없이 단순 호출
    tasks[url] = nil
}

private func onCompleted(task: URLSessionTask, result: Result<(Data, URLResponse?), KingfisherError>) {
    ...
    let callbacks = sessionTask.removeAllCallbacks() // 반환값 callbacks에 저장
    sessionTask.onTaskDone.call((result, callbacks)) 

}