
객체지향 프로그래밍인 Swift에서 '은닉화'는 중요한 개념이다. 이를 구현하기 위한 핵심 기능인 접근제어에 대해 알아보려고 한다.
접근제어
접근제어 Access Contorl 이란 코드끼리 상호작용을 할 때 파일/모듈 간 접근을 제한할 수 있는 기능이다. 이를 통해 코드의 상세 구현은 숨기고 허용된 기능만을 사용하는 인터페이스를 제공할 수 있다.
OOP (Object Oriented Programming)추상화 - 공통의 속성이나 기능을 묶어 이름을 붙이는 것. 다른 객체들과 구분되는 핵심적인 특징들에만 집중해 복잡도를 관리할 수 있도록 함.캡슐화 - 객체의 속성과 행위(메서드)를 하나로 묶고, 실제 구현 내용 일부를 외부에 감추어 은닉. 중요한 데이터를 보존, 보호하고 연관 있는 변수와 함수를 클래스로 묶는 작업을 함.은닉화 - 객체에서 속성을 직접 접근하지 못하게 숨기는 것. 변수에 접근 지정자를 private로 지정. setter, getter를 사용해 변수의 접근을 제어함.
객체지향 프로그래밍 패러다임에서의 중요한 캡슐화와 은닉화를 구현하는 이유는 외부에서 직접 접근하거나 보이면 안 되는 코드가 있기 때문이다. 꼭 필요한 부분의 코드가 아닌 전체 코드가 노출될 가능성이 있을 때 접근제어를 사용한다.
모듈과 소스파일
Swift의 접근제어는 모듈 Module과 소스파일을 기반으로 설계되어있다.
모듈은 배포할 코드의 묶음 단위이다. 프레임워크나 라이브러리 또는 애플리케이션이 이 모듈 단위가 될 수 있다. import 키워드를 사용하여 불러온다.
소스파일은 하나의 Swift 소스 코드 파일을 의미한다. Swift에서도 보통 파일 하나에 하나의 타입만 정의하지만, 소스 파일 하나에 여러 타입(여러 개의 클래스, 구조체, 열거형 등)이나 함수 등 많은 것을 정의/구현 가능하다.
접근수준
접근제어는 접근수준 키워드를 통해 구현이 가능하다. 클래스, 구조체, 열거형등에 특정 접근수준을 지정할 수 있으며, 메서드, 이니셜 라이저, 서브 스크립트, 프로퍼티 각각에 접근수준을 지정할 수 있다.
접근수준(Access Level) 종류
| 접근수준 | 키워드 | 접근도 | 범위 | 비고 |
| 개방 접근수준 | open | 높음 ⬍ 낮음 |
모듈 외부까지 | 클래스에서만 사용 가능 |
| 공개 접근수준 | public | |||
| 내부 접근수준 | internal | 모듈 내부 | ||
| 파일외부비공개 접근수준 | filePrivate | |||
| 비공개 접근수준 | private | 기능 정의 내부 |
공개 접근수준 - public
public키워드로 지정된 요소는 어디에서든 사용 가능- 소스 파일/소스에 속해 있는 모듈, 그 모듈을 가져다 쓰는 모듈 등 모든 곳에서 사용 가능
- 주로 프레임워크에서 외부와 연결될 인터페이스를 구현하는데 많이 쓰임
- Swift 기본 요소는 보통
public접근수준으로 구현되어있음
//인스턴스가 true 또는 false인 값 타입.
public struct Bool {
// 기본 이니셜라이저 불리언 값을 false로 초기화
print init()
}
개방 접근수준 - open
- 공개 접근수준 이상으로 높은 접근수준
- 클래스와 클래스 멤버에서만 사용 가능
- 공개 접근수준과 비슷하지만 차이점이 존재함
공개 접근수준과 개방 접근수준의 차이점
public접근수준을 제외한 다른 모든 접근수준의 클래스는 그 클래스가 정의된 모듈 안에서만 상속 가능open접근수준의 클래스는 그 클래스가 정의된 모듈 밖에서도 상속 가능public접근수준을 제외한 다른 모든 접근수준의 클래스 멤버는 해당 멤버가 정의된 모듈 안에서만override가능open접근수준의 클래스 멤버는 해당 멤버가 정의된 모듈 밖의 다른 모듈에서도override가능
클래스를 개방 접근수준으로 명시한다는 건 '그 클래스를 다른 모듈에서도 부모 클래스로 사용하겠다는 목적으로 설계하고 코드를 작성했다'는 의미이다.
open class NSString: NSObject, NSCopying, NSMutableCopying, NSSecureCoding {
open var length: Int { get }
open func character(at index: Int) -> unichar
public init()
public init?(coder aDecoder: NSCoder)
}
↪︎ Foundation 프레임워크에 정의되어 있는 개방 접근수준의 NSString 클래스
내부 접근수준 - internal
internal키워드로 지정된 요소는 소스파일이 속해 있는 모듈 어디에서든 사용 가능internal키워드는 생략해도 무관- 내부 접근수준은 모든 요소에 암묵적으로 지정하는 기본 접근 수준
- 내부 접근수준으로 지정된 모듈을 가져다 쓰는 외부 모듈에서는 접근 불가
- 외부에서 사용할 클래스나 구조체가 아님
- 모듈 내부에서 광역적으로 사용할 경우 내부 접근수준을 지정함
파일 외부 비공개 접근수준 - fileprivate
fileprivate키워드로 지정된 요소는 그 요소가 구현된 소스파일 내부에서만 사용 가능- 소스파일 외부에서 값이 변경되거나 함수를 호출하면 부작용이 생길 수 있는 경우에만 사용 권장
비공개 접근수준 - private
private키워드로 지정된 요소는 그 요소가 구현된 소스파일 내부에서만 사용 가능- 비공개 접근수준은 가장 한정적인 범위임
private로 지정한 기능은 심지어 같은 소스파일 안에 구현한 타른 타입이나 기능에서도 사용 불가

