티스토리 뷰

Swift

Unowned Optional References

Zedd0202 2021. 2. 22. 22:56
반응형

안녕하세요 :) Zedd입니다.

저번 글에서도 봤듯이, Swift 5.0부터 unowned가 Optional을 지원하게 되었습니다.

 

unowned는 weak와 달리  참조하는 인스턴스가 메모리에서 해제되어도 자동으로 nil로 만들어주지 않기 때문에

Optional을 지원하는게 딱히..와닿지는 않는데요.

Swift공식문서에 있는 Unowned Optional References를 공부해보겠습니다.

 

⚠️주의 : 저도 이해하지 못한 부분이 있습니다. 읽으실 때 주의해주세요.⚠️

 

Unowned Optional References


- ARC ownership model 측면에서 unowned optional reference와 weak reference는 동일한 컨텍스트 내에서 사용될 수 있음.

차이점 : unowned optional reference를 사용할 때 항상 유효한 객체를 참조하거나 nil로 설정되어있는지 확인해야함.

애플 예제인데요. 제가 한글로만 바꿔봤습니다. (더 헷갈리시는거 아니겠죠..)

학교에는 과가 있고, 과마다 들어야 하는 강의가 있습니다.

학과 ➞ 학과의 이름, 강의들 프로퍼티

강의 ➞ 강의 이름, 어느 학과에 속하는지, 다음강의

이런 프로퍼티들이 있는거에요. 

학과를 먼저 보겠습니다.

 

[학과]

학과를 보면 "강의들"이 있는데, 앞에 weak나 unowned 키워드가 없는걸 봐서는

강하게 참조하고 있는 것을 알 수 있습니다.

생각해보면, 학과 안에 강의가 있는것이지, 강의 안에 학과가 있는게 아니잖아요? 

ARC ownership model에서는 학과가 강의들을 소유하는 것입니다.

 

[강의]

강의에서는 2개의 unowned 프로퍼티가 있네요.

1. 학과

- 강의는 반드시 어느 학과에 속하게 되므로 학과 프로퍼티는 Optional이 아닙니다.

- 학과가 강의를 소유하는것이지 강의가 학과를 소유하는것이 아니죠? 학과가 나보다 메모리에서 먼저 해제될 일은 없기 때문에 unowned로 선언해준 것 같습니다. 

 

2. 다음_강의

- 일부 강의에서는 다음 강의가 없을 수 있으므로 다음_강의 프로퍼티는 Optional입니다.

왜 unowned로 선언되었는지는 하단에서 보도록 하겠습니다. 

 

학과를 하나 만들겠습니다.

오버워치학과를 하나 만들고

강의를 만듭니다. (초급은 없음ㅋ)

입문의 다음강의에 중급을,

중급의 다음강의에 고급을 넣습니다.

고급 다음 강의는 없으므로 nil입니다. (초기값이 nil임) 

그리고 오버워치학과의 강의들에 만든 강의들을 넣어줍니다.

 

그럼 이런 다이어그램이 나옵니다!

unowned optional reference가 nil일수 있다는 점을 제외하면 unowned reference가 ARC에서 수행하는 것과 동일하게 작동합니다. 

non-optional unowned references와 마찬가지로 nextCourse가 항상 할당해제 되지 않은 과정을 참조하도록 해야합니다.

 

Q : 그래 알겠어..알겠어...왜 다음_강의를 unowned로 선언했는데? 

A : 

다음_강의가 Optional 인것은 이해가 가실겁니다.

강의에 다음 강의가 없을 수 있기 때문이죠.

그럼 이 다음_강의를 

1. strong

2. weak

3. unowned

어떻게 선언해야 좋을지 보겠습니다. 

 

1. strong

오른쪽 파란색 unowned optional은 무시해주세요;;

만약 strong으로 잡혀있다면

1. 초급의 다음 강의(중급)가 없어짐

2. 초급이 메모리에서 해제가 되기 전까지 중급은 메모리에서 해제되지 않음. (강한 참조 때문에 RC가 증가했기 때문)

➞ strong은 적절하지 않습니다.

 

2. weak 

기존에는 unowned로 선언되어있는데요.

