Swift - 25. 접근 제어 Access Control

지우개·2022년 4월 28일
0

Swift study

목록 보기
14/15
post-thumbnail

접근 제어 Access Control

접근 제어란?

  • 다른 소스 파일과 모듈에서 코드의 부분에 대한 접근을 제한하는 것.
  • 코드 구현 세부를 숨기고 해당 코드에 접근하고 사용될 수 있는 기본 인터페이스를 지정할 수 있음.
  • 특정 접근 수준을 개별 타입(클래스, 구조체, 열거형), 해당 타입에 속하는 프로퍼티, 메소드, 초기화 구문, 서브 스크립트에 할당 가능. 특정 컨텍스트로 제한될 수 있음.

프로퍼티, 타입, 함수 등에 접근 제어를 적용할 수 있는 코드의 다양한 부분은 이후부터 “엔티티” 라고 부름


모듈과 소스 파일 Modules and Source Files

  • 모듈?
    • 단일 단위로 빌드되고 제공되는 프레임워크 또는 애플리케이션과 같은 코드 배포의 단일 단위
    • Swift의 import 키워드를 사용해 다른 모듈에서 가져올 수 있음
    • Xcode에서 각 빌드 타켓은 Swift에서 별도의 모듈로 처리됨.
  • 소스 파일?
    • 모듈 내에서 단일 Swift 소스 코드 파일 (실제 앱 또는 프레임워크 내의 단일 파일)

접근 수준 Access Levels

5가지 다른 접근 수준 제공

  • Open 접근과 Public 접근 : 정의한 모듈의 모든 소스 파일과 정의한 모듈을 가져오는 다른 모듈의 소스 파일에서 엔티티를 사용할 수 있음.
    • 일반적으로 프레임워크를 공개 인터페이스로 지정할 때 사용.
    • Open 접근은 클래스와 클래스 멤버에만 적용되고 모듈 외부의 코드를 하위 클래스와 재정의할 수 있다.
  • Internal 접근은 정의한 모듈의 모든 소스 파일 내에서 사용할 수 있지만 해당 모듈 외부 소스 파일에서는 사용할 수 없음.
    • 일반적으로 앱 또는 프레임워크의 내부 구조체를 정의할 때 사용.
  • File-private 접근은 자체 정의한 소스 파일로 제한한다.
    • 세부 내용은 파일 전체에서 사용되고 기능의 특정 부분의 구현 세부정보를 가리기 위해 사용.
  • Private 접근은 둘러싸인 선언과 같은 파일에 있는 해당 선언의 확장으로 제한한다.
    • 세부 내용은 단일 선언 내에서만 사용되고 기능의 특정 부분의 구현 세부정보를 가리기 위해 사용.

접근 수준의 기본 원칙 Guiding Principle of Access Levels

  • public 변수는 internal, file-private, private 타입으로 정의될 수 없다.
  • 함수는 파라미터 타입과 반환 타입보다 더 높은 접근 수준을 가질 수 없다. (주변 코드에서 구성 타입을 사용할 수 없는 상황에서 함수를 사용할 수 있기 때문에 )

기본 접근 수준 Default Access Levels

코드의 모든 엔티티는 명시적으로 접근 수준을 지정하지 않으면 Internal의 기본 접근 수준을 가진다.

단일 타겟 앱에 대한 접근 수준 Access Levels for Single-Target Apps

간단한 단일 타겟 앱의 코드는 일반적으로 앱 내에 자체적으로 포함됨. 앱의 모듈 외부에서 사용할 수 있도록 만들 필요 없음. 그러나 앱의 모듈 내에서 (다른 코드에서 구현 세부정보를 가리기 위해) file-private, private로 코드의 부분을 표기할 수 있음

프레임워크에 대한 접근 수준 Access Levels for Frameworks

프레임워크를 개발할 때 다른 모듈에서 보고 접근할 수 있게 하게 위해 공용 인터페이스를 open, public으로 표시함. 프레임워크 용 애플리케이션 프로그래밍 인터페이스 또는 API.

유닛 테스트 타겟에 대한 접근 수준 Access Levels for Unit Test Targets

유닛 테스트 타겟과 함께 앱을 작성할 때 앱의 코드는 테스트를 위해 해당 모듈에서 사용할 수 있어야 함.

