티스토리 뷰

Swift

[Swift] 접근 제어

희철 2022. 8. 28. 15:44

접근 제어

 

 

 

접근 제어를 사용하면 다른 소스파일들과 모듈들로부터 내 코드로의 접근을 제한할 수 있다.

 

 

또한 접근 제어를 사용하면 코드의 상세 구현을 숨기고 허용된 기능만 사용하는 인터페이스를 제공할 수 있음.

 

 

그렇다면 이 접근 제어를 왜 사용해야할까.

 

 

때로는 전체 코드가 아닌 필요한 부분만 제공해야하는 경우가 있다.

 

 

즉, 외부에서 접근하면 안되는 코드가 있는데 접근을 막지 않는다면 예상과 다른 결과를 얻게 될 수도 있다.

 

 

또한, 8월 27일 TIL에서 적었듯이 클래스같은 Dynamic Dispatch의 경우 컴파일 단계가 아닌 런타임 과정에서 호출되는 메서드들이 결정되므로  확인하는 작업이 많아지면 성능이 저하된다.

 

 

이때,  private과 fileprivate같은 접근 수준 키워드를 이용해 Dynamic Dispatch를 줄여 성능을 향상 시킬 수 있다.

 

 

모듈과 소스파일

 

 

스위프트의 접근 제어는 모듈과 소스파일을 기반으로 설계되었다.

 

 

모듈이란 배포할 코드의 묶음 단위로, import 키워드를 통해 불러올 수 있는 하나의 Framework나 Library 또는 애플리케이션이 될 수 있다.

 

 

소스파일은 모듈 내의 하나의 스위프트 소스 코드 파일이다.

 

 

보통 소스 파일 하나에는 하나의 타비만 정의하는 것이 일반적이지만, 여러 타입이나 함수들이 정의될 수도 있다.

(하나의 파일안에 여러 개의 구조체나 클래스를 정의할 수 있음.)

 

 

 

접근 수준(Access Level)

 

 

스위프트에선 다섯 가지의 접근 수준 키워드를 이용하여 접근 제어를 구현할 수 있다.

 

  • open
  • public
  • internal
  • fileprivate
  • private

 

클래스, 구조체, 열거형같은 타입뿐만아니라 타입 내부의 프로퍼티나 메서드, 이니셜라이저 등에도 접근 수준을 지정할 수 있다.

(싱글턴 패턴을 사용할 때 다른 파일에서 인스턴스를 생성하지 못하도록 이니셜라이즈에 private 키워드를 붙였었음)

 

 

open

 

가장 높은 접근 수준이며, 클래스와 클래스의 멤버에서만 사용할 수 있다.

 

 

 

위 두 가지의 특성을 통해 open수준의 클래스는 다른 모듈에서 상속될 목적으로 작성된 것을 의미한다.

Foundation 프레임워크에 정의된 NSString클래스는 open으로 작성되었다.

 

 

public

 

open보다 한 단계 낮은 수준이며, public으로 지정된 요소는 어디서든 사용될 수 있다.

 

 

public은 주로 프레임워크에서 외부와 연결될 인터페이스를 구현하는데 쓰인다.

 

 

public과 open은 모두 어디서든 사용될 수 있을텐데, 그렇다면 차이점은 무엇일까.

 

 

우선, open 접근 수준의 클래스는 해당 클래스가 정의된 모듈뿐만 아니라 외부의 다른 모듈에서도 상속할 수 있다.

 

-> public으로 작성된 클래스는 다른 모듈에서 상속될 수 없다. 즉, 커스텀 프레임워크를 만들어서 open과 public 두 가지의 클래스를 선언했을 경우, 프레임워크를 import하여도 접근 수준이 open인 클래스만 상속이 가능하다.

 

 

또한, open 클래스의 멤버는 다른 모듈에서 override될 수 있다.

 

-> public수준의 class는 다른 모듈에서 상속될 수 없기 때문에 멤버 또한 override 될 수 없다.

 

 

아래의 코드를 통해 직접 확인해보자.

커스텀 프레임워크를 만들어 내부에 위와 같이 open, public 클래스를 선언해주었다.

 

 

이때, 다른 모듈에서도 인스턴스를 생성할 수 있도록 public init() {}도 작성해주었다.

(다른 모듈에서 사용할 수 있는 접근 수준 키워드는 public과 open인데, open은 클래스에서만 사용가능하므로 public으로 작성)

 

 

만든 프레임워크를 import한 뒤, 인스턴스를 생성해보았다. 인스턴스 생성은 두 클래스 모두 잘 된다. 

하지만 OpenClass와 달리 PublicClass는 다른 모듈에서 사용될 수 없으므로 오류가 뜨는 것을 확인할 수 있다.

 

 

internal

 

우리가 일반적으로 접근 수준 키워드 없이 작성하는 것들은 전부 internal 접근 수준을 갖고 있는 것이다.

(디폴트 값이 internal)

 

 

internal 접근 수준으로 지정된 요소는 소스파일이 속해 있는 모듈 내에서는 어디에서도 쓰일 수 있다.

 

 

지금까지 아무 키워드도 붙이지않았기 때문에 서로 다른 소스파일에서 문제없이 사용할 수 있었던 것이다.

 

 

 

fileprivate

 

