본문 바로가기
swift

스위프트 조건문

by 승환파크 2024. 4. 6.

다른 말로 분기문(Branch Statements)이라고도 불리는 조건문은 프로그램에서 하나 또는 그 이상의 조건값에 따라 특정 구문을 실행하도록 프로그램의 흐름을 분기하는 역할을 한다. 조건문에 사용되는 조건값은 프로그램이 어떻게 분기되고, 어느 부분의 코드가 실행될 지를 결정하는데에 사용된다. 실행 방식에 따라 조건문은 몇 가지 종류로 세분화되는데, 스위프트에서 제공하는 조건문은 크게 세 가지 이다.

  1. if
  2. guard
  3. switch

 

if문

하나 또는 그 이상의 조건을 평가하고 결과에 따라 코드 블록의 실행 여부를 결정하는 if 구문은 대부분의 프로그래밍 언어에서 가장 많이 사용되는 구문 중 하나이다. if 구문은 몇 가지 형태로 바꾸어 사용할 수 있는데, 이들 형태는 모두 코드 블록을 여닫는 중괄호 {}가 사용된다는 공통점을 가진다. 아래는 if 구문의 가장 기본적인 형태로 하나의 if 족너절을 사용하여 조건식의 평가 결과가 참(true)일 때만 코드 블록 내부의 구문을 실행하고, 거짓(false)이라면 코드 블록을 빠져나가 if 블록 다음에 위치한 코드를 수행한다.

if <조건식> {
	<실행할 구문>
}

 

키워드 if 다음에는 조건식이 사용되는데, 이 조건문은 반드시 Bool 타입의 참(true), 거짓(false)를 판단할 수 있는 형태의 구문이어야 한다. 과거 C 스타일의 if 구문에서는 참, 거짓 대신 0이나 1을 사용할 수 있었지만 스위프트에서는 이를 허용하지 않는다. 또한 조건식이 복잡한 경우 소괄호 ()를 사용하여 조건식을 감싸 주어도 되지만, 강제 사항은 아니다. 조건식 다음에는 {}로 둘러싸인 실행 코드 블록이 작성된다. 이 코드 블록 내부에는 주어진 조건이 참일 때 실행할 구문만이 들어가는데, 조건문이 참일 때만 실행된다. 아래 코드는 실제 사용되는 예시이다.

var adult = 19
var age = 15

if age < adult {
	print("미성년자")
}

// 결과값
// 미성년자

 

if ~ else 문

위의 예에서는 조건식이 true/false 중 어느 하나일 때에만 구문을 실행할 수 있었다. 하지만 만약 조건식이 참일 때에는 A 구문을, 참이 아닐 때에는 B 구문을 실행하고 싶다면, 스위프트에서는 else 구문을 제공한다. else 구문은 {}로 이루어지는 실행 블록을 가지는 구문으로, if 구문과 함께 사용되어 조건식의 결과가 참이 아닐 때에만 해당 블록을 실행한다. else 구문에서는 조건식이 사용되지 않기 때문에 if 조건절 없이 단독으로 사용할 수 없다.

if <조건식> {
	<조건이 참일 때 실행할 구문>
} else {
	<조건이 거짓일 때 실행할 구문>
}

 

else 구문에 연결된 코드 블록은 조건식이 참이 아닌 모든 경우에 실행된다. 조건식에 발생 가능한 모든 경우는 수학적으로 참이거나 참이 아닌 경우 둘 밖에 있을 수 없으므로 if와 else 둘 중의 하나에는 반드시 속하게 된다. 다시 말해 if 블록과 else 블록 둘 중의 하나는 반드시 실행된다.

 

아래 코드는 앞에서 살펴본 예제를 else 구문으로 확장한 예시이다.

var adult = 19
var age = 21

if age < adult {
	print("미성년자")
} else {
	print("성인")
}

// 결과값
// 성인

 

앞에서 작성했던 if 구문에 else 절을 추가한 것이다. 미성년자이면서 동시에 성인인 경우나 미성년자가 아니면서 동시에 성인이 아닌 경우는 존재할 수 없으므로 논리적으로 모든 조건식의 결과가 if 또는 else 절 중 하나에 걸리게 된다. 조건문에 사용된 adult와 age의 값에 따라 실행 결과를 출력한다.

 

if ~ else if 문

if 문, if ~ else 문 이외에도 한가지 구문이 있는데 바로 if ~ else if 문이다. 단순히 참, 거짓으로만 판단하기 어려운 여러 개의 조건이 있을 때 주로 사용한다.

if <조건1> {
	<조건1이 참일 때 실행할 구문>
} else if <조건2> {
	<조건2가 참일 때 실행할 구문>
} else {
	<앞의 조건들을 전부 만족하지 않았을 때 실행할 구문>
}

 