기본적으로 open, public 엔티티만 다른 모듈에서 접근할 수 있음. 그러나 모듈에 대한 가져오기 선언을 @testable 속성으로 표시하고 테스트를 활성화하여 컴파일하면 유닛 테스트 타겟은 모든 내부 엔티티에 접근할 수 있음.


접근 제어 구문 Access Control Syntax

public class SomePublicClass {}
internal class SomeInternalClass {}
fileprivate class SomeFilePrivateClass {}
private class SomePrivateClass {}

public var somePublicVariable = 0
internal let someInternalConstant = 0
fileprivate func someFilePrivateFunction() {}
private func somePrivateFunction() {}

// 따로 지정하지 않으면 기본은 internal
class SomeInternalClass {}              // implicitly internal
let someInternalConstant = 0            // implicitly internal

사용자 정의 타입 Custom Types

  • 타입을 정의할 때 접근 수준을 명시적으로 지정
  • 해당 타입의 멤버(프로퍼티, 메소드, 초기화 구문, 서브 스크립트)의 기본 접근 수준에도 영향

‼️ Public 타입은 기본적으로 internal 멤버를 가짐!
public으로 하려면 명시적으로 표시해야 함

public class SomePublicClass {                  // explicitly public class
    public var somePublicProperty = 0            // explicitly public class member
    var someInternalProperty = 0                 // implicitly internal class member
    fileprivate func someFilePrivateMethod() {}  // explicitly file-private class member
    private func somePrivateMethod() {}          // explicitly private class member
}

class SomeInternalClass {                       // implicitly internal class
    var someInternalProperty = 0                 // implicitly internal class member
    fileprivate func someFilePrivateMethod() {}  // explicitly file-private class member
    private func somePrivateMethod() {}          // explicitly private class member
}

fileprivate class SomeFilePrivateClass {        // explicitly file-private class
    func someFilePrivateMethod() {}              // implicitly file-private class member
    private func somePrivateMethod() {}          // explicitly private class member
}

private class SomePrivateClass {                // explicitly private class
    func somePrivateMethod() {}                  // implicitly private class member
}

튜플 타입 Tuple Types

튜플 타입에 대한 접근 수준은 해당 튜플에서 사용되는 모든 타입 중 가장 제한적인 접근 수준을 따라감.

함수 타입 Function Types

함수 타입에 대한 접근 수준은 함수의 파라미터 타입과 반환 타입 중 가장 제한적인 접근 수준을 따라감.

열거형 타입 Enumeration Types

열거형의 개별 케이스는 열거형과 같은 접근 수준을 받음. 개별 열거형 케이스에 대해 다른 접근 수준을 지정할 수 없음.

열거형 정의의 모든 원시값 또는 연관된 값에 사용되는 타입은 열거형의 접근 수준보다 높은 접근 수준을 가져야 함.

중첩된 타입 Nested Types

중첩된 타입의 접근 수준은 포함한 타입이 public이 아닌 경우 포함한 타입과 동일함.

public 타입 내에 정의된 중첩된 타입은 자동으로 internal 접근 수준을 가짐.


서브 클래싱 Subclassing

현재 접근 컨텍스트에서 접근할 수 있고 하위 클래스와 동일한 모듈에 정의된 모든 클래스를 하위 클래스로 지정할 수 있음. 다른 모듈에 정의된 모든 open 클래스도 하위 클래스로 지정할 수 있음.

  • 하위 클래스는 상위 클래스의 접근 수준보다 높은 접근 수준을 가질 수 없음.
    • 예) internal 상위 클래스에 public 하위 클래스를 작성할 수 없음.
  • 재정의override는 상속된 클래스 멤버를 상위 클래스 버전보다 더 쉽게 접근하도록 할 수 있음.
    public class A {
        fileprivate func someMethod() {}
    }
    
    internal class B: A {
        override internal func someMethod() {}
    }
  • 하위 클래스 멤버보다 더 낮은 접근 권한을 가진 상위 클래스 멤버 호출도 가능 (상위 클래스의 멤버 호출이 허용된 접근 수준 컨텍스트 내에서 발생할 경우에만)
    public class A {
        fileprivate func someMethod() {}
    }
    
    internal class B: A {
        override internal func someMethod() {
            super.someMethod()
        }
    }

