APPLE/Swift 문법

[ 기초 문법 ] 옵셔널

pandada 2022. 8. 8. 15:52
반응형

이번에는 옵셔널에 대해서 알아보도록 하자.

옵셔널이 뭐 Swift에서 특이한 매우 좋은 기능이라고 하는데..

아직까지는 정확히 잘 모르겠다.

이 글을 작성하는 동안에도 Swift특유의 기능이라고는 생각이 안들기 때문에...

하지만 기본적인 개념에 대해서는 알아둘 필요가 있기 때문에 한번 진행을 해보려고 한다.

 

옵셔널

  • 옵셔널 ( 선택적인? ) 기능.
  • 스위프트의 가장 큰 기능 중 하나로 값이 있을 수도 있고, 없을 수도 있다.
  • 옵셔널 타입을 사용하려면 기본 데이터 타입 뒤에 ? 를 붙이면 된다.
  • 옵셔널로 정의한 변수는 옵셔널로 정의하지 않은 변수와 서로 다르다.

우선 대략적인 옵셔널의 정의에 대해서 알아봤다.

 

솔직히 이렇게 진행한다고 하면... 아무리 필자라도 잘 모르겠다.

한번 실습을 통해서 알아보도록 하자.

 

< 옵셔널의 선언 >

우선 기본적인 옵셔널의 선언에 대해서 확인해봤다.

이렇게 옵셔널로 선언할 경우에는 값이 nil이다. 명백히 값으로 얘기를 하면 안되고, 그냥 nil 이라고 생각하면 된다.

 

자 그럼 이렇게 보면 정확히 모르기 때문에 우리가 여태까지 변수를 선언했던 방식으로 선언을 해서 데이터를 비교 해보도록 하자.

 

< 옵셔널과 일반 변수 차이 >

이렇게 옵셔널을 넣은 것과 옵셔널을 넣지 않은 것과 차이를 볼 수 있다.

 

실질적으로 옵셔널을 넣고 빌드를 할 경우에는 nil이 표기가 되지만, 옵셔널을 넣지 않은 경우에는 아무런 값이 없다.

즉, 여기서 값이 없는것도 값이다. 다시말하면 그냥 빈 공간이라는 것이다.

 

 

그럼 이제 옵셔널로 선언한 변수에 대해서 값을 한번 넣어보도록 하자.

 

< 옵셔널 변수에 TEST 삽입 >

optionName으로 선언한 옵셔널 변수에 "TEST" 문자열을 넣었다.

우선적으로 자동 실행창을 통해서 확인하면 기본적으로 TEST 로 표기가 된다. 

이제 이 값을 print 함수를 통해서 출력을 진행해보도록 하자.

 

< Optional 출력 >

옵셔널을 사용한 변수를 출력할 경우에는 하단의 실행창 또는 옆부분의 자동 실행창에 출력시에는 Optional이라는 랩핑으로 TEST가 포장이 되어있는 것을 확인할 수 있다.

 

또한 Expression implicitly coerced from 'String' to 'Any' 이렇게 경고 문구가 뜨는 것을 확인할 수 있다.

이렇게 경고문구가 뜨는 것은 암시적으로 String에서 Any로 변경이 되었다는 것을 뜻한다. 

즉, 옵셔널로 선언을 했지만 String 형태는 가지고 있고, 표현이 어느정도는 가능하다는 것을 의미한다.

 

자 그럼 현재까지 진행한 옵셔널에 대해서 추가적인 설명을 진행해보도록 하겠다.

 

< 옵셔널의 추가 정의 >

옵셔널을 통해서 nil이냐 값이 있냐 없냐에 대한 내용을 간략히 작성해봤다.

 

자 그럼 위에서 옵셔널 변수와 일반 변수와 서로 다르다고 위에서 언급을 했는데 이부분에 대해서 내용을 확인해보도록 하자.

 

< 일반 변수에 옵셔널 변수 삽입 >

필자는 optionName2라는 일반 String 변수를 선언했고, 이후에 옵셔널로 선언한 "TEST"를 넣어봤다.

이럴경우 Value of optional type 'String?' must be unwrapped to a value of type 'String' 이런 에러가 발생했다.

해당 에러에 대해서 확인해보자.

선택적 유형 String?의 값은 String으로 랩핑을 해제해야한다.

대략 이런 뜻이다. 

 

보다 자세히 얘기를 하자면 랩핑된 String?을 String으로 만들고 넣어라. 이말이다.

해당 내용이 되지 않는 이유는 optionName2는 String 타입으로 인하여 항상 값을 가지고 있어야 하기 때문에 optionName 처럼 값이 있을 수도 있고, 없을 수도 있는 타입의 값은 넣을 수가 없다.

