Swift๋ฅผ ์ฒ˜์Œ ๊ณต๋ถ€ํ•˜๋ฉด์„œ ๊ฐ€์žฅ ์–ด๋ ค์› ๋˜๊ฒŒ ์ด Optional์ธ ๊ฒƒ ๊ฐ™๋‹ค. ์• ์ดˆ์— ๊ฐœ๋ฐœ๋„ ์ฒ˜์Œํ•  ์‹œ๊ธฐ์˜€์œผ๋‹ˆ, ์ด๋Ÿฐ ์ž๋ฃŒ๊ตฌ์กฐ๊ฐ€ ์™œ ํ•„์š”ํ•œ์ง€ ์ „ํ˜€ ๋ชฐ๋ž์—ˆ๋˜ ์‹œ๊ฐ„์ด ์žˆ์—ˆ๋‹ค. ํ•ด๋‹น ์ด์œ ๋Š” Either์™€ Result ์ดํ•ด์™€ ์‹ค์ œ ์‚ฌ์šฉ์˜ˆ ์•Œ์•„๋ณด๊ธฐ ํฌ์ŠคํŠธ๋ฅผ ์ฐธ๊ณ ํ•ด์ฃผ๊ธธ ๋ฐ”๋ž€๋‹ค. ๊ทธ๋Ÿผ, Optional์˜ ์ •์ฒด์™€ ๊ถ๊ธˆํ–ˆ๋˜ ์ ์„ ์ •๋ฆฌํ•˜๋Š” ํฌ์ŠคํŒ…์„ ์‹œ์ž‘ํ•ด๋ณด๋„๋ก ํ•˜๊ฒ ๋‹ค.

Optional

enum Optional<T> {
  case none
  case some(<T>)
}
 
// ์‹ค์ œ ๋ฌธ์„œ์—๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ์ ํ˜€ ์žˆ๋‹ค. generic ํƒ€์ž… ํŒŒ๋ผ๋ฏธํ„ฐ์— ๋Œ€ํ•ด ๋ช…์‹œ์ ์œผ๋กœ ์ ๊ธฐ ์œ„ํ•ด ์ด๋ ‡๊ฒŒ ๋˜์–ด ์žˆ๋‹ค.
enum Optional<Wrapped> {
  case none
  case some(<Wrapped>)
}

์ผ๋‹จ, ํ•ต์‹ฌ์€ Optional์€ enum์ด๋ผ๋Š” ๊ฒƒ์ด๋‹ค. case ์ด๋ฆ„ ๋’ค์— ()๊ฐ€ ๋ถ™์€ ๊ฒƒ์€, ์ด some์ด๋ผ๋Š” ํŠน์ • ํƒ€์ž…์— ๋Œ€ํ•ด ์ถ”๊ฐ€์ ์ธ ์ •๋ณด๋ฅผ ์ €์žฅํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค. ์ด ๊ฒฝ์šฐ๋Š” ๋ชจ๋“  ํƒ€์ž…์˜ ์ธ์Šคํ„ด์Šค๊ฐ€ ๋“ค์–ด๊ฐ„ ๊ฒƒ์„ some์ด๋ผ๋Š” ํƒ€์ž…์˜ ์ถ”๊ฐ€์ •๋ณด๋กœ ์„ค์ •ํ–ˆ์Œ์„ ๋งํ•œ๋‹ค. ์ด๊ฑธ Associoated Values(์—ฐ๊ด€๊ฐ’)์ด๋ผ ํ•œ๋‹ค.

var hello: String?
var hello: String? = "hello"
var hello: String? = nil
 
var hello: Optional<String> = .none
var hello: Optional<String> = .some("hello")
var hello: Optional<String> = .none

์ด๋ ‡๊ฒŒ ์Šค์œ„์น˜๋ฌธ์œผ๋กœ ํ• ๋‹น๋˜๋Š” ๊ฒƒ์ด ์ „๋ถ€์ด๋‹ค!

Optional Unwrapping