분명 애플문서의 의도가 있겠지만..제가 이해를 못한건지 ㅠ..저는 다음_강의를 unowned로 선언해서 얻는 이점..을 모르겠어요.

차라리 weak인게 훨씬 자연스럽지 않나요?

 

어떤 사정이 생겨서 입문의 다음강의인 중급이 nil이 되었다고 칩시다.

학과의 강의들 프로퍼티가 중급 인턴스를 잡고 있으므로 

강의들에서도 nil로 할당해야 비로소 중급 강의가 메모리에서 사라지게 됩니다.
(이렇게 하려면 학과의 강의들 프로퍼티가 [Course?]로 되어야겠죠)

그럼 

1. 입문 강의의 다음_강의가 중급강의였음.

2. 중급 강의가 메모리에서 해제됨

3. 입문 강의의 다음_강의가 nil이됨

이게 자연스러운거 아니에요..?

 

3. unowned 

unowned로 해버리면 중급 강의가 메모리에서 사라졌을 때

입문 강의의 다음_강의가 nil이 되지 않아, 

에러가 난단 말이죠..??

 

차라리 이전_강의라고 했으면 더 unowned에 맞지 않았을까요..!?

이전_강의는 무조건 나보다 먼저 해제될 일이 없는 그런 느낌이니깐ㅎ..

 

그래서 저는 잘...모르겠습니다..다음_강의를..unowned로 선언해준 이유를..

하지만 마음으로 이해했다고 칩시다⁉️

 

Swift 5.0이전, unowned가 Optional을 지원하지 않았기 때문에

다음_강의가 있을수도 있고 없을 수도 있는 상황에서는

strong Optional

weak Optional

이 2가지 선택지 밖에 없었어요. 

하지만 Swift 5.0이후 부터 unowned Optional도 선택지에 추가가 된거죠!

 

[Swift 5.0이전]

 

unowned로 선언되어있고, 이미 메모리에서 없어져버린 인스턴스를 가리키고 있을 때 

이 tenant에 접근하면 무조건 에러가 났었어요. 

근데? nil로도 못만들어 

왜냐? Optional을 지원안하거든 ㅠ

 

[Swift 5.0이후]

unowned로 선언되어있고, 이미 메모리에서 없어져버린 인스턴스를 가리키고 있을 때 

혹시 모를 위험을 제거하고 싶다면, tenant를 unowned Optional로 선언한다음 내가 명시적으로 nil을 줄 수 있게 된겁니다.

내가 nil을 할당해버리면, tenant에 접근해도 이제 에러가 안나겠죠!!

(물론 nil할당 안하고 tenant에 접근하면 crash🔥)

 

Unowned Optional References에 대해서 조금 감이 오시나요..!?

그리고 이 StackOverFlow에서 본건데, 

1. weak로 선언

2. 저번 글에서 배웠듯이, 참조하고 있는 인스턴스가 메모리해서 해제되면 ARC가 자동으로 nil을 할당.

 이것도 하나의 작업임. 관련 weak 참조 친구들을 전부 추적(Track)하고 있어야함. 

 원치않는 오버헤드

 고객-신용카드 예제처럼 신용카드는 고객보다 절대..! 절대 먼저 메모리에서 해제될 일이 없다는 걸 보장 할 수 있다면, weak로 선언하는것은 시간/공간/계산의 복잡성을 낭비하는 것임(위에서 말한 추적 비용)

 이럴 때 unowned optional을 사용하면 

1) 내가 unowned로 참조하고 있는 인스턴스가 절대 먼저 메모리에서 해제 될 일이 없다는 것을 "의도"로 나타낼 수 있음.

2) 위에서 언급한  시간/공간/계산의 복잡성을 제거할 수 있음.

이렇게 2가지 이점을 얻을 수 있게 된다고 해요.

weak참조에 대한 오버헤드는 그리 크지 않을 것 같긴 한데...추적하고 있는 참조 수에 따라 다르겠죠..!?!!?

 

# 참고

제가 위에서

이 사진을 첨부했었는데요.

애플 공식 문서에서는

이렇게 나와있습니다.

제가 만든거 / 애플 공식 문서

