iOS/Swift

[Swift] 접근 제어자 (Access Control)

kimsangjunzzang 2025. 1. 12. 16:22
728x90
반응형

접근 제어자란..?

코드를 작성하는 한 파일에서 다른 파일에 있는 코드에 대한 접근을 명시적으로 작성하여 이를 관리하는 것입니다.

이를 이용해 우리는 modulesource file에 따라 다른 접근을 할 수 있게 됩니다.

Module

하나의 프레임워크를 의미하여 코드 상에서 import 키워드로 추가되는 것들이 바로 module이다. 대표적으로 UIKit, Foundation 등이 module에 해당하며, 프로젝트 하위에 있는 각각의 target들도 하나의 module에 속합니다.

Source File

각 module 안에 있는 파일들을 말한다. 예를 들어, viewContoller.swift 같은 파일들이 하나의 source file에 해당됩니다.

Swift의 5가지 접근 제어자

특정 접근 제어자가 적용되는 대상을 entity라 하며, entity는 접근 제어자를 작성할 수 있는 class, struct, 프로퍼티, 메소드 등의 집합을 의미합니다.

open, public 프로젝트 내 모든 module에서 해당 entity에 접근 가능
internal default로 설정되는 접근 제어자. entity가 작성된 module에서만 접근 가능
fileprivate entity가 작성된 source file에서만 접근 가능
예를 들어, 서로 다른 클래스가 같은 파일에 있고 fileprivate로 선언되어 있다면 두 클래스는 서로 접근할 수 있다.  
private 특정 객체에서만 사용할 수 있도록 제한하는 가장 제한적인 접근 제어자
서로 다른 두 클래스가 같은 파일 내에 있더라도 private으로 선언되어 있다면 둘은 서로 접근할 수 없다.  

open과 public의 차이

open은 다른 모듈에서 subClass가 가능하지만, public은 그렇지 않습니다.

 

open은 클래스에만 사용될 수 있으며, 한 모듈에서 만든 클래스를 superClass로 하는 subClass를 다른 모듈에서 만들기 위해서는 해당 superClass가 open으로 선언되어야 한다. 당연히 overriding도 이 규칙이 적용됩니다.

접근 제어자 관련 규칙

  • 접근 제어자의 디폴트 값은 internal
  • 상위 entity보다 더 제한적인 접근 제어자를 갖는 entity는 정의할 수 없다.

예시를 들어보겠습니다.

private struct Car {
		public var engine: String    // error
}

보면 Car는 private, 그 안의 engine은 public으로 정의되어 있는데, 이러한 접근 제어자 형태는 사용할 수 없습니다.

 

접근 제어자는 특정 entity로부터의 상대적인 기준이 적용되는 것이 아니라 전체 프로젝트를 기준으로 적용되기 때문입니다.

따라서 특정 entity 안의 변수나 메소드들은 해당 entity의 접근 제어자보다 강하게만 적용될 수 있고 더 약하게 적용될 수는 없습니다.

유용한 기타 사항

Unit Test에서는 @testable 키워드로 모듈을 import하여 public과 open이 아닌 entity도 사용할 수 있습니다.

@testable import [module_name]

 

특정 Unit Test 파일의 상단에 위와 같이 선언해주면, 해당 모듈의 entity를 internal 형태로 사용할 수 있게 된다.

Getter와 Setter에서 서로 다른 접근 제어자를 적용할 수 있습니다.

Swift에서는 setter를 getter보다 더 제한적으로 설정할 수 있습니다. (그 반대는 불가능)

private(set) var name: String

 

예를 들어 위와 같이 적용할 경우, getter는 internal이 되고 setter는 private이 됩니다.

 

protocol에서 선언된 변수의 접근제어자는 조건을 만족한 경우에만 사용할 수 있다. 여러가지 예시 중 private(set)과 관련된 예시를 살펴봅시다.

protocol Car {
		//
}
struct CarModel: Car {
		private(set) var engine: String
}

위 예시에서 Car protocol의 빈 영역에 어떤 접근제어자가 들어가야 할까요?

→ private(set)은 외부에서 settable 하지 않기 때문에 프로토콜에는 gettable만 들어가게 된다.

protocol Car {
		var engine: String { get }
}
struct CarModel: Car {
		private(set) var engine: String
}

이 외 예시는 https://stackoverflow.com/questions/30573872/swift-protocol-get-only-settable/38281420#38281420를 참고하면 좋을거 같습니다.

 

Swift Protocol get only settable?

why can I do this without any error: var testDto = ModelDto(modelId: 1) testDto.objectId = 2 while I define this: protocol DataTransferObject { var objectType: DtoType { get } var

stackoverflow.com

 

출처

Swift 접근 제어자(Access Control)

 

Swift 접근 제어자(Access Control)

Swift의 접근제어자에 대해 간단히 정리했습니다.

hcn1519.github.io

 


오늘도 화이팅입니다!

728x90
반응형