스위프트에서는 안정성을 위해서 옵셔널로 설정된 변수의 값을 일반 변수의 값에 넣을 수 없게 만들어놨다.

 

이것이 스위프트에서 강조하는 안정성이라고 하는데... 필자는 아직까지 정확히 Swift에서 자랑하는 안정성에 대해서 정확히 모르겠다.

뭐 나중에 천천히 공부를 해나가다 보면 알게될 것 같지만..

 

추가적으로 옵셔널 변수는 일반 변수에 대해서 대입 뿐만이 아니라 연산 자체도 불가능하다.

이것을 해결하기 위해서 옵셔널 바인딩이라는 함수를 통해서 진행이 가능하다.

 

옵셔널 해제 방법

 ♦︎ 명시적 해제

     → 강제 해제

     → 비강제 해제 ( 옵셔널 바인딩 )

 

 ♦︎ 묵시적 해제

     → 컴파일러에 의한 자동 해제

     → 옵셔널의 묵시적 해제

 

 

옵셔널 해제 방법에 대해서는 이렇게 존재한다.

이번에도 글만 가지고 설명을 할 경우에는 제대로 내용 이해가 되지 않기 때문에 예제를 통해서 작업을 진행해보도록 하자.

 

< 옵셔널의 강제적 해제 >

명시적 해제중의 강제적 해제에 관련된 내용이다. number라는 Int형의 옵셔널 변수에 7을 대입시키고, 일반적인 print와 강제적 해제를 진행한 내용이다.

 

일반적으로 print(number)를 했을 경우에는 기존처럼 Optional 랩핑이 되어있는 것을 확인할 수 있다.

이를 해제하기 위한 방법으로 변수명 뒤에 ! 를 붙여주는 것이다.

 

print(number!)를 했음으로 숫자 7로 프린트 된것을 볼 수 있다.

매번 이렇게 해제를 하면 되겠구나.. 생각을 할 수도 있지만 이렇게 옵셔널을 강제적으로 해제할 경우 매우 위험하다.

 

만약 옵셔널 number가 nil이라고 가정을 하자. 이럴경우 옵셔널을 강제적으로 number!를 할 경우에 에러가 발생해 프로그램이 강제적으로 종료가 되는 사건이 발생할 수도 있다.

이럴 경우 프로그램 강제종료로 인하여 디버깅에도 어려움을 가질 수 있음으로 이런 방법은 평상시에 거의 사용하지 않는다.

 

< 옵셔널 바인딩 >

옵셔널의 비강제해제에 대해서 확인을 해봤다. 

추가적인 설명을 한다면 옵셔널 바인딩은 조건문에서는 사용이 가능하다는 점이다.

즉, if문 조건으로 통하여 let result라는 상수를 하나 만들었고, 이 상수에 number라는 옵셔널 값을 넣을 수 있다는 점이다.

따라서 이때에는 print되는 값이 자동으로 옵셔널이 해제되서 프린트가 된다.

 

정리하자면 강제적으로 해제를 할 수 있고, if문과 같은 조건문 안에서는 일반 변수에 대입이 가능하다는 얘기다.

이건 추가의 내용이지만 if문과 같은 조건문에서 선언한 변수는 조건문 내에서만 사용이 가능하다.

다른 개발 언어를 했을 경우에는 뭐 지역 변수, 전역 변수 개념으로 이해를 하면 될 것 같다.

만약 다른 언어를 하지 않았을 경우에는 그냥 조건문에서 사용한 것은 조건문 내부에서만 사용 가능하구나~ 이렇게 이해하고 넘어가면 된다.

 

자 그럼 이제 조건문의 추가 종류 guard 도 사용을 하면서 진행을 해보자.

guard에 대해서는 나중에 추가 설명을 진행할 예정으로 그냥 이런 것이 있구나.. 로 우선적으로 넘기면 된다.

 

< guard 사용 >

위의 이미지 상에도 적어놨지만, guard에 대해서 간단히 얘기를 하자면

gurad 문은 조건이 true 일때에만 guard 문을 통과하고, 그렇지 않을 경우에는 else 문을 통과하여 흐름을 종료시킨다.

 

즉 test 함수에 대해서 추가 설명을 진행해보겠다.

 

test 함수 안에서만 사용할 수 있는 상수 number 옵셔널 변수를 만들었고, 그 변수에 7이라는 값을 대입했다.

guard 문을 통해서 옵셔널변수를 일반 상수 result 변수에 값을 넣었고, 이게 맞을 true 일경우 즉, 이게 값이 있음으로 true로 인하여 else 문을 통과하지 않았다.

 

