[swift] 동적 디스패치와 정적 디스패치

소프트웨어 개발에서 디스패치(dispatch)는 프로그램이 메서드나 함수를 호출할 때 해당하는 코드를 실행하는 프로세스를 의미합니다. 이 디스패치에는 정적 디스패치(static dispatch)동적 디스패치(dynamic dispatch)가 있습니다. 여기에서는 이 둘의 차이와 각각의 장단점에 대해 살펴보겠습니다.

정적 디스패치(static dispatch)

정적 디스패치는 컴파일 타임에 메서드 또는 함수의 호출 타겟을 이미 알고 있는 방식입니다. 컴파일러는 호출되는 메서드 또는 함수가 어떤 것인지 정확히 파악하고, 이에 맞게 해당 코드를 직접 연결합니다. 이는 컴파일러가 호출되는 메서드 또는 함수의 시그니처와 일치하는 것을 찾아서 코드를 최적화하는 데 도움이 됩니다.

예를 들어, 다음과 같이 Swift 언어에서 정적 디스패치를 사용하는 코드를 살펴봅시다.

class Shape {
    func draw() {
        print("Shape를 그립니다.")
    }
}

class Circle: Shape {
    override func draw() {
        print("원을 그립니다.")
    }
}

let shape: Shape = Circle()
shape.draw()

위 코드에서 shape 변수에 Circle 인스턴스를 할당했습니다. 이때 shape.draw()를 호출하면 컴파일러가 정적 디스패치를 사용하여 Circle 클래스의 draw 메서드를 호출합니다.

정적 디스패치는 런타임에 추가적인 타입 체크나 다형성 검사를 할 필요가 없으므로 실행 속도가 빠릅니다. 하지만 정적 디스패치는 상속과 다형성을 지원하기 어렵다는 단점이 있습니다.

동적 디스패치(dynamic dispatch)

동적 디스패치는 런타임에 메서드 또는 함수의 호출 타겟을 결정하는 방식입니다. 이때 컴파일러는 호출 시점에 메서드 또는 함수가 속한 객체의 타입을 확인하고, 이에 따라 적절한 코드를 실행합니다. 이 과정에서 객체의 실제 타입이 고려되므로 다형성(polymorphism)을 지원합니다.

다음은 Swift 언어에서 동적 디스패치를 사용하는 예시입니다.

class Shape {
    func draw() {
        print("Shape를 그립니다.")
    }
}

class Circle: Shape {
    override func draw() {
        print("원을 그립니다.")
    }
}

let shape: Shape = Circle()
shape.draw()

위 코드는 정적 디스패치와 동일하지만, 여기서 draw 메서드의 호출은 변수 shape의 실제 타입에 따라 런타임에 동적으로 처리됩니다.

동적 디스패치는 상속과 다형성을 지원하는 반면, 런타임에 추가적인 타입 체크와 다형성 검사 등이 필요하므로 실행 속도가 상대적으로 느릴 수 있습니다.

결론

정적 디스패치와 동적 디스패치는 각각 컴파일 타임과 런타임에서의 메서드 또는 함수의 호출 방식을 나타냅니다. 두 방식 모두 장단점을 갖고 있으며, 개발 환경과 요구사항에 맞게 적절히 선택하는 것이 중요합니다.

이러한 디스패치 방식에 대한 이해는 프로그래밍 언어와 프레임워크의 동작 원리를 이해하고, 효율적인 코드를 작성하는 데 도움이 될 것입니다.

참고 자료: https://swiftdoc.org/guides/dispatch/