Published on

Kotlin tour

Authors

Kotlin tour 란?

Kotlin tour 는 코틀린 공식 도큐먼트에서 코틀린의 기초 학습을 도와주기 위해 있는 가이드 입니다. 모든 학습을 브라우저 안에서 할 수 있습니다.

Kotlin tour 링크 : https://kotlinlang.org/docs/kotlin-tour-welcome.html

Kotlin 을 해당 도큐먼트로 공부한 내용을 이번 포스트에 정리해보겠습니다.

Hello world

fun main() {
    println("Hello, world!")
    print("Hello, world!")
}
# 출력
Hello, world!
Hello, world!
  • 코틀린에서 함수를 선언할 떄 fun 을 사용합니다.
  • 코틀린은 main() 함수에서 프로그램을 시작합니다.
  • 함수는 중괄호 {} 로 감쌉니다.
  • 기본 출력을 위해서 printlnprint 를 사용할 수 있습니다.

변수(Variables)

코틀린에서 변수는 크게 valvar 이 있습니다.

  • val 은 read-only 인 불변(immutable) 변수를 선언할 때 사용합니다.
  • var 은 가변(mutable) 변수를 선언할 때 사용합니다.

변수에 값 할당은 = 을 통해 이루어집니다.

val popcorn = 5    // 팝콘(popcorn)이 5 박스
val hotdog = 7     // 핫도그(hotdog)가 7개
var customers = 10 // 대기줄에 손님(customers)이 10명

// 손님(customers)들이 대기줄을 떠남
customers = 8
println(customers)
// 8
# 출력
8

변수는 프로그램의 시작, main() 함수 바깥에 선언될 수 있습니다. 이렇게 선언된 변수들은 최상위(top level) 선언된 변수라고 합니다.

customers 는 var 로 선언된 가변(mutable) 변수이므로 재할당이 가능합니다.

기본적으로 변수는 val 로 선언을 하고 필요할 때문 var 로 선언하는 것을 추천합니다.

문자열 템플릿(String templates)

문자열 템플릿(String templates) 를 사용해 문자열 내에 변수 혹은 표현식을 사용해 값을 문자열에 포함시킬 수 있습니다. 문자열 템플릿은 항상 달러 표시 $ 를 사용해 시작합니다.

템플릿 표현식 안에 코드를 실행시키려면 코드를 중괄호 {} 안에 넣은 후 앞에 달러 표시 $ 를 붙여주어야 합니다.

val customers = 10
println("There are $customers customers")
// There are 10 customers

println("There are ${customers + 1} customers")
// There are 11 customers
# 출력
There are 10 customers
There are 11 customers

더 자세한 정보는 String templates 를 통해 확인할 수 있습니다.

앞선 예제들에서 변수에 타입이 선언이 되지 않았습니다. 코틀린은 타입을 명시하지 않아도, 변수가 선언될 때 할당된 값을 기반으로 타입을 추론해줍니다.

기본 자료형(Basic types)

코틀린의 모든 변수와 자료구조는 데이터 타입을 갖습니다. 컴파일러는 데이터의 타입을 통해 해당 변수 혹은 자료구조로 어떤 작업이 가능한지 판단하기 때문에 매우 중요한 요소입니다.

앞서 customers 예시를 통해 코틀린에서는 변수에 어떤 데이터 타입이 들어가는지 타입 추론(type inference)을 하는 것을 확인했습니다.
customers 변수 에 정수 정수 값이 할당되었기에,customersInt 데이터 타입을 갖을 것으로 추론합니다.
그 결과 customers 변수를 사용하는 산술 연산이 가능합니다.

var customers = 10

// 손님(customers)들이 대기줄을 떠남
customers = 8

customers = customers + 3 // 덧셈 예시: 11
customers += 7            // 덧셈 예시: 18
customers -= 3            // 뺄셈 예시: 15
customers *= 2            // 곱셈 예시: 30
customers /= 3            // 나눗셈 예시: 10

println(customers) // 10

코틀린은 다음과 같은 기본 자료형이 있습니다.

CategoryBasic types
IntegersByte, Short, Int, Long
Unsigned integersUByte, UShort, UInt, ULong
Floating-point numbersFloat, Double
BooleansBoolean
CharactersChar
StringsString

코틀린의 기본 자료형과 속성들에 대한 더 자세한 정보는 Basic types 에서 확인할 수 있습니다.

자료형을 사용하면 변수를 초기화하기 전에 선언해두고 나중에 초기화를 해줄 수 있습니다. 변수를 사용하기 전에는 초기화를 해 주어야 합니다.

초기화를 하지 않고 변수를 선언해 줄 경우, : 를 사용해 타입을 명시해주어야 합니다.

// 초기화를 하지 않고 변수 선언
val d: Int
// 변수 초기화
d = 3

// 명시적으로 변수 타입 선언하며 초기화
val e: String = "hello"

// 변수가 초기화되었기에 읽을 수 있습니다.
println(d) // 3
println(e) // hello

컬렉션(Collections)

프로그래밍을 할 때에는 데이터를 자료구조 안에 넣는 것이 추후 처리를 하는데 유리합니다. 코틀린을 이를 위해 컬렉션(collections)를 제공합니다.

