본문 바로가기

코틀린

코틀린(Kotlin) - 기본 요소 : 함수와 변수

코틀린을 구성하는 기본 단위인 함수와 변수를 살펴보며, 코틀린에서 타입 선언을 생략해도 된다는 사실에 대해 알아보고자 합니다.

Hello World!

우선, 프로그래밍에 가장 기초가 되는 첫 번째 단계인 "Hello World!" 를 찍어보는 예제로 시작을 하겠습니다.

 

fun main(args: Array<String>) {
  println("Hello World!")
}

 

이렇게 간단한 코드에서 코틀린 문법의 여러 특성을 발견 할 수가 있는데,

  • 함수를 선언할 때, "fun" 키워드를 사용한다.
  • 파라미터명 뒤에 그 파라미터의 타입을 정의하며, 콜론(:)으로 구분한다. (변수 선언할 때도 동일한 방식으로 타입을 지정)
  • System.out.println 대신, println 이라고 쓴다. (코틀린 라이브러리는 자바 라이브러리 함수를 간결하게 사용할 수 있는 Wrapper를 제공하기 때문)
  • 최신 프로그래밍 언어 답게, 줄 끝에 세미콜론(;) 을 붙이지 않는다.

함수 선언

위의 예제에서 한가지 또 발견할 수 있는 부분은, 아무런 값도 반환하지 않는 void 함수를 어떻게 선언하는지도 살펴볼 수가 있습니다.

그렇다면, 결과값을 반환하는 함수의 경우 리턴 값의 타입을 어디에 지정해야 하는지 살펴보겠습니다.

 

fun max(a: Int, b: Int) : Int {
  return if(a > b) a else b
}

 

함수 선언은 fun 키워드로 시작하며, fun 다음에는 함수명을 정의합니다.

함수의 리턴 타입은 파라미터 목록 괄호 다음에 정의하는데, 괄호와 함수 리턴 타입 사이를 콜론(:)으로 구분해야 합니다.

 

또한, 여기서 흥미로운 부분은 if문이 값을 반환하는 "식"의 기능도 한다는 것을 알 수가 있습니다.

코틀린에서는 삼항 연산자를 지원하지 않기 때문에, 위와 같이 if문을 식으로 활용하여 구현할 수 있습니다.

식이 본문인 함수

위의 함수를, 더 간결하게 표현할 수도 있습니다.

 

fun max(a: Int, b: Int) : Int = if(a > b) a else b

 

앞의 함수 본문은, if 식 하나로만 이루어져 있기 때문에, 이런 경우 위와 같이 중괄호를 없애고, return을 제거하면서 등호(=) 를 붙여서 더 간결하게 함수를 표현할 수 있습니다.

 

추가적으로, 위의 함수를 더! 간략하게 만들 수가 있는데,

 

fun max(a: Int, b: Int) = if(a > b) a else b

 

이와 같이 함수의 반환 타입을 생략하여 더 간략하게 할 수 있습니다.

 

이처럼 함수 반환 타입을 생략할 수 있는 이유는, 컴파일러가 함수 본문 식을 분석해서 식의 결과 타입을 함수 반환 타입으로 정해주기 때문입니다.

이렇게, 컴파일러가 타입을 분석해 프로그래머 대신 타입을 정해주는 기능을 타입 추론이라고 합니다.

유의할 점은, 반드시 식이 본문인 함수에서만 생략이 가능하다는 점입니다! (블록이 본문인 경우, 반드시 반환 타입을 정의하고 return으로 반환 값을 명시해줘야 합니다)

 

사실상 실무에서는, 긴 함수 안에 return문이 여럿 들어있는 경우가 자주 있기도 하고, 그런 경우 반환 타입을 명시하고 return을 사용하는 것이 이 함수가 어떤 타입의 값을, 어디서 반환하는지 더 쉽게 알아볼 수 있기 때문에, 위 함수들처럼 저 정도로 생략하면서까지 코딩하는 경우는 자주 있진 않습니다...ㅎㅎ (취향에 따라 어색하기도 하고, 가독성이 떨어질 수 있어서)

 


