타입 추론과 타입 어노테이션

  • 스위프트에서 변수는 선언과 초기화를 동시에 할 수도 있지만, 선언만 먼저 해 놓은 다음 필요한 시점에서 초기화를 하는 것으로 분리하여 작성할 수도 있다
// 선언과 초기화를 동시에
var day = 7

//선언과 초기화를 분리
var year : Int // 선언
year = 1999 // 초기화
  • 선언과 초기화를 분리한 year 변수를 보면, 선언할때 콜론 ( : )과 함께 Int 자료형을 명시해 놓는다
    • 주어진 구문에서 ( : Int )부분을 제거하면 오류가 발생한다
      • “type annotation missing in pattern”

Type annotation (타입 어노테이션)

  • 타입 어노테이션이란, 변수나 상수를 선언할 때 그 타입을 명시적으로 선언해 줌으로써 어떤 타입의 값이 저장될 것인지를 컴파일러에 직접 알려주는 문법
  • 변수나 상수명 뒤에 콜론 ( : )을 붙이고, 이어서 저장될 값의 타입을 작성
var year : Int // 명시적인 Int 타입
var name : String // 명시적인 String 타입
var firstChr : Character // 명시적인 Character 타입
var distance : Double // 명시적인 Double 타입
var pi : Float // 명시적인 Float 타입
var flag : Bool //  명시적인 Bool 타입
  • 타입 어노테이션을 사용하여 변수와 상수의 타입을 지정하는 예
// 타입을 명시한 변수 선언
var name : String = "김광준"
var year : Int = 1991

// 타입을 명시한 상수 선언
let firstName : String = "광준"
let birthYear : Int = 1991
  • 위의 주어진 구문은 모두 네 개의 변수와 상수가 선언되어 있다
  • 이같은 타입 어노테이션을 통한 컴파일러는 추론 없이 각각의 변수나 상수 타입을 정확히 인지할 수 있다

타입 추론(Type Inference)

  • 변수나 상수를 선언할 때 타입을 명시해 주지 않고 그냥 값만 넣어 초기화가 가능
    • 타입 추론 기능
  • 스위프트 특성 중에 “설계에 의한 안전성(Safety by design)”이라는 항목이 있다
    • 아키텍처적인 안전성을 담보하기 위해 스위프트가 여러 장치를 도입했다는 것이 핵심 내용
      • 그 중의 하나가 바로 타입 추론 기능
  • 타입 추론은 변수나 상수를 초기화할 때 입력된 값을 분석하여 변수에 적절한 타입을 컴파일러가 스스로 추론하는 기능
    • 초기값으로 “Hello”가 입력되었다면, 이 변수는 String타입 이라고 추론
    • 초기값으로 1999가 입력되었다면 정수로 초기화 되었으니 Int타입 이라고 추론
      • 이러한 판단이 이에 해당한다
  • 타입 추론 덕분에 변수나 상수에 명시적으로 타입을 지정해 주지 않아도 되었던 것이다
    • 왠만한 값들은 타입 추론 기능에 의해 적절한 타입이 지정된다
  • 타입 어노테이션이라는 문법이 있다고 해서 매번 타입을 명시해 줄 필요는 없다
  • 보통의 경우에는 스위프트에 내장된 타입 추론기가 변수의 초기값을 이용하여 타입이 무엇인지 추론해내기 때문이다
// 타입을 명시하지 않은 변수 선언
var name = "김광준"
var year = 1991

// 타입을 명시하지 않은 상수 선언
let firstName = "광준"
let birthYear = 1991

