๊ธ€ ์ž‘์„ฑ์ž: ์ด์ง€์›๐ŸŒฉ๏ธ
๐Ÿ’ก ์˜ต์…”๋„ ์ฒด์ด๋‹ ๋“ฑ ์ผ๋ถ€ ๋น ์ง„ ๊ฐœ๋…์€ ์ข€ ๋” ๊ณต๋ถ€ํ•˜๊ณ ์„œ ์ฑ„์šธ ์˜ˆ์ •
๐Ÿ’ก ์Šค์œ„ํ”„ํŠธ์—์„œ๋Š” NULL์„ nil๋กœ ํ‘œ๊ธฐํ•œ๋‹ค.

์Šค์œ„ํ”„ํŠธ๋ฅผ ์ฒ˜์Œ ์ ‘ํ•˜๋ฉด์„œ ๊ฐ€์žฅ ๋จผ์ € ๋งŒ๋‚˜๋Š” ์ƒ์†Œํ•œ ๋ฌธ๋ฒ•์€ Optional ์ด ์•„๋‹๊นŒ ์ƒ๊ฐํ•œ๋‹ค. ์ฝ”ํ‹€๋ฆฐ์—๋Š” Nullable์ด๋ผ๋Š” ๊ฐœ๋…์ด ์žˆ์ง€๋งŒ ๋‚ด๊ฐ€ ์ฃผ๋กœ ์‚ฌ์šฉํ–ˆ๋˜ ์ž๋ฐ”๋‚˜ ํŒŒ์ด์ฌ์—๋Š” ์—†๋Š” ๋ฌธ๋ฒ•์ด์—ˆ๋‹ค. (Java8 ๋ถ€ํ„ฐ ๋„์ž…๋˜์—ˆ๋‹ค.)
์ž๋ฐ”(ํ˜น์€ ๋‹ค๋ฅธ ์–ธ์–ด)์—์„œ ์‚ฌ์šฉํ–ˆ๋˜ ๊ฒƒ ์ฒ˜๋Ÿผ ์Šค์œ„ํ”„ํŠธ์—์„œ nil์„ ์‚ฌ์šฉํ•˜๋ฉด Xcode์—์„œ๋Š” ๋ฌด์ˆ˜ํ•œ ๋นจ๊ฐ„ ์ค„์ด ๋ฐ˜๊ธด๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ณ ์น˜๊ธด ํ•ด์•ผ ํ•˜๋‹ˆ๊นŒ ์˜๋ฌธ๋„ ๋ชจ๋ฅธ ์ฒด Fix๋ฅผ ๋ˆŒ๋Ÿฌ์„œ ๊ณ ์นœ๋‹ค. ๋‹ค๋“ค ์ด๋Ÿฐ ๊ฒฝํ—˜ ํ•œ๋ฒˆ์ฏค์€ ์žˆ์„ ๊ฑฐ๋‹ค.

์–„ํŒํ•œ ์ง€์‹๊ณผ, ์ข‹์€ ์ž๋ฃŒ๋“ค์„ ์ฝ์œผ๋ฉด์„œ ์ •๋ฆฌํ•ด๋ดค๋‹ค. ๋ชจ์ชผ๋ก ๋ˆ„๊ตฐ๊ฐ€์—๊ฒŒ๋Š” ๋„์›€์ด ๋˜๊ธธ ๋ฐ”๋ผ๋ฉฐ, ์ž˜๋ชป๋œ ์ง€์‹์€ ๋Œ“๊ธ€๋กœ ๋‚จ๊ฒจ์ฃผ์‹œ๋ฉด ๊ฐ์‚ฌํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

 

์ผ๋‹จ, Optional์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณด์ž.

The Swift Programming Language (Swift 5.3) ํŽ˜์ด์ง€์—์„œ Optional์„ ์ด๋ ‡๊ฒŒ ์„ค๋ช…ํ•œ๋‹ค.

You use optionals in situations where a value may be absent. An optional represents two possibilities: Either there is a value, and you can unwrap the optional to access that value, or there isn’t a value at all.