변수 선언

자바에서는 변수를 선언할 때 타입이 맨 앞에 오지만, 코틀린에서는 타입 지정을 생략하는 경우가 흔합니다.

 

// 타입을 생략해도 된다.
val name = "안드로이드"
val age = 10

// 타입을 명시해도 된다.
val name: String = "안드로이드"
val age: Int = 10

// 초기화식을 사용하지 않고, 변수를 선언하려면 변수 타입을 반드시 명시해야 된다.
val age: Int
age = 10

★ 변경 가능한 변수와 변경 불가능한 변수

변수 선언 시 사용하는 키워드는 두 가지가 있습니다.

 

val (값을 뜻하는, value)

  - 변경 불가능한(immutable) 참조를 저장하는 변수로, val로 선언된 변수는 초기화하고 나면 변경이 불가능합니다.

    자바로 말하자면 final 변수에 해당합니다.

 

val name = "안드로이드"
name = "코틀린"  //에러 발생!

 

var (변수를 뜻하는, variable)

  - 변경 가능한(mutable) 참조를 저장하는 변수로, var로 선언된 변수의 값은 바뀔 수 있습니다.

    자바의 일반 변수에 해당합니다.

 

var name = "안드로이드"
name = "코틀린"  //변경 가능!

널 가능성

기본적으로, 코틀린의 변수는 null을 가질 수 없기 때문에 null이 될 수 있는 타입을 명시해야 합니다.

또한, null 가능으로 명시한 변수를 not null 타입으로 변경 할 수도 있습니다.

 

var name = "코틀린"
name = null //오류 발생
        
var name: String? = null //널 가능
name = null //정상 실행

var name: String? = null //널 선언(? 물음표)
var notNullName = name!! //not null 선언(!! 느낌표 두개)
notNullName = null //오류 발생 (not null이라 선언해놓곤, null을 선언하려고 하기 때문에

 

  • 널이 될 수 있는 타입(nullable) : 자료형 뒤에 ?(물음표) 명시
  • 널이 될 수 없는 타입(not-null) : 널에 대해 !!(느낌표 두개) 명시

문자열 템플릿

코틀린에는 문자열 템플릿이라는 기능이 있습니다. 문자열 안에서 변수를 사용할 수 있는 기능입니다.

예를 들어, 자바에서 문자열 접합 연산을 한다면

 

String name = "안드로이드";
System.out.println("안녕, " + name);
[ 실행결과 ]
안녕, 안드로이드

이와 같이 코딩을 하게 되지만,

 

코틀린의 문자열 템플릿 기능을 사용해서 표현한다면

 

val name = "안드로이드"
println("안녕, $name")
[ 실행결과 ]
안녕, 안드로이드

이와 같이 표현이 가능합니다.

 

다만 여기서 한 가지 주의할 점이 있는데, 한글을 문자열 템플릿에서 사용 시 변수 바로 뒤에 한글을 붙여 사용하게 된다면, 코틀린 컴파일러는 영문자(name)와 한글(안녕)을 한꺼번에 식별자로 인식하기 때문에 컴파일 에러가 발생하게 됩니다. 

 

val name = "안드로이드"
println("$name안녕") //Error:unresolved reference

 

이 문제를 해결하는 방법은, 중괄호({})로 변수명을 감싸주면 에러가 발생하지 않습니다.

 

val name = "안드로이드"
println("${name}안녕")

 

또한, 나중에 정규식 등을 통해 검색하거나 일괄 변환할 때에도 중괄호를 쓴 경우가 처리가 더 쉽고,

가독성 측면에서도, 문자열 템플릿 안에서 변수가 쓰인 부분이 훨씬 더 쉽게 눈에 띄기 때문에

문자열 접합 시에는, 항상 중괄호로 감싸주는 습관을 들여주시면 더 좋을 것 같습니다.