값에서 프로그램이 시작된다
프로그램은 값을 다루는 일에서 시작합니다. 이름, 나이, 가격, 로그인 여부, 계산 결과처럼 코드 안에서 사용하는 모든 정보가 값입니다. 코틀린에서는 이런 값을 변수에 담아 사용합니다.
가장 작은 예제부터 보겠습니다.
fun main() {
val name = "Kotlin"
val year = 2026
println(name)
println(year)
}name에는 문자열 값 "Kotlin"이 들어 있고, year에는 정수 값 2026이 들어 있습니다. println()은 값을 화면에 출력하는 함수입니다.
여기서 중요한 점은 코틀린이 name과 year의 타입을 자동으로 추론한다는 것입니다. "Kotlin"은 문자열이므로 String, 2026은 정수이므로 Int로 판단합니다.
val name: String = "Kotlin"
val year: Int = 2026위처럼 타입을 직접 적어도 됩니다. 다만 값만 봐도 타입이 분명하다면 코틀린에서는 타입을 생략하는 편이 자연스럽습니다.

val과 var: 바꿀 수 있는가, 없는가
코틀린에서 변수를 선언할 때 가장 먼저 선택하는 키워드는 val과 var입니다.
val: 한 번 값을 넣으면 다시 바꿀 수 없습니다.var: 값을 다시 바꿀 수 있습니다.
fun main() {
val language = "Kotlin"
var level = 1
// language = "Java" // 오류: val은 다시 대입할 수 없음
level = 2
println(language)
println(level)
}val은 값이 고정됩니다. var는 값이 변할 수 있습니다. 이 차이는 단순해 보이지만 코드를 안정적으로 만드는 데 매우 중요합니다.
변할 필요가 없는 값까지 var로 선언하면, 나중에 어디선가 값이 바뀌어 버그가 생길 수 있습니다. 반대로 val을 기본으로 사용하면 "이 값은 바뀌지 않는다"는 의도를 코드에 분명히 남길 수 있습니다.
코틀린에서는 특별한 이유가 없다면 val을 먼저 사용하고, 정말 값이 바뀌어야 할 때만 var를 사용하는 습관이 좋습니다.
val price = 10_000
val quantity = 3
val total = price * quantity
println(total)price, quantity, total은 계산 중에 바뀔 필요가 없습니다. 이런 값은 val이 적절합니다.
반대로 다음처럼 점수가 계속 변하는 상황이라면 var를 사용할 수 있습니다.
var score = 0
score = score + 10
score += 5
println(score) // 15score += 5는 score = score + 5와 같은 뜻입니다.
타입은 값의 종류를 알려준다
타입은 값의 종류입니다. 코틀린은 타입을 기준으로 값에 어떤 연산을 할 수 있는지 판단합니다.
예를 들어 숫자는 더할 수 있지만, 참과 거짓을 나타내는 값은 곱할 수 없습니다.
val age = 20
val isAdult = true
println(age + 1)
// println(isAdult * 2) // 오류타입을 알면 코드가 왜 되는지, 왜 안 되는지 이해할 수 있습니다.
정수 타입: Int와 Long
정수를 표현할 때 가장 자주 쓰는 타입은 Int입니다.
val count = 10
val temperature = -3위 값들은 기본적으로 Int로 추론됩니다. 더 큰 정수가 필요하면 Long을 사용합니다. Long 값을 직접 쓸 때는 숫자 뒤에 L을 붙입니다.
val population = 51_000_000
val bigNumber = 9_000_000_000L숫자 사이의 _는 읽기 쉽게 넣는 구분자입니다. 값에는 영향을 주지 않습니다.
val price = 1_000_000
println(price) // 1000000코틀린에는 Byte, Short, Int, Long 같은 정수 타입이 있지만, 일반적인 코드에서는 Int를 가장 많이 사용합니다. 아주 큰 수가 필요할 때 Long을 선택하면 됩니다.
실수 타입: Double과 Float
소수점이 있는 숫자는 실수 타입으로 표현합니다. 코틀린에서 실수의 기본 타입은 Double입니다.
val rate = 0.15
val average = 82.5Float을 사용하려면 숫자 뒤에 f 또는 F를 붙입니다.
val height: Float = 172.5f일반적인 계산에서는 Double을 사용하는 경우가 많습니다. Float은 메모리를 더 아껴야 하거나 특정 API가 요구할 때 사용합니다.
정수와 실수를 함께 계산하면 결과가 실수가 될 수 있습니다.
val result = 10 / 4
println(result) // 2
val preciseResult = 10 / 4.0
println(preciseResult) // 2.510 / 4는 정수끼리 나누기 때문에 결과도 정수입니다. 소수점 아래는 버려집니다. 정확한 소수 계산이 필요하다면 한쪽 값을 실수로 만들어야 합니다.
Boolean: 참과 거짓을 표현하기
Boolean은 true 또는 false만 가질 수 있는 타입입니다.
val isLoggedIn = true
val hasPermission = false조건을 판단할 때 자주 사용합니다.
val age = 20
val isAdult = age >= 19
println(isAdult) // trueage >= 19의 결과는 참 또는 거짓입니다. 그래서 isAdult의 타입은 Boolean입니다.
Boolean 값은 뒤에서 배울 if, when, 반복문과 함께 프로그램의 흐름을 결정하는 핵심 재료가 됩니다.
Char와 String: 문자 하나와 문자열
문자 하나는 Char입니다. 작은따옴표를 사용합니다.
val grade = 'A'
val firstLetter = 'K'여러 글자로 이루어진 문자열은 String입니다. 큰따옴표를 사용합니다.
val language = "Kotlin"
val message = "Hello, Kotlin"작은따옴표와 큰따옴표는 서로 바꿔 쓸 수 없습니다.
val charValue = 'A'
val stringValue = "A"둘 다 화면에는 A처럼 보이지만 타입은 다릅니다. charValue는 문자 하나인 Char, stringValue는 문자열인 String입니다.
문자열은 + 연산자로 이어 붙일 수 있습니다.
val firstName = "Kim"
val lastName = "Min"
val fullName = firstName + " " + lastName
println(fullName)하지만 코틀린에서는 문자열 템플릿을 사용하는 편이 더 읽기 좋습니다.
문자열 템플릿으로 값 조합하기
문자열 안에서 변수 값을 바로 사용할 수 있습니다. 이것을 문자열 템플릿이라고 합니다.
val name = "Jisoo"
val age = 20
println("이름: $name")
println("나이: $age")변수 이름 앞에 $를 붙이면 문자열 안에 값이 들어갑니다.
계산식이나 속성 접근처럼 조금 더 복잡한 표현식은 ${}로 감쌉니다.
val price = 10_000
val quantity = 3
println("총액은 ${price * quantity}원입니다.")문자열 템플릿을 사용하면 +로 여러 조각을 이어 붙이는 코드를 줄일 수 있습니다.
val name = "Kotlin"
val version = 2
println("$name version $version")간단한 변수는 $name처럼 쓰고, 계산이 들어가면 ${}를 사용한다고 기억하면 됩니다.
타입 변환: 자동으로 바뀌지 않는다
코틀린은 타입 변환에 엄격합니다. Int 값을 Long 변수에 자동으로 넣어 주지 않습니다.
val intValue: Int = 10
// val longValue: Long = intValue // 오류직접 변환해야 합니다.
val intValue: Int = 10
val longValue: Long = intValue.toLong()
println(longValue)자주 사용하는 변환 함수는 다음과 같습니다.
toByte()toShort()toInt()toLong()toFloat()toDouble()toString()
예를 들어 숫자를 문자열로 바꾸고 싶다면 toString()을 사용합니다.
val age = 20
val text = age.toString()
println(text)문자열을 숫자로 바꿀 수도 있습니다.
val input = "123"
val number = input.toInt()
println(number + 1) // 124단, 숫자로 바꿀 수 없는 문자열에 toInt()를 사용하면 오류가 발생합니다.
val input = "abc"
// val number = input.toInt() // 실행 중 오류안전하게 변환하고 싶다면 toIntOrNull()을 사용할 수 있습니다. 변환에 실패하면 null을 돌려줍니다. null은 값이 없다는 뜻이며, 이후 장에서 자세히 다룹니다.
val input = "abc"
val number = input.toIntOrNull()
println(number) // null지금은 코틀린이 타입을 마음대로 바꾸지 않는다는 점만 기억하면 충분합니다. 필요한 변환은 개발자가 명시해야 합니다.
산술 연산자: 숫자를 계산하기
산술 연산자는 숫자 계산에 사용합니다.
| 연산자 | 의미 |
|---|---|
+ | 더하기 |
- | 빼기 |
* | 곱하기 |
/ | 나누기 |
% | 나머지 |
예제를 보겠습니다.
val a = 10
val b = 3
println(a + b) // 13
println(a - b) // 7
println(a * b) // 30
println(a / b) // 3
println(a % b) // 1%는 나머지를 구합니다. 어떤 수가 짝수인지 홀수인지 판단할 때 자주 사용합니다.
val number = 8
val isEven = number % 2 == 0
println(isEven) // true값을 누적해서 바꿀 때는 복합 대입 연산자를 사용할 수 있습니다.
var point = 100
point += 10 // point = point + 10
point -= 5 // point = point - 5
point *= 2 // point = point * 2
point /= 3 // point = point / 3
println(point)값을 1씩 늘리거나 줄일 때는 ++, --를 사용할 수 있습니다.
var count = 0
count++
count++
count--
println(count) // 1다만 무조건 짧게 쓰는 것이 좋은 코드는 아닙니다. 처음에는 count += 1처럼 의미가 분명한 방식으로 써도 괜찮습니다.
비교 연산자: 두 값을 비교하기
비교 연산자는 두 값을 비교하고 결과로 Boolean을 만듭니다.
| 연산자 | 의미 |
|---|---|
== | 같다 |
!= | 같지 않다 |
> | 크다 |
< | 작다 |
>= | 크거나 같다 |
<= | 작거나 같다 |
val age = 20
println(age == 20) // true
println(age != 20) // false
println(age > 19) // true
println(age <= 18) // false문자열도 ==로 비교할 수 있습니다.
val a = "Kotlin"
val b = "Kotlin"
println(a == b) // true코틀린에서 ==는 값이 같은지를 비교합니다. 문자열의 내용이 같으면 true입니다.
참고로 ===라는 연산자도 있습니다. 이것은 두 대상이 메모리에서 같은 객체인지 비교합니다. 초반에는 거의 사용할 일이 없습니다. 일반적인 값 비교에는 ==를 사용하면 됩니다.
논리 연산자: 조건을 조합하기
논리 연산자는 여러 조건을 연결할 때 사용합니다.
| 연산자 | 의미 |
|---|---|
&& | 그리고. 양쪽이 모두 참이면 참 |
| ` | |
! | 부정. 참을 거짓으로, 거짓을 참으로 바꿈 |
val age = 20
val hasTicket = true
val canEnter = age >= 19 && hasTicket
println(canEnter) // true&&는 양쪽 조건이 모두 참이어야 합니다.
val isMember = false
val hasCoupon = true
val canDiscount = isMember || hasCoupon
println(canDiscount) // true||는 둘 중 하나라도 참이면 참입니다.
val isOpen = false
println(!isOpen) // true!는 결과를 반대로 바꿉니다.
논리 연산자는 실제 코드에서 조건문과 함께 많이 사용됩니다.
val age = 17
val hasParentPermission = true
val canUseService = age >= 19 || hasParentPermission
println(canUseService) // true이 코드는 "성인이거나 보호자 동의가 있으면 서비스를 사용할 수 있다"는 뜻입니다.
범위 연산자: 값의 구간 표현하기
코틀린에는 범위를 표현하는 문법이 있습니다.
val range = 1..51..5는 1부터 5까지의 범위입니다. 끝값 5도 포함합니다.
어떤 값이 범위 안에 있는지 확인할 때는 in을 사용합니다.
val score = 85
val isValidScore = score in 0..100
println(isValidScore) // true범위 밖에 있는지 확인할 때는 !in을 사용합니다.
val score = 120
val isInvalidScore = score !in 0..100
println(isInvalidScore) // true끝값을 포함하지 않는 범위가 필요하면 until을 사용합니다.
val index = 4
val isInRange = index in 0 until 5
println(isInRange) // true0 until 5는 0, 1, 2, 3, 4를 의미합니다. 5는 포함하지 않습니다. 배열이나 리스트의 인덱스를 다룰 때 자주 사용합니다.
큰 수에서 작은 수로 내려가는 범위는 downTo를 사용합니다.
val count = 3
val isInCountdown = count in 5 downTo 1
println(isInCountdown) // true간격을 지정하려면 step을 사용할 수 있습니다.
val number = 6
val isEvenStep = number in 0..10 step 2
println(isEvenStep) // true범위는 다음 장에서 배울 반복문과 함께 더 자주 등장합니다. 지금은 .., until, downTo, step, in의 의미를 익혀 두면 됩니다.
작은 예제로 묶어 보기
지금까지 배운 변수, 타입, 문자열 템플릿, 연산자를 하나의 예제로 묶어 보겠습니다.
fun main() {
val productName = "Keyboard"
val price = 45_000
val quantity = 2
val discountRate = 0.1
val originalTotal = price * quantity
val discountAmount = originalTotal * discountRate
val finalTotal = originalTotal - discountAmount
val hasFreeShipping = finalTotal >= 50_000
println("상품명: $productName")
println("수량: $quantity")
println("정가 합계: ${originalTotal}원")
println("할인 금액: ${discountAmount.toInt()}원")
println("최종 결제 금액: ${finalTotal.toInt()}원")
println("무료 배송 여부: $hasFreeShipping")
}이 예제에는 여러 개념이 들어 있습니다.
val로 바뀌지 않는 값을 선언했습니다.String,Int,Double,Boolean타입이 함께 사용되었습니다.*,-,>=연산자를 사용했습니다.문자열 템플릿으로 출력 문장을 만들었습니다.
toInt()로 실수 결과를 정수로 변환했습니다.
조금 더 현실적인 계산에서는 소수점 처리, 반올림, 통화 계산 방식까지 고민해야 합니다. 하지만 지금 단계에서는 타입이 서로 어떻게 섞이고, 연산 결과가 어떻게 만들어지는지 이해하는 것이 더 중요합니다.
자주 하는 실수
val 값을 다시 바꾸려고 한다
val name = "Kotlin"
// name = "Java" // 오류값을 바꿔야 한다면 var를 사용해야 합니다. 하지만 먼저 정말 바꿔야 하는 값인지 생각해 보세요.
정수 나눗셈 결과를 실수로 기대한다
val result = 5 / 2
println(result) // 2정수끼리 나누면 결과도 정수입니다. 2.5를 원한다면 한쪽을 실수로 만들어야 합니다.
val result = 5 / 2.0
println(result) // 2.5타입이 자동 변환될 것이라고 생각한다
val count: Int = 10
// val total: Long = count // 오류코틀린은 자동 변환을 쉽게 허용하지 않습니다.
val total: Long = count.toLong()명시적으로 바꿔야 코드의 의도가 분명해집니다.
문자열과 숫자를 헷갈린다
val a = "10"
val b = 20
// println(a + b) // 상황에 따라 의도와 다른 코드가 될 수 있음"10"은 숫자가 아니라 문자열입니다. 계산하려면 숫자로 변환해야 합니다.
val a = "10".toInt()
val b = 20
println(a + b) // 30연습 문제
다음 문제를 직접 입력해 보세요. 코드를 눈으로만 읽는 것보다 직접 실행해 보는 편이 훨씬 빠르게 익숙해집니다.
문제 1
이름, 나이, 사는 도시를 각각 변수로 선언하고 다음 형식으로 출력해 보세요.
제 이름은 민수입니다. 나이는 21살이고, 서울에 살고 있습니다.문자열 템플릿을 사용하세요.
문제 2
상품 가격과 수량을 변수로 선언한 뒤 총액을 계산해 출력해 보세요.
조건은 다음과 같습니다.
상품 가격: 12,000원
수량: 4개
출력:
총액은 48000원입니다.
문제 3
점수 하나를 변수로 선언하고, 그 점수가 0 이상 100 이하인지 Boolean 값으로 출력해 보세요.
val score = 85in 연산자를 사용해 보세요.
문제 4
어떤 숫자가 짝수인지 확인하는 코드를 작성해 보세요.
힌트는 % 연산자입니다.
val number = 14문제 5
다음 코드의 출력 결과를 예상해 보세요.
val a = 7
val b = 2
println(a / b)
println(a % b)
println(a > b && b > 0)
println(a in 1..10)예상한 뒤 직접 실행해서 확인하세요.
정리
이번 장에서는 코틀린의 가장 기본이 되는 변수, 타입, 연산자를 배웠습니다.
val은 다시 대입할 수 없는 변수입니다.var는 값을 바꿀 수 있는 변수입니다.특별한 이유가 없다면
val을 먼저 선택하는 습관이 좋습니다.코틀린은 타입을 추론하지만, 모든 값은 분명한 타입을 가집니다.
자주 쓰는 기본 타입에는
Int,Long,Double,Boolean,Char,String이 있습니다.숫자 타입은 자동으로 변환되지 않으므로
toLong(),toDouble()같은 변환 함수를 사용해야 합니다.문자열 템플릿을 사용하면 값을 간결하게 출력할 수 있습니다.
산술, 비교, 논리, 범위 연산자는 조건과 계산의 기초가 됩니다.
이제 값과 계산을 표현할 수 있게 되었습니다. 다음 장에서는 이 값을 바탕으로 프로그램이 상황에 따라 다르게 움직이도록 만드는 흐름 제어를 배웁니다.
이 노트는 보도·비평·교육·연구 목적으로 작성되었습니다. 저작권 문의가 있으시면 에서 알려주세요.