네..빨간 박스를 주목해주시면..저는 nil을 넣었는데, 애플 문서에는 인스턴스가 들어있는 것을 볼 수 있습니다.

이걸 보면서 굉장히 많은...고뇌를 했는데요..

코드에서 볼 수 있다시피, 고급의 다음_강의는 nil입니다.

그럼 이렇게 되는게 맞지 않냐고 ㅠ...

weak설명 할 때는 nil로 잘 들어가있는데..

Zedd : 왜...왜...nil이 아니지? 내가 지금 unowned에 대해 아직 잘 모르는건가? 그래 unowned가 좀 특별하니까 뭔가 다른가...?
애플 문서가 잘못될리가 없는데...무려 Swift.org자나..이 문서가 잘못될 수 있을까..? 아니 근데 왜 nil이 아니지..??

아무튼 엄청 고민하다가

Swift 포럼에 글을 올렸습니다.

감사하게도 댓글이 달렸따...암튼 nil...이라고 저는 지금 믿고 있는데..

+ ) 공식문서도 업데이트 되었네요!

 

 

Unowned Optional References에 대해서 틀린 부분이 있다면 댓글로 남겨주세요!

 

참고 : docs.swift.org/swift-book/LanguageGuide/AutomaticReferenceCounting.html

반응형
댓글
  • 프로필사진 익명 비밀댓글입니다 2021.02.23 09:41
  • 프로필사진 익명 비밀댓글입니다 2021.02.23 12:37
  • 프로필사진 익명 비밀댓글입니다 2021.02.23 13:38
  • 프로필사진 익명 비밀댓글입니다 2021.02.24 12:34
  • 프로필사진 숲숲이 왜 unowned 인지 답을 찾으셨나요?
    글읽고 고민해봐도 모르겠어요
    2021.02.27 18:09
  • 프로필사진 Favicon of https://zeddios.tistory.com BlogIcon Zedd0202 아뇨 다시 봐도 잘 모르겠어요~ ㅠㅠ 2021.02.27 18:20 신고
  • 프로필사진 Favicon of https://oscar.tistory.com BlogIcon 오스카 그런데 다 맞게 설명하신거 같은데 어떤 부분이 이상한건가요? 2021.02.28 11:26 신고
  • 프로필사진 Favicon of https://zeddios.tistory.com BlogIcon Zedd0202 아 다음_강의를 unowned로 선언한 부분이 이해가 잘 안가고 있어요 ㅎㅎ 2021.02.28 13:05 신고
  • 프로필사진 Favicon of https://oscar.tistory.com BlogIcon 오스카 쓴 글에서 설명한 것처럼

    1) 내가 unowned로 참조하고 있는 인스턴스가 절대 먼저 메모리에서 해제 될 일이 없다는 것을 "의도"로 나타낼 수 있음.

    2) 위에서 언급한 시간/공간/계산의 복잡성을 제거할 수 있음.

    - 이게 그 답이긴 한데요. 혹시 2)가 이상하다면 보통은 이럴 일이 없어서 그런데, 객체 그래프가 커다란 앱이라면 이게 유의미한 오버헤드가 될 수도 있습니다.

    아... 다시 글을 보니까 다음 강의가 삭제된 경우이군요. 사실 이건 예제를 만들다 보니 그렇게 된거 같긴 하군요. 예제에서 저런 식으로 삭제가 될려면 courses 타입도 [Course?]가 되어야 하고, Course의 init도 Optional이 되어야 할 거 같은데 음...

    만일 이런 비슷한 형태로 만든다면, zedd 말대로 weak로 하던가, private으로 하고 별도 메서드로 조작하는게 안전하겠네요.
    2021.02.28 21:01 신고
  • 프로필사진 weak 참조의 경우 life time의 관점에서 내가 참조하는 인스턴스가 더이상 메모리에 존재하지 않을때 nil을 할당하기 위해서 optinal 로 선언되는 것이고.
    unowned optional의 경우 life time이 아니라, 논리적인 관계에 초점을 맞춘거라고 전 이해했어요. 위의 예에서처럼 다음 강의가 있을 수도 없을 수도 있는 것처럼요.
    2021.06.04 20:06
댓글쓰기 폼
반응형
Total
4,016,118
Today
610
Yesterday
2,463