변수는 정확하게 정의된 단일 타입을 가지는 값을 담는 상자의 이름이다. 이 장에서는 변수 선언과 초기화를 자세하게 짚은 다음 스위프트의 빌트인 자료형에 대해 알아본다.
변수는 참조를 위한 이름을 부여하는 것뿐만 아니라 선언된 위치에 따른 값의 스코프와 수명을 부여해준다.
변수의 스코프와 수명은 세 가지 레벨로 나눌 수 있다.
전역 변수(global)는 스위프트 파일의 최상위에 선언된 변수이다. 전역 변수는 프로그램이 실행하는 동안 계속 존재한다.
또한 전역(global) 변수라는 이름처럼 같은 파일의 어느 곳에서든 변수에 접근할 수가 있다. 기본적으로는 같은 모듈의 다른 파일에서도 전역 변수에 접근할 수 있다. 같은 모듈 안에 있는 스위프트 파일은 자동으로 다른 파일들을 볼 수 있기 때문에 다른 파일의 최상위에도 접근이 가능하다.
프로퍼티는 object 타입(enum, struct, class)의 최상위에 선언된 변수이다. 프로퍼티에는 두 가지 종류가 있다.
Instance properties
기본적으로 프로퍼티는 인스턴스 프로퍼티이다. 인스턴스 프로퍼티의 값은 각 인스턴스마다 다를 수 있다. 또한 인스턴스 프로퍼티의 수명은 인스턴스의 수명과 같다.
Static/class properties
static
또는 class
키워드가 앞에 붙은 프로퍼티는 static/class 프로퍼티이다. 이 프로퍼티들의 수명은 object 타입의 수명과 같다. object 타입이 파일의 최상위에 선언된 경우에는 프로퍼티는 프로그램이 실행하는 동안 계속 살아있게 된다.
프로퍼티는 오브젝트를 통해서만 접근할 수 있다.
먼저 오브젝트의 메소드는 그 오브젝트의 프로퍼티에 바로 접근할 수 있다. self
키워드와 dot-notation을 통해서 프로퍼티에 접근할 수 있지만 대부분 self
키워드를 생략한다.
기본적으로 다른 코드에서도 인스턴스 프로퍼티에 접근할 수 있다. 이때 코드가 인스턴스에 대한 레퍼런스를 가지고 있어야 하며, 인스턴스 레퍼런스와 dot-notation으로 인스턴스 프로퍼티에 접근할 수 있다.
static/class 프로퍼티는 기본적으로 object 타입의 이름을 볼 수 있는 다른 코드에서 접근할 수 있다. 이때는 object 타입과 dot-notation으로 프로퍼티에 접근할 수 있다.
지역 변수는 함수의 본문 안에서 선언된 변수이다. 지역 변수는 함수의 중괄호({}
)가 갖는 스코프가 유효할 때만 살아있다. 지역 변수는 프로그램 실행된 후 함수 안에 들어와서 변수를 선언한 곳에 다다랐을 때부터 존재하게 된다. 그리고 프로그램이 스코프 밖으로 벗어난 후에는 지역 변수는 존재하지 않는다.
지역 변수는 같은 스코프 안에 있으면서 변수 선언 코드 다음에 위치한 코드만 접근할 수 있다.
변수는 let
또는 var
키워드로 선언한다.
let
: 상수. 처음 값이 할당된 후에는 값을 바꿀 수 없다.var
: 새로운 값을 할당할 수 있다.주로 초기화를 통해서 변수를 선언하지만 바로 변수에 값을 할당하지 않아도 된다. 단, 타입은 반드시 선언해주어야 한다. 타입은 명시적 또는 암시적으로 선언할 수 있다.
var x : Int
변수를 선언할 때 타입을 명시하지 않고 초기화를 하면 스위프트가 할당된 값을 이용해서 타입을 추론한다.
var x = 1 // x is an Int
var x : Int = 1
처럼 한 번에 타입을 명시하고 초깃값을 할당하는 것도 물론 가능하다. 이렇게 타입을 명시하고 초깃값을 할당해야 하는 경우들은 다음과 같다.
let value : Float = 2.0
Float
변수가 필요한데 스위프트는 Int
또는 Double
로 추론하는 경우처럼 숫자 자료형 변수를 선언할 때 자주 발생하는 상황이다.
스위프트가 초깃값의 타입을 추론하지 못하는 경우도 있다.
var opts = [.autoreverse, .repeat] // compile error
컴파일러는 위 코드의 .autoreverse
와 .repeat
의 타입을 알지 못한다. 따라서 개발자가 타입을 명시해주어야 한다.
let opts : UIView.AnimationOptions = [.autoreverse, .repeat]
let duration : CMTime = track.timeRange.duration
개발자가 코드를 더 잘 이해하기 위해 일부러 타입을 명시해주는 경우도 있다.
💡 TIP) 컴파일러가 타입을 추론하는 데에도 시간이 소요된다. 변수의 타입을 명시해줌으로써 컴파일 시간을 줄일 수 있다.상수(let
) 역시 초깃값을 가지지 않아도 된다.
let x : Int
나중에 값이 할당되면 변수의 값을 변경할 수 없다.
그러나 지역 변수는 초기화와 함께 값을 할당하는 것이 좋은데, 예외적으로 조건에 따라 초기화를 해야 하는 경우에는 나중에 값을 할당해야 한다.