제어 흐름

토파즈의 제어 흐름 구조를 마스터하세요. 조건문, 반복문, 패턴 매칭, 가드 조건을 통해 프로그램의 실행 흐름을 효과적으로 제어하는 방법을 학습합니다.

제어 흐름은 프로그램이 어떤 순서로 실행되는지를 결정합니다. 토파즈는 강력하고 표현력 있는 제어 흐름 구조를 제공합니다. 🎯

🔀 조건문

if 문

let 나이 = 25
let 점수 = 85

// 기본 if 문
if 나이 >= 18 {
    print("성인입니다")
}

// if-else 문
if 점수 >= 90 {
    print("A등급")
} else {
    print("더 노력이 필요합니다")
}

// if-else if 체인
if 점수 >= 90 {
    print("A등급 - 우수")
} else if 점수 >= 80 {
    print("B등급 - 양호")
} else if 점수 >= 70 {
    print("C등급 - 보통")
} else {
    print("재시험이 필요합니다")
}

// 복합 조건
let 사용자명 = "김토파즈"
let 로그인시도 = 3

if 사용자명.length() > 0 && 로그인시도 < 5 {
    print("로그인을 시도할 수 있습니다")
}

조건식

// v3에서는 ?: 대신 if 표현식을 사용하세요
let 성인여부 = if 나이 >= 18 { "성인" } else { "미성년자" }
let 통과여부 = if 점수 >= 60 { "통과" } else { "탈락" }

// 중첩 조건
let 등급 = if 점수 >= 90 { "A" }
    else if 점수 >= 80 { "B" }
    else if 점수 >= 70 { "C" }
    else { "F" }

// 조건부 값
let 할인율 = if 회원등급 == "VIP" { 0.2 }
    else if 회원등급 == "골드" { 0.1 }
    else { 0.05 }

print("나이: {나이}, 상태: {성인여부}")
print("점수: {점수}, 등급: {등급}")

표현식으로서의 if

// if를 표현식으로 사용
let 메시지 = if 시간 < 12 {
    "좋은 아침입니다!"
} else if 시간 < 18 {
    "좋은 오후입니다!"
} else {
    "좋은 저녁입니다!"
}

// 복잡한 조건부 계산
let 배송비 = if 주문금액 >= 50000 {
    0
} else if 거리 <= 10 {
    3000
} else {
    5000
}

print(메시지)
print("배송비: {배송비}원")

🔄 반복문

for 루프

// 범위 기반 for 루프
for i in 0..5 {
    print("반복 {i}")
}

// 포함 범위 (inclusive)
for i in 1..=10 {
    print("숫자: {i}")
}

// 배열 반복
let 과일들 = ["사과", "바나나", "오렌지", "포도"]
for 과일 in 과일들 {
    print("과일: {과일}")
}

// 인덱스와 값 함께 반복
for (인덱스, 과일) in 과일들.enumerate() {
    print("{인덱스}: {과일}")
}

// 객체 키-값 반복
let 사용자정보 = {
    이름: "김토파즈",
    나이: 25,
    직업: "개발자"
}

for (키, 값) in 사용자정보 {
    print("{키}: {값}")
}

// 단계별 반복
for i in (0..20).step(2) {
    print("짝수: {i}")
}

while 루프

// 기본 while 루프
let mut 카운터 = 0
while 카운터 < 5 {
    print("카운터: {카운터}")
    카운터 += 1
}

// 조건부 while 루프
let mut 입력 = ""
while 입력 != "종료" {
    입력 = input("명령을 입력하세요 (종료하려면 '종료' 입력): ")
    if 입력 != "종료" {
        print("입력받은 명령: {입력}")
    }
}

// 무한 루프 (break 사용)
let mut 시도횟수 = 0
while true {
    시도횟수 += 1
    let 성공 = Math.random() > 0.8
    
    if 성공 {
        print("성공! {시도횟수}번 시도 후 성공")
        break
    }
    
    if 시도횟수 >= 10 {
        print("최대 시도 횟수 초과")
        break
    }
}

루프 제어

