⭐️ 옵셔널 ❗️

DEVJUN·2022년 4월 29일
1

Swift 문법

목록 보기
5/14
post-thumbnail

  옵셔널은 스위프트에서 도입된 새로운 개념으로 언어 차원에서 프로그램의 안전성을 높이기 위해 사용하는 개념이다.

  옵셔널 개념은 nil을 사용할 수 있는 타입과 사용할 수 없는 타입으로 구분하고, 사용할 수 있는 타입을 가리켜 옵셔널 타입이라고 부른다.

  nil은 다른 언어에서 null과 같다. 값이 없음을 의미하는 특수한 값이다.

  다음 예시 코드를 보자!

	var capital = ["KR" : "Seoul", "CN" : "Beijing", "JP" : "Tokyo"]
    capital["Ko"] // nil

  딕셔너리가 정적으로 선언되어 있고 값이 할당되어 있다. 이 딕셔너리를 참조할 때 올바른 키값을 입력해주어야 하지만 코드에선 "Ko"라는 존재하지 않는 키를 통해 값을 참조하려 한다. 이럴 경우 오류가 발생하는 것이 정상이다. 그러나 스위프트는 겨우 이런 잘못된 참조 하나 때문에 실행을 중단시키지 않고, 최대한 안전성을 높이고자 노력하는 언어이기에 오류가 아닌 nil을 반환한다.

  하지만 모든 타입이 nil을 반환할 수 있는 것이 아니고 오직 옵셔널 타입만 nil을 반환 할 수 있다.

  중요한 것은 "오류가 발생할 가능성이다." 오류가 발생하지 않을 수도 있지만, 언젠가 오류가 발생할 가능성이 조금이라도 있다면 모두 옵셔널 타입으로 정의해야 한다.

  스위프트에서는 nil의 사용에 제약을 걸어두었다. 바로 일반자료형(String, Int, Double, Character, Float등 )은 nil을 가질 수 없다는 것이다. 함수도 마찬가지이다. 함수는 반환 타입이 정해져 있기 때문에 항상 그 타입에 맞는 값을 반환해야 하는데, 처리 과정이 실패했을 경우에는 nil을 반환하지만 일반 자료형에는 nil을 할당할 수 없기 때문에 nil을 반환하면 오류가 발생한다.

  이때 사용하는 것이 바로 옵셔널 타입❗️

  옵셔널 타입으로 선언된 자료형은 nil 값을 저장할 수 있다. 옵셔널 타입은 별도로 존재하는 자료형이 아니고, 모든 기본 자료형에는 그에 대응하는 옵셔널 타입이 존재한다. 정수 타입을 옵셔널 타입으로 바꾸면 Optional Int, 문자열을 바꾸면 Optional String이 되는 것이다.

	let v = Int("123") //"123"이라는 문자열을 정수형으로 변환하여 상수형 변수 v에 할당
    print(v) // Optional(123)

  위의 코드는 문자열 "123"을 숫자로 변환한 값을 반환하는 예제이다. 여기서 실제로 123을 반환하는 것이 아니라 옵셔널 타입으로 값을 감싼 Optional(123)을 반환한다.
  만약 숫자로 변환하지 못하는 문자열 "안녕"과 같은 문자열이 입력될 경우 nil 값을 반환한다.

   이렇게 옵셔널타입으로 둘러쌓여 있는 것을 옵셔널 래핑(Optional Wrapping) 이라고 한다. 이렇게 받은 값은 옵셔널 언래핑(Optional Unwrapping)이라고 불리는 특수한 과정을 통해 옵셔널 타입을 해제하고 실제 값을 추출하여 사용해야 한다.

  1.  옵셔널 타입 선언과 정의

    일반 자료형을 옵셔널 타입으로 만드는 방법은 단순하다.  우리가 사용하느 자료형 뒤에 ? 만 붙이면 된다.

  //옵셔널 Int 타입
  var optInt : Int?
  optInt =3 //값 할당
  
  //옵셔널 String 타입
  var optStr : String?
  optStr = "Swift"
  
  //옵셔널 Double 타입
  var optDouble : Double?
  
  //옵셔널 Array 타입
  var optArr : Array?
  optArr = ["C", "JAVA", "Python"]
  
  //옵셔널 Dictionary 타입
  var optDic : Dictionary<String, String>?
  var optDic2 : [String:String]?
  
  //옵셔널 Class 타입
  var optClass : AnyObject?
  

  2.  옵셔널 값 처리

  옵셔널 타입의 결과값은 그 자체로 아무것도 할 수 없다. 연산이나 결합을 할 수 없는 것이다.

  옵셔널 값을 사용하기 위해서는 옵셔널을 해제 해야 한다. 옵셔널 언래핑(Optional Unwrapping)이라고 한다. 옵셔널 해제 방식은 명시적 해제묵시적 해제로 나누어진다.

  명시적 해제는 다시 강제적인 해제비강제적인 해제로 나눌 수 있고 묵시적 해제는 각각 컴파일러에 의한 자동 해제연산자를 사용한 자동 해제로 나눌 수 있다.

    1. 옵셔널 강제 해제