상수, 변수, 프로퍼티, 서브 스크립트 Constants, Variables, Properties, and Subscripts

  • 상수, 변수, 프로퍼티는 타입보다 더 공개할 수 없다.
  • 서브 스크립트는 인덱스 타입 또는 반환 타입보다 더 공개할 수 없다.

Getter와 Setter

  • 상수, 변수, 프로퍼티, 서브 스크립트에 대한 getter와 setter는 자동으로 속해있는 상수, 변수, 프로퍼티, 서브 스크립트와 같은 접근 수준을 받는다.
  • 해당 부분에 읽기-쓰기 범위를 제한하기 위해 getter보다 더 낮은 접근 수준으로 setter를 제공할 수 있음.
    • var 또는 subscript 전에 fileprivate(set)private(set), 또는 internal(set) 을 작성하여 더 낮은 접근 수준을 할당

초기화 구문 Initializers

  • 사용자 정의 초기화 구문은 초기화 하는 타입보다 더 낮거나 같은 접근 수준을 할당할 수 있음
  • 필수 초기화 구문은 예외로, 자신이 속한 클래스와 동일한 접근 수준을 가져야 함.
  • 초기화 구문의 파라미터 타입은 초기화 구문의 자체 접근 수준보다 더 비공개일 수 없음.

기본 초기화 구문 Default Initializers

  • 타입이 public으로 정의되지 않는 한 초기화하는 타입과 같은 접근 수준을 가진다.
  • public으로 정의된 타입 → internal로 간주함

구조체 타입에 대한 기본 멤버별 초기화 구문 Default Memberwise Initializers for Structure Types

  • 구조체의 모든 저장된 프로퍼티가 같은 접근 수준을 가지면 구조체 타입의 기본 멤버별 초기화 구문은 그 접근 수준을 가진다. 아닐 경우 internal의 접근 수준을 가짐.

프로토콜 Protocols

  • 프로토콜을 정의할 때 접근 수준 할당 → 특정 접근 컨텍스트 내에서만 채택될 수 있는 프로토콜 생성

프로토콜 상속 Protocol Inheritance

기존 프로토콜에서 상속하는 새로운 프로토콜을 정의한다면 새로운 프로토콜은 상속된 프로토콜과 최대 동일한 접근 수준을 가질 수 있다.

프로토콜 준수 Protocol Conformance

  • 타입은 타입 자체보다 더 낮은 접근 수준으로 프로토콜을 준수할 수 있음.
  • 타입이 특정 프로토콜을 준수하는 컨텍스트는 타입의 접근 수준과 프로토콜의 접근 수준의 최소이다.
    • 타입이 public이지만 준수하는 프로토콜이 internal인 경우 프로토콜에 대한 타입의 준수성도 internal이다.
  • 프로토콜을 준수하기 위해 타입을 작성하거나 확장할 때 각 프로토콜 요구사항의 타입의 구현이 해당 프로토콜에 대한 타입의 준수성과 최소한 같은 접근 수준을 갖고 있는지 확인해야 함
    • public 타입이 internal 프로토콜을 준수하는 경우, 각 프로토콜 요구사항의 타입의 구현은 적어도 internal이어야 함

확장 Extensions

  • 확장에 추가된 모든 타입 멤버는 확장된 기존 타입에 선언된 타입 멤버와 같은 기본 접근 수준을 가짐.
  • 확장 내에서 정의된 개별 멤버에 대해 새로운 기본 접근 수준 설정 → 명시적으로 접근 수준 수식어를 확장에 표기

확장에서 Private 멤버

확장 안에 코드가 기존 타입의 선언의 부분으로 작성된 것처럼 동작

  • 기존 선언에서 private 멤버를 선언하고 같은 파일의 확장에서 해당 멤버를 접근
  • 한 확장에서 private 멤버를 선언하고 같은 파일의 다른 확장에서 해당 멤버를 접근
  • 확장에서 private 멤버를 선언하고 같은 파일의 기존 선언에서 해당 멤버를 접근

제너릭 Generics

제너릭 타입 또는 함수 자체의 접근 수준과 해당 타입 파라미터에 대한 모든 타입 제약조건의 접근 수준의 최소


타입 별칭 Type Aliases

타입 별칭은 별칭이 지정된 타입의 접근 수준보다 작거나 같은 접근 수준을 가질 수 있음

0개의 댓글