// break와 continue
for i in 1..=20 {
    if i % 3 == 0 && i % 5 == 0 {
        print("{i}: FizzBuzz")
        continue
    }
    
    if i % 3 == 0 {
        print("{i}: Fizz")
        continue
    }
    
    if i % 5 == 0 {
        print("{i}: Buzz")
        continue
    }
    
    if i > 15 {
        print("15를 초과했으므로 중단")
        break
    }
    
    print("{i}")
}

// 레이블이 있는 루프
외부루프: for i in 1..=3 {
    for j in 1..=3 {
        if i * j > 6 {
            print("곱이 6을 초과하므로 외부 루프 중단")
            break 외부루프
        }
        print("{i} × {j} = {i * j}")
    }
}

🎭 패턴 매칭 (match)

기본 match 문

let 요일 = "월요일"

match 요일 {
    case "월요일" => print("한 주의 시작!")
    case "금요일" => print("불금!")
    case "토요일" | "일요일" => print("주말!")
    case _ => print("평범한 요일")
}

// 값을 반환하는 match
let 근무형태 = match 요일 {
    case "월요일" | "화요일" | "수요일" | "목요일" | "금요일" => "근무일"
    case "토요일" | "일요일" => "휴일"
    case _ => "알 수 없음"
}

print("오늘은 {근무형태}입니다")

숫자 패턴 매칭

let 점수 = 87

let 등급 = match 점수 {
    case 90..=100 => "A"
    case 80..=89 => "B"
    case 70..=79 => "C"
    case 60..=69 => "D"
    case _ => "F"
}

// 가드 조건 사용
let 평가 = match 점수 {
    case x if x >= 95 => "완벽한 점수!"
    case x if x >= 90 => "우수한 성과"
    case x if x >= 80 => "양호한 결과"
    case x if x >= 70 => "보통 수준"
    case x if x >= 60 => "통과"
    case _ => "재시험 필요"
}

print("점수: {점수}, 등급: {등급}, 평가: {평가}")

구조체/객체 패턴 매칭

let 사용자 = {
    이름: "김토파즈",
    나이: 25,
    직업: "개발자",
    위치: "서울"
}

// 구조 분해 매칭
match 사용자 {
    case { 이름: "김토파즈", 나이, 직업: "개발자" } => {
        print("토파즈 개발자님, 나이: {나이}")
    }
    case { 나이: age, 위치: "서울" } if age < 30 => {
        print("서울의 젊은 사용자")
    }
    case { 직업: "개발자", 위치 } => {
        print("{위치}의 개발자")
    }
    case _ => {
        print("일반 사용자")
    }
}

// 중첩된 객체 매칭
let 주문 = {
    고객: { 이름: "이토파즈", VIP: true },
    항목들: ["노트북", "마우스"],
    총액: 1500000
}

match 주문 {
    case { 고객: { VIP: true }, 총액: amount } if amount > 1000000 => {
        print("VIP 고객 대형 주문: {amount}원")
    }
    case { 고객: { 이름 }, 항목들: items } if items.length() > 1 => {
        print("{이름}님의 복수 아이템 주문")
    }
    case _ => {
        print("일반 주문")
    }
}

배열 패턴 매칭

let 숫자들 = [1, 2, 3, 4, 5]

match 숫자들 {
    case [] => print("빈 배열")
    case [첫번째] => print("요소 하나: {첫번째}")
    case [첫번째, 두번째] => print("두 요소: {첫번째}, {두번째}")
    case [첫번째, ...나머지] => {
        print("첫 번째: {첫번째}, 나머지: {나머지}")
    }
}

// 특정 패턴 매칭
let 점수목록 = [95, 87, 92]

match 점수목록 {
    case [100, ...] => print("만점으로 시작!")
    case [..., 100] => print("만점으로 끝!")
    case [a, b, c] if a > 90 && b > 90 && c > 90 => print("모든 점수가 90점 이상!")
    case 점수들 if 점수들.all(x => x >= 80) => print("모든 점수가 80점 이상")
    case _ => print("일반적인 점수 분포")
}

열거형(enum) 패턴 매칭

