📂 BaseViewController
- import 라이브러리, addSubview, 오토레이아웃, textColor, backgroundColor 등등.. 반복되는 코드를 단축시킬 수 있는 방법 중 하나
 
- UIViewController를 상속받는 BaseViewController를 만들고 다른 ViewController에서 BaseViewController를 상속받도록 설정하면 됨
 
📂 loadView()
- viewDidLoad 이전에 먼저 호출되는 메서드
 
- viewcontroller의 root view를 로드할 때 호출됨, 새로운 뷰를 반환하려고 할 때
 
var mainView = SignView()
override func loadView() {
	self.view = mainView
}
📂 URLSessionDelegate
- Completion Handler는 데이터가 모두 처리되기 전까지는 실행되지 않음
 
- Shared Session은 Delegate 지원x 
 
- URLSessionDelegate를 사용하고 싶은 경우에는 Default Session 사용해야함
 
- Default Session 생성
 
var session: URLSession!
func request() {
	let url = URL(string: "")!
    
    
    
    session = URLSession(configuration: .default, delegate: self, delegateQueue: .main)
    session.dataTask(with: url).resume()
    
    
    let configuration = URLSessionConfiguration.default
    configuration.allowsCellularAccess = false 
}
- URLSessionDataDelegate 
 
- URLSessionDataDelegate를 통해서 작업이 얼마나 이뤄졌는지 등등 더 자세하게 확인할 수 있음
 
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive response: URLResponse) async -> URLSession.ResponseDisposition { }
- 서버에서 최초로 응답받은 경우 호출(상태코드에 대한 분기처리를 진행해줄 수 있음)
 
- 200이면 계속 서버 응답을 받고 500이면 에러로 유도
 
- 큰 데이터의 경우 데이터를 나눠서 보내기 때문에 첫번째 나눠진 데이터가 도착할 때(?)를 첫번째 응답으로 판단
 
- 헤더에 들어있는 "Content-Length" 값을 이용해서 전체 데이터의 길이를 알아내고 네트워킹 진행률을 계산해줄 수 있음
 
if let response = response as? HTTPURLResponse, (200...299).contains(response.statusCode) {
            total = Double(response.value(forHTTPHeaderField: "Content-Length")!) ?? 0
            return .allow
        } else {
            return .cancel
        }
var buffer: Data? {
        didSet {
            let result = Double(buffer?.count ?? 0) / total
            label.text = "\(result * 100)/100"
        }
}
    
override func viewDidLoad() {
        super.viewDidLoad()
        
        buffer = Data() 
}
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
        buffer?.append(data)
}
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) { }
- 항상 에러를 캡쳐하는 메서드는 아님
 
- 에러없이 응답이 완료되었을 때 error 매개변수에는 nil이 전달됨
 
- 이번 예제에서는 받아온 데이터를 이미지로 변환하는 과정 등이 해당 메서드에서 실행된다.
 
	if let error = error {
            
            print("오류가 발생했다.", error)
        } else {
            print("성공!") 
            
            
            guard let buffer = buffer else { 
                print("buffer error")
                return
            }
            
            let image = UIImage(data: buffer)
            imageView.image = image
        }