Kotlin 코틀린 소개와 기초 문법 알아보기
코틀린의 기초 사용법을 알아보자
코틀린(Kotlin) 기초 시리즈의 첫 번째 시간입니다. 이번 시간에는 코틀린을 소개하고 코틀린 프로그래밍을 위한 개발 환경을 설정하는 법 그리고 코틀린의 기초 문법을 알아보겠습니다.
소개
정의
코틀린이란 젯브레인(JetBrains)에서 만든 오픈 소스(open-source) 크로스 플랫폼(cross-platform) 언어입니다. 코틀린은 현재 구글(Google)의 안드로이드(Anroid) 공식 개발 언어입니다.
- 플랫폼(platform)
- 컴퓨터 CPU와 운영체제(operating system, OS)의 조합을 이르는 말로 플랫폼마다 고유한 언어를 사용함
- 크로스 플랫폼(cross-platform)
- 특정 운영체제에 제한되지 않고 여러 운영체제에서 동작할 수 있는 소스를 한 번에 프로그래밍하는 기술로 멀티 플랫폼(multi-platform)이라고도 부름
- 네이티브(native)
- 크로스 플랫폼에 반대되는 단어로 소프트웨어를 특정 기기 또는 운영체제에 맞춰 개발하는 기술
장점
코틀린은 크게 세 가지 장점을 지니고 있습니다. 첫째, 코틀린은 자바(Java)와 완벽하게 상호운영(interoperable)됩니다. 완벽하게 상호 운영된다는 뜻은 코틀린과 자바(Java)가 100% 호환된다는 의미입니다. 코틀린과 자바의 개발 환경에서는 서로의 라이브러리를 그대로 가져와 사용할 수 있습니다.
둘째, 코틀린은 프로그램의 안정성이 높습니다. 코틀린은 정적 언어(statically typed language)입니다. 프로그래밍 언어 종류와 언어별 특징에서도 살펴보았듯 정적 언어는 자료형을 컴파일 단계에서 미리 검사하여 확정하는 언어입니다. 자료형의 오류를 초기에 발견할 수 있기 때문에 안정적입니다.
널 포인터(Null pointer)로 인해 프로그램이 중단되지 않는 것도 코틀린의 장점입니다. 널 포인터 예외(NullPointerException, NPE)는 객체에 값이 할당되지 않았을 때, 즉 null
값이 할당되었을 때 해당 객체를 호출하면 발생하는 오류입니다.
다른 프로그래밍 언어에서는 참조된 변수가 null
이면 프로그램이 중단됩니다. 하지만 코틀린에서는 기본적으로 null
값을 허용하지 않습니다. 대신 nullable
변수를 사용합니다. nullable
변수는 null
을 데이터 타입(data type)으로 갖는 변수입니다. 그래서 이 변수는 참조해도 오류가 발생하지 않습니다. 코틀린에서 nullable
변수를 사용하는 법은 아래 기초 문법에서 살펴보겠습니다.
마지막으로 코틀린을 사용하면 코드를 간결하게 작성할 수 있습니다. 코틀린은 객체지향 프로그래밍(Object-Oriented Programming, OOP)과 더불어 함수형 프로그래밍(Functional Programming, FP)을 지원하는 다중 패러다임(paradigm) 언어입니다. 함수형 프로그래밍의 기법을 사용하면 코드를 단순화하고 같은 양의 코드로도 더 많은 일을 할 수 있습니다. 또한 코틀린에서는 최신 프로그래밍의 언어 경향에 따라 코드 끝에 관례로 사용 하던 세미콜론(;)을 붙이지 않아도 됩니다. 그래서 코드가 더 깔끔합니다.
플랫폼 기술
이처럼 많은 장점이 있는 코틀린은 안드로이드 앱 개발 외에도 풀스택(full-stack) 웹과 iOS앱, 임베디드 IoT 등 다양한 분야의 개발을 지원합니다. 코틀린이 사용하는 플랫폼은 다음과 같습니다.
- Kotlin/JVM: JVM에서 동작하는 자바(Java) 기반 애플리케이션을 만드는 기술
- Kotlin/JS: 자바스크립트(JavaScript, JS)로 웹 브라우저에서 동작하는 애플리케이션을 만드는 기술
- Kotlin/Native: LLVM 컴파일러를 이용해 멀티 플랫폼을 타깃으로 하는 애플리케이션을 만드는 기술
우리가 여기서 다룰 것은 Kotlin/JVM 기술입니다. 코틀린은 자바와 마찬가지로 자바 바이트코드(Java Bytecode)로 컴파일(compile)되어 자바 가상 머신(Java Virtual Machine, JVM)에서 동작합니다. 자바 바이트코드는 JVM이 이해할 수 있는 이진 코드입니다. JVM은 자바 플랫폼에서 자바 프로그램을 실행하는 가상 소프트웨어 시스템이고요.
자바가 등장하기 전 개발자들은 플랫폼별로 매번 컴파일 작업을 수행해야 했습니다. 사용하는 운영체제(operating system, OS)마다 서로 다른 컴파일 결과물을 만들어냈죠. 한 플랫폼에서 컴파일된 결과물은 다른 플랫폼에서 다시 사용할 수 없었습니다.
- 바이트코드
- CPU가 아닌 가상 머신이 이해할 수 있는 이진 코드(binary code) 언어
- 컴파일(compile)
- 여러 소스 코드를 하나의 목적 파일(object file)로 번역하는 과정
- LLVM
- 여러 플랫폼을 위한 중간 언어(비트코드)를 생성해 ARM(iOS, Android), x86(일반 데스크톱 PC 환경 - MacOS, Windows, Linux) 등에서 모두 실행할 수 있는 코드를 만드는 도구
JVM은 바이트코드라는 수단을 통해서 컴파일 과정의 플랫폼 종속성 문제를 해결합니다. 특정 운영체제에 종속되지 않는 공용어, 소스 코드 파일과 기계어 파일의 중간 코드인 바이트코드를 통해서 말이죠. JVM은 컴파일 과정의 결과물이 여러 운영체제로 나뉘기 전에 일종의 중앙 허브 역할을 해서 바이트코드를 각 운영체제에 적합한 기계어로 번역해줍니다. 이제는 사용하고 있는 운영 체제에 상관없이 컴파일 과정을 1번만 수행하면 됩니다.
물론 JVM은 운영체제별로 다릅니다. 제조사들은 각 운영체제에 맞는 JVM을 개발해야 합니다. 하지만 개발자들은 자유로워졌습니다. 운영체제를 고려하지 않고 프로그램을 개발하고 JVM 위에 자바 프로그램을 돌리기만 하면 되기 때문입니다. JVM과 바이트코드는 운영체제마다 달랐던 프로그래밍 언어의 컴파일 과정을 단일화하면서 개발 생산성을 높입니다.
지금까지 코틀린을 간략하게 소개하고 코틀린의 장점과 플랫폼 기술을 살펴보았습니다. 그럼 지금부터는 코틀린으로 실습하기 위해 프로그래밍 환경 설정법을 알아보겠습니다.
환경 설정
코틀린을 실습하기 위해서는 두 가지 준비물이 필요합니다. 하나는 자바 개발 키트(Java Development Kit, JDK)이고 다른 하나는 통합 개발 환경(Integrated Development Environment, IDE)입니다.
JDK는 자바 기반의 소프트웨어를 "개발"을 위해 필요한 도구 패키지입니다. JDK는 JVM 상에서 코틀린을 실행하고 자바 라이브러리를 이용하기 위해 필요합니다. JDK의 구성 요소는 다음과 같습니다.
- 자바 런타임 환경(Java Runtime Environment, JRE): JVM에서 실행하기 위한 자바 애플리케이션을 로드하는 온디스크 프로그램으로 JVM 포함
- 자바 컴파일러(Java compiler):
javac.exe
로 자바 소스 코드 파일(.java)을 자바 바이트코드(Java Bytecode) 파일(.class)로 번역- 디버깅 툴(debugging tools)
- 각종 자바 개발 툴(javap 등)
JDK는 코틀린으로 안드로이드 앱 개발을 위해 필요한 종합 개발 키트라고 생각하면 됩니다. 여기서는 JDK로 OpenJDK인 Zulu를 IDE로는 인텔리제이 IDE(IntelliJ IDEA)를 사용하겠습니다. Zulu와 인텔리제이 IDE의 설치 방법은 Kotlin 코틀린 프로그래밍 환경 설정하기(JDK, IDE 설치)를 참조해주세요. 인텔리제이 IDE 외에 다양한 종류의 개발 환경을 알고 싶은 분들은 통합 개발 환경(IDE), 텍스트 에디터 인기 순위 (2022년)를 참조해주세요.
JDK와 IDE 준비를 완료하셨다면 지금부터는 코틀린의 기초 문법을 알아보겠습니다.
기초 문법
기본 코드 구조
코틀린에서 가장 기본적인 코드는 fun main()
입니다. main
함수는 코틀린 앱의 진입점(entry point)입니다. 이 함수에 코드를 넣으면 코드가 실행됩니다. 코드는 함수 다음에 나오는 중괄호() 안에 작성합니다. 예제로 살펴보겠습니다.
화면에 "Hello, World!"와 "Have a nice day."라는 문자열을 출력하려고 합니다. 문자열을 출력하려면 println
함수를 사용하면 됩니다. println
은 코틀린의 출력 함수로 작성한 코드를 한 줄씩 출력합니다. 예제 코드는 다음과 같습니다.
kotlinfun main() {println("Hello, World!")println("Have a nice day.")}/* 결과 */Hello, World!Have a nice day.
만약 문자열을 한 줄에 모두 출력하고 싶다면 print
함수를 사용하면 됩니다. print
함수는 문자열을 한 줄에 모두 출력해주는 함수입니다. 예제 코드는 아래와 같습니다.
kotlinfun main() {print("Hello, World! ")print("Have a nice day.")}/* 결과 */Hello, World! Have a nice day.
두 문자열 사이에 간격을 두기 위해 "Hello, World! "에서 느낌표(!) 다음에 공백을 넣었습니다. 만약 print
함수를 사용하면서 문자열을 한 줄씩 출력하려면 아래와 같이 개행 문자 \n
을 사용하면 됩니다.
kotlinfun main() {print("Hello, World!\n")print("Have a nice day.")}# 결과Hello, World!Have a nice day.
주석
위에서 살펴본 코드는 코틀린의 기본 코드 구조입니다. 여기에 코드를 설명하는 주석을 달고 싶다면 //
또는 /* */
기호를 이용하면 됩니다.
//
: 한 줄 주석/* */
: 여러 줄 주석
예제 코드는 다음과 같습니다.
kotlinfun main {// 한 줄 주석var greeting = "Hello"/* 여러 줄 주석* greeting에 다시 "Hi" 값 할당*/greeting = "Hi"}
지금까지 코틀린의 기본 코드 구조를 살펴보았습니다. 다른 프로그래밍 언어에서와 마찬가지로 코틀린에서도 값을 참조하는 매커니즘인 변수(variables)를 이용하면 코드를 더 간략하게 표현할 수 있습니다. 코틀린에서 변수는 어떻게 사용할 수 있을까요?
변수
코틀린에서 변수를 사용하려면 선언 방법과 선언 규칙을 이해해야 합니다. 먼저 변수를 선언하는 방법부터 알아보겠습니다.
선언 방법
코틀린에서 변수를 선언할 때는 val
또는 var
키워드를 사용하면 됩니다. 두 키워드를 나누는 기준은 "변수에 할당된 값의 변경 여부"입니다. 결론부터 말하면 val
은 값을 변경할 수 없는 변수를 선언할 때 사용합니다. 반면 var
은 값을 변경할 수 있는 변수를 선언할 때 사용합니다. 먼저 val
부터 알아보겠습니다.
val
val
은 변경 불가능한(immutable) 참조를 저장하는 변수입니다. val
은 값을 뜻하는 "value"에서 따왔습니다. val
로 선언한 변수는 초기화하고 나면 변수에 할당된 값을 변경할 수 없습니다. 다음은 기본 코드 구조에서 살펴본 예제에서 "Hello, World!"를 출력하는 코드를 val
을 이용해 작성한 예제입니다.
kotlinfun main() {val greeting = "Hello, World!"println(greeting)}/* 결과 */Hello, World!
val
로 선언한 변수에 할당된 값을 변경하려고 하면 Val cannot be reassigned
라는 오류가 발생합니다. 이 오류는 val
로 선언한 변수의 값은 재할당될 수 없다는 의미입니다. 예제 코드는 다음과 같습니다.
kotlinfun main() {val greeting = "Hello, World!" // val은 한 번 지정하면 변경할 수 없는 변수greeting = "Hi"print(greeting)}/* 결과 */Val cannot be reassigned
var
반면 var
은 변경가능한(mutable) 참조를 저장하는 변수입니다. var
은 변수를 뜻하는 "variable"에서 가져왔습니다. var
로 선언된 변수에 할당된 값은 언제든 변경할 수 있습니다. 다음은 var
로 선언한 변수의 값을 바꾸는 예제입니다.
kotlinfun main() {var greeting = "Hello, World!" // var은 값을 업데이트할 수 있는 변수greeting = "Hi"print(greeting)}/* 결과 */Hi
위 코드를 실행하면 변경한 값인 "Hi"가 출력됩니다. 변수의 키워드로 값을 재할당할 수 있는 var
을 사용했기 때문이죠.
선언 규칙
코틀린에서 변수를 선언하는 데는 몇 가지 지켜야 할 규칙이 있습니다.
표기법
코틀린에서는 변수를 선언할 때 첫 단어만 소문자로 시작하고 나머지는 대문자로 표기하는 카멜(camel) 표기법을 사용합니다.
자료형 선언과 생략
코틀린에서 변수를 사용할 때 원칙적으로는 변수의 자료형을 선언합니다. 자료형은 데이터를 식별하는 분류 체계입니다. 자료형의 종류에 대해서는 아래에서 자세히 다루겠습니다. 여기서는 가장 기본적인 정수 자료형을 예로 들어보겠습니다. 정수 자료형인 값을 참조하는 변수를 선언하고 싶다면 초기화 식을 이용해 다음과 같이 작성할 수 있습니다.
kotlinval myValue: Int = 5
초기화 식은 변수가 참조할 값의 자료형을 추론하기 위해 필요합니다. 초기화 식이 없으면 컴파일러가 변수에 대해 아무런 정보를 가지고 있지 않기 때문에 에러가 발생합니다. 만약 초기화 식을 사용하지 않고 변수를 선언하려면 반드시 변수의 자료형을 미리 명시해야 합니다. 다음은 초기화 식을 사용하지 않고 변수 타입을 선언하는 예제입니다.
kotlinval myValue: Int // 변수 자료형 미리 명시myValue = 5
그런데 코틀린을 실무에서 사용할 때는 보통 변수의 자료형을 생략합니다. 코틀린에서는 타입 추론(type inference)이 가능합니다. 타입 추론(또는 자료형 추론)이란 변수나 함수를 선언하거나 연산이 이루어질 때 자료형을 코드에 명시하지 않아도 코틀린에서 자료형을 자동으로 추론해주는 기능입니다.
코틀린의 컴파일러는 변수를 선언하는 시점에 초기화 식으로부터 변수의 타입을 추론합니다. 그리고 변수 선언 이후 변수에 값을 재할당할 때는 이전에 추론한 변수의 자료형을 바탕으로 대입문의 자료형을 검사합니다. 위에서 살펴본 코드는 아래와 같이 자료형을 생략해서 더 간단하게 작성할 수 있습니다.
kotlinval myValue = 5
val 기본 사용
코틀린으로 코드를 작성할 때는 기본적으로 모든 변수를 val
키워드를 이용해 불변 변수로 선언하는 것이 좋습니다. 변수를 var
키워드로 선언하면 변수에 할당된 초기값의 자료형과 다른 자료형을 지닌 값으로 변경했을 때 컴파일 오류가 생길 수 있습니다. 예제로 살펴보겠습니다. 다음 코드를 실행하면 오류가 발생합니다.
kotlinvar vegetableName = 52 // 정수vegetableName = "오이" // 문자열
위 코드에서 변수 선언 시점에 컴파일러가 추론한 자료형은 정수형(integer)입니다. 하지만 변수에 값을 재할당할 때는 자료의 타입이 문자열(string)입니다. 처음 선언되었을 때 추론된 자료형과 이후 값을 변경했을 때 변수의 자료형이 달라서 오류가 발생합니다. 따라서 이후에 값을 변경하는 특별한 경우를 제외하고서는 변수를 선언할 때 val
을 사용하는 것이 좋습니다.
값 할당
코틀린에서 변수를 선언할 때는 반드시 변수에 값을 할당해야 합니다. 만약 변수에 값을 할당하지 않으면 아래와 같이 오류가 발생합니다.
kotlinfun main() {var carrots: Intprintln(carrots) // 값이 할당되지 않은 변수를 사용하려고 함}/* 결과 */Variable 'carrots' must be initialized
변수를 선언하는 시점에 반드시 변수에 값을 할당해야 하는 것은 아닙니다. 변수를 참조하여 실행하기 전까지만 값을 할당하면 됩니다. 다음 코드는 오류 없이 작동합니다.
kotlinfun main() {var carrots: Intcarrots = 5println(carrots)}/* 결과 */5
null 값
상황에 따라 변수에 값이 할당되지 않았다는 것 자체를 정보로 사용하고 싶은 경우도 있습니다. 코틀린의 장점에서 살펴본 것처럼 null
을 값 자체로 갖는 nullable
변수를 선언하는 것입니다. nullable
변수를 선언하려면 변수 자료형 다음에 물음표(?) 기호를 사용하면 됩니다. 예제는 다음과 같습니다.
kotlinvar myValue: Int? = null // 자 료형(Int) 다음에 물음표fun main() {println(myValue)}/* 결과 */null
지금까지 코틀린에서 변수를 선언하는 방법과 변수 선언 규칙을 살펴보았습니다. 지금부터는 코틀린의 자료형을 살펴보겠습니다.
자료형
코틀린의 원시 자료형(primitive data type)에는 숫자 자료형, 문자 자료형, 문자열 자료형, 논리 자료형이 있습니다. 먼저 숫자형 자료형부터 알아보겠습니다. 숫자형 자료형에는 정수형 자료형과 실수형 자료형이 있습니다.
숫자 자료형: 정수
정수 자료형은 자료형이 정수입니다. 정수 자료형의 종류와 각 자료형의 크기, 그리고 표기할 수 있는 숫자의 범위는 다음과 같습니다.
- Byte: 8비트 (최소 -128 ~ 최대 127)
- Short: 16비트 (최소 -32768 ~ 최대 32767)
- Int: 32비트 (최소 -2^31 ~ 최대 2^31 - 1)
- Long: 64비트 (최소 -2^63 ~ 최대 2^63 - 1)
코틀린에서 숫자는 10진수, 2진수, 16진수 리터럴로 표기할 수 있습니다. 8진수는 지원하지 않습니다. 먼저 10진수를 표기하는 방법부터 알아보겠습니다.
10진수 리터럴
코틀린에서 10진수를 표기하는 방법은 우리가 일상생활에서 숫자를 표기하는 방법과 같습니다. 예제 코드는 다음과 같습니다.
kotlinfun main() {// Byte(8비트)val byteValue: Byte = 5// Short(16비트)val shortValue: Short = 5// Int(32비트)val intValue: Int = 5// Long(64비트)val longValue: Long = 5L}
64비트인 Long
타입의 10진수에는 더 큰 메모리를 사용하는 정수라는 것을 표시하기 위해 숫자 뒤에 L
을 붙입니다.
16진수 리터럴
코틀린에서 16진수를 표기할 때는 16진수 앞에 0x
를 붙입니다. "x"는 16진수를 의미하는 "hexadecimal number"에서 "hex"의 x
를 의미합니다. 예제 코드는 다음과 같습니다.
kotlinfun main() {var intValueByHex: Int = 0x1af // 16진수 표기}
2진수 리터럴
코틀린에서 2진수를 표기할 때는 2진수 앞에 0b
를 더해줍니다. 여기서 "b"는 2진수를 뜻하는 "binary number"의 첫 글자 b
를 의미합니다.
kotlinvar intValueByBin:Int = 0b110110
지금까지 10진수, 16진수, 2진수 정수 자료형을 표기하는 법을 알아보았습니다. 이번에는 숫자 자료형 중 실수형 데이터를 표기하는 법을 알아보겠습니다.
숫자 자료형: 실수
실수형 자료형은 자료형이 실수(real number)입니다. 실수 자료형의 종류와 각 자료형의 크기는 다음과 같습니다.
- float: 32비트
- double: 64비트
실수 자료형의 기본값은 double
입니다. 따라서 float
을 따로 표기를 하지 않으면 기본적으로 double
형으로 선언됩니다. 만약 자료형을 float
으로 선언하고 싶다면 값 끝에 F
또는 f
를 붙이면 됩니다. 예제 코드는 다음과 같습니다.
kotlinfun main() {// Float(32비트)val floatValue: Float = 13.37F // Float 형 선언// Double(64비트)val doubleValue: Double = 3.14159val doubleValueWithExp: Double = 3.141e10 // 지수 표기법}
문자 자료형과 문자열 자료형
문자 자료형은 자료형이 1개의 문자입니다. 문자 자료형은 Char
로 선언합니다. 각 문자는 2바이트의 메모리 공간을 차지합니다. 코틀린에서 문자 한 개를 표기할 때는 작은따옴표('')를 사용합니다.
kotlinfun main() {val letterCharValue: Char = 'A'val digitCharValue: Char = '$'}
만약 문자열을 표기하고 싶다면 자료형으로 String
을 사용해야 합니다. 문자열 자료형 은 유니코드 중에서 UTF-16 BE 인코딩 방식을 사용하는데, 이 인코딩 방식에서는 문자 한 개가 2바이트입니다. 코틀린에서 문자열을 표기할 때는 큰따옴표("")를 사용합니다. 예제 코드는 다음과 같습니다.
kotlinfun main() {val stringValue: String = "Hello, World!"var firstCharInStr = stringValue[0] // 문자열의 첫 번째 값에 접근var lastCharInStr = stringValue[stringValue.length - 1] // 문자열의 마지막 값에 접근var myLength = stringValue.lengthprintln("First: " + firstCharInStr)println("Last: $lastCharInStr")println("Length: ${stringValue.length}")}/* 결과 */First: HLast: !Length: 13
여러 줄로 이루어진 문자열을 사용하려면 3중 따옴표(""")를 사용하면 됩니다.
kotlinfun main() {val multilineStringValue = """Hello, World! Good to see you."""println(multilineStringValue)}/* 결과 */Hello, World! Good to see you.
논리 자료형
논리 자료형은 불린(Boolean)값을 가집니다. 불린 리터럴을 표기할 때는 true
또는 false
를 사용하면 됩니다.
kotlinfun main() {var isSunny: Boolean = trueprintln(isSunny)}/* 결과 */true
다음은 지금까지 배운 자료형을 정리한 내용입니다.
kotlinfun main() {// 숫자 자료형(정수)var a1 = 1 // 10진수 정수 자료형 Intvar a2 = 0xABCD // 16진수는 Int로 추론됨var a3 = 0b01231 // 2진수는 Int로 추론됨var a4 = 1L // Long// 숫자 자료형(실수)var b1 = 1.5 // Doublevar b2 = 1.5f // Float// 문자 자료형과 문자열 자료형var c1 = 'c' // 문자var c2 = "Hello, World!" // 문자열// 논리 자료형var d = true // 불린}
지금까지 코틀린의 기초 문법을 살펴보았습니다. 다음 시간에는 코틀린에서 함수(functions)를 사용하는 법을 살펴보겠습니다. 모두 수고 많으셨습니다.
참고 문헌
- [1] 고현민,『혼자 공부하는 얄팍한 코딩 지식: 비전공자도 1:1 과외하듯 배우는 IT 지식 입문서』, 한빛미디어, 2022, 125.
- [2] 김인경, 「[함께 쓰는 풀리퀘]그 프로그래밍 언어에 담긴 이야기②」, Bloter, "https://www.bloter.net/newsView/blt202203270003"
- [3] 테크과학! DiMo. (2019, 08 12). 디모의 Kotlin 강좌. [비디오 파일]. 검색경로 https://www.youtube.com/playlist?list=PLQdnHjXZyYadiw5aV3p6DwUdXV2bZuhlN
- [4] Matthew Tyson, 「"JDK란 무엇인가" 자바 개발 키트 소개와 설치하기」, IT World, "https://www.itworld.co.kr/news/110817"