๊ทธ๋ ‡๋‹ค๋ฉด, Optional์„ ์–ธ๋ž˜ํ•‘ํ•  ๋•Œ, ์‹ค์ œ๋กœ ์–ด๋–ป๊ฒŒ ๋™์ž‘ํ•˜๋Š” ๊ฑธ๊นŒ? ๋จผ์ € ๊ฐ•์ œ ์–ธ๋ž˜ํ•‘์˜ ๊ฒฝ์šฐ๋ฅผ ๋ณด์ž.

let hello: String? = "์•ˆ๋…•!"
print(hello!)
 
switch hello {
  case .none // ์—๋Ÿฌ๋ฐœ์ƒ Crash
  case .some(let data):
    print(data)
}

์•„๋ฌด๋ž˜๋„ swift์—์„œ๋Š” enum๊ณผ switch ๋ฌธ์„ ๋งŽ์ด ์‚ฌ์šฉํ•˜๋‹ค๋ณด๋‹ˆ, ์ด๋ ‡๊ฒŒ ์ ์–ด๋ณด์•˜๋‹ค. ๊ฒฐ๊ตญ ์˜ต์…”๋„์„ ์–ธ๋ž˜ํ•‘ํ•œ๋‹ค๋Š” ๊ฒƒ์€ switch๋ฌธ์„ ํ†ตํ•ด ํ’€์–ด์ฃผ๋Š” ํ–‰์œ„๋ฅผ ๋งํ•œ๋‹ค. ์ด๋ฒˆ์—๋Š” ์˜ต์…”๋„ ๋ฐ”์ธ๋”ฉ์„ ๋ณด์ž.

let hello: Optional<String> = "์•ˆ๋…•!"
if let hello = hello {
  print(hello)
}
 
switch hello {
  case .some(let data):
    print(hello)
  case .none:
    // ์•„๋ฌด์ผ๋„ ์•ˆํ•จ
}

none๊ณผ some์˜ ์œ„์น˜๊ฐ€ ๋ณ€๊ฒฝ๋˜์—ˆ๋‹ค. ์ด๋ฒˆ์—๋Š” ์•”์‹œ์ ์œผ๋กœ ํ’€์–ด์ง„ ์˜ต์…”๋„์„ ๋ณด์ž.

var hello: String!
hello = "์•ˆ๋…•!"
print(hello)
 
var hello: Optional<String> = .none //์•„๋ฌด ์ดˆ๊ธฐ์ธ์ž๊ฐ€ ์—†์ด ์ƒ์„ฑ๋˜์—ˆ์„ ๊ฒฝ์šฐ ์ดˆ๊ธฐ๊ฐ’์€ .none์ด๋‹ค. ?Optional๋„ ๋‹น์—ฐํžˆ ๊ฐ™์€ enum์ด๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ™๋‹ค.
 
switch hello { // ๋‹ค๋งŒ ์˜ต์…”๋„ ๋ฐ”์ธ๋”ฉ์ด๋‚˜ ๊ฐ•์ œ ์–ธ๋ž˜ํ•‘์„ ํ•ด์ฃผ์ง€ ์•Š์•„๋„ switch๋ฌธ์„ ์‹คํ–‰ํ•œ๋‹ค.
  case .none // ์—๋Ÿฌ๋ฐœ์ƒ Crash
  case .some(let data):
    print(data)
}

์•”์‹œ์  ์˜ต์…”๋„์˜ ๊ฒฝ์šฐ, ์˜ต์…”๋„ ์–ธ๋ž˜ํ•‘์„ ํ•ด์ฃผ์ง€ ์•Š์€ ์ƒํƒœ์—์„œ๋„ ์—ฐ์‚ฐ์ด ๊ฐ€๋Šฅํ•˜๋‹ค ํ–ˆ๋‹ค. ์ด ์ด์œ ๋Š” ๋‹ค๋ฅธ ๊ฒƒ์ด ์•„๋‹ˆ๊ณ , ์•”์‹œ์  ์˜ต์…”๋„๋กœ ์„ ์–ธ๋œ ๋ณ€์ˆ˜์— ๋Œ€ํ•ด ์‹คํ–‰ํ•  ๋•Œ, ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ์•Œ์•„์„œ ํ•ด๋‹น ์Šค์œ„์น˜๋ฌธ์„ ๋งŒ๋“ค์–ด์ฃผ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