else if 구문은 if 절과 함께 사용해야 한다는 점에서 else 절과 비슷하지만 자신만의 조건식을 갖는다는 특성이 있다. else if구문은 조건식이 if 조건절을 만족하지 못한 경우에 호출되어 자신의 조건식을 만족하는지를 체크한다.

 

else if 구문은 else와 달리 여러 번 사용할 수 있다. 따라서 비교해야 할 값이 여러 개일 때 사용하기 좋다. else 구문은 앞에서 진행된 if ~ else if 구문들의 조건 체크가 모두 끝난 후 어느 것에도 속하지 않았을 때에만 실행되어야 하므로 항상 조건문의 맨 마지막에 위치해야 한다.

var browser = "Safari" // 입력받을 브라우저명
var browserName : String // 브라우저 이름을 저장할 변수

if (browser == "IE") {
	browserName = "인터넷 익스플로러"
} else if (browser == "FF") {
	browserName = "파이어폭스"
} else if (browser == "Chrome") {
	browserName = "크롬"
} else if (browser == "Opera") {
	browserName = "오페라"
} else if (browser == "Safari") {
	browserName = "사파리"
} else {
	browserName = "알려지지 않은 브라우저"
}

print("사용하고 계신 브라우저는 \(browserName)입니다.")

// 결과값
// 사용하고 계신 브라우저는 사파리입니다.

 

guard 구문

guard 구문은 if 구문과 마찬가지로 주어진 표현식의 결과가 참인지 거짓인지에 따라 구문의 실행 여부를 결정짓는 방식의 조건문이다. if 구문과의 차이점은 guard 구문에는 else 블록이 필수지만, 표현식의 결과가 참일 때 실행되는 블록이 없다는 점이다.

guard <조건식 또는 표현식> else {
	<조건식 또는 표현식의 결과가 false 일 때 실행 될 코드>
}

 

guard 구문은 주로 후속 코드들이 실행되기 전에 특정 조건을 만족하는지 확인하는 용도로 사용된다. 다시 말해 특정 조건을 만족하지 않을 채로 후속 코드를 실행하면 심각한 오류가 발생할 경우에, 전체 구문을 조기 종료(Early Exit)하기 위한 목적으로 사용되는 것이 guard 구문이다. 따라서 guard 구문의 else 블록에는 이후의 코드 진행을 막아주는 구문이 반드시 포함되어야 한다. return 또는 break 구문 등이 이에 해당한다. guard 구문은 보통 함수나 메소드에 사용되는데, 이때에는 return 구문이 이같은 조기 종료 처리 역할을 한다.

var stopNum = 10

while true {
	stopNum = Int.random(in:1 ... 10)
    
    guard stopNum <= 8 else {
    	print("stopNum = \(stopNum) : 변수가 8보다 큰 수가 들어와 반복문을 종료합니다.")
        break
	}
    
    print("stopNum = \(stopNum) : 변수가 8 보다 작습니다. 반복문을 계속 실행합니다.")
}

// 결과값
// stopNum = 4 : 변수가 8 보다 작습니다. 반복문을 계속 실행합니다.
// stopNum = 1 : 변수가 8 보다 작습니다. 반복문을 계속 실행합니다.
// stopNum = 7 : 변수가 8 보다 작습니다. 반복문을 계속 실행합니다.
// stopNum = 3 : 변수가 8 보다 작습니다. 반복문을 계속 실행합니다.
// stopNum = 9 : 변수가 8 보다 큰 수가 들어와 반복문을 종료합니다.

 

guard 구문을 이용해 while 반복문을 정지 시키는 예제이다. 하지만 실제로는 while 문의 조건문에 'stopNum <= 8' 이라는 조건을 넣어주는 것이 더욱 효율적이다. 반복문 안에서 stopNum에 랜덤한 정수를 대입한다. guard 구문에서 stopNum이 8보다 작거나 같으면 통과시키지만 8보다 크다면 break를 통해 반복문을 종료시킨다. 이처럼 guard 구문의 조건절을 만족시키지 않는다면 else 구문을 통해 다른 동작을 구현할 수 있다.

 

#available 구문

앱을 개발하다 보면 기기의 OS 버전별로 구문을 나누어 작성해야 할 때가 종종 있다. 사용하고자 하는 기능이 OS 버전에 따라 다르게 제공되거나 하위 버전에서는 지원되지 않는 것이 가장 큰 원인이다. 애플에서 제공하는 코코아 터치 프레임워크의 주요 API들은 대부분 iOS 버전이 업그레이드 될 때마다 개량을 거듭해온 것이어서 iOS 버전에 따라 종종 사용이 제한되기 때문에, 특정 API를 사용할 때에는 앺르 개발자용 API 문서를 확인해서 사용 가능한 OS 버전과 기기를 체크해야한다. 이 경우 코드 상에서 해당 처리를 할 수 있게 해주는게 #available 구문이다.

