변수(variable)는 임시로 혹은 영구적으로 값을 기억해두기 위한 저장소를 말합니다. 쉽게 말하자면 값을 담아두는 상자로, 수학의 변수와 비슷하다고 볼 수 있습니다. 우리가 어떤 한 상자에 알기 쉽게 이름표를 붙여두면, 나중에 필요할 때마다 그 상자를 열어 무언가를 넣거나 내용물을 살펴볼 수 있습니다. 그 말인즉슨, 이 이름표(변수명)를 가지고 지금 가지고 있는 스마트폰의 메모리 공간에 접근할 수 있다는 말이기도 합니다.

var message: String = "Hello!"

변수 선언

그럼 코틀린에서는 어떻게 변수를 선언할 수 있을까요? 그리고 그 변수에 어떻게 값을 할당할까요? 차근차근 알아보도록 하겠습니다.

할당(assignment)? 선언(declaration)? 초기화(initialization)?
할당은 변수가 가리키는 메모리 공간에 값을 복사하는 것, 즉 값을 변수에 대입하는 걸 말합니다. '변수 num에 5를 할당한다.'라고 한다면 아래와 같이 적을 수 있습니다.
num = 5​
선언은 컴파일러에게 변수가 있다는 걸 알려주는 것입니다. '정수형 변수 num을 선언한다.'라고 한다면 아래와 같이 적을 수 있습니다.
var num: Int​

그리고 초기화는 초기 값 할당, 즉 처음으로 값을 저장하는 걸 말합니다. '정수형 변수 num을 값 5로 초기화한다.'라고 한다면 아래와 같이 적을 수 있습니다.

코틀린에선 아래와 같이 변수를 선언할 수 있습니다. 그리고 두 번째 줄처럼 선언과 동시에 어떤 값으로 변수를 초기화할 수도 있습니다.

var 변수명: 타입
var 변수형: 타입 = 값

예를 들어서, '문자열 타입의 변수 message를 값 Hello!로 초기화한다.'라고 한다면 아래와 같이 쓸 수 있습니다.

var message: String = "Hello!"

이제부터 위의 문장을 하나하나씩 분해해보도록 하겠습니다.

변수 정의 키워드

코틀린에서는 val, var로 변수를 만들 수 있습니다. 두 개의 차이점을 한번 알아보도록 하겠습니다.

가변 변수(mutable variables) var

variable(변수)의 줄임말로 한 번 입력된 값을 다시 변경할 수 있습니다.

message = "World!"

레벨이나 경험치 등과 같이 값이 계속해서 변한다면 아래와 같이 var로 변수를 선언합니다.

fun main() {
    var message: String = "Hello!"
    message = "World!"
    println(message) // World!
}

불변 변수(immutable variables) val

value(값)의 줄임말로 초기화만 할 수 있으며 한 번 입력된 값을 변경할 수 없습니다. 따라서 val은 오직 읽기만 할 수 있습니다. 아래에서 변수 PI를 3.14란 값으로 초기화한 후 다른 값을 할당하려고 하면 에러가 발생합니다.

fun main() {
    val PI: Float = 3.14f
    PI = 3.141592f // error: val cannot be reassigned
}

만약에 앱이 실행되고 있는 중에 값을 변경할 필요가 없다면 val로 변수를 선언하는 것이 좋습니다. 우리가 변경되지 말아야 할 값을 실수로 변경하려고 했을 때 컴파일러가 이를 조기에 막아주기 때문입니다.

변수명

