본문 바로가기
IOS App Programming/Swift

접근제한자 정리 및 성능 향상 이유 + final 제한자

by B_Tori 2024. 2. 23.

프로젝트를 진행할 당시 적절한 접근제한자를  설정하는 것이 성능 향상에 도움이 되니
외부 접근이 없다면 private 처리를 해보자라는 피드백을 받아 코드를 수정했던 경험이 있다.

그래서 접근제한자에 대해 간단히 정리하고 성능에 어떠한 영향을 주는지 정리를 해보았다.

 

접근 제어는 객체지향의 중요 특징 중 하나인 은닉화를 구현하기 위한 핵심기능이다.

파일 간 또는 모듈 간에 접근을 제한할 수 있는 기능이다.

 

접근 제한자는 open, public, internal, fileprivate, private 다섯 가지 존재

 

접근 제한자 정리

  • public - 공개 접근 수준
    어디서든 접근 가능 (자신이 구현된 소스파일, 그 소스파일이 속해있는 모듈, 그 모듈을 가져다 쓰는 모듈 등 모든 곳 가능)
  • open - 개방 접근 수준
    공개 접근 수준과 비슷한 접근 레벨을 가지고 있지만 클래스와 클래스 멤버에서만 사용 가능
    클래스를 모듈 밖에서 상속될 수도 있고, 클래스의 멤버를 모듈 밖에서 재정의 할 수 있도록 할 수 있음
    (그 외의 접근 수준들은 접근은 가능하지만 상속 및 재정의는 클래스가 정의된 모듈 안에서만 가능했음)
    => open으로 명시를 했다는 건 그 클래스를 다른 모듈에서도 부모클래스로 사용하겠다는 목적으로 설계함을 의미함
  • internal - 내부 접근 수준
    접근제한자 default 값 -> 접근 제한자를 명시하지 않으면 자동으로 internal로 취급
    소스파일이 속해있는 모듈 내에서는 어디서든 접근 가능 (단 외부 모듈은 접근 불가)
  • fileprivate - 파일 외부 비공개 접근 수준
    이 요소가 구현된 소스파일 내부에서만 사용할 수 있다.
    즉 같은 파일 내에 다른 타입에서도 사용가능
  • private - 비공개 접근 수준
    그 기능을 정의하고 구현한 범위 (예를 들어 구현한 클래스, 구조체 내)에서만 사용할 수 있다.
    fileprivate과 다르게 같은 소스파일이라도 다른 타입 내에 있으면 사용이 불가능하다.

정리해 보면 (제약 적음) open < public < internal < fileprivate < private (제약 많음)과 같은 은닉 수준을 가지고 있다.

 

그렇다면 왜 성능 향상에 도움이 될까?

프로그램의 성능을 높이기 위해서 Dynamic Dispatch를 줄이면 된다고 한다.

Dispatch는 어떤 메서드를 호출할 것인가를 결정하여 그것을 실행하는 과정으로

Static Dispatch, Dynamic Dispatch로 두 가지 방식이 있다.

 

  • Static Dispatch
    컴파일 시점에 어떤 메서드가 사용될지 명확하게 결정
  • Dynamic Dispatch
    컴파일 시점에는 알아내지 못하고 런타임 시점에 어떤 메소드가 사용될지 결정되는 것

특히 클래스에서 많이 발생되는데 class는 상속 가능성을 가지고 있기 때문이다.

Dynamic Dispatch는 컴파일 시 제대로 결정되지 못하고 런타임 시점에 어디서 실행되는지 건너 건너 찾아가야 한다.

 

ex. class의 메서드를 오버라이딩 한 경우
해당 메서드의 타입은 모두 같기 때문에 컴파일 시점에 어떤 클래스의 메서드인지 알 수 없기 때문에 런타임에 찾아야 함
-> 실제 오버라이딩 여부는 상관없이 오버라이딩 되지 않았어도 컴파일러는 가능성을 염두에 두고 런타임으로 넘기게 된다.

 

여기서 또 알아야 할 점이 vtable이다.

Dynamic Dispatch는 vtable을 통한 간접 호출 방식이다.

이는 함수 포인터들의 배열로 표현되며, 하위 클래스가 메서드를 호출할 때 이 배열을 참조하여 실제 호출할 함수를 결정한다. 

Static Dispatch의 경우 직접 호출하기 때문에 vtable을 사용하는 Dynamic Dispatch이 더 느릴 수밖에 없다.

 

그렇다면 여기서 포인트는 class는 상속 가능성을 가지고 있어 오버라이딩을 염두에 두고 Dynamic Dispatch 방식을 사용한다는 것이다. -> 이 가능성을 제거해 버리면 Static Dispatch를 사용할 수 있다.

 

 

그렇기 때문에 private을 사용하여 외부에서 접근을 못하게 하면 Static Dispatch을 사용하게 되어 성능이 향상된다.

같은 원리로 final 접근제한자도 클래스의 상속을 제한하기 때문에 성능이 향상된다. 

 

 

 

댓글