본문 바로가기

Development

Kotlin 기본 문법 1.

Kotlin 으로 업무도 많이 했지만,

Android 개발을 Java 로 시작해서 Kotlin 으로 점차 넘어갈 때는 제대로 공부를 못하고 바로 업무를 하게 되었다.

 

Java 를 쓰다 Kotlin 으로 넘어오면, 비슷한 부분이 많아 크게 어려운 부분은 없고

검색해보면 금방 처리 할 수는 있었다.

 

하지만 기본적인 것을 건너뛰고 바로 업무에 사용하다보니

모르고 사용하던 것들도 많고, 효율적이지 못한 코드도 많이 사용해온 것 같다.

Java 에 비해 간결하게 짤 수 있는 코드도, 기본기가 없었던 내겐 단지 동작에 문제가 없으면 만족할 뿐이었다.

 

서론이 길었지만, 이제라도 기본기를 다듬고 싶어서 천천히, 너무나 쉬운 내용부터 정리를 해본다.

 

변수 선언 : val 과 var

// val = value -> immutable
val a: Int = 0
a = 1 // X : 컴파일 에러 발생.

// var = variable -> mutable
var b: Int = 0
b = 1 // O

 

String template :

Java 에서는 string 데이터와 변수를 같이 사용할 때, + 를 이용했지만 Kotlin 에는 String template 라는 것이 있다.

//1. 단일 변수에 대해서는 아래와 같이 사용하면 된다.
val name = "1minute"
println("my blog name is $name")

//2. 꼭 변수 뿐 아니라, 중괄호를 이용해 아래와 같이 사용할 수 있다.
println("1 + 2 는 ${1 + 2} 이야")

//3. 변수, 연산, 함수의 반환값 등을 중괄호에 감싸서 사용할 수 있다.

//4. 실제 $를 문자로 사용하고 싶다면, 짐작가겠지만 backslash("\")를 앞에 붙여주면 된다.
println("나는 문자열 \$를 사용할 거야.")

 

조건문

이미 다른 개발 언어를 사용하던 사람이라면, 비슷한 방식으로 사용할테니 어려움은 없을 것이다.

때문에 Java 기준으로 조금 다른 부분만 정리한다.

 

- if

// kotlin 에는 삼항 연산자가 없지만, 비슷한 방법으로 사용할 수 있다

fun compare(a: Int, b: Int) = if(a < b) b else a

/**
* kotlin을 많이 사용해보지 않은 사람이 봤을 땐,
* 함수 치고는 의아할 수 있는 한 줄이기에 추가로 설명을 남겨본다.
*
* 우선, kotlin 에서는 함수 반환형을 함수명 뒤에 콜론(:)을 붙여 작성한다.
*/

// 예시
fun getString(): String {
	return "string"
}

// 반환형을 생략하면 java 의 void 와 같지만
fun setString(str: String) {
	this.str = str
}

// 실제로는 반환형 Unit 이 생략된 것으로, 굳이 따지면 void 와 조금 다르다.
fun setString(str: String): Unit {
	this.str = str
}

/**
* 이제 다시 맨 위 예시 코드를 보면 이렇게 설명할 수 있겠다.
*
* 자동 타입 추론으로 인해 반환형도 생략되었고,
* return 또한 사용하지 않고 아래와 같은 방식으로 간결하게 사용이 가능하다.
*/

fun compare(a: Int, b: Int) = if(a < b) b else a

 

- when : switch 와 비슷

// 평범하게 사용해보면, 아래와 같이 사용할 수 있다.
fun getResult(score: Int): String {
	when(score) {
		0 -> return "babo"
		100 -> return "genius"
		else -> return "normal"
	}
}

// 위의 함수는 해당 값에 일치할 경우이지만, 아래와 같이 범위를 지정할 수도 있다.
fun getResult(score: Int): String {
	when(score) {
		in 0..50 -> return "babo"
		in 90..100 -> return "genius"
		else -> return "normal"
	}
}

// 가독성을 위해 위와 같이 사용했지만, 마찬가지로 아래와 같이 간결하게 작성할 수도 있다.
fun getResult(score: Int) = when(score) {
	in 0..50 -> "babo"
 	in 90..100 -> "genius"
	else -> "normal"
}

 

Expression 과 Statement

이해하고 있는 내용으로는 아래와 같이 설명할 수 있다.

/**
* [Expression]
* 아래 코드의 grade 변수는 non-null 변수이기 때문에 else 가 존재해야만 한다.
* 그렇지 않다면, 컴파일 오류가 발생할 것이다.
* (non-null 에 대해서는 아래에서 설명할 예정이다.)
**/
val grade = when(score) {
    in 0..50 -> "babo"
    in 90..100 -> "genius"
    else -> "normal"
}

