๐ ์ค์ํํธ vs ์ค๋ธ์ ํฐ๋ธ-C: ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ์ ARC์ ํจ์จ์ฑ ๋ํํ! ๐ง

๐ ์ค์ํํธ vs ์ค๋ธ์ ํฐ๋ธ-C: ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ์ ARC์ ํจ์จ์ฑ ๋ํํ! ๐ง
์๋ , ์น๊ตฌ๋ค! ์ค๋์ ์ ๋ง ํฅ๋ฏธ์ง์งํ ์ฃผ์ ๋ก ์ฐ๋ฆฌ ํจ๊ป iOS ๊ฐ๋ฐ์ ์ธ๊ณ๋ก ๋ ๋๋ณผ ๊ฑฐ์ผ. ๋ฐ๋ก ์ค์ํํธ์ ์ค๋ธ์ ํฐ๋ธ-C์ ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ ๋ฐฉ์์ ๋ํด ๊น์ด ํํค์ณ๋ณผ ๊ฑฐ๊ฑฐ๋ . ํนํ ARC(Automatic Reference Counting)๋ผ๋ ๋ ์์ด ์ด๋ป๊ฒ ์ด ๋ ์ธ์ด์์ ํจ์จ์ ์ผ๋ก ์๋ํ๋์ง ์์๋ณผ ๊ฑฐ์ผ. ์ค๋น๋๋? ๊ทธ๋ผ ์ถ๋ฐ~! ๐
๐ ์ ๊น! ์๊ณ ๊ฐ์! ์ด ๊ธ์ '์ฌ๋ฅ๋ท'์ '์ง์์ธ์ ์ฒ' ๋ฉ๋ด์ ๋ฑ๋ก๋ ์์ ์ด์ผ. ์ฌ๋ฅ๋ท์ ๋ค์ํ ์ฌ๋ฅ์ ๊ฑฐ๋ํ๋ ํ๋ซํผ์ธ๋ฐ, ์ฌ๊ธฐ์ ์ฐ๋ฆฌ๊ฐ ๋ฐฐ์ฐ๋ ํ๋ก๊ทธ๋๋ฐ ์ง์๋ ์ถฉ๋ถํ ์ฌ๋ฅ์ด ๋ ์ ์์ง. ์ด์ฉ๋ฉด ๋์ค์ ๋๋ iOS ๊ฐ๋ฐ ์ฌ๋ฅ์ ๊ณต์ ํ ์ ์์์ง๋ ๋ชฐ๋ผ!
๐ Chapter 1: ์ค์ํํธ์ ์ค๋ธ์ ํฐ๋ธ-C, ๋๊ตฌ์ผ ๋? ๐ค
์, ์ฐ๋ฆฌ์ ์ฃผ์ธ๊ณต๋ค์ ๋จผ์ ์๊ฐํ ๊ฒ. ํ ์ฝ๋์๋ ์ค๋ธ์ ํฐ๋ธ-C, ๋ค๋ฅธ ์ฝ๋์๋ ์ค์ํํธ๊ฐ ์์ด. ์ด ๋์ ๋ง์น ํ์ ์ฒ๋ผ iOS ๊ฐ๋ฐ์ ์ค์ฌ์ ์ ์์ง.
๐ฐ๏ธ ์ค๋ธ์ ํฐ๋ธ-C: ๊ณ ์ ์ ๋ฏธํ
์ค๋ธ์ ํฐ๋ธ-C๋ ๋ง์น ์ฐ๋ฆฌ ํ ์๋ฒ์ง ๊ฐ์ ์กด์ฌ์ผ. 1983๋ ์ ํ์ด๋ฌ์ผ๋๊น ์ ๋ง ์ค๋๋์ง? ํ์ง๋ง ๋์ด๊ฐ ๋ง๋ค๊ณ ๋ฌด์ํ๋ฉด ์ ๋ผ. ์ด ๋ ์, ์์ง๋ ๋ง์ iOS ์ฑ์ ๊ธฐ๋ฐ์ด ๋๊ณ ์๊ฑฐ๋ .
- C ์ธ์ด๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๋ง๋ค์ด์ก์ด
- ๊ฐ์ฒด ์งํฅ ํ๋ก๊ทธ๋๋ฐ์ ์ง์ํด
- ๋์ ํ์ดํ์ด ๊ฐ๋ฅํด (๋ฐํ์์ ํ์ ๊ฒฐ์ )
- ๋ฉ์์ง ์ ๋ฌ ๋ฐฉ์์ ์ฌ์ฉํด
์ค๋ธ์ ํฐ๋ธ-C์ ํน์ง ์ค ํ๋๋ ๋ฐ๋ก '๊ดํธ ์ฌ๋'์ด์ผ. ์ฝ๋๋ฅผ ๋ณด๋ฉด ๊ดํธ๊ฐ ์ ๋ง ๋ง์ด ๋ณด์ผ ๊ฑฐ์ผ. ์๋ฅผ ๋ค์ด๋ณผ๊น?
NSString *greeting = [[NSString alloc] initWithString:@"์๋
, ๋๋ ์ค๋ธ์ ํฐ๋ธ-C์ผ!"];
NSLog(@"%@", greeting);
์ด๋? ๊ดํธ๊ฐ ๊ฝค ๋ง์ง? ์ด๊ฒ ๋ฐ๋ก ์ค๋ธ์ ํฐ๋ธ-C์ ๋งค๋ ฅ์ด๋ผ๊ณ ํ ์ ์์ด. ๋ณต์กํด ๋ณด์ด์ง๋ง, ์ด ๊ตฌ์กฐ๊ฐ ์ค๋ธ์ ํฐ๋ธ-C์ ๊ฐ๋ ฅํ ๊ธฐ๋ฅ๋ค์ ๊ฐ๋ฅํ๊ฒ ํด์ฃผ๋ ๊ฑฐ์ง.
๐ ์ค์ํํธ: ๋ชจ๋ํ ์ ์
๋ฐ๋ฉด์ ์ค์ํํธ๋ ์ฐ๋ฆฌ์ ํํ ์ฌ์ด ๊ฐ์ ์กด์ฌ์ผ. 2014๋ ์ ์ ํ์ด ์ ๋ณด์ธ ์ด ์ธ์ด๋ ํ๋์ ์ด๊ณ ์์ ํ ํ๋ก๊ทธ๋๋ฐ์ ์งํฅํด.
- ๊ฐ๊ฒฐํ๊ณ ์ฝ๊ธฐ ์ฌ์ด ๋ฌธ๋ฒ
- ํ์ ์์ ์ฑ (์ปดํ์ผ ์์ ์ ํ์ ์ฒดํฌ)
- ์ฑ๋ฅ ์ต์ ํ
- playground ๊ธฐ๋ฅ์ผ๋ก ์ฝ๋ ์คํ์ด ์ฌ์
์ค์ํํธ๋ '์ฌํํจ'์ ์ถ๊ตฌํด. ์ค๋ธ์ ํฐ๋ธ-C์ ๊ฐ์ ์ฝ๋๋ฅผ ์ค์ํํธ๋ก ์์ฑํ๋ฉด ์ด๋ ๊ฒ ๋ณํด:
let greeting = "์๋
, ๋๋ ์ค์ํํธ์ผ!"
print(greeting)
์ด๋? ํจ์ฌ ๊ฐ๊ฒฐํ์ง? ์ด๊ฒ ๋ฐ๋ก ์ค์ํํธ์ ๋งค๋ ฅ์ด์ผ. ์ฝ๊ธฐ ์ฝ๊ณ , ์ฐ๊ธฐ๋ ์ฝ์ง.
๐ก ์ฌ๋ฅ๋ท Tip! ํ๋ก๊ทธ๋๋ฐ ์ธ์ด๋ฅผ ๋ฐฐ์ฐ๋ ๊ฒ๋ ํ๋์ ์ฌ๋ฅ์ด์ผ. ์ฌ๋ฅ๋ท์์๋ ์ด๋ฐ ํ๋ก๊ทธ๋๋ฐ ์คํฌ์ ๊ณต์ ํ๊ณ ๊ฑฐ๋ํ ์ ์์ด. ์ค์ํํธ๋ ์ค๋ธ์ ํฐ๋ธ-C๋ฅผ ๋ง์คํฐํ๋ฉด, ๋๋ ์ฌ๋ฅ ํ๋งค์๊ฐ ๋ ์ ์์ ๊ฑฐ์ผ!
๐ง Chapter 2: ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ, ์ ์ค์ํ ๊น? ๐ค
์, ์ด์ ์ฐ๋ฆฌ์ ์ฃผ์ธ๊ณต๋ค์ ๋ง๋ฌ์ผ๋ ๋ณธ๊ฒฉ์ ์ผ๋ก ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ์ ๋ํด ์๊ธฐํด๋ณผ๊น? ๊ทผ๋ฐ ์ ๊น, ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ๊ฐ ๋ญ๊ธธ๋ ์ด๋ ๊ฒ ์ค์ํ ๊ฑธ๊น?
๐ ๋ฉ๋ชจ๋ฆฌ, ์ฐ๋ฆฌ ์ง ๊ฐ์ ์กด์ฌ
๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ฐ๋ฆฌ ์ง์ด๋ผ๊ณ ์๊ฐํด๋ณด์. ์ง์ ๋ฌผ๊ฑด์ ๋ค์ฌ๋์ ๋๋ง๋ค ๊ณต๊ฐ์ ์ฐจ์งํ์ง? ํ๋ก๊ทธ๋จ๋ ๋ง์ฐฌ๊ฐ์ง์ผ. ๋ณ์๋ฅผ ๋ง๋ค๊ณ , ๊ฐ์ฒด๋ฅผ ์์ฑํ ๋๋ง๋ค ๋ฉ๋ชจ๋ฆฌ๋ผ๋ '์ง'์ ๋ญ๊ฐ๋ฅผ ๋ค์ฌ๋๋ ๊ฑฐ์ผ.
๊ทผ๋ฐ ๋ง์ฝ ์ง์ ๋ฌผ๊ฑด๋ง ๋ค์ฌ๋๊ณ ์ ๋ ์น์ฐ์ง ์๋๋ค๋ฉด ์ด๋ป๊ฒ ๋ ๊น? ๋ง์, ๊ฒฐ๊ตญ ์ง์ด ๋ฌผ๊ฑด์ผ๋ก ๊ฐ๋ ์ฐจ์ ๋ฐ ๋๋ ํ๋ ์๊ฒ ๋๊ฒ ์ง. ํ๋ก๊ทธ๋จ๋ ๋๊ฐ์. ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ ๋๋ก ๊ด๋ฆฌํ์ง ์์ผ๋ฉด ํ๋ก๊ทธ๋จ์ด ๋๋ ค์ง๊ฑฐ๋ ์ต์ ์ ๊ฒฝ์ฐ ํฌ๋์๊ฐ ๋ ์๋ ์์ด.
๐ฎ ์ฐ๋ ๊ธฐ ์๊ฑฐ์ ์ค์์ฑ
๊ทธ๋์ ์ฐ๋ฆฌ๋ '์ฐ๋ ๊ธฐ ์๊ฑฐ'๋ผ๋ ๊ฐ๋ ์ ๋์ ํ์ด. ์ค์ ์ํ์์๋ ์ฐ๋ ๊ธฐ๋ฅผ ์ ๋ ๋ฒ๋ฆฌ์ง ์์ผ๋ฉด ์ง์์ด ์๋ง์ด ๋์์? ํ๋ก๊ทธ๋๋ฐ์์๋ ๋ง์ฐฌ๊ฐ์ง์ผ.
- ๋ฉ๋ชจ๋ฆฌ ๋์ ๋ฐฉ์ง: ๋ ์ด์ ์ฌ์ฉํ์ง ์๋ ๊ฐ์ฒด๊ฐ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๊ณ์ ์ฐจ์งํ๋ ๊ฑธ ๋ง์์ค
- ์ฑ๋ฅ ํฅ์: ํ์ ์๋ ๋ฐ์ดํฐ๋ฅผ ์ ๋ฆฌํ๋ฉด ํ๋ก๊ทธ๋จ์ด ๋ ๋น ๋ฅด๊ฒ ๋์ํด
- ์์ ์ฑ ์ฆ๊ฐ: ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ๋ฅผ ์ํ๋ฉด ํ๋ก๊ทธ๋จ์ด ์์์น ๋ชปํ๊ฒ ์ข ๋ฃ๋๋ ์ผ์ ์ค์ผ ์ ์์ด
๐ฑ ํ๊ฒฝ ๋ณดํธ Tip! ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ๋ ๋ง์น ์ฌํ์ฉ๊ณผ ๋น์ทํด. ๋ ์ด์ ํ์ ์๋ ์์์ ํจ์จ์ ์ผ๋ก ์ฌ์ฌ์ฉํ๋ ๊ฑฐ์ง. ์ด๋ฐ ๋ง์ธ๋๋ ํ๋ก๊ทธ๋๋ฐ๋ฟ๋ง ์๋๋ผ ์ค์ ์ํ์์๋ ์ค์ํด. ์ฌ๋ฅ๋ท์์๋ ์ด๋ฐ '์์ ํจ์จ์ฑ'์ ๋ํ ์์ด๋์ด๋ฅผ ๊ณต์ ํ๋ฉด ์ข์ ๊ฒ ๊ฐ์!
๐ฅ ์ฐธ์กฐ ์นด์ดํ : ์ธ๊ธฐ ํฌํํ๊ธฐ
์, ์ด์ ์ฐธ์กฐ ์นด์ดํ ์ด๋ผ๋ ๊ฐ๋ ์ ์๊ฐํ ๊ฒ. ์ด๊ฑด ๋ง์น ์ธ๊ธฐ ํฌํ์ ๋น์ทํด. ์ด๋ค ๊ฐ์ฒด๊ฐ ์ผ๋ง๋ ๋ง์ 'ํฌ'์ ๊ฐ์ง๊ณ ์๋์ง ์ธ๋ ๊ฑฐ์ผ.
๊ฐ์ฒด๊ฐ ์์ฑ๋ ๋๋ง๋ค ์นด์ดํฐ๊ฐ 1 ์ฆ๊ฐํ๊ณ , ๋๊ตฐ๊ฐ ๊ทธ ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ ๋๋ง๋ค ์นด์ดํฐ๊ฐ ๋ ์ฆ๊ฐํด. ๋ฐ๋๋ก ๋๊ตฐ๊ฐ ๊ทธ ๊ฐ์ฒด๋ฅผ ๋ ์ด์ ์ฌ์ฉํ์ง ์๊ฒ ๋ค๊ณ ํ๋ฉด ์นด์ดํฐ๊ฐ 1 ๊ฐ์ํด. ์นด์ดํฐ๊ฐ 0์ด ๋๋ฉด? ๊ทธ๋ ๊ทธ ๊ฐ์ฒด๋ "์, ๋๋ฅผ ์๋ฌด๋ ์ฌ์ฉํ์ง ์๋๊ตฌ๋"๋ผ๊ณ ์๊ฐํ๊ณ ์ค์ค๋ก ๋ฉ๋ชจ๋ฆฌ์์ ์ฌ๋ผ์ ธ.
์ด ๊ทธ๋ฆผ์ ๋ณด๋ฉด, ํ๋์ ๊ฐ์ฒด(์ฃผํฉ์ ์)๊ฐ ์ธ ๊ฐ์ ๋ค๋ฅธ ๊ฐ์ฒด๋ ๋ณ์(์ด๋ก์ ์)์ ์ํด ์ฐธ์กฐ๋๊ณ ์์ด. ๊ทธ๋์ ์ด ๊ฐ์ฒด์ ์ฐธ์กฐ ์นด์ดํธ๋ 3์ด ๋๋ ๊ฑฐ์ง.
๐ค ์๋ vs ์๋: ๋ก๋ด ์ฒญ์๊ธฐ์ ๋ฑ์ฅ
์์ ์๋ ์ด ๋ชจ๋ ๊ณผ์ ์ ํ๋ก๊ทธ๋๋จธ๊ฐ ์ง์ ๊ด๋ฆฌํด์ผ ํ์ด. ๋ง์น ์ง ์ฒญ์๋ฅผ ์ผ์ผ์ด ์์ผ๋ก ํ๋ ๊ฒ์ฒ๋ผ ๋ง์ด์ผ. ํ์ง๋ง ์ง๊ธ์? ๋ก๋ด ์ฒญ์๊ธฐ๊ฐ ์์์!
ARC(Automatic Reference Counting)๊ฐ ๋ฐ๋ก ์ฐ๋ฆฌ์ ๋ก๋ด ์ฒญ์๊ธฐ์ผ. ์ด ๋ ์์ด ์๋์ผ๋ก ์ฐธ์กฐ ์นด์ดํ ์ ๊ด๋ฆฌํด์ฃผ๋ ๊ฑฐ์ง. ๋๋ถ์ ์ฐ๋ฆฌ๋ ๋ ์ค์ํ ์ผ(์ฆ, ์ฑ์ ํต์ฌ ๊ธฐ๋ฅ ๊ฐ๋ฐ)์ ์ง์คํ ์ ์๊ฒ ๋์ด.
๐ ํ์ต Tip! ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ๋ ๋ณต์กํ ์ฃผ์ ์ฒ๋ผ ๋ณด์ด์ง๋ง, ์ดํดํ๊ณ ๋๋ฉด ์ ๋ง ์ฌ๋ฏธ์์ด์ ธ. ์ฌ๋ฅ๋ท์์ ์ด๋ฐ ๊ฐ๋ ์ ์ฝ๊ฒ ์ค๋ช ํ๋ ํํฐ๋ฅผ ์ฐพ์๋ณด๋ ๊ฒ๋ ์ข์ ๋ฐฉ๋ฒ์ด์ผ. ๋๊ตฐ๊ฐ์๊ฒ ์ด ๊ฐ๋ ์ ๊ฐ๋ฅด์น๋ค ๋ณด๋ฉด, ๋ค ์ค๋ ฅ๋ ํจ๊ป ๋์ด๋ ๊ฑฐ์ผ!
๐๏ธโโ๏ธ Chapter 3: ์ค๋ธ์ ํฐ๋ธ-C์ ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ - ๊ณ ์ ์ ํ ๐ช
์, ์ด์ ์ฐ๋ฆฌ์ 'ํ ์๋ฒ์ง' ์ค๋ธ์ ํฐ๋ธ-C๊ฐ ์ด๋ป๊ฒ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๊ด๋ฆฌํ๋์ง ์์ธํ ๋ค์ฌ๋ค๋ณผ ์๊ฐ์ด์ผ. ์ค๋ธ์ ํฐ๋ธ-C๋ ์ค๋๋ ์ธ์ด์ง๋ง, ๊ทธ๋งํผ ๊น์ด ์๋ ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ ๋ฐฉ์์ ๊ฐ์ง๊ณ ์์ด.
๐ฐ๏ธ ์๋ ์ฐธ์กฐ ์นด์ดํ ์ ์๋
์ค๋ธ์ ํฐ๋ธ-C๋ ์ฒ์์ ์๋ ์ฐธ์กฐ ์นด์ดํ ๋ฐฉ์์ ์ฌ์ฉํ์ด. ์ด๊ฑด ๋ง์น ์ง์ ์ฒญ์๋ฅผ ๋ชจ๋ ์์ผ๋ก ์ง์ ํ๋ ๊ฒ๊ณผ ๋น์ทํด. ํ๋ค์ง๋ง, ๊ตฌ์๊ตฌ์ ๊ผผ๊ผผํ๊ฒ ๊ด๋ฆฌํ ์ ์์ง.
ํ๋ก๊ทธ๋๋จธ๊ฐ ์ง์ retain(์ ์ง)๊ณผ release(ํด์ )๋ฅผ ํธ์ถํด์ ๊ฐ์ฒด์ ์๋ช ์ ๊ด๋ฆฌํ์ด. ์ด๋ ๊ฒ ๋ง์ด์ผ:
NSString *myString = [[NSString alloc] initWithString:@"Hello, Objective-C!"];
[myString retain]; // ์ฐธ์กฐ ์นด์ดํธ ์ฆ๊ฐ
// ์ฌ๊ธฐ์ myString ์ฌ์ฉ
[myString release]; // ์ฐธ์กฐ ์นด์ดํธ ๊ฐ์
์ด ๋ฐฉ์์ ์ฅ๋จ์ ์ ํ๋ฒ ์ดํด๋ณผ๊น?
- ๐ ์ฅ์ :
- ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ์ ์ ํํ๊ฒ ์ ์ดํ ์ ์์ด
- ๊ฐ์ฒด์ ์๋ช ์ฃผ๊ธฐ๋ฅผ ๋ช ํํ๊ฒ ์ดํดํ ์ ์์ง
- ๐ ๋จ์ :
- ์ค์๋ก release๋ฅผ ๋นผ๋จน์ผ๋ฉด ๋ฉ๋ชจ๋ฆฌ ๋์๊ฐ ๋ฐ์ํด
- ์ด๋ฏธ ํด์ ๋ ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ๋ฉด ํฌ๋์๊ฐ ๋ ์ ์์ด
- ์ฝ๋๊ฐ ๋ณต์กํด์ง๊ณ ๊ด๋ฆฌํ๊ธฐ ์ด๋ ค์์ ธ
๐ง Autorelease Pool: ์ง์ฐ๋ ์ฒญ์
์ค๋ธ์ ํฐ๋ธ-C๋ ๋์ค์ 'Autorelease Pool'์ด๋ผ๋ ๊ฐ๋ ์ ๋์ ํ์ด. ์ด๊ฑด ๋ง์น "๋์ค์ ์น์ธ๊ฒ~"๋ผ๊ณ ๋งํ๋ ๊ฒ๊ณผ ๋น์ทํด.
๊ฐ์ฒด๋ฅผ autorelease ํ๋ฉด, ๊ทธ ๊ฐ์ฒด๋ ํ์ฌ์ Autorelease Pool์ด drain(๋น์ฐ๊ธฐ)๋ ๋๊น์ง ๋ฉ๋ชจ๋ฆฌ์ ๋จ์์์ด. ์ด๋ ๊ฒ ํ๋ฉด ๊ฐ์ฒด๋ฅผ ์ฆ์ ํด์ ํ์ง ์๊ณ ๋ ์์ ํ๊ฒ ์ฌ์ฉํ ์ ์์ง.
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSString *myString = [[[NSString alloc] initWithString:@"Hello"] autorelease];
// myString ์ฌ์ฉ
[pool drain]; // ์ฌ๊ธฐ์ myString์ด ํด์ ๋ผ
์ด ๊ทธ๋ฆผ์์ ๋ณผ ์ ์๋ฏ์ด, Autorelease Pool ์์ ๊ฐ์ฒด๋ค์ Pool์ด drain๋ ๋๊น์ง ์ด์์์ด. ๊ทธ๋ฆฌ๊ณ drain๋๋ ์๊ฐ ๋ชจ๋ ํ๊บผ๋ฒ์ ํด์ ๋๋ ๊ฑฐ์ง.
๐ ARC์ ๋ฑ์ฅ: ๋ฐ์๋ ์ฒญ์๊ธฐ
๊ทธ๋ฆฌ๊ณ ๋ง์นจ๋ด, ์ค๋ธ์ ํฐ๋ธ-C์๋ ARC(Automatic Reference Counting)๊ฐ ๋์ ๋์ด. ์ด๊ฑด ๋ง์น ๋ฐ์๋ ์ฒญ์๊ธฐ๋ฅผ ์ป์ ๊ฒ๊ณผ ๊ฐ์.
ARC๋ ์ปดํ์ผ๋ฌ๊ฐ ์๋์ผ๋ก retain๊ณผ release ์ฝ๋๋ฅผ ์ฝ์ ํด์ค. ๋๋ถ์ ํ๋ก๊ทธ๋๋จธ๋ ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ์ ๋ํด ๋ ์ ๊ฒฝ ์ฐ๋ฉด์๋ ์์ ํ ์ฝ๋๋ฅผ ์์ฑํ ์ ์๊ฒ ๋์ง.
// ARC ํ๊ฒฝ์์๋ ์ด๋ ๊ฒ๋ง ํด๋ ๋ผ
NSString *myString = [[NSString alloc] initWithString:@"Hello, ARC!"];
// ์๋์ผ๋ก ๊ด๋ฆฌ๋๋๊น release ๋ถํ์
๐ก ์ฌ๋ฅ๋ท Tip! ์ค๋ธ์ ํฐ๋ธ-C์ ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ ๋ฐฉ์์ ์ดํดํ๋ ๊ฒ์ iOS ๊ฐ๋ฐ์ ๊ทผ๋ณธ์ ์๋ ๊ฒ๊ณผ ๊ฐ์. ์ฌ๋ฅ๋ท์์ ์ด๋ฐ ๊น์ด ์๋ ์ง์์ ๊ณต์ ํ๋ฉด, ๋ง์ ๊ฐ๋ฐ์๋ค์๊ฒ ๋์์ด ๋ ๊ฑฐ์ผ. ํนํ ๋ ๊ฑฐ์ ์ฝ๋๋ฅผ ๋ค๋ฃจ๋ ๊ฐ๋ฐ์๋ค์๊ฒ๋ ์ ๋ง ๊ท์คํ ์ ๋ณด๊ฐ ๋ ์ ์์ง!
๐ Weak References์ Strong References
ARC ํ๊ฒฝ์์๋ 'weak'์ 'strong' ์ฐธ์กฐ๋ผ๋ ๊ฐ๋ ๋ ์ค์ํด์ ธ. ์ด๊ฑด ๋ง์น ๊ด๊ณ์ ๊ฐ๋๋ฅผ ์ ํ๋ ๊ฒ๊ณผ ๋น์ทํด.
- Strong Reference: ๊ธฐ๋ณธ์ ์ธ ์ฐธ์กฐ ๋ฐฉ์. ๊ฐ์ฒด์ ์๋ช ์ ์ฐ์ฅ์์ผ.
- Weak Reference: ๊ฐ์ฒด์ ์๋ช ์ ์ํฅ์ ์ฃผ์ง ์์. ์ฃผ๋ก ์ํ ์ฐธ์กฐ๋ฅผ ๋ฐฉ์งํ๊ธฐ ์ํด ์ฌ์ฉํด.
@property (strong, nonatomic) NSString *strongString;
@property (weak, nonatomic) NSString *weakString;
Weak reference๋ ํนํ ๋ธ๋ฆฌ๊ฒ์ดํธ ํจํด์์ ์์ฃผ ์ฌ์ฉ๋ผ. ์ด๋ ๊ฒ ํ๋ฉด ์ํ ์ฐธ์กฐ๋ฅผ ํผํ ์ ์๊ฑฐ๋ .
๐ ๋๋ฒ๊น ๊ณผ ๋๊ตฌ๋ค
์ค๋ธ์ ํฐ๋ธ-C๋ก ๊ฐ๋ฐํ ๋ ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ๋ฅผ ๋๋ ์ฌ๋ฌ ๋๊ตฌ๋ค์ด ์์ด:
- Instruments: Xcode์ ๋ด์ฅ๋ ๊ฐ๋ ฅํ ํ๋กํ์ผ๋ง ๋๊ตฌ
- Leaks: ๋ฉ๋ชจ๋ฆฌ ๋์๋ฅผ ์ฐพ์์ฃผ๋ ๋๊ตฌ
- Allocations: ๊ฐ์ฒด ํ ๋น๊ณผ ํด์ ๋ฅผ ์ถ์ ํ๋ ๋๊ตฌ
์ด๋ฐ ๋๊ตฌ๋ค์ ์ ํ์ฉํ๋ฉด, ๋ฉ๋ชจ๋ฆฌ ๊ด๋ จ ๋ฒ๊ทธ๋ฅผ ํจ์ฌ ์ฝ๊ฒ ์ฐพ์ ์ ์์ด.
๐ฑ ์ฑ์ฅ Tip! ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ ๋๊ตฌ๋ค์ ๋ฅ์ํ๊ฒ ๋ค๋ฃจ๋ ๊ฒ๋ ํ๋์ ํฐ ์ฌ๋ฅ์ด์ผ. ์ฌ๋ฅ๋ท์์ ์ด๋ฐ ๋๊ตฌ ์ฌ์ฉ๋ฒ์ ๋ํ ํํ ๋ฆฌ์ผ์ ์ ๊ณตํ๋ฉด ์ด๋จ๊น? ๋ง์ ๊ฐ๋ฐ์๋ค์ด ๊ด์ฌ์ ๊ฐ์ง ๊ฑฐ์ผ!
๐ Chapter 4: ์ค์ํํธ์ ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ - ํ๋ํ์ ๊ฒฐ์ ์ฒด ๐
์, ์ด์ ์ฐ๋ฆฌ์ 'ํํ ์ฌ์ด' ์ค์ํํธ๊ฐ ์ด๋ป๊ฒ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๊ด๋ฆฌํ๋์ง ๊น์ด ๋ค์ฌ๋ค๋ณผ ์๊ฐ์ด์ผ. ์ค์ํํธ๋ ํ๋์ ์ด๊ณ ์์ ํ ์ธ์ด๋ฅผ ๋ชฉํ๋ก ๋ง๋ค์ด์ก๊ธฐ ๋๋ฌธ์, ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ๋ ๋์ฑ ์ค๋งํธํด์ก์ด.
๐ ARC์ ์งํ: ์์ ์๋ํ๋ ์ฒญ์ ๋ก๋ด
์ค์ํํธ์์์ ARC๋ ์ค๋ธ์ ํฐ๋ธ-C์ ๊ทธ๊ฒ๋ณด๋ค ํ์ธต ๋ ๋ฐ์ ํ์ด. ๋ง์น ์ธ๊ณต์ง๋ฅ์ด ํ์ฌ๋ ์ต์ ํ ๋ก๋ด ์ฒญ์๊ธฐ ๊ฐ์ง.
์ค์ํํธ์ ARC๋ ์ปดํ์ผ ์์ ์ ๋๋ถ๋ถ์ ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ ๊ฒฐ์ ์ ๋ด๋ ค. ์ด๋ ๋ฐํ์ ์ค๋ฒํค๋๋ฅผ ์ค์ด๊ณ ์ฑ๋ฅ์ ํฅ์์ํค๋ ๋ฐ ํฐ ๋์์ด ๋ผ.
class Person {
var name: String
init(name: String) {
self.name = name
print("\(name) is being initialized")
}
deinit {
print("\(name) is being deinitialized")
}
}
var reference1: Person?
var reference2: Person?
var reference3: Person?
reference1 = Person(name: "John Appleseed")
// Prints "John Appleseed is being initialized"
reference2 = reference1
reference3 = reference1
reference1 = nil
reference2 = nil
reference3 = nil
// Prints "John Appleseed is being deinitialized"
์ด ์์ ์์ ๋ณผ ์ ์๋ฏ์ด, ๊ฐ์ฒด์ ์ฐธ์กฐ ์นด์ดํธ๊ฐ 0์ด ๋๋ ์๊ฐ ์๋์ผ๋ก ๋ฉ๋ชจ๋ฆฌ์์ ํด์ ๋ผ. ํ๋ก๊ทธ๋๋จธ๊ฐ ์ง์ ๋ฉ๋ชจ๋ฆฌ ํด์ ๋ฅผ ์ ๊ฒฝ ์ธ ํ์๊ฐ ์์ด์ง ๊ฑฐ์ง.
๐ ๊ฐํ ์ฐธ์กฐ vs ์ฝํ ์ฐธ์กฐ vs ๋ฏธ์์ ์ฐธ์กฐ
์ค์ํํธ๋ ์ฐธ์กฐ ํ์ ์ ๊ด๊ณ๋ฅผ ๋์ฑ ์ธ๋ฐํ๊ฒ ์ ์ดํ ์ ์์ด:
- ๊ฐํ ์ฐธ์กฐ(Strong Reference): ๊ธฐ๋ณธ ์ฐธ์กฐ ํ์ . ๊ฐ์ฒด์ ์๋ช ์ ์ฐ์ฅ์์ผ.
- ์ฝํ ์ฐธ์กฐ(Weak Reference): ๊ฐ์ฒด์ ์๋ช ์ ์ํฅ์ ์ฃผ์ง ์์. nil์ด ๋ ์ ์์ด.
- ๋ฏธ์์ ์ฐธ์กฐ(Unowned Reference): ์ฝํ ์ฐธ์กฐ์ ๋น์ทํ์ง๋ง, nil์ด ๋ ์ ์์ด. ํญ์ ๊ฐ์ด ์๋ค๊ณ ๊ฐ์ ํด.
class Person {
let name: String
init(name: String) { self.name = name }
var apartment: Apartment?
deinit { print("\(name) is being deinitialized") }
}
class Apartment {
let unit: String
init(unit: String) { self.unit = unit }
weak var tenant: Person?
deinit { print("Apartment \(unit) is being deinitialized") }
}
var john: Person?
var unit4A: Apartment?
john = Person(name: "John Appleseed")
unit4A = Apartment(unit: "4A")
john!.apartment = unit4A
unit4A!.tenant = john
์ด ์์ ์์ `Apartment`์ `tenant` ์์ฑ์ด weak๋ก ์ ์ธ๋ ๊ฑธ ๋ณผ ์ ์์ด. ์ด๋ ๊ฒ ํ๋ฉด ์ํ ์ฐธ์กฐ๋ฅผ ๋ฐฉ์งํ ์ ์์ง.
์ด ๋ค์ด์ด๊ทธ๋จ์ Person๊ณผ Apartment ์ฌ์ด์ ๊ด๊ณ๋ฅผ ๋ณด์ฌ์ค. Person์ Apartment์ ๋ํด ๊ฐํ ์ฐธ์กฐ๋ฅผ ๊ฐ์ง๊ณ ์๊ณ , Apartment๋ Person์ ๋ํด ์ฝํ ์ฐธ์กฐ๋ฅผ ๊ฐ์ง๊ณ ์์ด. ์ด๋ ๊ฒ ํ๋ฉด ์ํ ์ฐธ์กฐ๋ฅผ ํผํ ์ ์์ง.
๐ ํด๋ก์ ์ ์บก์ฒ ๋ฆฌ์คํธ
์ค์ํํธ์์๋ ํด๋ก์ ๊ฐ ๊ฐ์ฒด๋ฅผ ์บก์ฒํ ๋ ๋ฐ์ํ ์ ์๋ ๊ฐํ ์ฐธ์กฐ ์ํ๋ ์ฐ์ํ๊ฒ ํด๊ฒฐํ ์ ์์ด.
์บก์ฒ ๋ฆฌ์คํธ๋ฅผ ์ฌ์ฉํ๋ฉด ํด๋ก์ ๋ด์์ ๊ฐ์ฒด๋ฅผ ์ด๋ป๊ฒ ์ฐธ์กฐํ ์ง ๋ช ์์ ์ผ๋ก ์ ์ํ ์ ์์ง. ์ด๋ ๊ฒ ๋ง์ด์ผ:
class HTMLElement {
let name: String
let text: String?
lazy var asHTML: () -> String = { [unowned self] in
if let text = self.text {
return "<\(self.name)>\(text)</\(self.name)>"
} else {
return "<\(self.name) />"
}
}
init(name: String, text: String? = nil) {
self.name = name
self.text = text
}
deinit {
print("\(name) is being deinitialized")
}
}
์ฌ๊ธฐ์ `[unowned self]`๋ ํด๋ก์ ๊ฐ self๋ฅผ ๋ฏธ์์ ์ฐธ์กฐ๋ก ์บก์ฒํ๋ค๋ ๊ฑธ ๋ํ๋ด. ์ด๋ ๊ฒ ํ๋ฉด ๊ฐํ ์ฐธ์กฐ ์ํ์ ํผํ ์ ์์ด.
๐ง ๋ฉ๋ชจ๋ฆฌ ์์ ์ฑ
์ค์ํํธ๋ ๋ฉ๋ชจ๋ฆฌ ์์ ์ฑ์ ํฐ ์ค์ ์ ๋๊ณ ์์ด. ์ปดํ์ผ๋ฌ๊ฐ ๋ง์ ๋ฉ๋ชจ๋ฆฌ ๊ด๋ จ ์ค๋ฅ๋ฅผ ๋ฏธ๋ฆฌ ์ก์๋ด์ฃผ์ง.
์๋ฅผ ๋ค์ด, ์ค์ํํธ๋ ๋์ผํ ๋ฉ๋ชจ๋ฆฌ ์์ญ์ ๋ํ ๋์ ์ ๊ทผ์ ๋ฐฉ์งํด. ์ด๊ฑด ์ ๋ง ์ค์ํ ๊ธฐ๋ฅ์ด์ผ. ์๋ํ๋ฉด ๋์ ์ ๊ทผ์ผ๋ก ์ธํ ๋ฒ๊ทธ๋ ์ฐพ๊ธฐ๊ฐ ์ ๋ง ์ด๋ ต๊ฑฐ๋ .
var stepSize = 1
func increment(_ number: inout Int) {
number += stepSize
}
// ์ด๋ ๊ฒ ํ๋ฉด ์ปดํ์ผ ์๋ฌ๊ฐ ๋ฐ์ํด
// increment(&stepSize)
// ๋์ ์ด๋ ๊ฒ ํด์ผ ํด
var copyOfStepSize = stepSize
increment(©OfStepSize)
stepSize = copyOfStepSize
์ด ์์ ์์ `stepSize`๋ฅผ ์ง์ `increment` ํจ์์ ์ ๋ฌํ๋ ค๊ณ ํ๋ฉด ์ปดํ์ผ๋ฌ๊ฐ ์๋ฌ๋ฅผ ๋ฐ์์์ผ. ์๋ํ๋ฉด `stepSize`๊ฐ ํจ์ ๋ด๋ถ์ ์ธ๋ถ์์ ๋์์ ์ ๊ทผ๋๊ธฐ ๋๋ฌธ์ด์ผ. ๋์ ๋ณต์ฌ๋ณธ์ ๋ง๋ค์ด ์ฌ์ฉํ๋ฉด ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์์ง.
๐ ํ์ต Tip! ์ค์ํํธ์ ๋ฉ๋ชจ๋ฆฌ ์์ ์ฑ ๊ธฐ๋ฅ์ ์ ๋ง ๊ฐ๋ ฅํด. ํ์ง๋ง ์ด๋ฅผ ์ ๋๋ก ์ดํดํ๊ณ ํ์ฉํ๋ ค๋ฉด ์ฐ์ต์ด ํ์ํด. ์ฌ๋ฅ๋ท์์ ์ด๋ฐ ๊ณ ๊ธ ์ฃผ์ ์ ๋ํ ์ค์ต ๊ณผ์ ๋ฅผ ์ ๊ณตํ๋ฉด ์ด๋จ๊น? ๊ฐ๋ฐ์๋ค์ ์ค๋ ฅ ํฅ์์ ํฐ ๋์์ด ๋ ๊ฑฐ์ผ!
๐ ์ค์ํํธ์ ๋ฉ๋ชจ๋ฆฌ ๋๋ฒ๊น
์ค์ํํธ๋ ๊ฐ๋ ฅํ ๋ฉ๋ชจ๋ฆฌ ๋๋ฒ๊น ๋๊ตฌ๋ฅผ ์ ๊ณตํด:
- ๋ฉ๋ชจ๋ฆฌ ๊ทธ๋ํ ๋๋ฒ๊ฑฐ: ๊ฐ์ฒด ๊ฐ์ ์ฐธ์กฐ ๊ด๊ณ๋ฅผ ์๊ฐ์ ์ผ๋ก ๋ณด์ฌ์ค
- ์ฃผ์ ์ด๊ท ๊ธฐ(Address Sanitizer): ๋ฉ๋ชจ๋ฆฌ ์ค๋ฅ๋ฅผ ์ค์๊ฐ์ผ๋ก ํ์งํด
- ์ค๋ ๋ ์ด๊ท ๊ธฐ(Thread Sanitizer): ๋ฐ์ดํฐ ๊ฒฝ์ ์กฐ๊ฑด์ ์ฐพ์๋ด
์ด๋ฐ ๋๊ตฌ๋ค์ ํ์ฉํ๋ฉด ๋ฉ๋ชจ๋ฆฌ ๊ด๋ จ ๋ฒ๊ทธ๋ฅผ ํจ์ฌ ์ฝ๊ฒ ์ฐพ๊ณ ํด๊ฒฐํ ์ ์์ด. ํนํ ๋ฉ๋ชจ๋ฆฌ ๊ทธ๋ํ ๋๋ฒ๊ฑฐ๋ ๋ณต์กํ ์ฐธ์กฐ ๊ด๊ณ๋ฅผ ํ๋์ ๋ณผ ์ ์๊ฒ ํด์ฃผ๋๊น ์ ๋ง ์ ์ฉํด.
๐ Chapter 5: ์ค์ํํธ vs ์ค๋ธ์ ํฐ๋ธ-C - ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ์ ์ต์ข ๋๊ฒฐ! ๐ฅ
์, ์ด์ ์ฐ๋ฆฌ์ ๋ ์ฃผ์ธ๊ณต์ ๋๋ํ ๋๊ณ ๋น๊ตํด๋ณผ ์๊ฐ์ด์ผ. ์ค์ํํธ์ ์ค๋ธ์ ํฐ๋ธ-C, ์ด๋ค ์ ์ด ๋ค๋ฅด๊ณ ์ด๋ค ์ ์ด ๋น์ทํ ๊น?
๐ ๊ณตํต์ : ARC์ ๊ธฐ๋ณธ ์๋ฆฌ
์ค์ํํธ์ ์ค๋ธ์ ํฐ๋ธ-C ๋ชจ๋ ARC๋ฅผ ์ฌ์ฉํด ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๊ด๋ฆฌํด. ์ด๊ฑด ์ ๋ง ํฐ ๊ณตํต์ ์ด์ผ.
- ๋ ๋ค ์ฐธ์กฐ ์นด์ดํ ์ ์ฌ์ฉํด ๊ฐ์ฒด์ ์๋ช ์ ๊ด๋ฆฌํด
- ๊ฐํ ์ฐธ์กฐ์ ์ฝํ ์ฐธ์กฐ์ ๊ฐ๋ ์ด ์กด์ฌํด
- ์ํ ์ฐธ์กฐ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํ ๋ฐฉ๋ฒ์ ์ ๊ณตํด
๐ฅ ์ฐจ์ด์ : ๋ ์ค๋งํธํด์ง ์ค์ํํธ
ํ์ง๋ง ์ค์ํํธ๋ ๋ช ๊ฐ์ง ์ค์ํ ์ ์์ ์ค๋ธ์ ํฐ๋ธ-C๋ฅผ ์์๊ฐ๊ณ ์์ด:
| ํน์ง | ์ค์ํํธ | ์ค๋ธ์ ํฐ๋ธ-C |
|---|---|---|
| ์ปดํ์ผ ์์ ์ต์ ํ | ๊ฐ๋ ฅํจ | ์ ํ์ |
| ๋ฉ๋ชจ๋ฆฌ ์์ ์ฑ | ๋งค์ฐ ๋์ | ์ค๊ฐ |
| ๊ฐ ํ์ ์ง์ | ๊ด๋ฒ์ํจ | ์ ํ์ |
| ํด๋ก์ ์บก์ฒ ๋ฆฌ์คํธ | ์ง์ | ๋ฏธ์ง์ |
์ค์ํํธ์ ๊ฐ์ฅ ํฐ ์ฅ์ ์ ์ปดํ์ผ ์์ ์์์ ๊ฐ๋ ฅํ ์ต์ ํ์ผ. ์ด๋ ๋ฐํ์ ์ฑ๋ฅ์ ํฌ๊ฒ ํฅ์์ํค๊ณ , ๋ง์ ๋ฉ๋ชจ๋ฆฌ ๊ด๋ จ ๋ฒ๊ทธ๋ฅผ ๋ฏธ๋ฆฌ ์ก์๋ผ ์ ์๊ฒ ํด์ค.
๐๏ธโโ๏ธ ์ฑ๋ฅ ๋น๊ต
์ผ๋ฐ์ ์ผ๋ก ์ค์ํํธ๊ฐ ์ค๋ธ์ ํฐ๋ธ-C๋ณด๋ค ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ ์ธก๋ฉด์์ ๋ ํจ์จ์ ์ด๋ผ๊ณ ์๋ ค์ ธ ์์ด. ํ์ง๋ง ์ด๊ฑด ์ํฉ์ ๋ฐ๋ผ ๋ค๋ฅผ ์ ์์ด.
์ด ๊ทธ๋ํ๋ ์ผ๋ฐ์ ์ธ ์ํฉ์์์ ๋ฉ๋ชจ๋ฆฌ ํจ์จ์ฑ์ ๋ณด์ฌ์ค. ์ค์ํํธ๊ฐ ์กฐ๊ธ ๋ ํจ์จ์ ์ด์ง๋ง, ์ค๋ธ์ ํฐ๋ธ-C๋ ์ฌ์ ํ ๊ฐ๋ ฅํด.
๐ค ์ด๋ค ์ธ์ด๋ฅผ ์ ํํด์ผ ํ ๊น?
๊ฒฐ๊ตญ ์ ํ์ ํ๋ก์ ํธ์ ์๊ตฌ์ฌํญ๊ณผ ๊ฐ๋ฐ์์ ๊ฒฝํ์ ๋ฐ๋ผ ๋ฌ๋ผ์ง ๊ฑฐ์ผ.
- ์๋ก์ด ํ๋ก์ ํธ๋ฅผ ์์ํ๋ค๋ฉด ์ค์ํํธ๊ฐ ์ข์ ์ ํ์ด ๋ ๊ฑฐ์ผ
- ๋ ๊ฑฐ์ ์ฝ๋๋ฅผ ์ ์ง๋ณด์ํด์ผ ํ๋ค๋ฉด ์ค๋ธ์ ํฐ๋ธ-C ์ง์์ด ํ์ํ ๊ฑฐ๊ณ
- ๋ ์ธ์ด๋ฅผ ๋ชจ๋ ์๋ฉด ๊ฐ์ฅ ์ด์์ ์ด๊ฒ ์ง!
๐ก ์ฌ๋ฅ๋ท Tip! ๋ ์ธ์ด์ ์ฅ๋จ์ ์ ๊น์ด ์ดํดํ๋ ๊ฒ์ ์ ๋ง ๊ฐ์น ์๋ ๊ธฐ์ ์ด์ผ. ์ฌ๋ฅ๋ท์์ ์ด ๋ ์ธ์ด๋ฅผ ๋น๊ต ๋ถ์ํ๋ ๊ฐ์ข๋ฅผ ๊ฐ์คํ๋ฉด ์ด๋จ๊น? ๋ง์ iOS ๊ฐ๋ฐ์๋ค์ด ๊ด์ฌ์ ๊ฐ์ง ๊ฑฐ์ผ!
๐ญ Chapter 6: ์ค์ ์๋๋ฆฌ์ค - ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ์ ํ์ฅ ๐๏ธ
์, ์ด์ ์ฐ๋ฆฌ๊ฐ ๋ฐฐ์ด ๋ด์ฉ์ ์ค์ ์ํฉ์ ์ ์ฉํด๋ณผ ์๊ฐ์ด์ผ. ๊ฐ๋ฐ์๋ค์ด ์์ฃผ ๋ง์ฃผ์น๋ ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ ์๋๋ฆฌ์ค๋ฅผ ์ดํด๋ณด๊ณ , ์ค์ํํธ์ ์ค๋ธ์ ํฐ๋ธ-C์์ ๊ฐ๊ฐ ์ด๋ป๊ฒ ํด๊ฒฐํ ์ ์๋์ง ์์๋ณด์.
๐ ์๋๋ฆฌ์ค 1: ์ํ ์ฐธ์กฐ ํด๊ฒฐํ๊ธฐ
๊ฐ์ฅ ํํ ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ ๋ฌธ์ ์ค ํ๋๋ ๋ฐ๋ก ์ํ ์ฐธ์กฐ์ผ. ๋ ๊ฐ์ฒด๊ฐ ์๋ก๋ฅผ ๊ฐํ๊ฒ ์ฐธ์กฐํ๋ฉด ์ด๋ป๊ฒ ๋ ๊น?
์ค์ํํธ์์์ ํด๊ฒฐ์ฑ :
class Person {
let name: String
weak var apartment: Apartment?
init(name: String) {
self.name = name
}
deinit {
print("\(name) is being deinitialized")
}
}
class Apartment {
let unit: String
weak var tenant: Person?
init(unit: String) {
self.unit = unit
}
deinit {
print("Apartment \(unit) is being deinitialized")
}
}
var john: Person? = Person(name: "John")
var unit4A: Apartment? = Apartment(unit: "4A")
john?.apartment = unit4A
unit4A?.tenant = john
john = nil
unit4A = nil
// ๋ ๊ฐ์ฒด ๋ชจ๋ ์ ์์ ์ผ๋ก ํด์ ๋จ
์ค๋ธ์ ํฐ๋ธ-C์์์ ํด๊ฒฐ์ฑ :
@interface Person : NSObject
@property (nonatomic, strong) NSString *name;
@property (nonatomic, weak) Apartment *apartment;
@end
@interface Apartment : NSObject
@property (nonatomic, strong) NSString *unit;
@property (nonatomic, weak) Person *tenant;
@end
@implementation Person
- (void)dealloc {
NSLog(@"%@ is being deinitialized", self.name);
}
@end
@implementation Apartment
- (void)dealloc {
NSLog(@"Apartment %@ is being deinitialized", self.unit);
}
@end
Person *john = [[Person alloc] init];
john.name = @"John";
Apartment *unit4A = [[Apartment alloc] init];
unit4A.unit = @"4A";
john.apartment = unit4A;
unit4A.tenant = john;
john = nil;
unit4A = nil;
// ๋ ๊ฐ์ฒด ๋ชจ๋ ์ ์์ ์ผ๋ก ํด์ ๋จ
๋ ๊ฒฝ์ฐ ๋ชจ๋ weak ์ฐธ์กฐ๋ฅผ ์ฌ์ฉํด ์ํ ์ฐธ์กฐ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ์ด. ์ค์ํํธ์ ๊ฒฝ์ฐ ์ข ๋ ๊ฐ๊ฒฐํ ๋ฌธ๋ฒ์ผ๋ก ๊ฐ์ ๊ฒฐ๊ณผ๋ฅผ ์ป์ ์ ์์ง.
๐ ์๋๋ฆฌ์ค 2: ํด๋ก์ ์ ์บก์ฒ ๋ฆฌ์คํธ
ํด๋ก์ ๋ฅผ ์ฌ์ฉํ ๋ self๋ฅผ ์บก์ฒํ๋ฉด ์ํ ์ฐธ์กฐ๊ฐ ๋ฐ์ํ ์ ์์ด. ์ด๋ฅผ ์ด๋ป๊ฒ ํด๊ฒฐํ ๊น?
์ค์ํํธ์์์ ํด๊ฒฐ์ฑ :
class HTMLElement {
let name: String
let text: String?
lazy var asHTML: () -> String = { [weak self] in
guard let self = self else { return "" }
if let text = self.text {
return "<\(self.name)>\(text)</\(self.name)>"
} else {
return "<\(self.name) />"
}
}
init(name: String, text: String? = nil) {
self.name = name
self.text = text
}
deinit {
print("\(name) is being deinitialized")
}
}
var paragraph: HTMLElement? = HTMLElement(name: "p", text: "hello, world")
print(paragraph!.asHTML())
paragraph = nil
// "p is being deinitialized" ์ถ๋ ฅ๋จ
์ค๋ธ์ ํฐ๋ธ-C์์์ ํด๊ฒฐ์ฑ :
@interface HTMLElement : NSObject
@property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) NSString *text;
@property (nonatomic, copy) NSString *(^asHTML)(void);
- (instancetype)initWithName:(NSString *)name text:(NSString *)text;
@end
@implementation HTMLElement
- (instancetype)initWithName:(NSString *)name text:(NSString *)text {
if (self = [super init]) {
_name = name;
_text = text;
__weak typeof(self) weakSelf = self;
_asHTML = ^NSString *{
__strong typeof(weakSelf) strongSelf = weakSelf;
if (strongSelf) {
if (strongSelf.text) {
return [NSString stringWithFormat:@"<%@>%@</%@>", strongSelf.name, strongSelf.text, strongSelf.name];
} else {
return [NSString stringWithFormat:@"<%@ />", strongSelf.name];
}
}
return @"";
};
}
return self;
}
- (void)dealloc {
NSLog(@"%@ is being deinitialized", self.name);
}
@end
HTMLElement *paragraph = [[HTMLElement alloc] initWithName:@"p" text:@"hello, world"];
NSLog(@"%@", paragraph.asHTML());
paragraph = nil;
// "p is being deinitialized" ์ถ๋ ฅ๋จ
์ค์ํํธ์์๋ ์บก์ฒ ๋ฆฌ์คํธ๋ฅผ ์ฌ์ฉํด ๊ฐ๋จํ ํด๊ฒฐํ ์ ์์ง๋ง, ์ค๋ธ์ ํฐ๋ธ-C์์๋ ์ฝํ ์ฐธ์กฐ์ ๊ฐํ ์ฐธ์กฐ๋ฅผ ์กฐํฉํด ์ฌ์ฉํด์ผ ํด. ์ค์ํํธ์ ๋ฐฉ์์ด ์ข ๋ ์ง๊ด์ ์ด๊ณ ์์ ํด ๋ณด์ด์ง?
๐ฑ ์ฑ์ฅ Tip! ์ด๋ฐ ์ค์ ์๋๋ฆฌ์ค๋ฅผ ๋ง์ด ์ ํด๋ณด๋ ๊ฒ ์ค์ํด. ์ฌ๋ฅ๋ท์์ ๋ค์ํ ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ ์๋๋ฆฌ์ค๋ฅผ ๋ค๋ฃจ๋ ์ํฌ์ต์ ๊ฐ์ตํ๋ฉด ์ด๋จ๊น? ๊ฐ๋ฐ์๋ค์ด ์ค์ ์ํฉ์์ ์ด๋ป๊ฒ ๋์ฒํด์ผ ํ ์ง ๋ฐฐ์ธ ์ ์์ ๊ฑฐ์ผ!
๐ ์๋๋ฆฌ์ค 3: ๋ธ๋ฆฌ๊ฒ์ดํธ ํจํด์์์ ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ
๋ธ๋ฆฌ๊ฒ์ดํธ ํจํด์ iOS ๊ฐ๋ฐ์์ ์ ๋ง ์์ฃผ ์ฌ์ฉ๋๋๋ฐ, ์ฌ๊ธฐ์๋ ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ๊ฐ ์ค์ํด.
์ค์ํํธ์์์ ํด๊ฒฐ์ฑ :
protocol DataManagerDelegate: AnyObject {
func dataManagerDidUpdate(_ data: [String])
}
class DataManager {
weak var delegate: DataManagerDelegate?
func fetchData() {
// ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๋ ๋ก์ง
let newData = ["Apple", "Banana", "Cherry"]
delegate?.dataManagerDidUpdate(newData)
}
}
class ViewController: UIViewController, DataManagerDelegate {
let dataManager = DataManager()
override func viewDidLoad() {
super.viewDidLoad()
dataManager.delegate = self
}
func dataManagerDidUpdate(_ data: [String]) {
print("Data updated: \(data)")
}
}
์ค๋ธ์ ํฐ๋ธ-C์์์ ํด๊ฒฐ์ฑ :
@protocol DataManagerDelegate;
@interface DataManager : NSObject
@property (nonatomic, weak) id<DataManagerDelegate> delegate;
- (void)fetchData;
@end
@protocol DataManagerDelegate <NSObject>
- (void)dataManagerDidUpdate:(NSArray<NSString *> *)data;
@end
@implementation DataManager
- (void)fetchData {
// ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๋ ๋ก์ง
NSArray *newData = @[@"Apple", @"Banana", @"Cherry"];
[self.delegate dataManagerDidUpdate:newData];
}
@end
@interface ViewController : UIViewController <DataManagerDelegate>
@property (nonatomic, strong) DataManager *dataManager;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.dataManager = [[DataManager alloc] init];
self.dataManager.delegate = self;
}
- (void)dataManagerDidUpdate:(NSArray<NSString *> *)data {
NSLog(@"Data updated: %@", data);
}
@end
๋ ๊ฒฝ์ฐ ๋ชจ๋ ๋ธ๋ฆฌ๊ฒ์ดํธ๋ฅผ weak ์ฐธ์กฐ๋ก ์ ์ธํด ์ํ ์ฐธ์กฐ๋ฅผ ๋ฐฉ์งํ๊ณ ์์ด. ์ค์ํํธ์์๋ ํ๋กํ ์ฝ์ AnyObject๋ฅผ ์ถ๊ฐํด ํด๋์ค๋ง ๋ธ๋ฆฌ๊ฒ์ดํธ๋ก ์ฌ์ฉํ ์ ์๊ฒ ์ ํํ๊ณ ์์ง.
๐ฌ Chapter 7: ๊ฒฐ๋ก - ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ์ ๋ฏธ๋ ๐ฎ
์, ์ฐ๋ฆฌ์ ๊ธด ์ฌ์ ์ด ๊ฑฐ์ ๋๋๊ฐ๊ณ ์์ด. ์ค์ํํธ์ ์ค๋ธ์ ํฐ๋ธ-C์ ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ์ ๋ํด ์ ๋ง ๋ง์ ๊ฒ์ ๋ฐฐ์ ์ง? ์ด์ ๋ง์ง๋ง์ผ๋ก ์ ์ฒด๋ฅผ ์ ๋ฆฌํ๊ณ , ์์ผ๋ก์ ์ ๋ง์ ๋ํด ์ด์ผ๊ธฐํด๋ณผ๊ฒ.
๐ ํต์ฌ ์์ฝ
- ARC์ ์ค์์ฑ: ๋ ์ธ์ด ๋ชจ๋ ARC๋ฅผ ์ฌ์ฉํด ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๊ด๋ฆฌํด. ์ด๋ ๊ฐ๋ฐ์์ ๋ถ๋ด์ ํฌ๊ฒ ์ค์ฌ์ฃผ์ง.
- ์ค์ํํธ์ ์ง๋ณด: ์ค์ํํธ๋ ๋ ์์ ํ๊ณ ํจ์จ์ ์ธ ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ ๊ธฐ๋ฅ์ ์ ๊ณตํด. ํนํ ์ปดํ์ผ ์์ ์ ์ต์ ํ๊ฐ ๋ฐ์ด๋.
- ์ค๋ธ์ ํฐ๋ธ-C์ ์ ์ฐ: ์ค๋ธ์ ํฐ๋ธ-C๋ ์ฌ์ ํ ๋ง์ ๋ ๊ฑฐ์ ์ฝ๋์์ ์ฌ์ฉ๋๊ณ ์์ด. ๊ทธ๋์ ์์ง๋ ์ค์ํ ์์น๋ฅผ ์ฐจ์งํ๊ณ ์์ง.
- ์ํ ์ฐธ์กฐ ์ฃผ์: ๋ ์ธ์ด ๋ชจ๋ ์ํ ์ฐธ์กฐ ๋ฌธ์ ๋ฅผ ์กฐ์ฌํด์ผ ํด. weak๋ unowned ์ฐธ์กฐ๋ฅผ ์ ์ ํ ์ฌ์ฉํ๋ ๊ฒ ์ค์ํด.
- ํด๋ก์ ์ ๋ธ๋ก: ํด๋ก์ (์ค์ํํธ)๋ ๋ธ๋ก(์ค๋ธ์ ํฐ๋ธ-C)์ ์ฌ์ฉํ ๋ ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ์ ํนํ ์ฃผ์ํด์ผ ํด.
๐ฎ ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ์ ๋ฏธ๋
์์ผ๋ก ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ๋ ์ด๋ป๊ฒ ๋ณํ ๊น? ๋ช ๊ฐ์ง ์์ธก์ ํด๋ณผ๊ฒ:
- ๋ ์ค๋งํธํ ์ปดํ์ผ๋ฌ: ์ปดํ์ผ๋ฌ๊ฐ ๋ ๋ง์ ๋ฉ๋ชจ๋ฆฌ ๊ด๋ จ ์ต์ ํ๋ฅผ ์๋์ผ๋ก ์ํํ ๊ฑฐ์ผ.
- ์ค์๊ฐ ๋ฉ๋ชจ๋ฆฌ ๋ถ์: ์ฑ ์คํ ์ค ์ค์๊ฐ์ผ๋ก ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ์ ๋ถ์ํ๊ณ ์ต์ ํํ๋ ๋๊ตฌ๊ฐ ๋ฐ์ ํ ๊ฑฐ์ผ.
- AI ๊ธฐ๋ฐ ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ: ์ธ๊ณต์ง๋ฅ์ด ์ฝ๋๋ฅผ ๋ถ์ํด ์ต์ ์ ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ ์ ๋ต์ ์ ์ํ ์๋ ์์ด.
- ํ๋์จ์ด ์ง์: ์ ํ์ ์นฉ์ด ๋ ๋ฐ์ ํ๋ฉด์, ํ๋์จ์ด ๋ ๋ฒจ์์ ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ๋ฅผ ์ง์ํ ์๋ ์์ด.
๐ ํ์ต Tip! ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ๋ ํญ์ ๋ณํํ๊ณ ๋ฐ์ ํด. ์ต์ ํธ๋ ๋๋ฅผ ๋ฐ๋ผ๊ฐ๋ ๊ฒ ์ค์ํด. ์ฌ๋ฅ๋ท์์ ์ ๊ธฐ์ ์ผ๋ก ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ ๊ธฐ์ ์ ๋ํ ์ ๋ฐ์ดํธ ์ธ๋ฏธ๋๋ฅผ ์ด๋ฉด ์ด๋จ๊น? ๊ฐ๋ฐ์๋ค์ด ํญ์ ์ต์ ๊ธฐ์ ์ ์ตํ ์ ์์ ๊ฑฐ์ผ!
๐ ๋ง์ง๋ง ์กฐ์ธ
๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ๋ iOS ๊ฐ๋ฐ์์ ์ ๋ง ์ค์ํ ๋ถ๋ถ์ด์ผ. ํ์ง๋ง ๋๋ฌด ๊ฒ๋จน์ ํ์๋ ์์ด. ์ด๋ ๊ฒ ๊ธฐ์ตํด:
- ์ค์ต์ด ์ค์ํด: ์ด๋ก ๋ง ์๋ฉด ๋ถ์กฑํด. ์ค์ ๋ก ์ฝ๋๋ฅผ ์์ฑํ๊ณ ๋๋ฒ๊น ํด๋ณด๋ ๊ฒ ๊ฐ์ฅ ์ข์ ํ์ต ๋ฐฉ๋ฒ์ด์ผ.
- ๋๊ตฌ๋ฅผ ํ์ฉํด: Xcode์ ๋ฉ๋ชจ๋ฆฌ ๊ทธ๋ํ ๋๋ฒ๊ฑฐ, Instruments ๊ฐ์ ๋๊ตฌ๋ค์ ์ ๊ทน ํ์ฉํด๋ด.
- ์ฝ๋ ๋ฆฌ๋ทฐ๋ฅผ ํด: ๋ค๋ฅธ ๊ฐ๋ฐ์๋ค๊ณผ ์ฝ๋๋ฅผ ๊ณต์ ํ๊ณ ๋ฆฌ๋ทฐ๋ฐ์. ์๋ก์ด ์๊ฐ์ผ๋ก ๋ฌธ์ ๋ฅผ ๋ฐ๊ฒฌํ ์ ์์ด.
- ๋์์์ด ํ์ตํด: ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ ๊ธฐ์ ์ ๊ณ์ ๋ฐ์ ํด. ํญ์ ์๋ก์ด ๊ฒ์ ๋ฐฐ์ฐ๋ ค๋ ์์ธ๊ฐ ์ค์ํด.
๊ธฐ์ตํด, ์๋ฒฝํ ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ๋ ์์ด. ํ์ง๋ง ์ฐ๋ฆฌ๋ ๊ณ์ํด์ ๊ฐ์ ํ๊ณ ๋ฐ์ ํ ์ ์์ด. ์ด ์ฌ์ ์ ์ฆ๊ธฐ๋ฉด์, ๋ ๋์ ๊ฐ๋ฐ์๊ฐ ๋์ด๊ฐ๋ ๊ณผ์ ์ ์ฆ๊ฒจ๋ด!
์, ์ด์ ์ ๋ง ๋์ด์ผ. ๊ธด ์ฌ์ ์ด์์ง๋ง, ์ ๋ง ๊ฐ์ง ์๊ฐ์ด์์ด. ์ด์ ๋ํฌ๋ค์ iOS ๊ฐ๋ฐ์์ ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ์ ๋ฌ์ธ์ด ๋ ๊ฑฐ์ผ! ์์ผ๋ก์ ๊ฐ๋ฐ ์ธ์์ ์ด ์ง์์ด ํฐ ๋์์ด ๋๊ธธ ๋ฐ๋๊ฒ. ํ์ดํ ! ๐
๊ด๋ จ ํค์๋
๋๊ธ ์์ฑ
์ด ๊ธ์ ๋ํ ์ฌ๋ฌ๋ถ์ ์๊ฐ์ ๋ค๋ ค์ฃผ์ธ์
๋ก๊ทธ์ธ์ด ํ์ํฉ๋๋ค
๋๊ธ์ ์์ฑํ๋ ค๋ฉด ๋จผ์ ๋ก๊ทธ์ธํด์ฃผ์ธ์.
๋๊ธ 0
์ง์์ธ์ ์ฒ - ์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
- ์ ์๊ถ ๋ฐ ์์ ๊ถ: ๋ณธ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ๋ ์ AI ๊ธฐ์ ๋ก ์์ฑ๋์์ผ๋ฉฐ, ๋ํ๋ฏผ๊ตญ ์ ์๊ถ๋ฒ ๋ฐ ๊ตญ์ ์ ์๊ถ ํ์ฝ์ ์ํด ๋ณดํธ๋ฉ๋๋ค.
- AI ์์ฑ ์ปจํ ์ธ ์ ๋ฒ์ ์ง์: ๋ณธ AI ์์ฑ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ์ง์ ์ฐฝ์๋ฌผ๋ก ์ธ์ ๋๋ฉฐ, ๊ด๋ จ ๋ฒ๊ท์ ๋ฐ๋ผ ์ ์๊ถ ๋ณดํธ๋ฅผ ๋ฐ์ต๋๋ค.
- ์ฌ์ฉ ์ ํ: ์ฌ๋ฅ๋ท์ ๋ช ์์ ์๋ฉด ๋์ ์์ด ๋ณธ ์ปจํ ์ธ ๋ฅผ ๋ณต์ , ์์ , ๋ฐฐํฌ, ๋๋ ์์ ์ ์ผ๋ก ํ์ฉํ๋ ํ์๋ ์๊ฒฉํ ๊ธ์ง๋ฉ๋๋ค.
- ๋ฐ์ดํฐ ์์ง ๊ธ์ง: ๋ณธ ์ปจํ ์ธ ์ ๋ํ ๋ฌด๋จ ์คํฌ๋ํ, ํฌ๋กค๋ง, ๋ฐ ์๋ํ๋ ๋ฐ์ดํฐ ์์ง์ ๋ฒ์ ์ ์ฌ์ ๋์์ด ๋ฉ๋๋ค.
- AI ํ์ต ์ ํ: ์ฌ๋ฅ๋ท์ AI ์์ฑ ์ปจํ ์ธ ๋ฅผ ํ AI ๋ชจ๋ธ ํ์ต์ ๋ฌด๋จ ์ฌ์ฉํ๋ ํ์๋ ๊ธ์ง๋๋ฉฐ, ์ด๋ ์ง์ ์ฌ์ฐ๊ถ ์นจํด๋ก ๊ฐ์ฃผ๋ฉ๋๋ค.
์์ง ๋๊ธ์ด ์์ต๋๋ค.