옵셔널 강제 해제는 가장 많이 사용되는 해제 방법이다. 가장 단순하다. 옵셔널 타입 값 뒤에 '!' 기호만 붙여주면 된다.

	var optInt: Int? = 3

	print("옵셔널 값 : \(optInt)") // Optional(3)
	print("옵셔널 해제 값: \(optInt!)") // 3

	
	Int("123")! + Int("100")! //223

  값이 만약 nil인 옵셔널 변수에 ! 연산자를 붙이면 오류가 발생한다. 따라서 강제 해제 연산자를 사용할 때에는 먼저 옵셔널 값이 nil인지 점검해야 한다.

	var str = "123"
	var intFromStr = Int(str)

	if intFromStr != nil {
		print("값 변환. \(intFromStr!)")
	} else {
  		print("값 변환 실패")
  	}

  위 코드와 같이 사용해야 오류 없이 안전하게 옵셔널 타입을 해제하여 사용할 수 있다.


    2. 옵셔널 바인딩

  옵셔널 바인딩은 조건문 내에서 일반 상수에 옵셔널 값을 대입하는 방식으로 이루어진다.

	var str = "Swift"
	if let intFromStr = Int(Str) {
		print("값이 변환됨 \(intFromStr)")
	} else {
		print("값 변환 실패")
	}

  이 코드는 위에 강제해제 연산자를 사용하는 코드와 유사하지만 intFromStr이 상수로 선언되었다는 점과 이 상수가 옵녀널이 아닌 일반 타입이라는 점이 다르다.
 강제 해제 연산자를 사용하지 않아도 옵셔널 값이 일반 변수나 상수에 할당되면서 자연스럽게 옵셔널 타입이 해제되지만 값이 nil이더라도 값의 할당이 실패하여 결과값이 false로 반환될 뿐 오류는 발생하지 않는다.


	func intStr(str: String) {
		guard let intFromStr = Int(str) else {
			print("값 변환 실패")
			return
	}
	
	print("값 변환. 변환된 값은 \(intFromStr)")

  위 코드는 guard 구문을 이용하여 옵셔널 바인딩을 구현한 에제이다. guard 구문은 특성상 함수나 메소드에만 사용할 수 있기 때문에 intStr 함수를 정의하고 그 안에 guard 구문을 작성하였다.



    3. 컴파일러에 의한 옵셔널 자동 해제

  옵셔널 타입은 강제해제를 하지 않아도 컴파일러에서 자동으로 해제해 주는 경우가 있다.

	let optInt = Int("123")
	
	if(optInt == 123) {
	   	print("optInt == 123") //얘가 실행됨....
	} else {
		print("optInt != 123")
	}

  optInt는 강제 해제 되지 않았다. Optional(123)이다. 그러나 if 문이 실행되었다...

  옵셔널 객체의 값을 비교 연산자를 사용하여 비교하는 경우는 굳이 해제하지 않아도 자동으로 컴파일러가 옵셔널 타입을 해제하여 비교 연산을 수행하게 된다.



    4. 옵셔널 묵시적 해제

  옵셔널 타입을 선언하기 위해서 자료형 뒤에 '?'를 붙였다. 옵셔널 묵시적 해제는 일반 옵셔널 타입의 변수 선언 구문과 매우 유사하다. ? 대신 !연산자를 붙여주면 된다.


	var str: String? = "Swift Optional"
	print(str) // Optional("Swift Optional")

	var str: String! = "Swift Optional"
	print(str) //Swift Optional

	var value: Int? = 10
	value + 5 //오류

	var value: Int! = 10
	value + 5 // 15
	

  편리하지만 염두에 두어야 할 것이 있다. 바로 변수의 값이 nil이 될 가능성이 있다면 묵시적 옵셔널 해제를 사용하지 않아야 한다는 것이다.

  반대로 묵시적 옵셔널 해제를 사용하는 경우는 한 가지이다. 형식상 옵셔널로 정의해야 하지만, 실제로 사용할 때에는 절대 nil 값이 대입될 가능성이 없는 변수일 경우이다.

profile
🧑🏻‍💻iOS

0개의 댓글