๊ฐ’์ด ์—†์„ ์ˆ˜ ์žˆ๋Š” ์ƒํ™ฉ์—์„œ ์˜ต์…”๋„์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์˜ต์…”๋„์€ ๋‘๊ฐ€์ง€ ๊ฐ€๋Šฅ์„ฑ์„ ๋‚˜ํƒ€๋‚ธ๋‹ค: ๊ฐ’์ด ์žˆ๊ณ  ์˜ต์…”๋„์„ ํ’€์–ด์„œ ํ•ด๋‹น ๊ฐ’์— ์•ก์„ธ์Šค ํ•  ์ˆ˜ ์žˆ๊ฑฐ๋‚˜ ๊ฐ’์ด ์ „ํ˜€ ์—†๋Š” ๊ฒฝ์šฐ.

 

์˜ต์…”๋„ ๋ณ€์ˆ˜(๋˜๋Š” ์ƒ์ˆ˜)๋ฅผ ๋งŒ๋“œ๋Š” ๋ฒ•

Intํ˜• ๋ณ€์ˆ˜๋ฅผ ๋งŒ๋“ ๋‹ค๊ณ  ํ•ด๋ณด์ž. ์šฐ๋ฆฌ๋Š” ๋ชจ์ข…์˜ ์ด์œ ๋กœ ๋ณ€์ˆ˜๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ๋‚˜์ค‘์— ๊ฐ’์„ ์ดˆ๊ธฐํ™”ํ•ด์ฃผ๊ณ  ์‹ถ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ด๋Ÿฌํ•œ ์ƒํ™ฉ์„ ํŒŒ์ด์ฌ์œผ๋กœ ์ž‘์„ฑํ•œ๋‹ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

num = None
num = 7
print(num) # 7

๋‚˜์ค‘์— ๋„ฃ์€ 7์ด ์ž˜ ์ถœ๋ ฅ๋˜๋Š” ๊ฑธ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. ๋˜‘๊ฐ™์ด ์Šค์œ„ํ”„ํŠธ๋กœ ์ž‘์„ฑํ•˜๋ฉด ์–ด๋–จ๊นŒ?

var num: Int = nil // ๐Ÿ›‘ 'nil' cannot initialize specified type 'Int'
num = 7
print(num)

์Šค์œ„ํ”„ํŠธ๋Š” nil์— ๋Œ€ํ•ด์„œ ์—„๊ฒฉํ•œ ํŽธ์ด๋‹ค. ๊ทธ๋ž˜์„œ ์šฐ๋ฆฌ๊ฐ€ ํ‰์†Œ์— ๋‹ค๋ฅธ ์–ธ์–ด์—์„œ ์‚ฌ์šฉํ•˜๋˜ ๊ฒƒ์ฒ˜๋Ÿผ ๋ณ€์ˆ˜ ์ƒ์„ฑ ์‹œ nil์„ ๋„ฃ๊ณ  ๋‚˜์ค‘์— ์ดˆ๊ธฐํ™” ํ•˜๋ ค๊ณ  ํ•˜๋ฉด Xcode์—์„œ๋Š” 'nil' cannot initialize specified type 'Int' ์ด๋ผ๋Š” ๋ฌธ๊ตฌ์™€ ํ•จ๊ป˜ ๋นจ๊ฐ„ ์ค„์ด ๋œฌ๋‹ค.

์œ„ ์ƒํ™ฉ์ฒ˜๋Ÿผ ์ผ๋ฐ˜ ๋ณ€์ˆ˜์— nil์„ ํ• ๋‹นํ•˜๋ ค๊ณ  ํ•˜๋ฉด, ์ปดํŒŒ์ผ ์˜ค๋ฅ˜๊ฐ€ ์šฐ๋ฆฌ๋ฅผ ๋ฐ˜๊ธด๋‹ค. ์Šค์œ„ํ”„ํŠธ์—์„œ๋Š” ์˜ต์…”๋„ ๋ณ€์ˆ˜(์ƒ์ˆ˜)๊ฐ€ ์•„๋‹ˆ๋ฉด nil์„ ํ• ๋‹นํ•  ์ˆ˜ ์—†๋‹ค.

