CLOSE SEARCH

Swift Basics – Variables, Constants, Data Types, Tuples, Optionals

Comments

Swift에서는 Objective-C와 매우 유사한 방식으로 주석을 사용할 수 있습니다.  한줄 주석(//) 과 여러줄 주석(/* */)을 추가하는 방식은 동일하지만, 여러줄 주석의 경우 주석 내부에 또 다른 여러줄 주석을 내포할 수 있습니다. 그래서 주석을 작성할 때 */ 때문에 받았던 스트레쓰!가 사라지게 되었습니다 :)

 

Variables & Constants

Swift의 변수와 상수는 다른 언어와 개념적으로 동일하지만, 선언 문법에서 큰 차이를 보입니다. 변수를 선언할 때는 키워드 var, 상수를 선언할 때는 키워드 let을 사용합니다. 특히, 상수는 Swift에서 광범위하게 사용하며, 단지 변경될 필요가 없는 값을 저장하는 것 이상으로 코드를 좀 더 안전하고 이해하기 쉽게 하는 역할을 담당하고 있습니다.

코드 1-1을 보면 각 문장 뒤에 세미콜론(;)이 빠져 있다는 것을 확인하실 수 있습니다. Objective-C와 마찬가지로 세미콜론을 붙여주어도 오류없이 정상적으로 빌드되지만, Swift에서는 세미콜론이 없는 코딩 스타일을 사용하고 있기 때문에 이제는 새끼손가락을 좀 쉬게 해주자구요~:) 하지만, 여기에는 반드시 기억해야할 한가지 제약이 있습니다. 한 줄에 두개의 명령문을 작성하는 경우에는 반드시 각 명령문을 구분하기 위해서 세미콜론을 적어주어야 합니다.

Objective-C에서는 변수나 상수를 선언할 때 반드시 자료형을 지정해 주어야 했습니다. 하지만, Swift는 컴파일러가 자료형을 추론할 수 있는 경우 코드 1-3의 1번 라인과 같이 자료형을 생략하는 것을 허용합니다. 만약, 자료형을 명확히 지정해 주고 싶다면 2번 라인처럼 변수(또는 상수)명 뒤에 콜론을 적고 원하는 자료형을 적어주면 됩니다. 콜론과 자료형 사이에는 공백을 적어주는 것이 원칙이지만, 공백이 없더라도 정상적으로 빌드할 수 있습니다.
실제로 코드 1-3를 빌드해 보면 1번 라인에서 “Type annotation missing in pattern” 오류가 발생합니다. Swift는 자료형을 생략한 경우 초기값을 통해 자료형을 추론하는데, 1번 라인에는 그러한 정보(초기값)가 없기 때문에 자료형을 추론할 수 없게 됩니다. 만약, 1번 라인 다음에 foo = 10이라는 코드를 추가하더라도 선언 시점에 자료형을 추론할 수 없는 것은 마찬가지이기 때문에 동일한 오류가 발생합니다. 그러므로 자료형을 생략하려면 선언과 동시에 초기값을 설정해주거나, 2번 라인과 같이 명시적으로 자료형을 지정해 주어야 합니다.
변수와 상수의 이름정의 규칙은 Objective-C와 대부분 동일하며, 가장 큰 차이가 있다면 한글을 포함한 유니코드 문자를 사용할 수 있다는 것입니다. 그래서 아래와 같은 극단적인(?) 코드도 문제없이 빌드할 수 있습니다.
poopy-swift-code-example

