
## iOS 앱의 상태 변화에 따라 호출되는 메서드 종류에 대해 설명해주세요.
### 앱 실행 상태 변화시 호출되는 UIApplicationDelegate 메서드
|~iOS 12|iOS 13 ~|
|:-:|:-:|
|<img src="https://docs-assets.developer.apple.com/published/64a2e0dab8/app-state@2x.png" width="400">|<img src="https://docs-assets.developer.apple.com/published/c834d5ac04/scene-state@2x.png" width="400">|
#### 앱 초기화 관련 활용 메서드
(참고 링크: [UIApplicationDelegate](https://developer.apple.com/documentation/uikit/uiapplicationdelegate))
- `application(_: willFinishLaunchingWithOptions:)`
- 앱이 구동되어 필요한 초기 실행 과정이 완료되기 직전 호출되는 메서드
- 앱을 초기화하고 실행할 준비를 하는 데 필요한 처리
- `application(_: didFinishLaunchingWithOptions:)`
- 앱이 사용자에게 화면으로 표시되기 직전에 호출되는 메서드
- 앱이 실행된 후 진행할 커스터마이징 또는 초기화 코드 작성
- *iOS 12까지는 이 메서드를 통해 UIWindow 개체를 구성하고 ViewController 인스턴스를 할당했었음 -> SceneDelegate로 이동됨*
#### 앱 생명주기 관련 이벤트 메서드
- `applicationDidBecomeActive(_:)`
- 실행된 앱이 전면(Foreground)에 표시될 때 호출되는 메서드
- 앱이 Inactive 상태에 들어가면서 일이 중지된 작업이 있다면 재시작하는 코드를 여기에 작성해야 함(예: 타이머나 스톱워치는 Inactive 상태에서는 화면 갱신이 이루어지지 않음)
- `applicationWillResignActive(_:)`
- 앱이 백그라운드로 이동 중에 호출되는 메서드
- 일시정지, 타이머 비활성화 등의 코드 작성
- `applicationWillEnterForeground(_:)`
- 앱이 전면(Foreground)으로 올라올 때 호출되는 메서드
- API를 통한 앱 상태 갱신시 사용
- `applicationDidEnterBackground(_:)`
- 앱이 백그라운드 상태에 진입했을 때 호출되는 메서드
- 즉 미래 어느 순간에 앱이 종료된다는 의미 -> 공유 자원 해제 처리 & 사용자 데이터 및 다시 실행될 때 현재 상태를 복구할 수 있도록 필요한 상태 정보 저장 처리
- `applicationWillTerminate(_:)`
- 앱이 종료되기 직전에 호출되는 메서드
- 사용자 데이터 등을 종료 전에 한 번 더 저장
<br><details>
<summary>기타 환경 변화에 따른 이벤트 메서드</summary>
<div markdown="1">
#### 환경이 바뀔 때 실행되는 메서드
- `applicationProtectedDataDidBecomeAvailable(_:)`
- 보호된 파일이 사용할 수 있게 되었음을 알림
- `applicationProtectedDataWillBecomeUnavailable(_:)`
- 보호된 파일이 사용할 수 없어질 예정임을 알림
- `applicationDidReceiveMemoryWarning(_:)`
- 앱이 시스템 메모리 경고를 받았음을 알림
- `applicationSignificantTimeChange(_:)`
- 시간에 큰 변화가 생겼음을 알림
#### Background에서 데이터를 다운로드할 때
- `application(_:, handleEventsForBackgroundURLSession:, completionHandler:)`
- URL 세션과 관련된 이벤트가 처리되기를 기다리고 있다고 알림
...
</div>
</details>
<br>
### 앱 실행 상태 변화시 호출되는 UISceneDelegate 메서드
#### Scene 연결 및 연결 해제
- `scene(_:willConnectTo:options:)`
- 새로운 UI 인스턴스가 생성되거나 복원될 때 호출됨
- 이 메서드에서 해당 Scene과 관련된 UI 구성, 초기화 작업을 수행
- `sceneDidDisconnect(_:)`
- Scene이 메모리에서 제거되기 전 호출됨
- Scene이 더 이상 사용되지 않을 때 정리 작업을 수행
#### Foreground로 전환 중
- `sceneWillEnterForeground(_:)`
- Scene이 Foreground로 이동하기 전에 호출됨
- 앱 상태를 갱신하거나 데이터를 업데이트하는 작업에 사용
- 메서드 뒤에 항상 `sceneDidBecomeActive(_:)`를 호출
- `sceneDidBecomeActive(_:)`
- Scene이 활성화되어 사용자에게 보이기 전에 호출됨
- View 내용을 새로 고치거나, 타이머를 시작하거나, UI의 프레임 속도를 높일 수 있음
#### Background로 전환 중
- `sceneWillResignActive(_:)`
- Scene이 비활성화되어 백그라운드로 이동하기 직전 호출됨
- 사용자와의 상호작용을 중지하도록 준비
- 일시 중지, 타이머 비활성화 등을 수행하는 코드 작성
- Scene에 저장되지 않은 데이터가 있는 경우 해당 데이터가 손실되지 않도록 저장하는 방법 중 하나
- `sceneDidEnterBackground(_:)`
- Scene이 백그라운드로 이동할 때 호출됨
- Scene의 메모리 사용량을 줄이고 공유 리소스를 확보함
- 메서드 반환 후 App Swicher에 표시하기 위해 Scene 인터페이스 스냅샷을 찍음
- 스냅샷에 민감한 사용자 정보가 포함되어있지 않은지 확인 필요
<br><details>
<summary>기타 환경 변화에 따른 이벤트 메서드</summary>
<div markdown="1">
#### URL을 여는 중
- `scene(_:openURLContexts:)`
- Scene API를 통해 URL을 열도록 요청하는 메서드로 여러 뷰 컨트롤러를 관리하는 데 사용됨.
- 앱이 URL을 열 때 호출되고 주로 앱 내에서 다른 컨텐츠로 이동하거나 외부 앱과 상호작용할 때 사용됨.
#### 지속적인 사용자 활동
- `scene(_:willContinueUserActivityWithType:)`
- 지정된 유형의 활동 처리를 준비하기 위해 호출
- 메서드 반환 후 Scene이 활동을 처리하고 있다는 피드백을 사용자에게 제공함
- `scene(_:continue:)`
- 제공된 활동 객체의 데이터로 지정된 Scene을 업데이트하기 위해 호출
- 다른 기기에서 발생할 수 있는 활동 객체에 대한 모든 데이터를 수신한 후에만 앱의 메인 스레드에서 이 메서드를 호출
- `scene(_:didFailToContinueUserActivityWithType:error:)`
- 지정된 활동을 완료할 수 없음을 사용자에게 알리기 위해 호출
- 이 메서드를 구현하지 않으면 UIKit은 실패 이유에 대한 적절한 메시지와 함께 사용자에게 오류를 표시함
#### Scene의 상태 저장
- `stateRestorationActivity(for:)`
- Scene의 현재 상태에 대한 정보가 포함된 NSUserActivity 개체를 반환하기 위해 호출
- Scene의 연결을 끊었다가 다시 연결한 후 해당 상태를 다시 복원할 수 있도록 충분한 정보를 저장해야 함
- `scene(_:restoreInteractionStateWith:)`
- `scene(_:didUpdate:)`
- 지정된 사용자 활동 개체에 최종 데이터를 추가하기위해 호출
</div>
</details>
<br>
## App Delegate와 Scene Delegate의 역할 차이는 무엇인가요?
- App Delegate
- App 자체의(Process) Life Cycle 및 설정 관리
- 앱의 시작/종료 포함 애플리케이션 수준의 이벤트 처리
- 푸시 알림 등록, 위치 서비스 등의 외부 서비스 처리 가능
- Session의 Life Cycle 관리
- Scene Session을 통해 Scene에 대한 정보를 받아서 해당 사이클을 관리함
- application(_ : configurationForConnecting: options:) -> UISceneConfiguration
- 새 씬이나 윈도우가 필요할 때마다 호출됨
- 앱 시작시 호출되지 않고 새 씬이나 창을 가져야 하는 경우에만 호출됨
- application(_ : didDiscardSceneSessions:)
- 씬을 삭제할 때(예: 멀티 태스킹 창에서 스와이프) 또는 프로그래밍 방식으로 엡 제거시 호출
- Scene Delegate
- 화면에 표시될 내용(Scene/Window)을 관리
- UI Life Cycle 관리
- Entered Foreground, Became Active 상태 등은 Scene Delegate에서 관리
- UISceneSession의 Scene 생성, 파괴 및 상태 복원과 같은 Scene의 생명주기 이벤트 처리
- 하나의 앱은 여러개의 Scene과 SceneDelegate 객체를 동시에 활성화시킬 수 있음
### 꼬리 질문: UISceneDelegate는 직접 객체를 생성하면 안되는데 왜 그럴까요?
- SceneSession 및 Scene Configuration의 관리 시스템 기반으로 UIKit이 자동으로 UISceneDelegate 객체를 관리하도록 설계되었기 때문에 직접 UISceneDelegate 객체를 생성하면 이러한 시스템 관리 및 복잡성을 증가시킬 수 있으며, 예기치 않은 동작을 초래할 수 있다.
#### 2. UI 객체들의 계층 구조와 각 역할에 대해 설명해주세요.
|~iOS 12|iOS 13 ~|
|:-:|:-:|
|<img src="https://hackmd.io/_uploads/B1UVtBpWT.png" width="1000">|<img src="https://hackmd.io/_uploads/r1uEYSTWa.png" width="1000">|
- `UIView`
- 화면에 컨텐츠를 그리고 사용자와 직접 상호작용하여 처리하는 객체
- UI의 기본 클래스로 다른 뷰 또는 컨트롤 요소 계층
- `UIWindow`
- UIView의 서브 클래스로 앱의 UI에 대한 배경과 이벤트를 뷰에 전달하는 객체
- iOS 13 이전까지는 하나의 앱에서는 하나의 Window를 가졌지만 이후부터는 아이패드 지원으로 인해 AppDelegate와 SceneDelegate의 분리로 여러 개의 Window를 가질 수 있게 되었음
- `UIWindowScene`
- UIScene의 서브 클래스로 1개 또는 그 이상의 Window를 관리하는 객체
- window와 scene 두 가지의 프로퍼티를 갖음
- 해당 객체는 직접 생성을 권유하지 않음. 따라서 info.plist에서 configuration time에 UIWindowScene 객체를 사용할 클래스의 이름을 지정하여 사용하는 것을 권장
- `UIScreen`
- 하드웨어 기반 디스플레이와 관련된 속성을 정의하는 객체
- 하나 이상의 연결된 디스플레이에 대한 속성과 메서드를 제공하여 화면 크기, 해상도, 화면 방향 같은 관련 정보를 설정하는 데 사용됨
## GCD와 Operation의 차이에 대해 설명해주세요.
#### DispatchQueue
- Serial / Concurrent로 나뉘어 순차적, 병렬적 처리가 모두 가능하지만 늘 FIFO 방식으로 실행된다
- **꼬리질문: DispatchQueue에는 우선순위 처리방식이 없을까요?**
- 동시 처리일 경우 QoS 파라미터를 사용해서 우선순위 지정 가능
- userInteractive, userInitiated, default, utility, background
- 왼쪽으로 갈수록 빨리 처리되고, userInteractive는 유저와 상호작용도 가능. 기본값은 default
- UI 관련일 경우 userInteractive로 사용하는 것이 좋다
- 길게 지속되는 작업은 utility, 사용자에게 직접적으로 인지되지 않아도 되는 부분은 background 권장
- 우선순위가 높은 작업은 더 많은 thread에 배치된다
- (비고: 큐 자체에도 우선순위를 줄 수 있고, 작업을 대기열에 보내는 방식에도 QoS 값을 줄 수 있다. 이때 큐와 작업의 우선순위가 각자 다르다면 해당 작업이 끝날 때까지 둘 중 더 높은 쪽으로 자동 조절된다.)
- sync는 스레드를 재사용, async는 새로 생성 -> async 사용시 무한으로 늘어날 수 있음
- 기본적으로 멀티스레딩 방식이기 때문에 Thread Explosion을 야기할 수 있음
#### OperationQueue
- Operation 객체들을 priority에 의해서 실행시키는 queue
- 디스패치 큐의 코코아 대체제. NSOperationQueue 클래스 기반
- 오퍼레이션 큐는 언제나 동시적으로 진행되긴 하지만 순차적인 실행이 필요할 경우 디펜던시를 활용할 수 있다 -> FIFO가 아닌 우선순위 기반 처리를 진행함(우선순의 팩터를 전달받음)
- 오퍼레이션 큐에 넣는 태스크는 반드시 NSOperation 클래스 인스턴스여야 함
- 오퍼레이션 객체들은 KVO 알림을 생성해준다
- 일시중지, 다시시작, 취소 가능(취소 작업시 동작은 하단 참조). 기능은 많이 제공해주지만 때문에 더 무겁기도 함
- 동시 실행 가능한 연산의 최대수 지정 가능
- **꼬리질문: DispatchQueue를 활용하여 이 부분을 비슷하게 구현할 수는 없을까요?**
- DispatchSemaphore 활용할 수 있음
### 어떤 경우에 각각의 기술을 선택할지 자신의 선택 기준에 대해 알려주세요.
### 각각의 기술을 사용할 때 작업을 취소하면 곧바로 취소가 되나요?
- **GCD**: 작업을 취소하거나 중단하는 과정이 복잡하며 직접 처리해야 함. 이때 이미 시작된 작업은 취소되지 않음.
- **Operation**: Operation, OperationQueue는 작업을 취소하거나 중단하는 메커니즘을 제공하기 때문에 작업취소할 때 더 용이함. 이미 시작된 작업이 취소되었을 경우 해당 작업을 중지하고 완료된 것으로 표시함.
#### 작업을 취소할 때 벌어지는 일에 대해서 설명해주세요.
- **DispatchQueue**
- 취소 후에는 작업 항목을 실행하려는 시도가 모두 반환됨. 이미 시작된 작업 항목의 실행에는 영향을 미치지 않음.
- 관련 자원의 해제는 블록 객체의 실행이 다음에 시도될 때까지(또는 이미 진행 중인 실행이 완료될 때까지) 지연됨.
- **OperationQueue**
- 작업 객체를 취소해도 객체는 대기열에서 사라지지 않음. 하지만 가능한 한 빨리 작업을 중지해야 한다고 객체에 알림.
- 현재 실행 중인 작업의 경우, 작업 객체의 작업 코드가 취소 상태를 확인하고, 하고 있는 일을 중지하고, 완료된 것으로 표시함.
- 대기열에 있지만 아직 실행되지 않은 작업의 경우, 대기열은 여전히 작업 객체의 start() 메서드를 호출하여 취소 이벤트를 처리하고 완료된 것으로 표시함.
###