inflearn logo
강의

Course

Instructor

Allen Swift Concurrency for Swift 6 (Part-2)

ImageProject 관련 문의

Resolved

59

hyeonlee95123780

1 asked

0

안녕하세요,

ImageProject 관련하여 설명해주신 내용 중 궁금한 점이 있어 문의드립니다.

 

1.

await imageDownloader.cache.keys.contains(url)

let keys = await imageDownloader.cache.keys

if keys.contains(url)

중에

후자를 사용하는 것이 액터 재진입에 있어 더욱 안정적인 코드라고 말씀하셨는데요

액터 재진입 관점에서는 전자의 코드가 actor isolated 된 상태에서 contain 여부까지 확인이 되고

후자의 코드는 key값을 가져오고 contain 여부를 판단하는 시점에 actor에 다른 태스크가 진입하여 값이 변경될 가능성이 있기 때문에

전자가 더 안정적인 코드가 아닌가요?

어떤 이유 때문에 후자의 코드를 사용해야하는지 다시 설명해주시면 감사하겠습니다.

 

 

2.

privatelet storage = DiskStorage()

의 코드는

Global actor 'ImageDatabase'-isolated default value in a actor-isolated context

오류를 발생시켜 storage를 추후에 초기화 하도록 수정해주셨는데요

privatelazyvar storage = DiskStorage()

으로 하면 storage가 호출되는 시점에 초기화 되니 그 때에는 이미 actor의 격리영역이 정해진 상태라 이상이 없을 것이라고 생각했습니다만
같은 오류가 발생하더라구요.

@ImageDatabase 로 격리되어 있기 때문에 비동기적으로 초기화되어야 하지만 그렇지 못하기 때문에 오류가 발생하는 것인지 궁금합니다.

 

감사합니다.

ios swift 동시성 async-await concurrency

Answer 1

0

allen

네 안녕하세요 ㅎㅇ 님.

<1번 질문에 대한 답변>
결국, 해당 코드에서는.. 다른 객체(imageDownloader)가 가지고 있는 캐시에 URL을 가지고 있는 여부의 확인을 하려고 하는 것인데, Swift Concurrency에서는 내부적으로 await 코드의 시점에 재진입 문제가 발생할 수 있다는 것이 문제죠.

결국 "요청 시작" 시점부터 ===> "포함 여부 확인 완료" 시점까지 중간에 await 코드가 포함되어 있는지의 여부가 중요합니다.

1) 번의 경우

let keys = await imageDownloader.cache.keys
        
if keys.contains(url) {
     return try await imageDownloader.image(from: url)
}

요청 시점 ==== await (O) ====> 캐시 정보(keys) 가져옴 ==== await (X) ====> 포함 여부

 

요청 시점에서 캐시 정보를 가져 올때까지는 await 코드가 있긴 하지만, 실제 캐시 정보를 확인한 시점 이후에는 그 캐시 정보가 바뀌지 않는다는 것을 가정하는 코드라고 보시면 되고요. (따라서, 일단 캐시 정보의 스냅샷을 확인한 시점이후 캐시 데이터는 변할 틈이 없다고 보면 됨)

 

2) 번의 경우

if await imageDownloader.cache.keys.contains(url) {
      return try await imageDownloader.image(from: url)
}

요청 시점 ==== await (O) ====> contains호출 시점 ==== await (O) ====> 포함 여부

 

2번의 경우는.. 어떻게 보면 요청 시점부터 확인 시점까지 전 구간에 걸쳐서, await코드가 있는 것이기 때문에.. 해당 객체(imageDownloader)에 여러 요청(메서드 호출 등)이 있다면, 실제 contains메서드를 호출한 시점부터도 재진입 문제가 발생할 수 있다는 것이 문제라고 보시면 됩니다.

 

(쉽게 말씀드리면.. (실제 코드가 그렇다는게 아니라) 논리적으로 아래 코드와 비슷하다는 뜻입니다.)

let keys = await imageDownloader.cache.keys
let isCashed = await keys.contains(url)        
if isCashed {
     return try await imageDownloader.image(from: url)
}

그렇기 때문에, 재진입 문제와 관련해서는 1번 코드가 더 안정적인 코드라고 말씀드리고 있는 겁니다.

 

<2번 질문에 대한 답변>

네네, lazy var로 선언하시더라도 (글로벌 액터로 격리된) DiskStorage 클래스의 경우, DiskStorage타입의 존재 자체가 ImageDatabase에 의존하고 있기 때문에 발생하는 문제라고 보시면 됩니다.


ImageDatabase가 먼저 초기화 되어야 ==> DiskStorage 존재 가능 ==> 존재하려면 ImageDatabase 필요

이런식으로 순환해서 의존(필요)하고 있기 때문이라고 보시면 될 것 같습니다. lazy로 선언했다고 해서 어차피 컴파일러 자체가 논리적인 모든 순서를 파악할 수 있는 것은 아니기 때문에, 컴파일러는 DiskStorage 타입 자체의 초기화 문제로 바라보고 있는 것입니다.

 

 

감사합니다. :)

수강 기간 연장 문의

0

28

1

수강연장부탁드려도될까요..

0

42

2

Combine Playground 에서 실행 시

0

58

2

레디선 테스트코드에서 채널이름은 없어도 되는건가요?

0

39

2

70강 - 글로벌 액터로 격리된 Protocol 을 extension 에서 conform 시 타입 본체의 격리 수준 질문

0

42

1

searchable이 화면 하단에 위치해요

0

62

2

모니터와 synchronized, ReentrantLock, 원자적연산 CAS관련해서 추가적으로 더 깊게 공부했는데 제가 이해한 것이 맞나요??

0

85

1

mac python 3.10 - permission denied

0

54

1

Future cancel기능을 사용했지만 interrupt가 발생하지 않을 때 어떻게 처리해야하나요?

0

73

2

Drawing Cycle 관련 질문

0

72

1

2.스레드 생성과 실행 - 17P 그림 문의

0

74

2

자바 동시성 현업에서 사용예시가 궁금합니다

0

136

1

20강 Task 내부에서 nonisolated async 호출 예제 질문드립니다

0

78

2

19강 Actor 의 동작 관련해 질문드립니다

0

83

2

Actor에서 Task vs Task.detached 사용 시 재진입 문제 질문

0

104

2

18강 NSCache 예시 질문

0

99

2

Task 클로저 내 `non-Sendable` 값 타입 접근 시, 캡처 리스트가 정의된 Task 순서에 따른 컴파일러 에러 차이

0

118

1

3강 스레드 제어권 관리 질문드립니다

0

72

1

10번 강의 관련하여 질문드립니다.

0

71

2

10강 내용 문의드립니다.

0

84

2

강의를 들으면서 생긴 질문이 있습니다.

0

136

3

협력적 쓰레드 풀에서 쓰레드 운영방식 질문 드립니다.

0

81

1

안녕하세요. 액터 홉핑 관련 질문드립니다.

0

157

1

재개될 때 스레드 변경시 왜 컨텍스트 스위칭이 발생하지 않는 건가요?

0

315

2