์˜ต์…”๋„ ๋ณ€์ˆ˜(์ƒ์ˆ˜)๋ฅผ ์ƒ์„ฑํ•˜๊ณ  nil์„ ํ• ๋‹นํ•ด๋ณด์ž. ํƒ€์ž… ๋’ค์— ?๋ฅผ ๋ถ™์ด๋ฉด ๋œ๋‹ค.

var num: Int? = nil
num = 7
print(num) // Optional(7)

num๋ณ€์ˆ˜์— 7์„ ๋„ฃ๊ณ  ์ถœ๋ ฅ์„ ํ•ด๋ณด๋‹ˆ ์ถœ๋ ฅ์ด ๋˜๊ธด ํ•˜๋Š”๋ฐ, ๋ญ”๊ฐ€ ์ด์ƒํ•˜๋‹ค. ๊ฐ’์ด Optional()๋กœ ๊ฐ์‹ธ ์ ธ์„œ ์ถœ๋ ฅ๋œ๋‹ค. ์ด์ œ, ์˜ต์…”๋„ ๊ฐ’์„ ๊ณผ์ผ ๊นŽ๋“ฏ ์•Œ๋งน์ด๋งŒ ๋ฝ‘์•„๋‚ด๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋ณด์ž.

 

๊ฐ•์ œ ์ถ”์ถœ(Forced Unwrapping)

์˜ต์…”๋„ ๊ฐ’์„ ๊ฐ•์ œ๋กœ ์ถ”์ถœํ•˜๋ ค๋ฉด ์˜ต์…”๋„ ๊ฐ’ ๋’ค์— !๋ฅผ ๋ถ™์ธ๋‹ค. ์ด ๋ฐฉ๋ฒ•์€ ํ™•์‹คํ•˜์ง€๋งŒ ์œ„ํ—˜ํ•˜๋‹ค. ๋ฒ—๊ฒจ๋‚ด๋ ค๋Š” ์˜ต์…”๋„์ด ๊ฐ’์ด ์žˆ๋‹ค๋ฉด ๋ฌธ์ œ๊ฐ€ ์—†๊ฒ ์ง€๋งŒ, ๊ฐ’์ด ์—†๋Š” ์ƒํ™ฉ์ด๋ผ๋ฉด ์˜ค๋ฅ˜๊ฐ€ ์šฐ๋ฆฌ๋ฅผ ๋ฐ˜๊ธด๋‹ค.

var num: Int? = 7
if num != nil {
    print("num is \(num!)") // num is 7
}

๊ฐ€๊ธ‰์ ์ด๋ฉด ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ , ํ˜น์‹œ๋ผ๋„ ์“ฐ๊ฒŒ ๋œ๋‹ค๋ฉด ๋ฐ˜๋“œ์‹œ ๊ฐ’์ด ์žˆ์Œ์„ ๋ณด์žฅํ•˜๋Š” ์ƒํ™ฉ์—์„œ๋งŒ ์“ฐ์ž.

 

์˜ต์…”๋„ ๋ฐ”์ธ๋”ฉ(Optional Binding) - if

์˜ต์…”๋„ ๋ฐ”์ธ๋”ฉ์€ ์˜ต์…”๋„ ๋ณ€์ˆ˜(์ƒ์ˆ˜)์— ๊ฐ’์ด ์žˆ๋Š”์ง€ ํ™•์ธํ•˜๊ณ , ํ•ด๋‹น ๊ฐ’์„ ์ž„์‹œ ๋ณ€์ˆ˜(์ƒ์ˆ˜)์— ํ• ๋‹นํ•ด์„œ ์‚ฌ์šฉํ•˜๋Š” ๊ธฐ๋ฒ•์ด๋‹ค. if๋ฌธ์ด๋‚˜ while๋ฌธ๊ณผ ํ•จ๊ป˜ ์‚ฌ์šฉ๋œ๋‹ค.

func output(_ myName: String?) {
    if let name = myName {
        print("my name is \(name)")
    } else {
        print("unknown name")
    }
}