이후에 조건문에서 옵셔널변수를 받았음으로 인하여 print 할때에 옵셔널 랩핑이 해제된 내용을 확인할 수 있는 함수를 만들었다.

즉, 이번 guard 문법에 대해서는 일반적인 if문과 비슷한다는 것을 알 수 있다.

 

추가적으로 if문을 사용하여 옵셔널을 해제 했을 때에는 if문 안에서만 변수의 활용이 가능하지만 guard문을 활용해서 옵셔널 랩핑을 해제할 경우에는 guard 문 밖에서도 사용이 가능하다.

 

 

그럼 이번에 묵시적 해제 방법 중의 컴파일러에 의한 자동 해제에 대해서 확인해보도록 하자.

 

옵셔널 변수를 다른 값과 비교할 경우에는 컴파일러가 자동으로 해제하여 비교를 진행해준다.

 

< 컴파일러에 의한 해제 방법 >

이렇게 if문에 number3의 옵셔널 변수와 3이라는 숫자를 비교하는 내용을 넣고 진행했을 때에 정상적으로 비교 가되는 것을 확인할 수 있다.

그럼 위에거랑 뭐가다르냐. 위에는 옵셔널 변수의 값을 다른 변수에 넣은 것이고, 현재는 옵셔널 변수를 일반 숫자와 비교를 할때 사용한 내용이다.

그럼 이제 옵셔널 바인딩과 컴파일러에 의한 해제 방법이 뭐가 다른지에 추가적으로 좀 더 알아보도록 하자.

 

< 비교형 랩핑 에러 >

이렇게 변수와 변수를 비교할 경우에는 랩핑 에러가 표기가 된다. 이처럼 값이랑 비교를 할때에 컴파일러가 자동으로 옵셔널을 해제하는 내용이지, 특정 변수에 대입하는 내용과 서로 다르다는 것을 알아두면 된다.

비교 연산자를 활용하더라도 일반 변수의 값과는 비교가 불가능하다. 는 내용이다.

 

그러면 이제 옵셔널의 묵시적 해제에 대해서 알아보도록 하자.

 

옵셔널의 묵시적 해제는 옵셔널 타입이지만 값을 사용할 때에는 자동으로 해제되는 경우를 의미한다.

 

< 에러 발생 >

stringTest 라는 상수 변수에 12를 대입했고, 이 값을 Int 로 형변환을 진행했다.

형변환에 대해서는 나중에 진행하겠지만, 지금의 Int(stringTest)는 "12"라는 문자열을 Int 타입 12로 변경한다는 내용이다.

문자열에서 숫자로 형태를 변환했다고 해서 형변환이라고 언급한다.

 

그리고 변수 stringToInt의 옵셔널 Int 타입에 해당 12의 숫자를 대입했다.

 

그리고 나서 12? + 1 을 진행한 결과 옵셔널로 인하여 랩핑을 해제하고 해야한다고 또 오류가 발생했다.

에러가 발생할 것 같지 않은데 발생한 이유를 알아보자.

 

형변환을 해서 가져오는 값을 옵셔널로 설정한 이유는 형변환 시에 올바르지 않을 경우에는 형변환에 대한 결과값이 nil로 반환이 되기 때문에 값이 뭐가 올지 모르는 상황에서 옵셔널로 설정한다.

하지만 이렇게 에러가 발생하는데 이러한 내용을 해결하는 방법이 옵셔널의 묵시적 해제이다.

 

 

이럴 경우에는 아래와 같이 진행을 한다.

 

< 옵셔널 묵시적 해제 방법 >

이렇게 형변환을 할 경우에 형변환을 한 값을 넣어줄 때에 타입 뒤에 !가 있을 경우에 추후 해당 내용을 사용할 때에 옵셔널이 일시적으로 해제된다.

 

이렇게 다양하게 옵셔널을 해제하고, 사용하고 하면 된다.

 

이번에는 옵셔널에 대해서 알아봤는데 이걸 지금 적고 있는 필자도 그게 그거 아닌가... 하는 생각이 드는데..

 

추후에 프로젝트를 할 때에 어떻게 활용이 되는지 보면 좋을 것 같다. 참고로 필자도 계속해서 연습을 해보고 있는 중이다..

 

반응형

'APPLE > Swift 문법' 카테고리의 다른 글

[ 기초 문법 ] Init  (0) 2022.08.10
[ 기초 문법 ] 구조체와 클래스  (0) 2022.08.09
[기초 문법] 반복문  (0) 2022.08.05
[기초 문법] If문과 Switch 구문  (0) 2022.08.05
[기초 문법] 함수 ( func )  (0) 2022.08.04