조건문(if/switch)과 반복문(for/while)은 문법을 외우는 순간에는 쉬워 보이지만, 실제로는 “언제 if를 쓰고, 언제 while을 걸어야 하는지”가 헷갈리기 시작합니다. 가장 빠르게 감을 잡는 방법은 입력값 검증 예제로 배우는 겁니다. 회원가입처럼 사용자가 값을 입력하고, 그 값이 이상하면 막고, 다시 입력받는 흐름에서 조건문과 반복문이 자연스럽게 같이 쓰이기 때문입니다. 이번 글에서 “문법 설명”보다 예제 상황을 먼저 보여주고, 그 안에서 조건문과 반복문이 어떻게 동작하는지 코드로 해설해드리겠습니다.
숫자 범위 체크
가장 흔한 실전 상황은 이런 겁니다.
-
사용자가 “숫자”를 입력해야 함
-
그런데 문자를 입력할 수도 있음(파싱 실패)
-
숫자여도 범위를 벗어날 수 있음
-
올바른 값이 들어올 때까지 계속 다시 입력받아야 함
여기서 역할이 갈립니다.
-
if: 입력이 올바른지 “판별”
-
while: 올바를 때까지 “반복”
import 'dart:io';
int readIntInRange(String prompt, int min, int max) {
while (true) {
stdout.write(prompt);
final input = (stdin.readLineSync() ?? "").trim();
// 1) 숫자가 맞는지 검사 (조건문 if)
final value = int.tryParse(input);
if (value == null) {
print("오류: 숫자만 입력해 주세요.");
continue; // 다시 입력 받기 (반복으로 되돌림)
}
// 2) 범위가 맞는지 검사 (조건문 if)
if (value < min || value > max) {
print("오류: $min ~ $max 범위로 입력해 주세요.");
continue; // 다시 입력 받기
}
// 3) 여기까지 왔다 = 유효한 입력
return value;
}
}
void main() {
final number = readIntInRange("1~100 입력: ", 1, 100);
print("입력 완료: $number");
}
이 코드에서 초보자가 꼭 잡아야 하는 포인트는 continue입니다.
-
continue는 “아래 코드는 실행하지 말고 while의 처음으로 돌아가라”는 뜻 -
입력 검증에서는 “잘못된 입력이면 다시 받기”가 목적이라
continue가 매우 자주 등장합니다
회원가입 입력 검증
회원가입을 예로 들면, 조건문이 실제로 어떤 식으로 쓰이는지 더 선명해집니다.
-
아이디: 비어있으면 안 됨, 길이 제한, 허용 문자 제한
-
비밀번호: 최소 길이, 영문/숫자 포함
-
나이: 숫자만, 범위 제한
여기서 실무적으로 더 좋은 방식은 “입력 받는 로직”과 “검증 로직”을 분리하는 겁니다.
-
검증 함수는 에러 메시지 또는 null을 반환
-
입력 함수는 while로 재시도를 담당
검증 함수(조건문 if만 담당)
String? validateUsername(String input) {
final value = input.trim();
if (value.isEmpty) return "아이디를 입력해 주세요.";
if (value.length < 4) return "아이디는 4자 이상이어야 합니다.";
if (value.length > 20) return "아이디는 20자 이하로 입력해 주세요.";
final regex = RegExp(r'^[a-zA-Z0-9_]+$');
if (!regex.hasMatch(value)) return "아이디는 영문/숫자/언더스코어(_)만 가능합니다.";
return null; // 통과
}
String? validatePassword(String input) {
final value = input.trim();
if (value.isEmpty) return "비밀번호를 입력해 주세요.";
if (value.length < 8) return "비밀번호는 8자 이상이어야 합니다.";
final hasLetter = RegExp(r'[a-zA-Z]').hasMatch(value);
final hasDigit = RegExp(r'\d').hasMatch(value);
if (!hasLetter || !hasDigit) return "비밀번호는 영문+숫자를 포함해야 합니다.";
return null;
}
String? validateAge(String input) {
final value = input.trim();
if (value.isEmpty) return "나이를 입력해 주세요.";
final age = int.tryParse(value);
if (age == null) return "나이는 숫자만 입력해 주세요.";
if (age < 14) return "만 14세 이상만 가입할 수 있습니다.";
if (age > 120) return "나이를 다시 확인해 주세요.";
return null;
}
여기서 조건문이 하는 일은 단순합니다.
-
“틀린 케이스면 메시지 반환”
-
“모두 통과하면 null 반환”
이 패턴이 익숙해지면, 입력 검증 로직이 훨씬 예측 가능해집니다.
입력 함수(반복문 while만 담당)
import 'dart:io';
String readUntilValid(String prompt, String? Function(String) validator) {
while (true) {
stdout.write(prompt);
final input = stdin.readLineSync() ?? "";
final error = validator(input);
if (error == null) return input.trim();
print("오류: $error");
}
}
-
validator는 “판정만” -
readUntilValid는 “재시도만”
역할이 분리되니까 코드가 커져도 유지보수가 쉬워집니다.
회원가입 흐름(조건문 + 반복문 조합)
void main() {
print("=== 회원가입 ===");
final username = readUntilValid("아이디: ", validateUsername);
final password = readUntilValid("비밀번호: ", validatePassword);
final ageText = readUntilValid("나이: ", validateAge);
final age = int.parse(ageText);
print("\n가입 완료");
print("- 아이디: $username");
print("- 나이: $age");
print("- 비밀번호 길이: ${password.length}");
}
이 구조를 이해하면 “조건문/반복문”이 문법 뿐만 아니라 프로그램 흐름을 전체적으로 이해하는 감각이 생길거예요.
switch + while
switch는 보통 “선택지”를 처리할 때 if보다 훨씬 읽기 좋습니다.
그리고 입력이 잘못되면 다시 선택받아야 하니 while과 붙는 경우가 많습니다.
import 'dart:io';
String readSignupChannel() {
while (true) {
print("가입 경로 선택: 1) 이메일 2) 카카오 3) 네이버");
stdout.write("선택: ");
final choice = (stdin.readLineSync() ?? "").trim();
switch (choice) {
case "1":
return "email";
case "2":
return "kakao";
case "3":
return "naver";
default:
print("오류: 1~3 중에서 선택해 주세요.");
continue;
}
}
}
void main() {
final channel = readSignupChannel();
print("선택된 가입 경로: $channel");
}
여기서 핵심은 switch가 “분기 처리”, while이 “재시도”를 맡고 있다는 점입니다.
요약
-
if: “이 입력이 유효한가?”를 단계적으로 걸러내는 필터
-
while: “유효할 때까지 다시 받기”를 책임지는 루프
-
switch: “선택지 분기”를 간결하게 표현하는 도구
-
continue/break/return: “언제 다시 물어보고, 언제 빠져나갈지”를 결정하는 제어문
결론
조건문과 반복문은 문법 자체를 외우는 것보다, “입력값 검증” 같은 흐름에서 반복적으로 써보는 게 훨씬 빨리 익숙해집니다. 숫자 범위 체크처럼 잘못된 입력을 걸러내는 단계에서는 if가 판별을 담당하고, 올바른 값이 들어올 때까지 다시 받는 과정에서는 while이 재시도를 담당합니다. 선택지가 있는 상황에서는 switch를 붙이면 분기 처리가 깔끔해지고, continue/break/return으로 “다시 물어볼지, 종료할지”를 명확하게 제어할 수 있습니다. 결국 실전에서 중요한 것은 문법 이름이 아니라, 유효하지 않은 입력을 어떻게 차단하고 사용자에게 어떤 안내를 주며 정상 흐름으로 복귀시키는지입니다. 오늘 예제 구조대로 “검증 함수(판정)”와 “입력 루프(재시도)”를 분리해두면, 코드가 커져도 유지보수가 쉬워지고 Flutter Form 같은 UI 환경으로 옮길 때도 그대로 재사용할 수 있습니다.
FAQ
if와 switch는 언제 구분해서 쓰는 게 좋나요?
조건이 범위/조합처럼 다양하게 얽히면 if가 유리하고, 입력값이 “정해진 선택지(1,2,3 / A,B,C)”처럼 명확하게 나뉘면 switch가 읽기 좋습니다. 특히 메뉴 선택, 가입 경로 선택처럼 값이 한정된 경우 switch + default 조합이 실전에서 가장 깔끔합니다.
입력 검증에서 while(true)를 쓰는 게 안전한가요?
패턴 자체는 흔하고 안전합니다. 중요한 건 “반드시 빠져나가는 조건(return/break)이 존재해야” 한다는 점입니다. 예제처럼 유효한 입력이면 return으로 종료되고, 잘못된 입력이면 continue로 다시 받는 구조면 무한 루프가 아니라 “유효 입력을 보장하는 루프”가 됩니다.
continue와 break는 입력 검증에서 어떤 차이가 있나요?
continue는 현재 반복의 나머지 코드를 건너뛰고 “다시 입력 받는 지점(루프의 처음)”으로 돌아갈 때 씁니다. break는 루프 자체를 종료하고 “다음 단계로 진행”할 때 씁니다. 입력 검증에서는 오류일 때 continue, 정상일 때 break/return이 가장 흔한 형태입니다.
숫자 입력은 int.parse와 int.tryParse 중 무엇을 써야 하나요?
검증 단계에서는 tryParse가 더 적합합니다. parse는 실패 시 예외가 발생하므로, 사용자가 문자를 입력했을 때 프로그램이 깨질 수 있습니다. tryParse는 실패하면 null을 돌려주기 때문에 if로 자연스럽게 “숫자가 아님”을 처리할 수 있습니다.
검증 로직을 함수로 분리하는 이유가 뭔가요?
검증 규칙이 늘어날수록 코드가 금방 지저분해지기 때문입니다. “검증 함수는 판정만 하고(에러 메시지 또는 null)”, “입력 함수는 재시도만 한다(while)”처럼 역할을 분리하면, 재사용이 쉬워지고 테스트도 간단해집니다. Flutter Form에서도 validator에 그대로 연결하기 좋습니다.
정규식(RegExp)은 꼭 써야 하나요?
필수는 아니지만, 아이디/이메일/전화번호처럼 “허용 문자와 형식”이 중요한 입력에는 실무에서 자주 사용합니다. 다만 처음부터 복잡한 정규식을 쓰기보다, 길이/공백/숫자 여부 같은 기본 조건을 먼저 걸러낸 뒤 정규식을 마지막 단계로 두면 디버깅이 쉬워집니다.
회원가입에서 비밀번호 확인 같은 “두 값 비교”는 어떻게 처리하는 게 좋나요?
단일 값 검증(아이디, 나이)은 함수 하나로 충분하지만, 비밀번호 확인처럼 두 값의 일치 여부는 “password를 알고 있는 상태”에서 confirm을 검증해야 합니다. 그래서 confirm 검증은 password를 캡처해서 비교하는 방식(클로저)이나, (password, confirm)을 함께 받는 검증 함수로 분리하는 방식이 일반적입니다.
Flutter에서는 콘솔처럼 while로 재입력을 강제할 수 있나요?
UI에서는 보통 while로 재입력을 강제하지 않고, Form validator로 에러 메시지를 보여주고 사용자가 수정하게 하는 UX를 택합니다. 구조는 동일합니다. 콘솔의 “readUntilValid” 대신 Flutter의 “validator + validate()”가 같은 역할을 하며, 검증 함수는 그대로 재사용할 수 있습니다.
입력 검증 에러 메시지는 어떻게 쓰는 게 좋나요?
사용자가 바로 고칠 수 있도록 “무엇이 문제인지”와 “어떻게 고치면 되는지”가 짧게 드러나는 문장이 좋습니다. 예를 들어 “오류”처럼 뭉뚱그리기보다 “나이는 숫자만 입력해 주세요”, “아이디는 4자 이상이어야 합니다”처럼 조건을 그대로 메시지에 반영하는 방식이 실전에서 효과적입니다.