1. 논리 데이터 타입: Boolean
이미 확인했듯이 Kotlin에는 아주 유용한 연산자 if-else가 있습니다. 괄호 안의 조건이 참이면 하나의 명령 블록을 실행하고, 조건이 거짓이면 두 번째 명령 블록을 실행합니다.
참/거짓이 될 수 있는 표현식을 편하게 다루기 위해 Kotlin에는 특별한 타입 Boolean이 추가되어 있습니다. 이 타입의 가장 큰 특징은 변수가 오직 두 가지 값만 가질 수 있다는 점입니다: true(참)와 false(거짓).
Boolean 타입 변수에는 다른 어떤 값도 대입할 수 없습니다. 컴파일러가 허용하지 않습니다.
Boolean 타입 변수 예시:
val isAdult: Boolean = true
val hasMoney: Boolean = false
Boolean 타입 변수의 값은 두 개뿐입니다 — true(참)와 false(거짓). 끝! 성공한 테스트처럼 “통과” 아니면 “실패”(어...)
2. 비교 연산
그런데 이렇게 단순한 타입이 왜 필요할까요? Boolean의 진짜 힘은 논리 표현식을 만들 때 드러납니다. 보통 비교 연산자를 통해 만들어집니다.
| 연산자 | 의미 | 예시 | 값 |
|---|---|---|---|
|
같다 | |
true 또는 false |
|
같지 않다 | |
true 또는 false |
|
크다 | |
true 또는 false |
|
작다 | |
true 또는 false |
|
크거나 같다 | |
true 또는 false |
|
작거나 같다 | |
true 또는 false |
예시:
val age = 20
val isAdult = age >= 18 // true (20은 18보다 크거나 같다)
val isTeenager = age >= 13 && age < 18 // false (20은 18보다 작지 않다)
val isEven = age % 2 == 0 // true (20은 2로 나누어 떨어진다)
여기서 isAdult는 true가 됩니다. 20은 실제로 “성인” 나이이기 때문입니다.
중요 포인트 1:
두 글자로 이루어진 연산자는 중간을 띄어 쓰면 안 됩니다. 즉, 아래 코드는 컴파일되지 않습니다:
|
|---|
|
|
|
중요 포인트 2:
=>와 =< 연산자는 없습니다. 오직 <=와 >=만 있습니다. a =< 3처럼 쓰면 코드는 그냥 컴파일되지 않습니다.
중요 포인트 3:
Kotlin에서는 18 < age < 65 같은 표현식을 쓸 수 없습니다. 18 < age의 값은 true 또는 false인데, true < 65처럼(서로 다른 타입) 비교할 수 없기 때문입니다. 적어도 Kotlin에서는요.
3. 논리 연산
Kotlin에서는 18 < age < 65 표현식을 쓸 수 없으며, 문법적으로 올바르지 않아 프로그램이 컴파일되지 않습니다.
대신 이렇게 쓸 수 있습니다:
(18 < age) 그리고 (age < 65)
물론 위의 “그리고” 자리에 다른 논리 연산자가 들어가며, 지금부터 그것들을 자세히 살펴보겠습니다.
Kotlin에는 세 가지 논리 연산자가 있습니다: AND(그리고), OR(또는), NOT(아니다).
좋은 소식: 괄호를 사용하면 어떤 복잡도의 논리 표현식도 만들 수 있습니다.
나쁜 소식: Kotlin 개발자들은 and, or, not 같은 단어 대신 C++에서 쓰는 표기법을 사용하기로 했습니다.
화면을 보세요:
| 논리 연산자 | 기대 | 현실 |
|---|---|---|
|
|
|
|
|
|
|
|
|
다음은 Kotlin에서 논리 연산자를 사용하는 예시입니다:
| 표현식 | 해석 | 설명 |
|---|---|---|
|
(0 < a) and (a < 100) | (0 < a) 그리고 (a < 100) |
|
(not a) and (not b) | (NOT a) 그리고 (NOT b) |
|
not((not a) or (not b)) | NOT((NOT a) 또는 (NOT b)) |
4. 진리표
논리 연산을 간단히 짚고 넘어가겠습니다.
AND 연산자
AND 연산자(= AND, = &&)는 논리곱(Conjunction)에 해당합니다.
| 표현식 | 결과 |
|---|---|
|
|
|
|
|
|
|
|
즉, 표현식의 결과는 두 값이 모두 true(참)일 때만 true(참)입니다. 그 외의 경우에는 항상 false(거짓)입니다.
OR 연산자
OR 연산자(= OR, = ||)는 논리합(Disjunction)에 해당합니다.
| 표현식 | 결과 |
|---|---|
|
|
|
|
|
|
|
|
즉, 표현식의 결과는 참여하는 값 중 하나라도 true(참)이면 항상 true(참)입니다. 둘 다 false이면 결과는 false입니다.
NOT 연산자
NOT 연산자(= NOT, = !)는 논리 부정(Inversion)입니다.
| 표현식 | 결과 |
|---|---|
|
|
|
|
true를 false로, false를 true로 바꿉니다.
유용한 표현식:
| 표현식 | 결과 |
|---|---|
|
|
|
|
|
|
|
|
5. 논리 연산 예시: and, or, not
“AND” 연산은 &&로 표시합니다
결과는 두 변수가 모두 참일 때만 참입니다.
val age = 16
val hasTicket = true
val canAttend = age >= 14 && hasTicket // true (16은 14보다 크고, 티켓도 있다)
14세 이상 그리고 티켓이 있으면 — 들어오세요!
“OR” 연산은 (||)로 표시합니다
결과는 조건 중 하나라도 참이면 참입니다.
val isAdmin = false
val isModerator = true
val canEdit = isAdmin || isModerator // true (둘 중 하나라도 true면 편집 가능)
관리자 또는 모더레이터라면 — 버튼을 마음껏 누르세요!
“NOT” 연산은 (!)로 표시합니다
부정 연산은 참을 거짓으로, 거짓을 참으로 바꿉니다.
val isWeekend = false
val shouldGoToWork = !isWeekend // true (주말이 아니면 일하자)
주말이 아니라면 — 일어날 시간입니다!
조합하기: 원하는 만큼 복잡한 조건을 만들기
논리 연산을 얼마든지 조합할 수 있습니다(다만 “그가 NOT NOT NOT NOT 관리자라면...” 같은 게 되지 않게 너무 과하게만 하지 마세요). 괄호는 명확성을 위해 (그리고 사실상 반드시) 사용하는 게 좋습니다.
예시:
val age = 17
val hasTicket = false
val isVip = true
val canGo = (age >= 18 && hasTicket) || isVip // true, because isVip = true
이 예시의 로직은 다음과 같습니다: 성인이고 티켓이 있거나, 또는 VIP면 입장. VIP가 아니라면 성인이고 티켓이 있어야만 입장.
6. 단락 평가(Short-circuit)
지금부터는 레벨에서 가장 실용적인 아이디어 중 하나입니다. Kotlin에서 논리 연산자 &&와 ||는 경우에 따라 조건의 두 번째 부분을 아예 계산하지 않기도 합니다. 이를 단락 평가(short-circuit)라고 합니다.
“전기 문제”처럼 들릴 수 있지만, 실제로는 매우 유용한 메커니즘입니다. 안전하게 조건식을 작성하도록 도와줍니다: 먼저 “다음 검사를 해도 되는가?”를 확인하고, 그다음에 잠재적으로 위험한 계산(예: 나눗셈)을 수행합니다. 그 결과 “0으로 나누기” 같은 오류를 피할 수 있습니다. 더 중요한 점은, 오류를 잡아서(예외 처리) 피하는 게 아니라 애초에 발생하지 않게 만든다는 것입니다.
동작 방식
A && B의 경우:
- A가 이미 false라면 전체 결과는 확실히 false입니다;
- 따라서 B는 아예 계산하지 않아도 됩니다.
A || B의 경우:
- A가 이미 true라면 전체 결과는 확실히 true입니다;
- 따라서 B 역시 계산하지 않아도 됩니다.
&&와 || 계산 미니‑흐름도
flowchart TD
A[왼쪽 부분 A 계산] --> B{어떤 연산자?}
B -->|"&&"| C{"A == true?"}
C -->|"아니오"| D[결과 false, B는 계산하지 않음]
C -->|"예"| E[오른쪽 부분 B 계산, 결과 = B]
B -->|"||" | F{"A == true?"}
F -->|"예"| G[결과 true, B는 계산하지 않음]
F -->|"아니오"| H[오른쪽 부분 B 계산, 결과 = B]
단락 평가 실전: 0으로 나누기 방지
초보자 멘탈을 진짜로 지켜주는 가장 고전적인 예시입니다: 먼저 나누는 수가 0이 아닌지 확인하고, 그다음에 나눕니다.
올바른 순서: 먼저 안전, 그다음 수학
fun main() {
val x = 0
if (x != 0 && (10 / x) > 1) {
println("Quotient is greater than 1")
} else {
println("Either x = 0, or the quotient is not greater than 1") // Either x = 0, or the quotient is not greater than 1
}
}
여기서 중요한 “마법 아닌 마법”이 일어납니다: x == 0이면 x != 0는 false가 되고, Kotlin은 계산을 진행하지 않아 (10 / x) > 1을 평가하지 않습니다. 즉, 0으로 나누기가 아예 발생하지 않습니다.
잘못된 순서: 위험한 부분을 먼저 둠
반대로 먼저 나눗셈을 하고 그다음에 x != 0를 검사하면, 단락 평가가 도움이 되지 않습니다. 단락 평가가 동작하려면 그 지점까지 “살아남아야” 하기 때문입니다. 왼쪽에서 이미 터지면 오른쪽은 구해주지 못합니다.
GO TO FULL VERSION