fileprivate으로 지정된 요소는 그 요소가 구현된 소스파일 내에서만 사용할 수 있다.

 

 

마찬가지로 코드를 통해 확인해보자.

 

위와 같이 작성한 뒤, 같은 모듈의 다른 소스파일에서 ViewController의 프로퍼티에 접근해보았다.

fileprivate은 선언된 소스파일 내에서만 사용 가능하므로 자동완성도 되지 않을뿐더러 다른 소스파일에서 사용한다면 오류가 발생한다.

 

 

하지만 internal의 경우는 모듈 내의 어떤 파일에서든 사용이 가능한 것을 확인할 수 있다.

 

 

해당 소스파일 외부에서 값이 변경되거나 호출되지 않았으면 할 때 사용하면 될 것 같다.

 

 

 

private

 

 

가장 한정적인 범위의 접근 수준으로, 지정된 요소는 그 기능을 정의하고 구현한 범위 내에서만 사용할 수 있다.

 

 

즉, 같은 소스파일 안이어도 다른 타입이라면 사용할 수 없다.

filePrivate은 같은 소스파일 내에서는 접근할 수 있지만 private은 마찬가지로 자동완성도 안되고 접근 자체가 불가능하다.

 

 

 

참고 사항

 

 

상위 요소의 접근 수준보다 하위 요소가 더 높은 접근 수준을 가질 수 없다.

 

 

private클래스 안에 internal한 프로퍼티를 선언하더라도 ViewController자체가 private이기 때문에 internalValue도 private수준으로 취급된다.

 

만약 ViewController의 클래스가 internal보다 접근 수준이 높은 public을 사용한다면 internalValue는 지정한대로 internal의 접근 수준을 갖게 된다.

 

 

열거형의 접근수준은 case마다 다르게 접근수준을 부여할 수 없다.

 

애초에 case 앞에 작성할 수가 없는 것 같다.

 

위와 같이 작성하면 name과 gender는 열거형 자체의 접근 수준인 private으로 지정이 된다.

 

 

단일 타겟 앱에서는 open과 public이 의미가 없다.

-> 즉, 커스텀 프레임워크를 만들때 open이나 public으로 지정하여 다른 모듈에서 import했을때 접근할 수 있도록 해야한다.

(물론, 프레임워크 내에서도 private등을 이용하여 특정 소스에 대해서는 접근 제한을 지정할 수 있다.)

 

 

Getter와 Setter

 

 

프로퍼티의 get과 set은 자동으로 해당 프로퍼티의 접근 수준을 따라간다.

 

하지만 필요에 따라서는 해당 프로퍼티보다 더 낮은 접근 수준을 정할 수 있다.

 

 

Initializers

 

 

초기자의 접근 수준은 타입의 접근 수준보다 낮거나 같다.

 

커스텀뷰를 만들때 보았던 required init은 반드시 타입의 접근 수준과 같아야한다.

 

싱글턴 패턴을 이용할 때 보았던 private init() {}을 이용하면 다른 소스파일이나 타입에서 인스턴스를 생성할 수 없다.

 

 

Protocol

 

 

프로토콜의 접근 수준과 내부의 요구 사항들은 접근 수준이 동일하다.

 

하지만 마찬가지로 더 낮은 수준의 접근 수준으로는 지정할 수 있다.

 

즉, 접근 수준이 internal인 프로토콜에서 public인 요구사항을 만들 수 없는 것이다.

 

 

Extension

 

 

익스텐션에서 새롭게 추가된 것은 타입의 접근 수준을 따라간다.

 

프로토콜을 따르는 익스텐션에서는 그 타입의 멤버의 접근 수준에 상관없이 접근할 수 있다.

 

즉, 프로토콜과 구조체가 internal로 지정되고 구조체 안에 private 수준의 프로퍼티가 있다고 해보자.

 

구조체의 extension에서 프로토콜을 채택한다면, 프로토콜 내부의 internal메서드에서도 구조체의 private한 프로퍼티에 접근할 수 있다.

sayHi메서드는 프로토콜과 동일하게 internal이지만 private인 value에 접근 가능.


https://docs.swift.org/swift-book/LanguageGuide/AccessControl.html

 

Access Control — The Swift Programming Language (Swift 5.7)

Access Control Access control restricts access to parts of your code from code in other source files and modules. This feature enables you to hide the implementation details of your code, and to specify a preferred interface through which that code can be

docs.swift.org

 

https://zeddios.tistory.com/383?category=685736 

 

Swift ) Access Control(접근 제어) - (1)

안녕하세요 :) Zedd입니다. 오늘은 Access Control..Swift4에서 정말 조그마한 변경사항이 있기도 했고..그래서 전체적으로 볼려고 합니다 :) 오랜만의 Swift네요 XD 모든 내용은 The Swift Programming Languag..

zeddios.tistory.com

 

스위프트 프로그래밍 - 야곰

'Swift' 카테고리의 다른 글

[Swift] ARC에 대해서 알아보자  (0) 2022.10.18
[Swift] Optional(옵셔널)  (0) 2022.07.07
[Swift] 튜플(Tuple)  (0) 2022.06.10
[Swift] 진수 변환(radix)  (0) 2022.06.06
[Swift] 순열과 조합(Permutation / Combination) 구현해보기  (0) 2022.05.10
댓글
최근에 올라온 글
Total
Today
Yesterday