이름을 표현할 수 있는 범위는 넓어졌지만, 몇가지 제한도 존재합니다.
1) 연산에 사용되는 문자(+, -, *, / 등)들은 사용할 수 없습니다.
2) 특수문자 중 화살표, 라인, 박스에 해당되는 문자들은 사용할 수 없습니다.
3) 일부 유니코드 문자는 사용할 수 없고, 숫자로 시작되는 이름도 사용할 수 없습니다.
4) Swift의 키워드를 변수나 상수의 이름으로 사용할 수도 있지만, 반드시 필요한 경우가 아니라면 피해야 합니다. (이름을 ` 문자로 감싸면 됩니다.)

 

Good bye, NSLog

Swift에서는 println 함수를 사용해서 값을 출력할 수 있습니다. 이름에서 알 수 있듯이, 줄바꿈 문자를 마지막에 자동으로 붙여줍니다. 만약, 줄바꿈 문자가 필요없다면 print 함수를 대신 사용할 수 있습니다.
println 함수를 통해 복잡한 문자열을 출력하려면 string interpolation 기능을 사용합니다. Objective-C에서 formatted string 을 생성하는 것이라고 생각하시면 됩니다.

코드 2-1과 같이 \( 와 ) 사이에 출력할 표현식을 적어주면 됩니다.

 

Type Safety

Swift는 형식에 안전한 언어(type safe language)입니다. 쉽게 말해서, 실수로 Int 자료형에 String 값을 대입하는 것과 같이 서로 다른 여러가지 자료형을 조합해서 작업할 때 발생할 수 있는 다양한 오류를 사전에 방지해 줍니다. 이런한 작업은 type check라고 하며, 코드를 빌드할 때 컴파일러에 의해 수행됩니다. 물론, Objective-C도 이와 유사한 기능을 컴파일러 경고를 통해 제공해 주었지만, Swift는 좀 더 강력하고 제한적인 형식 확인을 수행합니다.

 

Type Inference

Swift는 앞서 설명한 것처럼 자료형을 추론할 수 있습니다. 이러한 기능을 형식 추론(Type Inference)이라고 하며, 컴파일러는 할당된 값을 기반으로 정확한 형식을 추론합니다. 그래서 Objective-C와는 달리 변수(또는 상수)를 선언할 때 자료형을 생략할 수 있습니다.
컴파일러는 정수의 경우에는 항상 Int, 부동소수의 경우에는 항상 Double 자료형으로 추론합니다. 정수와 부동소수가 조합된 경우에는 항상 더 큰 자료형(이 경우에는 Double)으로 추론합니다.

 

Literals

숫자 리터럴은 다양한 접두사를 사용해서 표현할 수 있습니다. 접두어가 없는 경우에는 10진수로 표현되며, 2, 8, 16진수는 각각 0b, 0o, 0x 접두어를 붙여서 표현합니다. 특히, 숫자의 가독성을 높이기 위해 코드 3-1과 같이 형식 문자를 조합해서 사용할 수도 있습니다.

 

Data Types

Objective-C와는 달리 Swift의 자료형의 이름은 대문자로 시작합니다.

Integers

Swift에서는 1, 2, 4, 8바이트 크기의 정수 자료형을 제공합니다. Objective-C에서는 UINT32_MAX와 같은 상수를 통해서 최대/최소값을 알아낼 수 있지만, Swift에서는 min, max 속성을 사용해서 자료형의 값의 범위를 확인할 수 있습니다.

정수형을 사용할 때는 대부분 UInt16, Int32 등과 같은 자료형 대신 Int(또는 UInt)를 사용하게 될 것입니다. Int는 C나 Objective-C의 int와 마찬가지로 CPU의 WORD와 동일한 크기를 가지는 자료형입니다. 즉, 32비트에서는 Int32가 되고, 64비트에서는 Int64가 되는 것입니다. Int를 사용하는 것은 명시적으로 크기를 지정하는 자료형을 사용하는 것에 비해 일관성과 호환성 측면에서 유리하기 때문에, Swift 문서에서도 Int를 사용할 것을 추천하고 있습니다.

Float & Double

Swift의 Float는 Objective-C의 float에 해당되는 자료형이며 4바이트의 크기를 가집니다. double에 해당되는 자료형은 Double이며 8바이트 크기를 가집니다.

Boolean

Swift에서는 참/거짓을 나타내는 Bool 자료형을 제공합니다. 그리고 YES, NO 대신 true, false를 불린 상수로 사용합니다. Objective-C나 C에서는 0 이외의 숫자는 모두 참(YES)으로 평가했지만, Swift에서는 이 편리한(?) 방법을 사용할 수 없습니다. 즉, 불린 표현식에서 true는 참이지만, 1은 참/거짓 어느것도 아닌 문법 오류가 됩니다.

 

Type Conversion

Swift에서는 암시적 형변환을 허용하지 않습니다. Objective-C에서는 int 값을 double에 대입할 때 자동 승급이 되었지만, Swift에서는 자료형의 크기나 종류에 관계없이 다른 자료형으로 형변환을 하기 위해서는 반드시 명시적으로 변환할 자료형을 지정해 주어야 합니다.

숫자 리터럴의 경우에는 이러한 제한이 적용되지 않습니다. 숫자 리터럴은 그 자체로 자료형을 가지고 있지 않고, 리터럴의 자료형은 컴파일 시점에 표현식을 통해 값이 평가되는 시점에 결정되기 때문입니다.

 

Type Aliase

Objective에서 자료형에 새로운 이름을 붙일 때는 typedef를 사용합니다. 그래서 CGFloat 선언을 보면 다음과 같이 되어 있습니다.

Swift에서는 typedef 대신 typealias 키워드를 사용합니다. 그리고 새로운 자료형 이름과 원본 자료형 사이에 =을 적어줍니다. 실제로 Swift에서 제공하는 CGFloat는 다음과 같이 선언되어 있습니다.

 

Tuples

튜플을 두개 이상의 값으로 구성되는 복합 값입니다. int나 double와 같은 Scalar 값과 대비되는 것으로 볼 수 있습니다. 튜플에 포함되는 자료형에는 제약이 없으며, 튜플을 구성하는 각 값이 반드시 동일한 자료형일 필요도 없습니다. 튜플은 함수에서 두개 이상의 값을 리턴하는 경우에 유용하게 사용할 수 있습니다.

코드 6-1은 HTML 404 에러를 표현한 튜플입니다. 변수 http404Error의 자료형은 (Int, String)입니다. 튜플에 포함된 각 요소의 값은 코드 6-2와 같이 접근할 수 있습니다.

먄약, 튜플에 포함된 요소 중 특정 요소의 값에만 접근하는 경우에는, 코드 6-3과 같이 필요없는 요소를 _ 로 표시할 수 있습니다.

앞에서 설명드린 방법은 새로운 상수를 생성한다는 측면에서 불편할수도 있습니다. 그래서 Swift는 인덱스 값을 통해서 각 요소에 접근할 수 있는 방법을 제공합니다. 이 인덱스는 zeor-base입니다.

인덱스를 이용한 접근 방식도 편리하지만, 가독성을 고려하면 좋은 코드는 아닙니다. 그래서 다음과 같이 튜플의 각 요소에 이름을 붙이고 . 연산자를 통해 접근하는 문법도 함께 제공합니다.

 

Optionals

Swift에서 Optional 이라는 새로운 기능이 도입되었습니다. 이것은 Objective-C에서 포인터와 nil을 함께 사용하는 것과 유사하지만, 클래스에만 국한되지 않고 Swift에서 제공하는 모든 자료형에 적용할 수 있습니다. 이 기능은 Objective-C의 nil 포인터에 비해 더 안정적이고 직관적이며, Swift에서 제공하는 새로운 기능들의 핵심이기도 합니다. 이러한 Optional은 Swift가 형식에 안전한 언어(type safe language)라는 것을 보여주는 한가지 사례가 됩니다. Swift는 Optional을 통해 String 자료형에 실수로 Int 값을 대입하는 것과 같은 실수를 사전에 방지해 주어, 개발 과정에서 발생할 수 있는 다양한 오류들을 조금 더 쉽게 발견하고 수정할 수 있도록 도와줍니다.

Optional은 C나 Objective-C에는 없었던 개념이기 때문에 이해하기 힘들수도 있습니다. 이것은 Objective-C에서 유효한 객체가 있는 경우 해당 객체를 리턴하고, 없을 경우 nil을 리턴하는 것과 유사하다고 볼 수 있습니다. 앞의 설명은 “객체”에 국한된 것이지만, Swift에서는 Optional이 객체가 아닌 자료형을 포함한 모든 자료형에 적용됩니다. NSNotFound와 같은 상수를 사용해서 값의 부재를 표현했던 것과 달리, Optional 하나로 모든 자료형의 값의 부재를 표현할 수 있게 된 것입니다.

Optional은 자료형 뒤에 ?를 붙여서 표현합니다. Int에 ?를 붙이면 Int?가 되고 “Optional int”라고 읽으면 됩니다.

코드 7-1에서 possibleNumber는 String 자료형으로 추론되고, convertedNumber 는 String의 toInt() 메소드를 통해 정수로 변환된 값으로 초기화 됩니다. “123”이라는 문자열은 모두 숫자이기 때문에 문제없이 정수로 변환될 수 있지만, “hello”와 같은 문자열은 정수로 변환될 수 없습니다. 문자열이 항상 정수로 변환될 수 있는 것이 아니기 때문에, toInt() 메소드는 Int가 아닌 Int? 값을 리턴하는 것입니다.
코드 7-2와 같이 if 문을 사용해서 optional이 유효한 값을 가지고 있는지 확인할 수 있습니다.

코드 7-2에서 convertedNumber는 optional이고 유효한 값을 가지고 있다면 if 문의 조건식은 true로 평가되고, 반대의 경우에는 false로 평가됩니다. 이렇게 if 문을 통해서 값의 유효성을 확인한 후에는 forced unwrapping 이라는 기능을 사용할 수 있습니다. 이 기능은 특정 optional이 유효한 값을 가지고 있는 것이 100% 확실하므로 해당 값을 “꼭” 사용하라고 알려주는 것입니다. 2번 라인에서 convertedNumber 뒤에 느낌표(!)가 붙어 있는 것을 확인하실 수 있을 것입니다. 바로 이 느낌표가 forced unwrapping을 사용하는 방법입니다. 유효한 값을 가지고 있지 않은 optional에 느낌표를 붙여도 컴파일 오류는 발생하지 않지만, 런타임 오류의 원인이 됩니다. 그러므로 반드시 optional이 값을 가지고 있는지 신중히 판단한 후에 느낌표를 붙여야 합니다.
forced unwrapping과 반대로 implicitly unwrapped optionals라는 기능도 제공합니다. 다음 코드는 두가지 방식의 차이를 보여줍니다.

possibleString은 String?으로 선언되었기 때문에 값을 사용하기 위해서 반드시 !를 붙여주어야 하지만, assumedString과 같이 String!으로 선언해 주면, optional을 선언함과 동시에 !를 붙이지 않고도 값을 사용할 수 있습니다. implicitly unwrapped optionals는 optional이 사용될 때 자동으로 unwrapped 되도록 미리 허가해 두는 것이라고 볼 수 있습니다.

possibleString!이 유효한 값을 가지고 있지 않을 경우 런타임 오류가 발생하는 것처럼, assumedString도 유효한 값이 없는 경우 런타임 오류가 발생하므로 주의해서 사용해야 합니다.

implicitly unwrapped optional은 다음과 같이 if 문을 통해 값의 유효성을 확인하거나, 뒤에서 설명할 Optional Binding에서 사용할 수도 있습니다.

Swift에서는 Optional Binding을 통해서 optional이 유효한 값을 가지고 있는지 확인한 후, 이 값을 임시 변수(또는 상수)로 사용합니다. if 문에서 optional에 저장된 값을 사용하려면 다음과 같은 코드를 사용할 수 있습니다.

코드 7-5에서 possibleNumber는 숫자를 포함하고 있을지도 모르는 String 변수이고, toInt() 메소드를 통해 리턴된 Int? 값을 actualNumber에 할당하고 있습니다. toInt()가 유효한 값을 리턴하는 경우에는 true로 평가되고, 그 외의 경우에는 false로 평가되므로, possibleNumber가 “777”이라면 2번 라인이 실행되고, let으로 선언한 actualNumber는 if 문의 본문에서 접근할 수 있게 됩니다. 이 예제에서는 actualNumber를 숫자를 출력하는 용도로만 사용하기 때문에 let으로 선언하였지만, if 문에서 값을 조작해야 한다면 let 대신 var를 사용해도 됩니다.

 

nil

Objective-C에서 nil은 “존재하지 않는 객체로의 포인터”를 나타내지만 Swift의 nil은 “값이 없음”을 나타냅니다. 즉, 전자는 포인터이지만, 후자는 포인터가 아닙니다. 전자는 객체형에만 사용할 수 있지만, 후자는 optional한 모든 자료형에 사용할 수 있습니다. 그리고 optional 변수(또는 상수)를 선언할 때 초기값을 지정해 주지 않으면 자동으로 nil이 할당됩니다.

 

 

ps. Facebook 페이지에 가입해서 함께 정보를 공유해보아요 :)   https://www.facebook.com/groups/254425194763076/

이 글의 예제 코드는 다음에서 발췌하였습니다: Apple Inc. ‘The Swift Programming Language.’ iBooks. https://itun.es/kr/jEUH0.l

Filed under: Swift

  1. 닥서클
    optional 문법이 변경된거 같습니다 if convertedNumber { } 아래와 같이 해야되네요. if convertedNumber != nil { }
    • 지나가는 이
      위의 것도 좋지만, apple의 권장 사항처럼 if let문을 쓰는 것도 좋아보이네요. ^^ 좋은 글 잘 보고 갑니다.(아 그리고 println문도 이제 없어졌네요.)