enum 상태 {
    대기중,
    처리중(진행률: int),
    완료(결과: string),
    오류(메시지: string)
}

let 현재상태 = 상태.처리중(진행률: 75)

match 현재상태 {
    case 상태.대기중 => print("대기 중입니다")
    case 상태.처리중(진행률: progress) => {
        print("처리 중: {progress}%")
        if progress > 50 {
            print("절반 이상 완료됨")
        }
    }
    case 상태.완료(결과: result) => print("완료: {result}")
    case 상태.오류(메시지: error) => print("오류 발생: {error}")
}

// Option 타입 매칭
let 선택값: Option<string> = Some("토파즈")

match 선택값 {
    case Some(값) => print("값이 있음: {값}")
    case None => print("값이 없음")
}

// Result 타입 매칭
function 나누기(a: int, b: int) -> Result<int, string> {
    if b == 0 {
        return Err("0으로 나눌 수 없습니다")
    }
    return Ok(a / b)
}

match 나누기(10, 2) {
    case Ok(결과) => print("나누기 결과: {결과}")
    case Err(오류) => print("오류: {오류}")
}

🛡️ 가드 조건과 고급 패턴

복합 가드 조건

let 온도 = 25
let 습도 = 60
let 계절 = "여름"

match (온도, 습도, 계절) {
    case (t, h, "여름") if t > 30 && h > 70 => print("매우 덥고 습함")
    case (t, h, "여름") if t > 25 && h < 50 => print("따뜻하고 건조함")
    case (t, _, "겨울") if t < 0 => print("매우 추움")
    case (t, h, _) if t >= 20 && t <= 25 && h >= 40 && h <= 60 => print("쾌적한 날씨")
    case _ => print("보통 날씨")
}

함수형 패턴 매칭

// 재귀적 패턴 매칭으로 리스트 처리
function 리스트합계(목록: [int]) -> int {
    match 목록 {
        case [] => 0
        case [첫번째, ...나머지] => 첫번째 + 리스트합계(나머지)
    }
}

// 이진 트리 순회
enum 트리<T> {
    비어있음,
    노드(값: T, 왼쪽: 트리<T>, 오른쪽: 트리<T>)
}

function 트리탐색<T>(트리: 트리<T>) {
    match 트리 {
        case 트리.비어있음 => {
            // 아무것도 하지 않음
        }
        case 트리.노드(값: value, 왼쪽: left, 오른쪽: right) => {
            트리탐색(left)
            print("노드 값: {value}")
            트리탐색(right)
        }
    }
}

print("리스트 합계: {리스트합계([1, 2, 3, 4, 5])}")  // 15

⚡ 고급 제어 흐름 패턴

루프와 패턴 매칭 결합

let 작업목록 = [
    { 타입: "이메일", 우선순위: 1, 내용: "회의 일정 확인" },
    { 타입: "전화", 우선순위: 3, 내용: "고객 상담" },
    { 타입: "문서", 우선순위: 2, 내용: "보고서 작성" }
]

for 작업 in 작업목록 {
    match 작업 {
        case { 타입: "이메일", 우선순위: 1, 내용 } => {
            print("긴급 이메일 처리: {내용}")
        }
        case { 타입: type, 우선순위: priority, 내용 } if priority <= 2 => {
            print("중요 {type} 작업: {내용}")
        }
        case { 타입, 내용 } => {
            print("일반 {타입} 작업: {내용}")
        }
    }
}

예외 처리와 제어 흐름

// try-catch 스타일의 에러 처리
function 안전한파일읽기(파일명: string) -> Result<string, string> {
    if !파일명.endsWith(".txt") {
        return Err("텍스트 파일만 지원됩니다")
    }
    
    // 파일 읽기 시뮬레이션
    if Math.random() > 0.7 {
        return Err("파일을 찾을 수 없습니다")
    }
    
    return Ok("파일 내용입니다")
}