변수명, 즉 변수에 붙여진 이름을 말합니다. 변수명은 개발자가 마음대로 지을 수 있지만, 보통 ageOfHead, numberOfChildren, unreadMessages 등과 같이 변수의 용도가 가장 잘 드러나는 이름으로 짓습니다. 이는 앞으로 배우게 될 함수나 클래스 등의 이름에서도 그렇습니다.

  • 영문자, 밑줄(_), 숫자가 들어갈 수 있지만, 1userBalance, 2things 등과 같이 숫자가 첫자리에 나올 수는 없습니다.
  • 공백은 사용할 수 없습니다.
  • 밑줄을 제외한 특수 기호(예: @, #, $, !, < 등)는 사용할 수 없습니다.
  • 대소문자를 구분합니다. 예를 들어서, num과 Num은 다른 변수입니다.
  • 하드 키워드를 변수명으로 쓸 수는 없습니다.

여기서 키워드는 코틀린 문법에서 사용되는 단어로, 그 자체로 특별한 의미를 가집니다.

하드 키워드(Hard keywords)
하드 키워드는 항상 키워드로 해석되며 식별자(identifier)로는 쓸 수 없습니다. 여기서 식별자는 데이터 항목을 식별하는 역할을 하며 쉽게 말해서 변수명, 함수명, 클래스명, 인터페이스명 등 서로를 구분하는 이름을 말합니다.
as, break, class, continue, do, else, false, for, fun, if, in,
interface, is, null, object, package, return, super, this, throw,
true, try, typealias, typeof, val, var, when, while

코틀린에서는 변수명을 소문자 카멜 표기법으로 쓰길 권장하고 있습니다. (더욱 자세한 가이드라인에 관심이 있으시면 이곳을 눌러 확인해보세요.)

소문자 카멜 표기법(Lower camel case)
프로그래밍에서 파일, 변수, 함수 등 대상의 이름을 띄어쓰기 없이 짓기 위하여 따르는 관례인 네이밍 컨벤션(Naming convention)의 하나입니다. 카멜 케이스에서는 단어 전체적으로 소문자를 사용하지만, 각 합성어의 첫 글자만 대문자로 표기합니다. 합성한 단어의 모양이 낙타(camel)의 등과 비슷하다는 뜻에서 이름이 붙었습니다.
예) logger, nonConstScalar, nonEmptyArray, mutableValues 등

타입

타입(자료형 또는 데이터 타입)은 코틀린에게 이 데이터는 어떤 형태의 데이터인지, 어떻게 저장하고 처리해야 하는지 등에 관해서 알려주는 역할을 합니다. 타입을 한 번 정해두면 잘못된 타입의 데이터가 변수에 할당될 수 없도록 만들 수 있습니다. 이 타입에 대해서는 여기서 간단하게 살펴보도록 하고, 다음 편에서 자세히 알아보도록 하겠습니다.

구분 타입 설명 값의 범위 및 예시
숫자형 Byte 8비트 정수 -128 ~ 127
Short 16비트 정수 -32,768 ~ 32,767
Int 32비트 정수 -2,147,483,648 (-2^31) ~ 2,147,483,647 (2^31 - 1)
Long 64비트 정수 -9,223,372,036,854,775,808 (-2^63) ~ 9,223,372,036,854,775,807 (2^63 - 1)
Float 32비트 실수 3.4E+/-38(7개의 자릿수)
Double 64비트 실수 1.7E+/-308(15개의 자릿수)
문자형 Char 한 개의 문자 '가', '나', '다', 'A', 'B', 'C' 등 (작은따옴표)
String 여러 개의 문자 "문자열은 연속된 문자들의 모임을 말한다." (큰따옴표)
논리형 Boolean true, false true 또는 false

타입 추론

이때까지는 타입을 명시하고 변수를 선언했습니다. 하지만 Android Studio에서 보면 아래와 같이 회색으로 밑줄 표시가 되어있는 걸 볼 수 있는데, 이렇게 타입을 명시하는 건 불필요하다는 소리입니다. 그 이유는 코틀린 컴파일러가 message에 할당된 값으로 String형이라는 걸 추론할 수 있기 때문입니다.

따라서 변수 선언과 동시에 어떤 값으로 초기화할 때는 아래와 같이 타입을 생략할 수 있습니다. 초기화되는 순간 할당되는 값에 따라서 변수의 타입이 결정됩니다.

var message = "Hello!" // String
var experiencePoints = 54 // Int

아래와 같이 변수 message의 값을 "Hello!"로 초기화하면 message의 타입이 String으로 결정됩니다. 이렇게 결정된 타입은 다시 변경할 수 없으며, 다른 타입의 값을 할당하려고 하면 에러가 발생합니다.

var message = "Hello!" // String
message = 3 // error: the integer literal does not conform to the expected type String

그러나 당연하게도 아래처럼 할당이나 타입을 모두 생략할 수는 없습니다. 적어도 하나는 명시를 해주어야 에러가 발생하지 않습니다.

var widgetCount // error: property must be initialized or be abstract

'정리 > Kotlin' 카테고리의 다른 글

번외. IEEE 754  (0) 2021.08.07
2편: 타입(Type)  (0) 2021.08.06