접근제어가 왜 필요하고 왜 중요한지 프레임워크를 만들어보면서 알아보자.
Framework
Framework가 뭔데?
iOS 앱을 개발할 때 외부 라이브러리를 import 해서 사용한다. 이런 식의 외부 라이브러리로 많이 사용하는 형태가 프레임워크이다.
프레임워크는 이미지, nib 파일, 다국어 문구, 문서, 공유 라이브러리, 헤더 파일 등을 포함하는 디렉토리이다.
프레임워크를 사용하는 이유는 코드와 리소스의 재사용성에 있다.
static library의 경우는 코드만 공유하지만 프레임워크는 이미지 파일 및 다국어 파일 등의 리소스 파일, 헤더 파일을 프레임워크 하나로 공유할 수 있기 때문이다.
(또한, 프로젝트 내부의 크기를 줄일 수 있다.)
디렉토리 구조는 아래와 같다.
CustomFramework.framework/
Modules/
module.modulemap
Headers/
CustomFramework.h
CustomFramework
Resources
가장 최상단의 프레임워크 디렉토리 아래에 Modules 와 Headers 서브 디렉토리가 있다.
헤더 디렉토리 안에는 프레임워크에서 사용할 수 있는 코드에 대한 헤더 파일들이 위치하고 모듈 디렉토리 안에는 모듈 설정 관련 파일들이 존재한다.
그리고 프레임워크 실행파일과 리소스 파일들은 CustomFramework.framework/ 아래에 위치한다.
프레임워크와 가장 많이 비교되는 개념은 라이브러리로 둘이 가장 큰 차이는 확장성이다.
Framework VS Library
Framework | Library |
apple이 만들어 놓은 UIKit | SwiftyJson과 같은 오픈소스라이브러리 |
자율적으로 수정이 불가 -> UILabel 을 UISokyte로 수정 불가 |
코드를 뜯어서 커스텀 가능 |
Framework 만들기
command + n 을 눌러서 새로운 파일을 하나 추가한다.
(.swift 파일을 추가하고 파일명은 구현하고자 하는 UI에 맞게 작성한다.)
Alert 창을 띄우는 코드를 만들어보자.
UIAlert의 경우 UIKit 를 상속받아서 구현할 수 있으므로 import Foundation을 import UIKit로 수정하고 코드를 작성한다.
import UIKit
extension UIViewController {
func showSokyteAlert(title: String, message: String, buttionTitle: String, buttonAction: @escaping (UIAlertAction) -> ()) {
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
let cancel = UIAlertAction(title: "취소", style: .cancel)
let ok = UIAlertAction(title: buttionTitle, style: .default, handler: buttonAction)
alert.addAction(cancel)
alert.addAction(ok)
self.present(alert, animated: true)
}
}
Access Control
코드에 대한 접근을 제한 (할 수 있는 기본 인터페이스를 제공)
크게 다섯 가지의 접근 제어자가 존재
- Open
- Public
- Internal
- filePrivate
- Private
밑에서 세 가지 접근 제어자의 경우, 프로젝트 안에서 효과가 있는 제어자이다.
이 다섯 가지의 접근 제어자가 어떻게 작동하는지 프레임워크를 통해서 알아보자.
먼저 위에서 만든 프레임워크 파일을 닫고 (close 한다.) 새로운 앱 프로젝트를 만들어준다. 그리고 아래와 같이 프로젝트 바로 아래에 프레임워크를 추가한다.
이렇게 프로젝트 바로 아래에 프레임워크 폴더를 추가하는 것이 아니라 파일을 추가해야 한다.
잘 추가가 되었다면, 위와 같이 추가한 프레임워크가 프로젝트 하단에 위치하는 것을 볼 수 있다.
그리고 나서 위와 같이 프로젝트 설정 > General > Frameworks, Libraries, and Embeded Content에서 해당 프레임워크를 선택하여 추가한다.
잘 추가가 되었다면 위와 같이 나타나는 것을 확인할 수 있다.
그리고 위에서 만든 alert 창을 사용하기 위해 ViewController에서 아래와 같이 코드를 작성할 수 있다.
import UIKit
import SokyteUIFramework
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
showSokyteAlert(title: "Test Alert", message: "Test Message", buttionTitle: "변경") { action in
self.view.backgroundColor = .systemPink
}
}
}
앱에 진입하자마자 바로 alert 창을 띄우기 위해서 viewDidAppear에서 호출한다.
그러나, 위의 코드 순서대로 작업을 진행했다면 오류가 나는 것을 확인할 수 있다.
이유는, 프레임워크에서 코드를 작성할 때, 접근제어자를 따로 지정하지 않고
extension UIViewController {
func showSokyteAlert(title: String, message: String, buttionTitle: String, buttonAction: @escaping (UIAlertAction) -> ()) {
...
}
}
라고 작성했다.
아무것도 작성하지 않을 경우 접근제어자는 internal로 설정이 된다. (default = internal)
internal은 모듈 내에서 접근할 수 있고, 외부에서는 해당 프로퍼티/메서드에 대해 접근을 제한하는 접근제어자이다.
그러므로, 외부 모듈에서 SokyteUIFramework의 alert의 showSokyteAlert에 대해 접근하고 싶다면, 위의 함수 코드 앞에 public 이라고 지정을 해야 한다.
Access Control란?
다시 정리를 해보자면, 접근제어자는 특정 코드의 접근을 다른 소스파일 or 모듈에서 제어하는 것을 말한다.
접근을 제어함으로써 특정 코드의 세부적인 구현을 감추고 필요한 만큼만 공개/접근할 수 있도록 하여 불필요한 작업이 발생하지 않도록 한다.
접근제어는 클래스, 구조체, 열거형뿐 아니라 그 타입에 속한 프로퍼티, 메서드, 초기자, 서브 스크립트에도 적용할 수 있다.
위에서 말한 다섯 가지의 접근제어자에 대해서 모듈 내/외부의 접근 , 파일 내/외부의 접근, 블록 내/외부의 접근으로 제어의 수준을 구분할 수 있다.
접근 수준 | 범위 | |
open | 개방 접근 | 모듈 외부에서 접근 가능 |
public | 공개 접근 | 모듈 외부에서 접근 가능 |
internal | 내부 접근 | 모듈 내부에서만 접근 가능 |
fileprivate | 파일 내부 접근 | 한 파일 내부에서만 접근 가능 |
private | 비공개 접근 | 정의한 블록 안에서만 접근 가능 |
왜 접근제어를 잘 사용해야 하는가?
앱 내(프로젝트 내에서) 사용할 프로퍼티/메서드임에도 불구하고 open/public으로 지정할 필요가 없다.
또한, UITableViewCell과 같은 경우 UI를 담당하는 코드 블록은 awakeFromNib과 같은 초기화 과정에서만 한번 불리면 되는 블록이다. 이런 메서드를 UIViewController에서 접근할 수 있게 된다면 오류가 날 수 있다.
이렇듯 접근제어자를 적재적소에 사용하지 못하면
개발자/사용자에게 너무 적은 권한 또는 너무 많은 권한을 주게 되어 오류가 날 수 있다.
'Swift' 카테고리의 다른 글
Type Casting Up? Down? (2) | 2022.08.19 |
---|---|
Framework (Dynamic VS Static) (1) | 2022.08.19 |
Attribute (@어쩌구) (0) | 2022.08.10 |
Closure (클로저) (0) | 2022.08.10 |
First-Class Citizen(일급 객체) (0) | 2022.08.09 |