코틀린은 아이템들(items)을 그룹화 하기 위해 다음과 같은 컬렉션을 제공합니다.

컬렉션 타입설명
Lists아이템들을 순서가 보장된 형태로 담고 있는 컬렉션들
Sets아이템들을 순서가 보장되지 않는 유니크한 형태로 담고 있는 컬렉션들
Mapskey 가 유니크하고 하나의 value 를 가리키는 key-value 쌍들

각각의 컬렉션은 타입은 mutable 할 수도 있고 immutable 할 수도 있습니다.

List

List 들은 아이템을 추가된 순서대로 저장합니다. 또한 중복된 아이템을 허용합니다.

수정 불가능(immutable)한 read-only List 를 생성하기 위해서는 listOf() 함수를 사용합니다.

수정 가능한(mutable) MutableList를 생성하기 위해서는 mutableListOf() 함수를 사용합니다.

리스트를 생성할 때, 코틀린은 저장된 아이템의 타입을 추론합니다. 명시적으로 타입을 표시하기 위해서는 <> 를 사용해 타입을 표기해줍니다.

// Read only 리스트
val readOnlyShapes = listOf("triangle", "square", "circle")
println(readOnlyShapes)
// [triangle, square, circle]

// 명시적으로 타입을 선언한 Mutable list
val shapes: MutableList<String> = mutableListOf("triangle", "square", "circle")
println(shapes)
// [triangle, square, circle]
# 출력
[triangle, square, circle]
[triangle, square, circle]

원하지 않는 수정을 방지하기 위해서는, List 로 할당을 하여 mutable list 의 read-only view 를 얻을 수 있습니다. 이를 캐스팅(casting) 이라고 합니다.

list 는 순서가 보장되기 때문에 indexed access operator[] 를 통해 아이템에 접근할 수 있습니다.

val readOnlyShapes = listOf("triangle", "square", "circle")
println("The first item in the list is: ${readOnlyShapes[0]}")
// The first item in the list is: triangle
# 출력
The first item in the list is: triangle

list 의 .first(), .last() 함수를 사용해 각각 처음, 마지막 아이템에 접근할 수 있습니다.

val readOnlyShapes = listOf("triangle", "square", "circle")
println("The first item in the list is: ${readOnlyShapes.first()}")
// The first item in the list is: triangle
# 출력
The first item in the list is: triangle

.first() 와 .last() 함수들은 확장 함수(extention function) 의 예시입니다. 객체에서 확장 함수를 호출하기 위해서는 객체에 온점 . 을 찍은 후 함수명을 작성합니다. 확장함수에 대한 자세한 정보는 Extention functions 에서 확인할 수 있습니다.

.count() 함수를 통해 리스트의 아이템 개수를 얻을 수 있습니다.

val readOnlyShapes = listOf("triangle", "square", "circle")
println("This list has ${readOnlyShapes.count()} items")
// This list has 3 items
This list has 3 items

in 연산을 사용해 list 안에 아이템이 있는지 확인할 수 있습니다.

val readOnlyShapes = listOf("triangle", "square", "circle")
println("circle" in readOnlyShapes)
// true
true

mutable 한 리스트에서 값을 추가하거나 빼려면 각각 .add(), .remove() 함수를 사용할 수 있습니다.

Set

List 들은 순서가 존재하고 중복된 아이템들을 저장하는 반면, Set 은 순서가 보장되지 않고 중복을 허용하지 않습니다.

수정 불가능(immutable)한 read-only Set 를 생성하기 위해서는 setOf() 함수를 사용합니다.

수정 가능한(mutable) MutableSet를 생성하기 위해서는 mutableSetOf() 함수를 사용합니다.

셋을 생성할 때, 코틀린은 저장된 아이템의 타입을 추론합니다. 명시적으로 타입을 표시하기 위해서는 <> 를 사용해 타입을 표기해줍니다.

// Read-only 셋
val readOnlyFruit = setOf("apple", "banana", "cherry", "cherry")
// 명시적으로 타입을 선언한 Mutable 셋
val fruit: MutableSet<String> = mutableSetOf("apple", "banana", "cherry", "cherry")

println(readOnlyFruit)
// [apple, banana, cherry]
# 출력
[apple, banana, cherry]

Set 은 중복을 허용하지 않기 때문에 중복된 "cherry" 아이템이 제거된 걸 확인할 수 있습니다.

원하지 않는 수정을 방지하기 위해, Set 으로 캐스팅하여 mutable set 의 read-only view 를 얻을 수 있습니다.

val fruit: MutableSet<String> = mutableSetOf("apple", "banana", "cherry", "cherry")
val fruitLocked: Set<String> = fruit

.count() 함수를 통해 set 의 아이템 개수를 얻을 수 있습니다.

val readOnlyFruit = setOf("apple", "banana", "cherry", "cherry")
println("This set has ${readOnlyFruit.count()} items")
// This set has 3 items
# 출력
This set has 3 items

in 연산을 사용해 set 안에 아이템이 있는지 확인할 수 있습니다.

