[Siwft] 디스패치란 무엇일까 ? dispatch

jae·2024년 11월 28일

swift

목록 보기
7/14

디스패치.. 음 그거 비동기 처리 하는 그거 아닌가?
그럼 그냥 스레드 제어 아니면 프로미스 뭐 그런거같은 개념 아닌가?
했으나 나의 착각이였고 내가 생각한 그 디스패치큐같은건 GCD였고 디스패치는 다른 개념이다

디스패치

코드에서 메소드나 함수가 실행되고 호출 될때 이 것이 실행되는 과정들을 말한다

class AA {
func sayHello { print("hello")}
}

class BB : AA {} // AA를 가져오며 AA의 메모리를 참조함
// 만약 여기 오버라이딩해서 sayHello를 다시 쓰면 새로운 메모리 주소를 부여받음


let bb : AA = BB() 
// 여기서의 디스패치 
// 1. BB()의 주소를 찾아서 메모리에 인스턴스를 생성한다
// 2. AA타입의 bb에게 BB()인스턴스를 담는다

bb.sayHello()
// 여기서의 디스패치
// 1. bb는 BB()의 인스턴스가 담기기위해 BB() 저장된 메모리를 찾는다.
// 2. BB()에는 sayHello를 찾는다
// 3. BB의 부모인 AA를 찾는다
// 4. 그안에 sayHello를 실행시킨다

그니깐 여기에 있는 이 코드가 어디서부터 나왔는지 실행경로를 찾는 매커니즘이다

js에서 변수나 상수를 찾아서 올라가는 스코프체인처럼
디스패치는 함수나 클래스, 인스턴스 생성등이 무엇이 어디에서 왔고 얘는 어떻게 왔어 라는 경로를 찾아가는 것이다

다이나믹 그리고 스태틱

다이나믹과 스태틱을 구분하는 제일 쉬운방법은 이 디스패치를 런타임 전에 아느냐 런타임 후에 알게 되느냐 인 것 같다.
두가지 디스패치가 존재하는 이유가 무엇일까?

다이나믹 디스패치 Dynamic Dispatch

스위프트에서 클래스 메서드가 기본적으로 사용하는 디스패치다.

class AA {
    func sayHello() {
        print("Hello from AA")
    }
}

class BB: AA {
    override func sayHello() {
        print("Hello from BB")
    }
}

let bb: AA = BB()
bb.sayHello() // "Hello from BB"
// bb는 AA를 쓰지만 실제 BB()를 참조하는 인스턴스다
// 1. 런타임에서 BB를 찾아 올라간다
// 2. BB의 sayHello를 실행한다

런타임에 호출할 메서드의 대상을 결정
컴파일 타임에는 호출할 메서드가 정해지지 않았으나
런타임에 객체의 실제 코드를 확인한 후 실행할 메서드를 찾는다

다이나믹 디스패치는 다형성을 지원 받기 위해 vtable(Virtual Table)를 사용하는데 객체가 어떤 클래스의 인스턴스인지를 확인하고, 그 클래스에서 정의된 메서드를 호출하도록 한다

vtable(Virtual Table), wtable (Witness Table)

클래스에서 다이나믹 라우트는 vtable(Virtual Table)
프로토콜을 다룬다면 wtable(Witness Table)를 사용하는데

vtable

  • 클래스에서 메서드 호출 시
  • 클래스의 인스턴스 생성 시 생성
  • vtable은 간략히 메서드 테이블로 만약 자식 클래스가 메소드를 오버라이드하면, 자식 클래스의 vtable에는 부모 클래스의 메서드 대신 자식 클래스에서 오버라이드한 메서드 주소가 들어간다.

wtable

  • 프로토콜을 채택한 타입에서 메서드 호출 시
  • 프로토콜 채택 시 동적으로 생성
  • wtable은 구현한 메서드에 대한 정보 프로토콜에 정의된 메서드에 대해 어떤 것이 사용될지를 결정할 때 사용

스태틱 디스패치 Static Dispatch

struct AA {
    func sayHello() {
        print("Hello from AA")
    }
}

let aa = AA()
aa.sayHello() //"Hello from AA"

구조체, 열거형, final키워드의 클래스에서 사용되는 디스패치로
런타임이 아닌 컴파일 단계에서 이미 이 코드에 대해 정해져있다

aa.sayHello()를 호출하지만 그 자리에는
사실은 모든 껍데기?를 다 벗기고 실제로 실행할 print("Hello from AA") 이거 하나만 있는 것이 된다.
즉 메소드의 직접적인 메모리 주소를 가져와 있기에 좀 더 빠르다

final class

final 키우드를 붙인 class는 왜 스태틱 디스패치 인걸까?
클래스는 상속을 받고 상속해주지만 final 키워드를 붙여서 상속을 받지도 않고 상속을 하지 않는다
즉 자식 클래스를 생성하지 않아서 인스턴스가 생기더라도 인스턴스는 그 final class외 다른 클래스를 바라볼 수 없다

그리고 final 키워드로 인해 오버라이딩도 불가능하여 동적으로 디스패치가 동작할 필요가 없다


다형성

  • 다형성은 코드 유연성과 재사용성을 높이기 위해 필요
  • 스위프트에서 다형성은 상속과 프로토콜을 통해 구현
  • 다양한 객체들이 동일한 메서드 호출에 대해 다른 동작

다이나믹 디스패치가 필요한 이유

다이나믹 디스패치가 왜 필요할까?
성능면에서는 이미 다 정적으로 코드가 박혀있을 다이나믹 디스패치보다 스태틱이 더 좋다면 안써도 되지않나? 한다면 당연히 다이나믹만의 장점이 있는데 그건 바로 다형성!

  1. 다양한 타입의 객체들이 각각 다르게 동작하려면 메소드의 호출을 런타임에 결정해야한다
  2. 다형성을 사용하면 동일한 메서드 호출이 객체의 실제 타입에 따라 다르게 동작할 수 있다
  3. 다형성을 실현하기 위한 방식으로 다이나믹 디스패치가 필요하다

다이나믹 디스패치가 없다면 다형성을 다룰수가 없기에
다이나믹 디스패치는 필요하다!!

결론

디스패치란?

디스패치는 메서드 호출의 타겟을 결정하는 과정을 말하며
정적인 스태틱 디스패치는 컴파일 타임에 결정하여 성능을 최적화하고,
동적인 다이나믹 디스패치는 다형성을 가능하게 해서 다양한 방식으로 메서드 호출을 처리한다

0개의 댓글