guard 문
- Swift의
guard 문은 특정 조건을 만족하지 않으면 실행을 중단하고 빠져나가는 제어문이다
- 주로 빠른 종료(Early Exit)를 위해 사용되며, 코드의 가독성을 높이는 데 도움일 준다
guard 문의 기본 문법
guard 조건 else {
}
guard 문의 조건을 평가하고
true(조건 만족) -> 다음 코드 계속 실행
false(조건 불만족) -> else 블록 실행 후 코드 종료(return, throw, break 필수)
guard 문의 특징
- "조건을 만족하지 않으면" 코드 블록을 실행하고 즉시 종료
if 문과 달리 "중첩된 블록을 줄일 수 있어" 코드 가독성이 향상된다
else 블록 내부에 return, throw, break, continue 중 하나를 반드시 포함해야 한다
guard 문을 통과하면 조건을 만족하는 변수는 이후에도 계속 사용 가능(Optional Unwrapping 가능)
if 문과 guard 문 비교
1. if 문을 사용한 코드
func checkNumber(_ number: Int?) {
if let num = number {
print("입력된 숫자는 \(num)입니다.")
} else {
print("숫자가 없습니다.")
return
}
print("이 코드는 옵셔널 해제 후 실행됨")
}
checkNumber(5)
checkNumber(nil)
입력된 숫자는 5입니다.
이 코드는 옵셔널 해제 후 실행됨
숫자가 없습니다.
if 문 안에서 num 이 선언되었기 때문에 else 블록에서 빠져나가지 않으면 코드가 중첩될 수 있다
2. guard 문을 사용한 코드
func checkNumber(_ number: Int?) {
guard let num = number else {
print("숫자가 없습니다.")
return
}
print("입력된 숫자는 \(num)입니다.")
print("이 코드는 옵셔널 해제 후 실행됨")
}
checkNumber(5)
checkNumber(nil)
입력된 숫자는 5입니다.
이 코드는 옵셔널 해제 후 실행됨
숫자가 없습니다.
guard 를 사용하면 옵셔널 해제 후 코드가 자연스럽게 진행된다 (코드 중첩 제거)
return 으로 함수가 즉시 종료되므로, 이후 코드가 깔끔하게 실행된다
guard 문의 다양한 활용 예제
1. 옵셔널 바인딩(Optional Unwrapping)
guard 를 사용하여 옵셔널 값을 안전하게 해제할 수 있다
func printUserName(_ name: String?) {
guard let userName = name else {
print("이름이 없습니다.")
return
}
print("안녕하세요, \(userName)님!")
}
printUserName("민수")
printUserName(nil)
name 이 nil 이면 guard 문에서 빠르게 종료 (return 실행)
- 이후 코드에서는
userName 이 안전하게 해제되어 사용 가능하다
2. 여러 개의 조건을 검증하는 guard 문
guard 를 사용하여 여러 개의 조건을 한 번에 확인할 수 있다
func validateUser(name: String?, age: Int?) {
guard let userName = name, let userAge = age, userAge >= 18 else {
print("유효하지 않은 사용자입니다.")
return
}
print("\(userName)님, 환영합니다! (나이: \(userAge))")
}
validateUser(name: "지수", age: 20)
validateUser(name: nil, age: 25)
validateUser(name: "철수", age: 16)
guard 문에서 여러 개의 변수를 한 번에 옵셔널 바인딩 가능
userName >= 18 조건까지 한 번에 검사할 수 있어 코드가 간결하다
3. 반복문에서 guard + continue 사용
- 반복문에서 특정 조건을 만족하지 않으면 건너뛸 수도 있다
let numbers = [1, 2, nil, 4, nil, 6]
for num in numbers {
guard let validNumber = num else {
print("유효하지 않은 값 건너뜀")
continue
}
print("유효한 값: \(validNumber)")
}
유효한 값: 1
유효한 값: 2
유효하지 않은 값 건너뜀
유효한 값: 4
유효하지 않은 값 건너뜀
유효한 값: 6
nil 값이 나오면 guard 문에서 continue 를 실행하여 해당 요소를 건너뛴다
4. guard + throw 를 사용한 에러 처리
guard 를 사용하여 잘못된 값이 들어오면 예외를 발생시킬 수 있다
enum LoginError: Error {
case invalidCredentials
}
func login(username: String?, password: String?) throws {
guard let user = username, let pass = password, pass.count >= 6 else {
throw LoginError.invalidCredentials
}
print("\(user)님, 로그인 성공!")
}
do {
try login(username: "admin", password: "123456")
try login(username: nil, password: "123456")
} catch {
print("로그인 실패: \(error)")
}
admin님, 로그인 성공!
로그인 실패: invalidCredentials
guard 문에서 throw를 사용하여 예외를 발생시킨다
do-catch 구문으로 예외를 안전하게 처리 가능
guard 문 사용 시 주의할 점
⚠️ else 블록에서 반드시 종료문(return, throw, break, continue)을 포함해야 한다
func checkValue(_ value: Int?) {
guard let number = value else {
print("값이 없습니다.")
}
}
올바른 예시
func checkValue(_ value: Int?) {
guard let number = value else {
print("값이 없습니다.")
return
}
print("값: \(number)")
}
guard 문 vs if 문
| 비교 항목 | if 문 | guard 문 |
|---|
| 조건이 참일 때 | 코드 실행 | 코드 실행 |
| 조건이 거짓일 때 | 중첩 코드 발생 | 즉시 빠져나감 (Early Exit) |
| 옵셔널 바인딩 | 중첩된 코드 필요 | 바인딩된 값이 이후 코드에서 사용 가능 |
| 가독성 | 코드가 길어질 가능성 있음 | 간결하고 깔끔함 |