/**
* [Statement]
* 하지만 아래 코드처럼 어딘가에 결과물을 담거나 하지않고,
* 단지 분기에 따라 출력만 한다면 else 가 없어도 문제가 없다.
**/
when(score) {
    in 0..50 -> println("you are babo")
    in 90..100 -> println("you are genius")
}

결과적으로 Kotlin의 모든 함수는 Expression 이라고 한다.

이유는 Java 의 반환형 void 는 반환되는 값이 없지만,

Kotiln은 반환형 생략 시 위에 말한대로 Unit을 반환하기 때문이다.

 

Java에서는 조건문을 Statement 로 밖에 사용을 못했지만,

Kotlin에서는 Expression 으로도 사용할 수 있는 차이가 있다.

 

반복문

 

- for

// 1 부터 10 까지 1씩 증가
for(i in 1..10) {
	println(i)
}

// 1 부터 10 까지 2씩 증가
for(i in 1..10 step 2) {
	println(i)
}

// 10 부터 1 까지 1씩 감소
for(i in 10 downTo 1){
	println(i)
}

// 10 부터 1 까지 2씩 감소
for(i in 10 downTo 1 step 2){
	println(i)
}

/** 
* 1 부터 10까지 1씩 증가하지만, 10을 포함하지 않는다
* Java 기준으로는 보통 array 나 list 로 반복문을 사용할 때 
* 조건을 size - 1 과 같은 식으로 입력해주어야 할 때 until 을 이용하면 된다.
**/
for(i in 1 until 10) {
	println(i)
}

/**
* 만약 과일 이름들이 담긴 list 변수 "fruits" 가 있다고 할 때, 
* 아래와 같이 withIndex() 를 이용하면 index 값도 얻어와 사용할 수 있다.
**/
for(fruit in fruits.withIndex()) {
	println("index : ${fruit.index}, value : ${fruit.value}")
}

 

Non-Null

Java 와 차이가 있는 부분 중 하나이다.

Java 의 경우 값이 null 인데, 사용하려는 경우 Runtime 오류로 NullPointerException 이 발생할 수 있다.

하지만, Kotlin 에서는 Runtime 시점이 아닌 Compile 시점에도 오류 확인이 가능하다.

 

변수 선언 시, 기본적으로는 Non-Null 방식이기 때문이다.

// 기본적으로 변수를 선언하면, non-null 방식으로 변수에 null 값이 들어갈 수 없다.
var blog: String = "1Minute"

// Null이 들어갈 수 있게 변수 선언을 하려면, 아래와 같이 ? 를 사용하면 된다.
var blog: String? = null

 

null 을 넣을 수 있는 Nullable 방식으로 변수를 선언했을 때, 

해당 변수를 사용하려 할 때, null 일 수 있는 상황에서는 error 가 표시된다.

사용할 때 null check 를 해주어야만 한다.

 

방법은 아래와 같이 여러가지가 있다.

 

- "?" 를 이용하는 방법
아래와 같이 Nullable 방식으로 스트링 변수를 선언 후
단순히 length 를 가져오려고만 해도 error 표시가 뜨는 것을 볼 수 있다.

var testString: String? = "test"
var length = testString?.length

이 때, 변수 뒤에 ? 를 붙여주면 
testString이 null 이 아니면, 정상적으로 length를 반환하고
testString이 null 이면, null을 반환한다.

 

Java 와 달리 "?" 하나로 간결하게 null 체크가 가능하다.

 

 

- "?:" 를 이용하는 방법

엘비스 연산자라고 표현하는데, null 인 경우 default 값을 설정해주는 것이다.

var testString: String? = null
var length = (testString?:"test").length

Nullable 방식으로 선언된 testString 값이 null 이기 때문에 위와 같이 사용할 경우,

default 값을 "test"로 지정했기 때문에 length 값은 4로 설정된다.

 

 

- "!!" 를 이용하는 방법

많이 사용하는 것은 좋지 않다. (나는 엄청 썼다.)

"null 이 아니다" 라고 직접 설정해주는 것이다.

var testString: String? = "test"
var length = testString!!.length

개발을 하다보면 정말로 해당 변수는 null 이 될 수 없는 상황이 있을 수 있다.

그 때만 사용한다면 문제가 없을 것이다.

(남발할 경우에는 NullPointerException 이 발생할 수 있다.)

 

 

- "let" 을 이용하는 방법

null 이 아닐 경우, let 람다식 안의 내용이 실행된다.

var testString: String? = "test"
testString?.let {
	println(it)
}

it 로 받아서 사용할 수 있다.

null 인 경우, let 블록 내의 내용이 실행되지 않기 때문에 안전하다고 볼 수 있다.

 

이렇게 기본적인 문법을 알아보았지만,

제목에서부터 알 수 있듯이 기본 문법에 대하여 추가로 정리를 할 예정이다.