타입 어노테이션을 써야 할지 말지 고민이 될 때에는 ??

  • 반드시 타입 어노테이션을 사용해야 하는 다음 두 가지 경우를 제외하면 타입을 명시적으로 선언하지 않아도 된다
    • 1. 선언과 초기화를 분리할 경우
      • 타입 추론은 변수나 상수의 선언 시 입력된 초기값을 이용하여 가장 적절한 타입을 추론해 내는 과정이다
      • 스위프트에서 변수와 상수는 선언하는 시점에서 타입이 결정되어야 하는데, 선언과 동시에 값을 초기화하면 자동으로 타입을 결정할 수 있어 타입 어노테이션이 필요 없다
      • 하지만 선언과 초기화가 동시에 이루어지지 않고, 선언과 초기화가 분리된 구문으로 작성될 경우 타입 추론을 위한 충분한 데이터가 없어 적절한 타입을 추론할 수 없게 된다
      • 따라서 이런 경우에는 타입 어노테이션을 사용하여 타입을 직접 지정해 주어야 한다
        // 선언 + 타입 어노테이션
        var year : Int
              
        // 초기화
        year = 1991
      
  • 상수는 선언과 초기화를 분리할 수 없으니 타입 어노테이션이 필요 없는 것 아닐까?
    • 일반적으로 상수를 선언할 때 반드시 초기화를 함께 해주어야 하지만, 클래스나 구조체에서 멤버로 선언된 상수는 선언과 초기화가 동시에 이루어지지 않더라도 오류가 발생하지 않는다
      • 단, 초기화 블록 내에서 상수의 값을 결정해 주어야 한다
    • 2. 타입 추론으로 얻어지는 타입이 아닌, 다른 타입을 직접 지정할 필요가 있을 경우
      • 두 번째 경우는 타입 추론으로 얻어지는 타입이 우리가 원하는 타입이 아닐 때이다
      • 이때에는 타입 어노테이션을 사용하여 원하는 타입을 직접 지정해 주어야 한다
      • 원하는 타입을 지정한다고 해서 모든 타입을 마음대로 지정할 수 있는 것은 아니다
      • 주로 Int 타입 대신 Double이나 Float 타입을, String 대신 Character 타입을, Double 대신 Float를 지정하는 경우가 대부분이다
        // Int 타입으로 정의
        var temper1 = 3
              
        // Float 타입으로 정의
        var temper2 : Float = 3
      
      • 위에서 보는 것 처럼 두 변수 모두 다 동일하게 3을 대입했으나 하나는 타입 추론을, 다른 하나는 타입 어노테이션을 이용하여 변수의 타입을 결정하고 있다
      • temper1 변수는 입력값 3에 가장 적합한 자료형인 Int로 결정되어 3이 그대로 저장, 타입 추론이 적용된 결과
      • temper2 변수는 입력 받은 3이 정수임에도 불구하고 Float 타입에 맞추어 실수 3.0으로 변환되어 저장되었다

문자열과 문자의 타입 추론 및 타입 어노테이션

  • 스위프트에서는 문자열과 문자에 모두 큰따옴표를 사용한다
  • 여러 글자로 이루어진 값이라면 문자열이라는 것을 금세 파악할 수 있겠지만, 한 글자인 경우에는 값만 봐서는 문자열인지 문자인지 구분하기 어렵다
  • 보통 이럴 때 컴파일러가 취할 수 있는 합리적인 판단은 더 넓은 범위의 타입으로 추론하는 것이다
    • 문자열과 문자의 관계에서는 문자열이 이에 해당한다
  • 타입 어노테이션 없이 변수나 상수에 한 글자 문자를 대입하면 컴파일러는 문자열로 추론하고, 해단 변수를 String 타입으로 정의한다
var stringValue = "문자열" // 여러 글자이므로 확실한 String
var charValue = "문" // String?? Character??
  • 위에서 보는 것 처럼 한글자로 입력된 값을 문자열이 아닌 문자로 인식시키고 변수의 타입을 Character 타입으로 정의하기 위해서는 변수에 타입 어노테이션을 명시해 주어야 한다
var stringValue = "문자열" // String 타입
var charValue: Character = "문" // Character 타입
  • 동일한 값이라도 마찬가지이다. 타입 어노테이션을 작성한 것과 작성하지 않은 것은 엄연히 다른 결과를 나타낸다
var cValue: Character = "C" // Character
var sValue = "C" // String
  • 위 두 변수는 동일한 “C”라는 값으로 초기화되지만 타입 어노테이션이 명시된 변수는 Character 타입으로 선언되는 반면 타입 어노테이션이 생략된 변수는 String 타입으로 선언된다
    • 타입 추론으로 얻어지는 타입이 아닌, 다른 타입을 직접 지정할 필요가 있을 경우
  • 1. 선언과 초기화를 분리할 경우
  • 2. 타입 추론으로 얻어지는 타입이 아닌, 다른 타입을 직접 지정할 필요가 있을 경우
    • 이 두 가지 경우를 제외한 나머지는 타입 어노테이션을 생략하고 타입 추론에 의존하면 된다
    • 가독성을 위해서, 혹은 타입 추론을 믿지 못한다는 이유로 타입 어노테이션을 무조건 사용하는 사람도 있다. 이것은 각자의 코딩 스타일이다