val readOnlyFruit = setOf("apple", "banana", "cherry", "cherry")
println("banana" in readOnlyFruit)
// true
# 출력
true

mutable 한 셋에서 값을 추가하거나 빼려면 각각 .add(), .remove() 함수를 사용할 수 있습니다.

val fruit: MutableSet<String> = mutableSetOf("apple", "banana", "cherry", "cherry")
fruit.add("dragonfruit")    // Add "dragonfruit" to the set
println(fruit)              // [apple, banana, cherry, dragonfruit]

fruit.remove("dragonfruit") // Remove "dragonfruit" from the set
println(fruit)              // [apple, banana, cherry]
# 출력
[apple, banana, cherry, dragonfruit]
[apple, banana, cherry]

Map

Map 들은 아이템을 key-avlue 쌍으로 저장합니다. key 를 참조하여 value 값에 접근할 수 있습니다. 음식점의 메뉴판처럼 음식의 이름(key) 를 통해 가격(value) 를 찾을 수 있습니다. Map 은 list 처럼 numbered index 를 활용하지 않고 value 값을 찾을 때 유용합니다. value 는 중복될 수 있지만, key 는 중복이 있으면 안됩니다.

수정 불가능(immutable)한 read-only Map 를 생성하기 위해서는 mapOf() 함수를 사용합니다.

수정 가능한(mutable) MutableMap를 생성하기 위해서는 mutableMapOf() 함수를 사용합니다.

맵을 생성할 때 코틀린은 저장된 아이템들의 타입을 추론합니다. 명시적으로 타입을 표시하기 위해서는 <> 를 사용해 타입을 표기해줍니다.

가장 쉽게 맵을 생성하는 방법은 key 와 연관된 value 사이에 to 를 사용하는 겁니다.

// Read-only 맵
val readOnlyJuiceMenu = mapOf("apple" to 100, "kiwi" to 190, "orange" to 100)
println(readOnlyJuiceMenu)
// {apple=100, kiwi=190, orange=100}

// 명시적으로 타입을 선언한 Mutable 맵
val juiceMenu: MutableMap<String, Int> = mutableMapOf("apple" to 100, "kiwi" to 190, "orange" to 100)
println(juiceMenu)
// {apple=100, kiwi=190, orange=100}

원하지 않는 수저을 방지하기 위해, Map 으로 캐스팅하여 mutable mpa 의 read-only view 를 얻을 수 있습니다.

val juiceMenu: MutableMap<String, Int> = mutableMapOf("apple" > to 100, "kiwi" to 190, "orange" to 100)
val juiceMenuLocked: Map<String, Int> = juiceMenu

map은 indexed access operator[] 에 key를 넣어 value에 접근할 수 있습니다.

// Read-only map
val readOnlyJuiceMenu = mapOf("apple" to 100, "kiwi" to 190, "orange" to 100)
println("The value of apple juice is: ${readOnlyJuiceMenu["apple"]}")
// The value of apple juice is: 100
# 출력
The value of apple juice is: 100

.count() 함수를 통해 map 의 아이템 개수를 얻을 수 있습니다.

// Read-only map
val readOnlyJuiceMenu = mapOf("apple" to 100, "kiwi" to 190, "orange" to 100)
println("This map has ${readOnlyJuiceMenu.count()} key-value pairs")
// This map has 3 key-value pairs
# 출력
This map has 3 key-value pairs

mutable 한 맵에서 값을 추가하거나 빼려면 각각 .put(), .remove() 함수를 사용할 수 있습니다.

val juiceMenu: MutableMap<String, Int> = mutableMapOf("apple" to 100, "kiwi" to 190, "orange" to 100)
juiceMenu.put("coconut", 150) // Add key "coconut" with value 150 to the map
println(juiceMenu)
// {apple=100, kiwi=190, orange=100, coconut=150}

juiceMenu.remove("orange")    // Remove key "orange" from the map
println(juiceMenu)
// {apple=100, kiwi=190, coconut=150}

containsKey 를 통해 특정 키가 이미 존재하는지 확인 할 수 있습니다.

val readOnlyJuiceMenu = mapOf("apple" to 100, "kiwi" to 190, "orange" to 100)
println(readOnlyJuiceMenu.containsKey("kiwi"))
// true

map 의 keys 혹은 values collection 을 얻기 위해서 keys 혹은 [][]value 속성을 사용할 수 있습니다.

val readOnlyJuiceMenu = mapOf("apple" to 100, "kiwi" to 190, "orange" to 100)
println(readOnlyJuiceMenu.keys)
// [apple, kiwi, orange]
println(readOnlyJuiceMenu.values)
// [100, 190, 100]

in 연산을 사용해 key 혹은 value 가 맵에 있는지 확인할 수 있습니다.

val readOnlyJuiceMenu = mapOf("apple" to 100, "kiwi" to 190, "orange" to 100)
println("orange" in readOnlyJuiceMenu.keys)
// true
println(200 in readOnlyJuiceMenu.values)
// false

collection 들의 더 자세한 내용은 Collections 에서 확인할 수 있습니다.

제어문 (Control Flow)