iOS/Common

[Swift] final 왜 막 갖다 붙이나요? (feat. vtable, dynamic dispatch)

TDCIAN 2022. 6. 6. 13:28

머릿속에 음원 자동재생 될 시 한일월드컵 때 뛰어다닐 수 있었던 사람임

 

 

우리가 코드를 짜다 보면 이렇게 final 키워드를 붙여서 쓰는 경우가 있잖아요?(반박할 시 코 쓱 닦음)

다른 사람들이 쓰니까 일단 따라 쓰긴 하는데, 이거 왜 쓰는 걸까요?

 

 

Swift의 LANGUAGE GUIDE 중 Inheritance 항목의 내용을 보시면 final에 대한 설명이 나옵니다.

링크 걸어놨습니다! 클릭하면 넘어갑니다!

(발 번역 주의)

 

“여러분은 final 키워드를 메소드나 프로퍼티, 또는 서브스크립트 앞에 사용함으로써 오버라이드 되는 것을 막을 수 있습니다.

(예시: final var, final func, final class, final subscript).

final을 써놓고 오버라이드를 하려고 하면 컴파일 에러가 발생합니다.

extension을 사용하는 경우에도 final 키워드를 사용할 수 있습니다. (이하 생략)”

 

 

그럼 이제 이런 생각이 들겠죠?

‘final 붙일 수 있는 건 알겠는데 그래서 왜 쓰냐고’

 

 

다음은 애플 깃허브에 있는 Optimization 팁들 중 final 사용이 성능을 개선시켜준다는 내용입니다.

 

자 봅시다

‘오버라이드 될 필요가 없는 경우에는 final 키워드를 사용해라’ 라고 나와있죠?

 

링크 걸어놨습니다! 클릭하면 넘어갑니다!

 

근데 사실 이 내용만 보면 아까 위에 내용과 다를 게 없죠.

그 위를 봅시다.

 

Swift에서 class는 기본적으로 메소드와 프로퍼티의 디스패치 방식으로 다이나믹 디스패치를 사용하게끔 되어 있다는데,

정작 다이나믹 디스패치를 줄이라고 하네요.

 

코드 아래에는 다음 내용이 있습니다.

‘Swift에서 다이나믹 디스패치는 기본적으로 vtable을 통한 간접 호출 방식입니다.(중략) 두 경우 모두 컴파일러의 최적화에 방해가 되기 때문에 직접 호출에 비해 느립니다. 뿐만 아니라 간접 호출 방식 자체에서 오버헤드가 발생합니다. 퍼포먼스에 민감한 코드를 작성해야 한다면 dynamic 활용을 엄격히 할 필요가 있습니다.’

 

 

우선 vtable이 무엇인지 알아볼까요?

vtable은 동적 디스패치를 지원하기 위해 사용되는 메커니즘이라고 하는군요.

 

‘이 포인터들은 실행 기간 도중에 정확한 함수를 가리키게 되는데, 왜냐하면 컴파일 타임에는 베이스 함수가 호출될 것인지 또는 베이스 클래스를 상속한 클래스에 의해서 구현될 지 알려져 있지 않기 때문이다.’

라는 설명이 우리가 알아야 할 부분이 되겠습니다.

 

그렇다면 이번에는 다이나믹 디스패치가 무엇인지 알아봅시다.

 

 

‘디스패치는 어떤 메소드를 호출할 것인가를 결정하여 그것을 실행하는 과정이다. 동적 디스패치와 정적 디스패치가 있는데, 동적 디스패치(dynamic dispatch)는 메소드 오버라이딩이 되어있는 경우 실행 시점에 어떤 메서드를 실행할지 결정되는 것이다. 정적 디스패치는 그와 다르게 컴파일 시점에 어떤 메서드를 실행할지 결정된다.

 

정말 날 것의 비유이지만, 이렇게 생각해봅시다.

 

여러분의 팀에서 회식이 있고, 여러분들이 회식 장소와 메뉴를 선정하는 일을 맡게 되었다고 가정해 봅시다.

 

여러분들이 어느 식당에 예약을 걸었다고 생각할 때,

시간에 대해서만 예약을 거는 경우와, 시간과 더불어 메뉴까지 예약을 한다면 어느 쪽이 더 빠르게 회식을 더 빠르게 시작할 수 있을까요? (메뉴 나오기 전에 미리 술부터 마시면 된다고 할 경우 코 쓱 닦음)

 

아까 Swift의 class는 기본적으로 dynamic dispatch를 사용한다고 했지요?

또 아까 오버라이드 될 일이 없는 경우에는 final 키워드를 써 주라고 했지요?

 

다시 식당 예약 상황으로 넘어가 봅시다.

어느 식당에 몇 시까지 갈 지 까지만 예약하는 경우(메뉴는 식당 와서 메뉴판 보고 정하는 경우)가 dynamic dispatch라고 할 수 있고, 아예 메뉴까지 정해서 예약을 하는 경우가 정적 디스패치(static dispatch)가 된다고 할 수 있겠습니다.

 

여러분이 식당 주인이라고 한다면, 어느 쪽이 더 빠르게 손님을 위한 테이블 세팅과 음식을 준비할 수 있을지 감이 오시죠? 

 

그러니까 앞으로 오버라이드 될 일이 없는 클래스 앞에는 꼭 final을 붙여줍시다!