핵심 요약
조건문은 분기 기준을, 반복문은 반복 종료 조건을 명확히 해야 하며 사용자 입력은 무한 반복보다 오류를 반환하는 흐름이 다루기 쉽습니다.
검수 범위
if·switch·for·while의 역할과 입력 검증 예제가 실제 앱 흐름에 맞는지 공식 문법 기준으로 확인했습니다.
조건문(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 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 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 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 환경으로 옮길 때도 그대로 재사용할 수 있습니다.
검증 기준과 참고 자료
이 글은 2026-09-08에 아래 공식 문서와 공개 기술 문서를 기준으로 내용과 용어를 다시 검수했습니다. 제품 버전과 기기 제조사에 따라 화면 이름은 달라질 수 있으므로 실제 화면과 공식 문서를 함께 확인하세요.