---
# System prepended metadata

title: ' iOS interview 2 '
tags: ["\U0001F4BB 면접 질문"]

---

<h1><center> iOS interview 2 </center></h1>

###### tags: `💻 면접 질문`
###### date: `2025-09-067:21:33.284Z`

> [iOS interview](https://github.com/JeaSungLEE/iOSInterviewquestions)

# 개요 

### 안진 KWDC 후기

1. 한글과 사과밭
-  한글이 단순 텍스트가 아닌 복합 문자 체계임을 이해하고, macOS·Windows의 정규화 차이로 인한 파일명·문자열 문제의 구조적 원인을 파악합니다. 실제 사례와 코드로 한글 처리 시 유의점을 배우며, 더 나은 한글 경험 제공 방향을 함께 모색합니다.
- 문자열 정규화 처리 방식에 대한 소개가 있었음! 처음보는데 모두가 활용하는 문자열에 대한 이야기라니.. 라는 감상
  - NFD (Normalization Form Decomposition)
  - NFC (Normalization Form Canonical Composition)
  - GPT 바보.. C, D에 의미가 있었습니다!
- 문자열 길이를 찍었을 때, NFC 적용과 NFD 적용의 방식이 다르다... => macOS, iOS에서 앱을 지원하려면 [ NFC -> **NFD** 변환을 해줘야한다..? ]
- 블로그 정보: https://cdecl.github.io/devops/nfd-to-nfc/
``` swift
import Foundation

let nfcString = "안녕하세요, 세상! é"
print("NFC (원래 문자열): \(nfcString)")

// NFC를 NFD로 변환
let nfdString = nfcString.decomposedStringWithCanonicalMapping
print("NFD (변환된 문자열): \(nfdString)")

// NFD를 다시 NFC로 변환
let nfcStringAgain = nfdString.precomposedStringWithCanonicalMapping
print("NFC (다시 변환): \(nfcStringAgain)")
```

2. actor boundary를 넘어서
- Swift 6에서 레거시 스레드 기반 API를 안전하게 사용하기 위해 actor 경계를 동기적으로 넘어가는 방법과, 이를 해결하는 커스텀 executor / DispatchQueue 방식 및 락 기반 접근법을 비교하고 소개합니다.

```
⚖️ 세션에서 할 말 (포인트 정리)

- Actor 격리 규칙: “actor 안의 프로퍼티는 그 actor 실행기 위에서만 접근 가능하다” → cross-actor 접근 시 항상 await.
왜?: 데이터 레이스 방지, 동시성 안전 보장.
⭐️ nonisolated 멤버: 예외 케이스.
> 이 친구들은 당므과 같은 특징이 있음...
- 생성 시점에 확정된 상수 (let) -> 스택 영역, 힙 영역 상관이 없나..?
- 순수 계산 프로퍼티 (var computed: Int { … }) 
- static 멤버 (타입 레벨 공유)

실무 사례:
id, name 같은 고정된 메타데이터는 nonisolated로 빼서 어디서나 읽게함.
내부 상태(balance, items)는 await로만 접근하도록 유지.
안티패턴 경고:
nonisolated로 mutable 데이터를 노출하면 actor 모델을 깨뜨려서 race condition 발생.
“겉보기 동기 접근”을 위해 nonisolated를 남용하지 말 것.
연결 포인트:
레거시 스레드 기반 API와 연결할 때도, 동기적으로 보이게 만드는 대신 내부 상태는 actor 격리를 지켜야 함.
▶️ 즉, actor 격리 vs nonisolated 예외의 균형이 핵심 메시지.

--------

세션 골자 (Key Takeaways)

Swift 6의 기본 전제: 동시성 안전성 강화로 “동기적 cross-actor 접근”은 원칙적으로 금지/제약.

레거시 스레드/콜백 API 다루기: await/메시지 패싱이 정석. 동기를 꼭 유지해야 한다면 “실제로 동기여야 하는 구간”을 최소화하고 경계(Bridge) 를 만드는 구조로.

대안 비교:

- Custom Executor + DispatchQueue 바인딩: 레거시 큐 규약을 보존하면서도 actor 격리 유지(추천).

- 순수 Dispatch(큐-기반) 래핑: 간단하지만 구조적으로 점진적 마이그레이션에 한계.

- 락(NSLock 등) 기반: 가장 직관적이지만 교착·우선순위 역전·재진입 문제에 취약(최후의 수단).

안티패턴: 실행기(Executor) 스레드를 블로킹하지 말 것. reentrancy/priority를 무시하지 말 것.

현실적 결론: “동기처럼 보이는 API 표면” 뒤에서 비동기 내부 구현으로 안전하게 속이기.
```

**Custom Executor + DispatchQueue 전략 (권장)**
레거시가 “이 큐에서 동작해야 한다”는 규약을 갖는 경우, actor를 해당 큐 실행기와 바인딩.
```swift
actor LegacyBoundActor {
    nonisolated var unownedExecutor: UnownedSerialExecutor { queue.asUnownedSerialExecutor() }
    private let queue = DispatchQueue(label: "legacy.queue") // 레거시 규약 큐

    // actor 메서드는 항상 이 큐에서 직렬 실행
    func doWork() { /* 레거시 객체 안전 접근 */ }
}
    
```
장점
- 레거시의 큐 제약을 언어 차원 격리와 결합.
- actor 격리 + 순서 보장 + 재진입 모델을 명시적으로 관리.
- 테스트 용이(큐 교체/인젝션).

주의
- 내부에서 블로킹 호출 금지(같은 큐에 다시 동기 진입하면 교착).
- 타 큐/스레드 소유 자원과 교차 락 금지(락 순서 정립 필요).
> 데모: 동일 큐 동기 재진입으로 교착이 나는 잘못된 코드와, await로 안전하게 hop 하는 올바른 코드 대비.

``` swift
@globalActor
struct MyGlobalActor {
    actor MyActor {}
    static let shared = MyActor()
}
```

GPT야 나 이거 하나도 모르겠는데 이거 알려면 뭘 알아야 해?
```
1. Swift Concurrency 자체
- Actor 격리 모델
  - actor가 상태를 어떻게 직렬화해서 보호하는지
  - cross-actor hop(await)이 왜 필요한지
- nonisolated
  - 언제 actor 격리 바깥에서 안전하게 접근할 수 있는지 (불변 데이터, 순수 함수)
- Executor
  - Swift의 실행기(Executor) 개념: actor 메서드를 어떤 스레드/큐에서 실행시킬지 결정
  - Custom Executor: actor를 특정 DispatchQueue 등과 연결하는 방법
- Reentrancy(재진입)
  - actor 내부에서 await 시 다른 작업이 끼어들 수 있다는 특징
  - 이를 막거나 다룰 수 있는 패턴 (스냅샷/불변성 강화)

2. 전통적 동시성 제어(레거시)
세션에서 Mutex(락) 이야기가 나온 건 과거 방식과의 비교 때문일 거예요.
- 뮤텍스(Mutex)/NSLock
  - 공유 자원을 보호하기 위해 쓰던 락
  - 문제점: 교착(deadlock), 우선순위 역전(priority inversion), 재진입 불가 상황 등
- DispatchQueue(GCD)
  - 큐 단위 직렬화 → 사실상 “락 대체재”
  - 여전히 많이 쓰이지만 Swift Concurrency와는 다른 추상화
- 세마포어(Semaphore)
  - 동기화 primitive, 동기 wait 가능
  - Swift Concurrency에서는 가급적 피하고, await 기반 구조로 전환 권장

3. 공부하면 좋은 키워드 모음
- Swift Concurrency 기본: async/await, Task, TaskGroup, Actor, MainActor
- Actor 관련: isolated, nonisolated, Sendable, @unchecked Sendable
- Executor 관련: SerialExecutor, UnownedSerialExecutor, DispatchQueue.asUnownedSerialExecutor()
- 안전성: Reentrancy(재진입), Cancellation(취소), Priority(우선순위)
- 전통 동시성: Mutex, Semaphore, Condition Variable, GCD(DispatchQueue, OperationQueue)
- 비교 관점: “락 기반 ↔ 큐 기반 ↔ actor 기반” 차이

4. 학습 포인트 정리
왜 actor가 필요한가? → 전통적 락(GCD, Mutex)의 문제를 해결하기 위해.
actor 격리 규칙 → cross-actor 접근 시 await이 필수인 이유.
nonisolated → 예외 상황 (불변, 타입 레벨 정보).
Custom Executor → 레거시 큐/스레드 규약을 Swift actor에 안전하게 이식하는 법.
Mutex 등 레거시 기법은 Swift Concurrency와의 차이와 단점을 이해하면 충분.
```

4. Array로부터 이해하는 Swift의 성능: 동기, 진화, 그리고 미래 -> ㅜ.ㅜ | inline array
![image](https://hackmd.io/_uploads/ryonv-t9lg.png)


6. 셰이더 몰라도 괜찮아, Metal 파이프라인은 이렇게 생겼어
이게 뭔지 잘 몰라서 이해를 ..
- Metal? -> GPU 로우레벨
- URL
- Metal4에 대해 이야기한대. MTLDevice. commandbuffer. commandallocator. renderpipelineState. pipeline, renderpass. rendercommandencoder.computecommandencoder. buffer, texture. 원래는 고정된 뭘 사용함. 하지만 드로우 늘어나면 리소스 늘어남. 퍼포먼스 부담. 동적으로 필요하면 bind 어쩌구. barrier api? metal기 gpu와 동작하는 방식에 대한 설명

https://www.google.com/url?sa=i&url=https%3A%2F%2Fwww.kodeco.com%2Fbooks%2Fmetal-by-tutorials%2Fv2.0%2Fchapters%2F3-the-rendering-pipeline&psig=AOvVaw1ipgjPIDBmPpM1dUw3M0Vx&ust=1757206714862000&source=images&cd=vfe&opi=89978449&ved=0CBIQjRxqFwoTCLjD4qz3wo8DFQAAAAAdAAAAABAE

https://developer.apple.com/library/archive/documentation/GraphicsImaging/Conceptual/drawingwithquartz2d/dq_layers/dq_layers.html

![스크린샷 2025-09-06 09.59.41](https://hackmd.io/_uploads/BJFKwWt9le.png)

![스크린샷 2025-09-06 09.59.16](https://hackmd.io/_uploads/Syy_w-F5ll.png)


7. PassKit / ID Verifier로 검증 프로세스 구축하기

- mDL (mobile Driver’s License)
  - 모바일 운전면허증.
  - 국제 표준 ISO/IEC 18013-5에 따라 NFC나 QR, BLE 등을 통해 다른 단말에 제시·검증 가능.

- mdoc (mobile document) 
  - mDL을 포함하는 더 넓은 개념.
  - 여권, 주민등록증, 학생증, 마이넘버카드 등 공식 신원 문서를 디지털화한 것.
  - 표준: ISO/IEC 23220 시리즈, 18013-5/7 등.
- 일본 사례: iPhone 안에서 마이넘버카드(mynumber card) 를 mdoc처럼 활용 → 정부와 Apple이 협력.

```
⭐️ CBOR: JSON보다 compact한 바이너리 데이터 포맷, 표준 mdoc 데이터 구조.

COSE: CBOR 기반의 서명·암호화 포맷.

Verifier / Holder / Issuer:

Issuer: 정부/기관 (면허증 발급)

Holder: 사용자(iPhone에 보관)

Verifier: 신원 확인하는 앱/단말

Presentation: mdoc 데이터를 제시하고 검증하는 과정.
```

8. Swift Testing으로 작성한 테스트 코드를 어떻게 찾고 수행할 수 있을까?
(안진 잘 모름 이슈..)
> Suite 실행했을 때...
![image](https://hackmd.io/_uploads/B13VYZF5ee.png)

9. Apple의 컨테이너화 프레임워크 이해하기 - 기초부터 시작하기
```
brew install 어쩌구 container
container system run
container run swift 어쩌구
container build -어쩌구 swift { print("hello world") }

잘 찍히는거 보여줌
```

- https://github.com/inductor


**여기에 주제를 던져 보겠습니다**

**태윤**
NFC와 NFD와 관련된 블로그 글: https://code-notes.tistory.com/160

**태현**

1. 한글과 사과밭

https://gist.github.com/oozoofrog/07d7eec63750c4992b09e2709f180497

한글?

- 문자열 처리 ? 
    - NFC(Normalization F? C?, NFD(- MACOS)?
    - 특정 문자가 없기때문에 깨지는 것이다. 
    - 유니코드

2. actor boundary 

- SerialExecutor
- Executor
- UnownedSerialExecutor

3. Array로부터 이해하는 Swift의 성능

- inline array


---

### DIContainer와 싱글톤

- 둘은 매칭되는 것이 아니다.
- 싱글톤 패턴을 쓴다 -> 내부 프로퍼티 값의 변화가 전역적으로 영향을 미친다.
- DIContainer는 객체 생성을 맨 처음하고, 전역적으로 생성되지만, 내부 프로퍼티 변화는 발생하지 않는다. (객체 추상화가 되니깐...)

#### 싱글톤
1. 높은 결합도: 싱글톤 인스턴스를 사용하는 클래스들이 특정 싱글톤 클래스에 직접적으로 의존하게 되어 코드의 재사용성과 유연성이 떨어집니다.
2. 테스트의 어려움: 싱글톤은 전역 상태를 가지므로, 독립적인 단위 테스트가 어렵습니다. 테스트를 할 때마다 싱글톤 객체의 상태를 초기화해야 하는 번거로움이 있습니다.
3. 멀티 스레드 문제: 직접 구현할 경우 동기화 문제를 고려해야 하며, 이는 코드의 복잡성을 높입니다.


#### 캐싱

서버에서 사용자 데이터 -> Core Data 데이터로 저장 -> A 객체

**문제**

- 네트워크 없을 때도 사용할 수 있게해야함
- 캐릭터 방?을 꾸민다? (자재)
- 사용자 에셋(서버, CoreData)

A <- set  

Core Data <- 최신화

state = 1, 2, 3 ~ 4

- 최신화 시점
- 서버

1. add

- Core Data
- server

A 객체로  

서버에서 사용자 데이터 > Realm -> 문구 -> A 개

1. Core Data Entity로 관리하기 힘든 상품들 (너무 케이스가 많음)
==> FileManager를 쓴다. | 상품이 너무 많고 타입 정리가 없어요... 이건 어떻게 할지 모르겠네... / **UserDefaults** vs FileManager
2. *굳이 Sync를 크게 고려 안해도 됨* 다시 다운 받으면 그만이야~ => 그래도 좀 덜 다운 받았으면 좋겠어
3-1. URLCache로 다운 받고 캐싱 되어있는 것은 안 다운받음... 저장은 어떻게? => *FileManager*로 json이든 뭐든 다운
3-2. 저장하기 전에 FileManager에 원하는 파일이 tempDirectory에 있는지 물음 -> 있으면 tempDirectory에서 사용, 없으면 다운받음 but, tempDir에 저장
UserDefaults
 https://ios-development.tistory.com/702
```
간단한 설정값인가? ➡️ **UserDefaults**를 사용하세요.
파일(이미지, 문서 등)이거나 크기가 큰 데이터인가? ➡️ **FileManager**를 사용하세요.

왜 그럴까?

데이터 형식과 위치: UserDefaults는 데이터를 **.plist(Property List)**라는 정해진 형식의 단일 파일에 키-값 형태로 저장합니다. 시스템이 이 파일을 관리하며, 최적화되어 있어 간단한 데이터에 빠르게 접근할 수 있습니다.

성능: UserDefaults에 수 메가바이트(MB)가 넘는 큰 데이터(이미지, 동영상 등)를 저장하면, 이 데이터를 처리하는 과정에서 앱의 전반적인 반응 속도가 저하될 수 있습니다. FileManager는 데이터를 파일 그대로 디스크에 저장하므로, 시스템에 주는 부담이 적습니다.
```

```
🧐 UserDefaults 성능과 데이터 크기 관계
1. 저장 방식

UserDefaults는 내부적으로 plist(XML) 파일에 직렬화(serialize)해서 저장합니다.

앱 실행 시 해당 plist 파일을 메모리로 로드해두고, 읽기/쓰기 작업을 할 때는 메모리에서 처리 → 주기적으로 파일에 동기화(synchronize)합니다.

2. 성능 이슈

작고 단순한 값(Bool, Int, String, Double, 작은 Array/Dictionary)은 거의 성능 문제가 없습니다.

하지만 데이터가 커지면(수십 KB~MB 이상):

앱 시작 시 UserDefaults 전체를 메모리에 로드해야 해서 런치 타임 지연

set() 호출 후 내부 plist 직렬화가 커져서 쓰기 성능 저하

iCloud Key-Value Store와 동기화 중인 경우, 불필요하게 많은 네트워크 트래픽 발생

즉, UserDefaults는 대량 데이터 저장에 최적화되지 않음.

3. 권장 크기

Apple 문서에서는 명확한 "최대 크기" 제한을 두진 않았지만, 일반적으로 수 KB 정도까지만 쓰는 게 안전합니다.

업계에서는 보통 한 key-value 쌍에 수십 KB 이상은 피하라는 가이드가 많습니다.

4. 큰 데이터를 쓰고 싶다면?

FileManager → JSON, Data 파일로 저장

CoreData / Realm → 구조화된 대량 데이터
```

<h1><center> iOS interview </center></h1>

###### tags: `💻 면접 질문`
###### date: `2025-09-06`

> [iOS interview](https://github.com/JeaSungLEE/iOSInterviewquestions)

# 개요 

> 레벨 1 질문 리스트 정리하기 

### 태윤 (그림)

#### 이야기 하면 좋을 것
1. 복잡한 UI에서 Auto Layout 성능이 느려질 때 어떻게 최적화하시겠습니까?
- 언제 느려질까? 어느 케이스에 느려질까? => Auto Layout 때문에 느려지나? 복잡한 UI 라면..? => Hitching..?
- StackView vs No StackView (Auto Layout) => Hidden 처리시 StackView가 더 빠르다. remakeConstraint 보단 StackView를 사용할 듯..?

- View update 상황과 관련이 있을까?
- (안진 궁금점)
  - 복잡한 UI에서 Auto Layout 성능이 느려지는 원인
    - hidden과 비교한다면,
    - **생성 자체가 비싸**니 시작점부터 성능 차이가 있아
    - 복잡한 UI -> 생성에 대한 설정 줄어들며 최적화
  - 성능이 느려짐을 체감하는 순간 상황?
    - 동적으로 View를 만들다보니, 지웠다가 다시 재생성하는 경우 관리/생성 측면에서
    - Constraint 동적 변화가 버벅임이 심하다 -> StackView로 만드는 작업을 했다
  - AutoLayout 구현 방식이 어떻길래 UI 그리는게 느려지는걸까? O(N^3)


2. SwiftUI에서 **Delegate** 패턴을 대체하는 방법은?
- 데이터 전달을 어떻게 하는가? -> Combine으로 처리를 변환시키나? / AsyncStream
- UIKit 뷰 간 통신에서 사용하는 Delegate -> View Binding, escaping closure, @Environment로 상위 객체 전달


19-2. deinit 메서드는 언제 호출되며, 어떤 역할을 하나요?
- deinit: 현재 객체가 사라지는지 정도만 - print()
- (안진) 뭐 상황이 아주 많겠지만.. 개인적으로 가장 최근에는 화면 애니메이션 처리가 아주 많은데 Task 를 property로 생성하고 deinit 될때 제거 처리를 해주는 경우가 있었습니다
- 네트워크 쿠키 제거 -> WebView DataSource 
- <!-- 키보드 subscribe 해제 -->

timer <- viewcontoller deinit
그림 생각: viewcontroller deinit -> timer도 사라짐 -> timer.invalidate deinit에서 부를 필요가? / viewdiddisappear에서 timer invalidate 호출

이오 생각: timer가 viewController를 알고 있음 -> viewController는 deinit이 불림
- TimerManager 만든 적 있는데 deinit에 stop() 있네요
ㄴ stop()을 부른 이유가 있을까요? 끝나야 하니까요? deinit 후에 타이머가 죽으면..? ? 죽어야 하니까 ..? ..?

------------------------------------------

12-2. 의존성 관리를 통해 얻을 수 있는 이점은 무엇인가요?
9-2. 프로토콜 확장(Protocol Extension)을 사용하는 이유는 무엇인가요?

#### 알아보면 좋을 것
5. Swift에서 클로저(Closure)란 무엇이며, 어떻게 사용하나요?
2-1. 클로저의 캡처(Capture) 기능은 무엇인가요?
2-2. @escaping 클로저와 non-escaping 클로저의 차이점은 무엇인가요?
19-1. Retain Cycle이 발생하지 않도록 방지하는 방법은 무엇인가요?
28. 여러 화면에서 동일한 알림 기능을 사용해야 할 때, 싱글톤 패턴 대신 어떤 디자인 패턴을 고려해볼 수 있나요?
28-1. Observer 패턴과 NotificationCenter의 관계는 무엇인가요?
28-2. Dependency Injection을 사용하면 싱글톤 대비 어떤 이점이 있나요?
28-3. Protocol을 활용한 의존성 역전은 테스트 가능성을 어떻게 향상시키나요?
27. SwiftUI에서 @State 변수를 변경했는데 화면이 업데이트되지 않는다면 어떤 문제를 의심해야 하나요?
=> Thread가 MainThread인지 / 변수 객체가 class인가? (Identifiable 한가..?)


### 안진 (이오)
1. Swift에서 프로토콜(Protocol)이란 무엇이며, 어떻게 활용하나요?
  1-1. 프로토콜 지향 프로그래밍(Protocol-Oriented Programming)의 장점은 무엇인가요? -> 실제로 체감하는 프로토콜의 장점이 있는지?

2. iOS에서 델리게이트 패턴(Delegate Pattern)은 어떤 목적
  2-1. 콜백 함수의 차이점
  2-2. 옵저버 패턴
  
(저는 두 분 적어두신 이야기를 따라 이야기하겠습니다)

### 태현 (데릭)

**레벨 1**

1. iOS 앱의 생명주기(App Life Cycle)에 대해 설명해주세요.

- Responder와 ResponderChain
- First Responder

- https://seizze.github.io/2019/11/26/iOS%EC%9D%98-Responder%EC%99%80-Responder-Chain-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0.html

2. 복잡한 UI에서 Auto Layout 성능이 느려질 때 어떻게 최적화하시겠습니까?

<!-- - 제약조건 hugging vs compression -->
- setneedslayout vs layoutifneeded

3. Swift에서 클로저(Closure)란 무엇이며, 어떻게 사용하나요?

- 트레일링 클로저(Trailing Closure) 문법은 어떤 경우에 유용한가요? 이게 머야? 

4.테이블뷰의 delegate 메서드가 호출되지 않는 문제를 어떻게 디버깅하시겠습니까?

- layout이 맞지 않으면 Cell을 등록해도 발생하지 않는 문제

- Delegate vs Closure vs Combine을 선택하는 기준은?
  - 1:1 통신과 1:N 통신에서 각각 어떤 패턴이 적합한가요?

5. Swift의 기본 데이터 타입과 컬렉션(Collection) 타입에는 어떤 것들이 있나요?

- 값 타입(Value Type)과 참조 타입(Reference Type)의 차이점은 무엇인가요?
- 구조체(Struct)와 클래스(Class)의 사용 시기는 어떻게 구분하나요?
- 열거형(Enum)의 원시값(Raw Value)과 연관값(Associated Value)은 무엇인가요?

7. Swift에서 프로토콜(Protocol)이란 무엇이며, 어떻게 활용하나요?

- Swift는 왜 프로토콜 지향 프로그래밍(Protocol-Oriented Programming)이라 하나요? 


8. API 호출이 실패했을 때 재시도 로직을 구현하려면 어떻게 하시겠습니까?

9. 동시성 프로그래밍에서 동기(Synchronous)와 비동기(Asynchronous)의 차이점은 무엇인가요?



------------

