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

2024. 12. 29. 20:35🍏/Swift

접근 제어자(Access Control Levels)

Swift의 접근 제어자는 코드 내에서 접근 가능한 범위를 정의하여 모듈성과 코드의 캡슐화를 향상시키는 데 사용됩니다.
Swift에서는 다섯 가지 접근 수준을 제공합니다:

1. open

  • 특징: 모듈 외부에서 접근 및 재정의 가능.
  • 사용 위치: 클래스 및 클래스 멤버에만 사용 가능.
  • 목적: 해당 클래스를 다른 모듈에서 확장(상속)하고, 메소드를 재정의하도록 허용.
  • 예시: 외부 모듈에서 상속과 오버라이드를 지원해야 하는 경우.
open class Car {
    open func horn() {
        print("honk")
    }
}

open class Morning: Car {
    override open func horn() {
        print("morning honk")
    }
}

let car = Car()
let morning = Morning()

car.horn() // "honk"
morning.horn() // "morning honk"

 

2. public

  • 특징: 모듈 외부에서 접근 가능하지만, 재정의와 상속은 불가능.
  • 사용 위치: 클래스, 구조체, 열거형, 프로토콜, 및 그 멤버.
  • 목적: API로 제공하되, 상속 및 재정의는 허용하지 않으려는 경우.
  • 차이점 (open vs public):
    • open은 외부에서 상속과 재정의가 가능.
    • public은 외부에서 접근만 가능하고 상속과 재정의는 불가능.
public class Car {
    public func horn() {
        print("honk")
    }
}

public class Morning: Car {
    override public func horn() { // 에러
        print("morning honk")
    }
}

 

다른 모듈에서 작성한 코드라면 재정의 불가능. 다른 모듈의 의미(외부 라이브러리 등)

 

3. internal (기본값)

  • 특징: 모듈 내부에서만 접근 가능.
  • 사용 위치: 클래스, 구조체, 열거형, 프로토콜, 및 그 멤버.
  • 목적: 모듈 내부에서만 사용되며, 외부에 노출되지 않아야 하는 코드.
  • 예시: 앱 모듈에서만 사용할 목적으로 작성된 코드.
internal class Car {
    internal func horn() {
        print("honk")
    }
}

internal class Morning: Car {
    override internal func horn() {
        print("morning honk")
    }
}

 

 

4. fileprivate

  • 특징: 같은 파일 내에서만 접근 가능.
  • 사용 위치: 클래스, 구조체, 열거형, 프로토콜, 및 그 멤버.
  • 목적: 특정 파일 내에서 코드가 상호작용해야 하지만, 다른 파일에는 노출되지 않아야 하는 경우.
  • 예시: 클래스의 내부 구현이 같은 파일 내의 다른 클래스를 사용할 때.
//  morning.swift
fileprivate class Morning: Car {
    override public func horn() {
        print("morning honk")
    }
}

//  main.swift
internal class Car {
    internal func horn() {
        print("honk")
    }
}

let morning = Morning() // 에러

morning.horn()

찾을 수 없음 에러가 뜬다.

 

5. private

  • 특징: 같은 선언 내에서만 접근 가능. (즉, 다른 클래스나 구조체에서도 접근 불가.)
  • 사용 위치: 클래스, 구조체, 열거형, 및 그 멤버.
  • 목적: 객체의 가장 엄격한 은닉을 유지하려는 경우.
  • 예시: 클래스 내부에서만 사용되는 보조 메소드나 프로퍼티.
//  main.swift
private class Car {
    private func horn() {
        print("honk")
    }
}

let car = Car()

 


접근 제어자를 사용하는 이유

  1. 캡슐화
    • 객체 내부의 구현 세부 사항을 외부에 숨겨 모듈화 및 유지보수를 용이하게 함.
    • 내부 구현이 변경되더라도 외부에 영향을 미치지 않도록 보호.
  2. 코드 안정성
    • 의도치 않은 접근이나 수정으로부터 보호하여 예기치 않은 오류를 방지.
  3. API 설계
    • 라이브러리나 프레임워크를 설계할 때, 외부에서 필요한 요소만 노출하고 내부 구현 세부 사항은 감춤.
  4. 보안
    • 민감한 데이터를 외부에서 직접 접근하지 못하도록 차단.

접근 제어자 결정 기준 (사용 시기)

  1. open vs public
    • 외부 모듈에서 상속 및 재정의가 필요하다면 open을 사용.
    • 외부에서 접근만 가능하고 변경은 불가해야 한다면 public을 사용.
  2. internal
    • 모듈 내부에서만 사용되는 경우. (기본값)
  3. fileprivate
    • 같은 파일 내에서 여러 클래스나 구조체 간의 협력이 필요한 경우.
      예: 클래스와 그 확장이 같은 파일에 있는 경우.
  4. private
    • 특정 클래스나 구조체 내부에서만 사용되도록 제한.
      예: 외부 노출이 필요 없는 헬퍼 메소드나 프로퍼티.

요약

Swift의 접근 제어자는 코드의 재사용성, 보안, 모듈화를 개선하며, 필요에 따라 가장 적합한 수준의 접근 제어자를 선택하여 사용해야 합니다. openpublic은 모듈 외부에서 사용할 수 있는지와 상속/재정의 가능 여부가 주요 차이이며, internal, fileprivate, private은 코드의 은닉화와 협력 범위를 정의하는 데 사용됩니다.