Swift 변수와 타입 | var, let, 옵셔널
이 글의 핵심
Swift 변수와 타입에 대한 실전 가이드입니다. var, let, 옵셔널 등을 예제와 함께 설명합니다.
들어가며
타입 추론과 **옵셔널(?)**으로 “값이 없을 수 있음”을 타입에 표시합니다. guard let·if let으로 언랩 흐름을 명확히 두는 패턴이 흔합니다.
1. 변수와 상수
var vs let
// 변수 (var): 변경 가능
var name = "홍길동"
name = "김철수" // OK
print(name) // 김철수
// 상수 (let): 변경 불가
let age = 25
// age = 26 // 컴파일 에러!
// 권장: 기본적으로 let 사용, 필요할 때만 var
let maxCount = 100
var currentCount = 0
타입 추론
// 타입 추론 (권장)
let name = "홍길동" // String으로 추론
let age = 25 // Int로 추론
let pi = 3.14 // Double로 추론
// 명시적 타입 (필요 시)
let name: String = "홍길동"
let age: Int = 25
let pi: Double = 3.14
2. 기본 타입
정수 타입
// Int (플랫폼에 따라 32bit 또는 64bit)
let int: Int = 10
let negativeInt: Int = -10
// UInt (부호 없는 정수)
let uint: UInt = 10
// let negativeUInt: UInt = -10 // 에러!
// 크기별 정수
let int8: Int8 = 127
let int16: Int16 = 32767
let int32: Int32 = 2147483647
let int64: Int64 = 9223372036854775807
// 최소/최대값
print(Int.min) // -9223372036854775808
print(Int.max) // 9223372036854775807
실수 타입
// Double (64bit, 기본)
let double: Double = 3.14159265359
// Float (32bit)
let float: Float = 3.14
// 타입 명시 필요
let pi = 3.14 // Double로 추론
let piFloat: Float = 3.14 // Float로 명시
문자열
let text: String = "Hello, Swift!"
// 문자열 보간
let name = "홍길동"
let age = 25
let message = "이름: \(name), 나이: \(age)"
print(message)
// 여러 줄 문자열
let multiline = """
첫 번째 줄
두 번째 줄
세 번째 줄
"""
// 문자열 연산
let hello = "Hello"
let world = "World"
let greeting = hello + ", " + world + "!"
불리언
let isActive: Bool = true
let isCompleted: Bool = false
// 논리 연산
let result1 = true && false // false
let result2 = true || false // true
let result3 = !true // false
3. 옵셔널 (Optional)
옵셔널이란?
// 일반 변수: nil 불가
var name: String = "홍길동"
// name = nil // 에러!
// 옵셔널: nil 가능
var optionalName: String? = "홍길동"
optionalName = nil // OK
print(optionalName) // Optional("홍길동") 또는 nil
옵셔널 바인딩 (if let)
옵셔널 값을 안전하게 추출하는 방법입니다:
var name: String? = "홍길동"
// if let: 옵셔널 바인딩
if let unwrappedName = name {
// name이 nil이 아니면 이 블록 실행
// unwrappedName: String 타입 (옵셔널 아님)
// name의 값이 unwrappedName에 언래핑되어 할당됨
print("이름: \(unwrappedName)")
// unwrappedName은 이 블록 안에서만 유효
} else {
// name이 nil이면 이 블록 실행
print("이름 없음")
}
// 여러 옵셔널 동시 바인딩
let firstName: String? = "홍"
let lastName: String? = "길동"
if let first = firstName, let last = lastName {
// 둘 다 nil이 아닐 때만 실행
print("이름: \(first)\(last)") // 이름: 홍길동
}
// guard let: 조기 반환 패턴
func greet(name: String?) {
// guard: 조건이 false면 else 블록 실행 후 반환
guard let name = name else {
// name이 nil이면 여기 실행
print("이름 없음")
return // 함수 종료 (guard는 반드시 return/throw/break 필요)
}
// 여기서는 name이 nil이 아님을 보장
// name: String 타입 (언래핑됨)
// guard let으로 추출한 변수는 함수 끝까지 유효
print("안녕하세요, \(name)님!")
// 추가 로직 작성 가능 (들여쓰기 깊이 감소)
}
greet(name: "홍길동") // 안녕하세요, 홍길동님!
greet(name: nil) // 이름 없음
if let vs guard let:
// if let: 옵셔널이 있을 때 처리
func processUser(user: User?) {
if let user = user {
// user 처리 (들여쓰기 깊어짐)
print(user.name)
// 여러 줄 로직...
}
}
// guard let: 옵셔널이 없으면 조기 반환 (권장)
func processUser(user: User?) {
guard let user = user else {
return // nil이면 즉시 종료
}
// 정상 흐름 (들여쓰기 얕음)
print(user.name)
// 여러 줄 로직...
}
여러 조건 체크:
func validateUser(name: String?, age: Int?, email: String?) {
// 모든 값이 nil이 아닌지 한 번에 체크
guard let name = name,
let age = age,
let email = email,
age >= 18, // 추가 조건도 가능
email.contains("@") else {
print("유효하지 않은 사용자")
return
}
// 모든 조건을 통과한 경우
print("유효한 사용자: \(name), \(age)세, \(email)")
}
옵셔널 체이닝
struct User {
var name: String
var email: String?
}
let user: User? = User(name: "홍길동", email: "[email protected]")
// 옵셔널 체이닝
let emailLength = user?.email?.count
print(emailLength) // Optional(17)
// 여러 단계
let firstChar = user?.email?.first?.uppercased()
Nil 병합 연산자 (??)
let name: String? = nil
let displayName = name ?? "Guest"
print(displayName) // Guest
// 체이닝
let email: String? = nil
let backup: String? = nil
let result = email ?? backup ?? "[email protected]"
강제 언래핑 (!)
let name: String? = "홍길동"
// 강제 언래핑 (위험!)
print(name!) // 홍길동
// nil이면 크래시
let nilName: String? = nil
// print(nilName!) // 런타임 에러!
// 암시적 언래핑 옵셔널
var implicitName: String! = "홍길동"
print(implicitName) // 자동 언래핑
4. 타입 변환
// 정수 → 실수
let intValue: Int = 10
let doubleValue: Double = Double(intValue)
// 문자열 → 정수
let str = "123"
if let number = Int(str) {
print(number) // 123
}
// 실패 시 nil
let invalid = Int("abc") // nil
5. 실전 예제
예제: 사용자 정보 처리
struct User {
let name: String
var age: Int
var email: String?
}
func printUserInfo(user: User?) {
guard let user = user else {
print("사용자 없음")
return
}
print("이름: \(user.name)")
print("나이: \(user.age)")
if let email = user.email {
print("이메일: \(email)")
} else {
print("이메일 미등록")
}
}
let user1 = User(name: "홍길동", age: 25, email: "[email protected]")
let user2 = User(name: "김철수", age: 30, email: nil)
printUserInfo(user: user1)
printUserInfo(user: user2)
정리
핵심 요약
- var: 변수(변경 가능), let: 상수(변경 불가)
- 기본 타입: Int, Double, String, Bool
- 옵셔널: nil 가능,
?로 표시 - 옵셔널 바인딩: if let, guard let
- 옵셔널 체이닝:
?.로 안전 접근 - Nil 병합:
??로 기본값
다음 단계
- Swift 함수와 클로저
- Swift 클래스와 구조체
- Swift 프로토콜
관련 글
- Java 변수와 타입 | 기본 타입, 참조 타입, 형변환
- Kotlin 변수와 타입 | val, var, 기본 타입 완벽 정리
- C++ numeric_limits |
- C++ 템플릿 |
- C++ 변수와 자료형 | int, double, string 완벽 정리 [초보자용]