var myName: String? = "์ง€์›"
output(myName) // my name is ์ง€์›

if๋ฌธ์—์„œ ์ƒ์„ฑํ•œ ์ž„์‹œ ์ƒ์ˆ˜ name์€ if๋ฌธ ๋‚ด๋ถ€์—์„œ๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

์œ„์™€ ๊ฐ™์€ ์ƒํ™ฉ์„ guard๋ฌธ์„ ์ด์šฉํ•ด์„œ ์ฒ˜๋ฆฌํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

 

์˜ต์…”๋„ ๋ฐ”์ธ๋”ฉ(Optional Binding) - guard

guard๋ฌธ์— ์žˆ๋Š” ์กฐ๊ฑด์ด false์ธ ๊ฒฝ์šฐ์—๋Š” guard๋ฌธ ๋‚ด๋ถ€๋กœ ์ง„์ž…ํ•˜๊ณ , true์ธ ๊ฒฝ์šฐ์—๋Š” ๋ฐ”๊นฅ ์ฝ”๋“œ๋ฅผ ์ง„ํ–‰ํ•œ๋‹ค.

if๋ฌธ์œผ๋กœ ์ƒ์„ฑํ•œ ์ž„์‹œ ์ƒ์ˆ˜๋Š” if๋ฌธ ๋‚ด๋ถ€์—์„œ๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, guard๋ฌธ์œผ๋กœ ์ƒ์„ฑํ•œ ์ƒ์ˆ˜๋Š” guard๊ตฌ๋ฌธ์ด ๋๋‚˜๊ณ  ๋‚œ ๋’ค๋ถ€ํ„ฐ ํ•จ์ˆ˜ ๋‚ด๋ถ€์˜ ์ง€์—ญ ์ƒ์ˆ˜์ฒ˜๋Ÿผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

func output(_ name: String?) {
    guard let name = myName else {
        print("unknown name")
        return
    }
    print("my name is \(name)")
}

var myName: String? = nil
output(myName) // unknown name

guard๋ฌธ ๋‚ด๋ถ€์˜ ๋์—๋Š” return, break, continue, throw๊ฐ€ ํฌํ•จ๋˜์–ด์•ผ ํ•œ๋‹ค.

 

Nil-Coalescing Operator - ??

?? ์—ฐ์‚ฐ์ž๋Š” ๊ฐ’์ด ํฌํ•จ๋˜์–ด ์žˆ๋Š” ๊ฒฝ์šฐ์—๋Š” ์˜ต์…”๋„์„ ๋ฒ—๊ธด ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๊ณ , ์—†๋Š” ๊ฒฝ์šฐ์—๋Š” default ๊ฐ’์„ ์„ค์ •ํ•ด์ค„ ์ˆ˜ ์žˆ๋‹ค.

var myNickname: Int? = nil
let nickname = myNickname ?? "๋จน๊ตฌ๋ฆ„"
print(nickname) // "๋จน๊ตฌ๋ฆ„"

 

!!

Double exclamation !! mark in Swift? ์ด๋ผ๋Š” ์Šคํƒ์˜ค๋ฒ„ํ”Œ๋กœ์šฐ ๊ธ€์„ ๋ณด๋ฉด, Optional(Optional(value))์™€ ๊ฐ™์ด ์ด์ค‘์œผ๋กœ ํฌ์žฅ๋˜์–ด์žˆ๋Š” ์ƒํ™ฉ์—์„œ ์‚ฌ์šฉํ•˜๋Š” ๊ฑฐ ๊ฐ™์ง€๋งŒ, ๋” ์ž์„ธํ•œ ์ž๋ฃŒ๋Š” ์ฐพ์ง€ ๋ชปํ•ด์„œ ์ผ๋‹จ ์ด ๋ถ€๋ถ„์€ ์ข€ ๋” ์ฐพ์•„๋ณด๋Š” ๊ฑธ๋กœ....

 

์ฐธ๊ณ  ์ž๋ฃŒ

๋ฐ˜์‘ํ˜•