๊ฒฐ๊ตญ enum์„ ๊ธฐ์ค€์œผ๋กœ ๊ฐ’์„ ๋‚˜๋ˆ ์ฃผ๋Š” ๊ฒƒ์ด Optional์˜ ๋ณธ์งˆ์ด๋‹ค.

Nil-Coalescing Operator (Optional Defaulting)

๋ฌธ๋ฒ• ์ค‘์—, ์˜ต์…”๋„์ธ ๊ฒฝ์šฐ ํ•ด๋‹น ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ, ๋งŒ์•ฝ nil์ธ ๊ฒฝ์šฐ default๊ฐ’์„ ๋ฐฐ์ •ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ์—ˆ๋‹ค. ?? ์—ฐ์‚ฐ์ž๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์ด์—ˆ๋Š”๋ฐ, ์ด์ œ ์ •์ฒด๋ฅผ ์•Œ์•˜์œผ๋‹ˆ ์ด ๊ตฌ๋ฌธ์ด ์–ด๋–ป๊ฒŒ ๋ณ€๊ฒฝ๋˜๋Š”์ง€ ์•Œ์•„๋ณด์ž.

let x: String? = "๋น„๊ฐ€ ๋งŽ์ด์™€"
let y = x ?? "์žฅ๋งˆ ๋๋‚ฌ๋Œ€"
 
if let x = x {
  y = x
} else {
  y = "์žฅ๋งˆ ๋๋‚ฌ๋Œ€"
}
 
switch x {
  case .none: y = "์žฅ๋งˆ ๋๋‚ฌ๋Œ€"
  case .some(let data): y = data
}

์ด์™€ ๊ฐ™์ด ๋™์ž‘ํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ์ •์ฒด๋ฅผ ์•„๋‹ˆ ์ƒ๊ฐ๋ณด๋‹ค ์—ญ์‹œ ๋ณ„๊ฒŒ ์—†๋‹ค.

Optional chaining

์ž ์ด๋ ‡๊ฒŒ Optional์˜ ๋ณธ์งˆ์„ ์•Œ์•˜๋‹ค๋ฉด, ์—ฌ๋Ÿฌ๊ฐœ์˜ Optional ์ฒด์ด๋‹์ด ์–ด๋–ป๊ฒŒ ์ผ์–ด๋‚˜๋Š”์ง€ ์•Œ์•„๋ณด์ž.

let x: String? = "๋„ˆ๋ฌด ๋”์›Œ"
let y = x?.foo()?.bar?.z
 
switch x {
  case .none: y = nil
  case .some(let data1):
    switch data1.foo() {
      case .none: y = nil
      case .some(let data2) {
        switch data2.bar {
          case .none: y = nil
          case .some(let data3): y = data3.z
        }
      }
    }
}

์š”๋Ÿฌ์ฝ”๋Ÿผ ๋™์ž‘ํ•œ๋‹ค! ๊ทธ๋ž˜์„œ ์ด์ „ ๊ธ€์—์„œ ๊ณต๋ถ€ํ–ˆ์„ ๋•Œ, ์•ž๋ถ€๋ถ„์—์„œ nil์ด ๋‚˜์˜ค๋Š” ๊ฒฝ์šฐ ํ•ด๋‹น ๊ตฌ๋ฌธ์ž์ฒด๊ฐ€ ์‹คํ–‰์ด ๋˜์ง€ ์•Š๊ณ  ๋„˜์–ด๊ฐ”๋˜ ๊ฒƒ.

Optional Binding์—์„œ ,์™€ &&

๋„ˆ๋ฌด ์ข‹์€ ๊ธ€์ด ์žˆ์–ด ๋งํฌ๋กœ ๋Œ€์ฒดํ•˜๊ฒ ๋‹ค!

ํ•ต์‹ฌ์€ &&์€ ๋‘๊ฐœ์˜ boolean ํ‘œํ˜„์„ ๋ฐ›๋Š” ๋…ผ๋ฆฌ ์—ฐ์‚ฐ์ž์ด๊ณ , ,๋Š” ์กฐ๊ฑด์„ ์ด์–ด๋ถ™์ด๋Š” ์šฉ๋„๋กœ ์‚ฌ์šฉํ•œ๋‹ค๋Š” ๊ฒƒ!