TIL: guard 문

Royce·2025년 3월 14일

Swift 문법

목록 보기
15/63

guard

  • Swift의 guard 문은 특정 조건을 만족하지 않으면 실행을 중단하고 빠져나가는 제어문이다
  • 주로 빠른 종료(Early Exit)를 위해 사용되며, 코드의 가독성을 높이는 데 도움일 준다

guard 문의 기본 문법

guard 조건 else {
    // 조건이 false일 때 실행할 코드 (예: 함수 종료, return, throw, break 등)
}
  • guard 문의 조건을 평가하고
    • true(조건 만족) -> 다음 코드 계속 실행
    • false(조건 불만족) -> else 블록 실행 후 코드 종료(return, throw, break 필수)

guard 문의 특징

  1. "조건을 만족하지 않으면" 코드 블록을 실행하고 즉시 종료
  2. if 문과 달리 "중첩된 블록을 줄일 수 있어" 코드 가독성이 향상된다
  3. else 블록 내부에 return, throw, break, continue 중 하나를 반드시 포함해야 한다
  4. 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)   // 이름이 없습니다.
  • namenil 이면 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)  // 지수님, 환영합니다! (나이: 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

비교 항목ifguard
조건이 참일 때코드 실행코드 실행
조건이 거짓일 때중첩 코드 발생즉시 빠져나감 (Early Exit)
옵셔널 바인딩중첩된 코드 필요바인딩된 값이 이후 코드에서 사용 가능
가독성코드가 길어질 가능성 있음간결하고 깔끔함
profile
iOS 개발자 지망생

0개의 댓글