if #available(<플랫폼이름 버전>, <...>, <*>) {
	<해당 버전에서 사용할 수 있는 API 구문>
} else {
	<API를 사용할 수 없는 환경에 대한 처리>
}

 

switch 구문

switch 구문은 앞에서 다룬 if와 guard처럼 분기문의 일종이지만, 처리 방식은 앞에서와 다르다. switch 구문은 입력받은 값을 조건식 여부가 아니라 패턴으로 비교하고 그 결과를 바탕으로 실행 블록을 결정하는 조건문이다. 이 구문은 나열된 패턴들을 순서대로 비교하다가 일치하는 첫 번째 패턴의 코드 블록을 실행한다.

 

switch 구문을 굳이 사용하지 않고 if ~ else if 구문만으로도 필요한 코드 작성은 가능하지만, 다양한 가능성이 있는 여러개의 조건 비교에 효율적으로 대응하기에는 조금 부족한 if 구문의 대안이 switch 구문이라고 할 수 있다.

 

switch 구문의 형태는 아래와 같다.

switch <비교 대상> {
	case <비교 패턴1> :
    	<비교 패턴1이 일치했을 때 실행할 구문>
	case <비교 패턴2>, <비교 패턴3> :
		<비교 패턴2 또는 3이 일치했을 때 실행할 구문>
	default :
    	<어느 비교 패턴과도 일치하지 않았을 때 실행할 구문>
}

 

모든 switch 구문은 case 키워드로 시작하는 여러 가능한 패턴을 나열하는 방식으로 구성된다. 비교 대상과 비교 패턴이 일치할 경우 그에 해당하는 구문이 실행된 후 나머지 case에 대한 비교 없이 switch 구문을 종료하고, switch 구문 다음에 나오는 실행 블록으로 진행한다. 만약 비교 패턴 어느 것과도 일치하지 않았다면, 맨 마지막에 작성된 default 구문의 코드가 실행된다.

 

스위프트의 switch 구문은 일치하는 비교 패턴이 있을 경우 해당 블록의 실행 코드를 처리하고, 더 이상의 비교 없이 전체 분기문을 종료한다. 설사 일치하는 비교 패턴이 여러 개 있더라도 맨 처음 일치하는 case 구문 하나만 실행한다. 오직 하나의 case 구문만 처리하고 나면 더 이상 비교를 진행하지 않는다. 다른 언어에서 switch 구문의 각 case 키워드 블록마다 추가해야하는 break 구문을 스위프트에서 생략할 수 있는 것은 이 때문이다.

let val = 2

switch val {
case 1:
    print("일치한 값은 1입니다.")
case 2:
    print("일치한 값은 2입니다.")
case 2 :
    print("일치한 값은 2가 더 있습니다.")
default :
    print("어느 패턴과도 일치하지 않습니다.")
}

// 결과값
// 일치한 값은 2입니다.

 

위에서 보는 것처럼 일치하는 구문이 두개이지만 위의 구문만 수행되고 종료된다. 이는 일치하는 비교 패턴 하나만 실행한 다음 종료하는 스위프트의 switch 구문 특성 때문이다.

 

switch 구문에는 패턴이 일치하는 case 블록을 실행하는 대신, 그 다음 case 블록으로 실행 흐름을 전달하는 문법이 있는데, 이를 Fall Through라고 한다. 스위프트에서는 다른 언어와 달리 명시적으로 fallthrough 구문을 사용해야 Fall Through가 적용된다.

let sampleChar : Character = "a"

switch sampleChar {
case "a" :
    fallthrough
case "A" :
   	print("글자는 A 입니다.")
default : 
    print("일치하는 글자가 없습니다.")
}

// 결과값
// 글자는 A 입니다.

 

fallthrough 구문이 사용된 case 블록은 비교 패턴이 일치할 경우 인접한 case 블록으로 실행 흐름을 전달한다. fallthrough에 의해 실행 흐름을 전달받은 case 블록은 비교 패턴의 일치 여부와 상관없이 작성된 구문을 실행한 후 switch 구문을 종료한다.

 

switch의 case 구문에서 사용할 수 있는 비교 패턴은 위와 같은 패턴만 있지 않고, 튜플, 객체, 범위 연산자 등 다양하게 사용될 수 있다.

'swift' 카테고리의 다른 글

스위프트 집단 자료형  (1) 2024.04.06
스위프트 제어 전달문  (1) 2024.04.06
스위프트 반복문  (1) 2024.04.05
스위프트 연산자  (1) 2024.04.03
스위프트 자료형  (1) 2024.04.03