접근제어 구현 참고사항
- 접근수준 공통 사항 : '상위 요소보다 하위 요소가 더 높은 접근수준을 가질 수 없다'
- 비공개 접근수준(
private)으로 정의한 구조체 내부의 프로퍼티로 내부수준 또는 공개수준을 갖는 프로퍼티 정의 불가 - 함수의 매개변수로 특정 접근수준이 부여된 타입이 전달/반환 되면, 그 타입의 접근수준보다 함수의 접근수준이 높게 설정 불가
- 함수뿐 아니라 튜플의 내부 요소 타입도 튜플의 접근수준과 같거나 높아야 한다
- 열거형의 각
case의 접근수준은 열거형 자체의 접근수준을 따른다 - 열거형의 접근 수준보다 낮은 접근수준의 타입/연관 값의 타입이 올 수 없다
private class SomeClass {
//public을 부여해도 SomeClass의 접근수준이 private 이므로
//someMethod의 접근수준도 private 접근수준으로 취급
public func someMethod() {
// ...
}
}
//someClass의 접근수준이 private 이므로
//public 접근수준 함수의 매개변수나 반환 값 타입으로 사용 불가.
public func someFunction(a: SomeClass) -> SomeClass {
return a
}
//error: 매개변수가 private 타입을 사용하기 때문에 함수를 public로 선언할 수 없습니다.
↪︎ 잘못된 접근수준
internal class InternalClass {}
private struct PrivateStruct {}
// 요소로 사용된 InteranlClass와 PrivateStruct의 접근수준이
// public보다 낮은 수준이기 때문에 사용 불가
public var publicTuple: (first: InternalClass, second: PrivateStruct) = (InternalClass(), PrivateStruct())
// 요소로 사용된 InteranlClass와 PrivateStruct의 접근수준이
// private와 같거나 높으므로 사용 가능
private var privateTuple: (first: InternalClass, second: PrivateStruct) = (InternalClass(), PrivateStruct())
↪︎ 튜플의 접근 수준
// AClass.swift와 Common.swift 파일이 같은 모듈에 속해있다는 전재 하에
// AClass.swift
class AClass {
func internalMethod() {} // internal 접근수준은 키워드 생략 가능
fileprivate func filepriavateMethod() {}
var interanlProperty = 0
fileprivate var fileprivateProperty = 0
}
// Common.swift
let firstInstance: AClass = AClass()
firstInstance.internalMethod() //같은 모듈이기 때문에 호출 가능
firstInstance.interanlProperty = 1 // 같은 모듈이기 때문에 접근 가능
firstInstance.filepriavateMethod() // error: 다른 파일이기 때문에 호출 불가
firstInstance.fileprivateProperty = 1 // error: 다른 파일기이 때문에 접근 불가
↪︎ 접근수준에 따른 접근 결과
프레임워크 및 그 외의 요소 접근수준
프레임워크를 만들 때는 다른 모듈에서 특정 기능에 접근할 수 있도록 API로 사용할 기능을 공개 접근수준인 public로 지정해주어야 한다. 그 외의 요소는 내부 접근수준인 interanl 이나 비공개 접근수준인 private 로 적절히 설정하면 된다.
열거형의 접근수준을 구현할 때는 열거형 내부의 각 case 별로 따로 접근수준을 부여할 필요 없이 각 case의 접근수준은 열거형 자체의 접근수준을 따른다. 또, 열거형의 원시 값 타입으로 열거형의 접근수준보다 낮은 접근수준의 타입이 올 수 없다.
private typealias NameValue = String
// 원시 값 사용 가능
private enum Name: NameValue {
case 서근
}
private typealias NameValue = String
// NameValue가 Name보다 접근수준이 낮기 때문에 원시 값으로 사용 불가
enum Name: NameValue {
case 서근
}
private와 fileprivate
같은 파일 내부에서 private과 fileprivate 접근수준은 사용할 때 분명한 차이가 존재한다.
fileprivate- 같은 파일 어떤 코드에서도 접근 가능private- 같은 파일 내부에 다른 타입 코드가 있어도 접근 불가능
private는 같은 파일에도 접근이 불가능 하지만 Extension 코드가 같은 파일에 존재하는 경에는 접근 가능하다.
public struct SomeType {
private var privateProperty: Int = 0
fileprivate var fileprivateProperty: Int = 0
}
//같은 extensiondptjsms private 요소 접근 가능
extension SomeType {
public func publicMethod() {
print("\(self.privateProperty), \(self.fileprivateProperty)")
}
private func privateMethod() {
print("\(self.privateProperty), \(self.fileprivateProperty)")
}
fileprivate func fileprivateMethod() {
print("\(self.privateProperty), \(self.fileprivateProperty)")
}
}
struct AnotherType {
var someInstance: SomeType = SomeType()
mutating func someMethod() {
//public 접근 수준은 어디서든 접근 가능
self.someInstance.publicMethod()
//fileprivate 접근수준은 같은 파일에 속해 있는 코드면 접근 가능
self.someInstance.fileprivateProperty = 2
self.someInstance.fileprivateMethod()
//error: 다른 타입 내부의 코드 이므로 private 요소 접근 불가
self.someInstance.privateProperty = 1
self.someInstance.privateMethod()
}
}
var anotherInstance = AnotherType()
anotherInstance.someMethod()
읽어주셔서 감사합니다 🤟
'SWIFT > Grammar' 카테고리의 다른 글
| Swift: 기초문법 [모나드 - 컨텍스트, 함수객체, 모나드] (0) | 2022.01.20 |
|---|---|
| Swift : 기초문법 [클로저 및 고차함수(map, filter, reduce)] (0) | 2022.01.19 |
| Swift : 기초문법 [인스턴스 #4 클로저 사용 프로퍼티 기본값, 디이니셜라이저] (2) | 2022.01.15 |
| Swift : 기초문법 [인스턴스 #3 초기화 위임, 실패가능한 이니셜라이저] (0) | 2022.01.15 |
| Swift : 기초문법 [인스턴스 #2 기본 이니셜라이저, 멤버와이즈 이니셜라이저] (0) | 2022.01.15 |