// 에러 처리를 포함한 제어 흐름
for 파일명 in ["data.txt", "config.json", "readme.txt"] {
    match 안전한파일읽기(파일명) {
        case Ok(내용) => {
            print("성공적으로 읽음: {파일명}")
            print("내용: {내용}")
            // 성공 시 다음 파일 처리 계속
        }
        case Err(오류메시지) => {
            print("오류 ({파일명}): {오류메시지}")
            if 오류메시지.contains("지원되지") {
                print("지원되지 않는 파일 형식, 건너뜀")
                continue  // 다음 파일로 계속
            } else {
                print("심각한 오류, 처리 중단")
                break     // 전체 처리 중단
            }
        }
    }
}

조건부 실행 체인

// 조건부 체이닝
function 사용자처리(사용자id: int) -> Result<string, string> {
    let 사용자데이터 = match 데이터베이스에서사용자가져오기(사용자id) {
        case Ok(데이터) => 데이터
        case Err(오류) => return Err("사용자 조회 실패: {오류}")
    }
    
    let 검증결과 = match 사용자검증(사용자데이터) {
        case Ok(_) => ()
        case Err(오류) => return Err("검증 실패: {오류}")
    }
    
    let 처리결과 = match 사용자데이터처리(사용자데이터) {
        case Ok(결과) => 결과
        case Err(오류) => return Err("처리 실패: {오류}")
    }
    
    return Ok("처리 완료: {처리결과}")
}

// 모나딕 체이닝 스타일
function 모나딕처리(사용자id: int) -> Result<string, string> {
    return 데이터베이스에서사용자가져오기(사용자id)
        .andThen(사용자검증)
        .andThen(사용자데이터처리)
        .map(결과 => "처리 완료: {결과}")
}

🎯 최적화와 베스트 프랙티스

1. 조건문 최적화

// 나쁜 예: 중복된 조건
let 점수 = 85
if 점수 >= 90 {
    print("A등급")
} else {
    if 점수 >= 80 {
        print("B등급")
    } else {
        if 점수 >= 70 {
            print("C등급")
        } else {
            print("F등급")
        }
    }
}

// 좋은 예: match 사용
let 등급 = match 점수 {
    case 90..=100 => "A"
    case 80..=89 => "B"
    case 70..=79 => "C"
    case _ => "F"
}
print("{등급}등급")

2. 조기 반환 패턴

function 사용자등록(이름: string, 이메일: string, 나이: int) -> Result<string, string> {
    // 조기 검증 및 반환
    if 이름.length() == 0 {
        return Err("이름이 필요합니다")
    }
    
    if !이메일.contains("@") {
        return Err("유효한 이메일이 필요합니다")
    }
    
    if 나이 < 0 || 나이 > 120 {
        return Err("유효한 나이가 필요합니다")
    }
    
    // 모든 검증이 통과된 경우에만 처리
    let 사용자 = 새사용자생성(이름, 이메일, 나이)
    return Ok("사용자 등록 완료: {사용자.id}")
}

3. 패턴 매칭 활용

// 복잡한 비즈니스 로직을 패턴으로 표현
enum 주문상태 {
    생성됨,
    결제완료,
    배송중,
    배송완료,
    취소됨
}

function 주문처리(상태: 주문상태, 결제금액: int, VIP여부: bool) -> string {
    match (상태, 결제금액, VIP여부) {
        case (주문상태.생성됨, _, _) => "결제를 진행해주세요"
        case (주문상태.결제완료, amount, true) if amount > 100000 => {
            "VIP 고객 특급 배송 준비"
        }
        case (주문상태.결제완료, amount, _) if amount > 50000 => {
            "일반 배송 준비"
        }
        case (주문상태.결제완료, _, _) => "표준 배송 준비"
        case (주문상태.배송중, _, true) => "VIP 배송 추적 서비스"
        case (주문상태.배송중, _, _) => "배송 중"
        case (주문상태.배송완료, _, _) => "배송 완료"
        case (주문상태.취소됨, _, _) => "주문 취소됨"
    }
}

토파즈의 제어 흐름은 강력하고 표현력이 뛰어납니다. 조건문, 반복문, 패턴 매칭을 적절히 조합하여 읽기 쉽고 유지보수하기 쉬운 코드를 작성하세요! 🚀