6. 조건문과 반복문: 프로그램 흐름 제어하기
지금까지는 프로그램이 위에서 아래로 차례대로만 흘렀습니다. 마치 정해진 레일 위를 달리는 기차 같았죠. 그런데 진짜 프로그램은 그렇게만 움직이면 심심합니다. 사용자의 입력이 다르면 다른 답을 해야 하고, 같은 작업을 여러 번 반복해야 하며, 어떤 경우에는 중간에 멈추기도 해야 합니다. 이런 흐름을 다루는 것이 바로 제어 흐름(control flow) 입니다.1
이번 장은 아주 중요합니다. 왜냐하면 여기서부터 프로그램이 조금은 생각하는 것처럼 보이기 시작하기 때문입니다. 물론 컴퓨터가 진짜 생각하는 건 아니지만, 조건을 보고 갈라지고, 목표를 향해 반복하는 순간부터 코딩이 훨씬 재미있어집니다.
이 장의 목표는 분명합니다. if, else, switch, for, while, do-while을 사용해 프로그램의 흐름을 직접 제어하는 것입니다.

제어 흐름이란 무엇일까
기본적인 프로그램은 순차적으로 실행됩니다. 한 줄이 끝나면 다음 줄, 또 다음 줄로 이어집니다. 하지만 현실의 문제는 늘 이렇게 단순하지 않습니다.1
예를 들어 이런 상황을 떠올려 봅시다.
점수가 90점 이상이면 A를 준다.
비밀번호가 틀리면 다시 입력받는다.
1부터 10까지 숫자를 모두 출력한다.
메뉴에서 1을 누르면 조회, 2를 누르면 저장을 실행한다.
이런 문제를 풀기 위해 필요한 도구가 두 가지입니다.
첫째는 조건문입니다. 조건에 따라 서로 다른 길로 보내는 문장입니다. 둘째는 반복문입니다. 같은 일을 여러 번 하게 만드는 문장입니다.
쉽게 말해, 조건문은 프로그램의 갈림길이고 반복문은 프로그램의 회전목마입니다. 잘 타면 즐겁고, 잘못 타면 무한 루프라는 어지럼증이 찾아옵니다.
if 문: 조건이 맞으면 실행
가장 기본적인 조건문은 if입니다.
#include <iostream>
using namespace std;
int main() {
int age = 20;
if (age >= 19) {
cout << "성인입니다." << endl;
}
return 0;
}if는 괄호 안의 조건식이 true일 때만 블록을 실행합니다. 거짓이면 그냥 지나갑니다.
여기서 중요한 점은 if가 판단하는 재료가 조건식이라는 것입니다. 지난 장에서 배운 비교 연산자와 논리 연산자가 바로 여기서 활약합니다.
if (score >= 60) {
cout << "합격" << endl;
}이 코드는 "점수가 60 이상인가?"라는 질문에 예라고 답할 때만 실행됩니다.
if-else: 둘 중 하나를 고르기
if만 있으면 조건이 참일 때만 무언가를 할 수 있습니다. 그런데 실제로는 거짓일 때의 처리도 자주 필요합니다. 그럴 때 else를 붙입니다.
#include <iostream>
using namespace std;
int main() {
int num;
cin >> num;
if (num > 0) {
cout << "양수입니다." << endl;
} else {
cout << "0 또는 음수입니다." << endl;
}
return 0;
}이제 프로그램은 둘 중 하나를 반드시 선택합니다. 마치 문 앞 경비원이 "들어오세요" 아니면 "잠깐만요"라고 말하는 것과 비슷합니다.
else if: 선택지가 여러 개일 때
둘 중 하나만 고르면 되는 상황도 있지만, 선택지가 셋 이상인 경우도 많습니다. 그럴 때 else if를 사용합니다.
#include <iostream>
using namespace std;
int main() {
int score;
cin >> score;
if (score >= 90) {
cout << "A" << endl;
} else if (score >= 80) {
cout << "B" << endl;
} else if (score >= 70) {
cout << "C" << endl;
} else {
cout << "F" << endl;
}
return 0;
}이 코드는 위에서 아래로 차례대로 검사합니다. 그리고 처음으로 참이 된 조건 하나만 실행합니다.5
그래서 순서가 중요합니다. 예를 들어 score >= 60을 맨 위에 두고 그 아래에 score >= 90을 쓰면, 95점도 먼저 60 이상에 걸려 버려서 A를 받을 기회를 잃어버립니다. 조건이 여러 개일수록 더 엄격한 조건을 먼저 두는 습관이 좋습니다.
중첩 if: 조건 안에 또 조건 넣기
조건문 안에 또 다른 조건문을 넣을 수도 있습니다.
#include <iostream>
using namespace std;
int main() {
int age = 22;
bool hasTicket = true;
if (age >= 19) {
if (hasTicket) {
cout << "입장 가능합니다." << endl;
} else {
cout << "티켓이 필요합니다." << endl;
}
} else {
cout << "미성년자는 입장할 수 없습니다." << endl;
}
return 0;
}이런 구조는 자연스럽지만, 너무 깊어지면 코드가 숲처럼 우거집니다. 초보자 단계에서는 한 번, 많아도 두 번 정도의 중첩까지만 가도 충분합니다. 들여쓰기가 계속 깊어지면 "이걸 함수로 나눌 때가 다가오고 있구나"라고 느끼면 됩니다.
switch 문: 값이 딱 맞을 때 깔끔하게 분기하기
switch는 하나의 값이 여러 고정된 경우 중 무엇과 일치하는지 검사할 때 유용합니다. if-else if로도 할 수 있지만, 값 비교가 많을 때는 switch가 더 읽기 쉬운 경우가 많습니다.2
#include <iostream>
using namespace std;
int main() {
int day;
cin >> day;
switch (day) {
case 1:
cout << "월요일" << endl;
break;
case 2:
cout << "화요일" << endl;
break;
case 3:
cout << "수요일" << endl;
break;
default:
cout << "잘못된 입력입니다." << endl;
break;
}
return 0;
}switch는 보통 정수형이나 문자형처럼 값이 정확히 일치하는 경우를 다룰 때 씁니다. 반대로 90 이상, 0보다 작음 같은 범위 비교는 if-else가 더 자연스럽습니다.2
즉, 이렇게 기억하면 편합니다.
정확한 값 비교면
switch범위나 복잡한 조건이면
if-else
break가 왜 중요한가
switch에서 break는 정말 중요합니다. 이게 없으면 일치한 case 아래의 코드가 다음 case까지 줄줄이 실행됩니다. 이것을 fall-through라고 합니다.4
switch (day) {
case 1:
cout << "월요일" << endl;
case 2:
cout << "화요일" << endl;
}만약 day가 1이면, 위 코드는 "월요일"만 출력하고 끝나지 않습니다. break가 없어서 아래로 계속 내려가 "화요일"도 출력합니다.
의도적으로 이렇게 쓰는 경우도 있지만, 초보자에게는 대부분 실수입니다. 그래서 처음에는 case 끝에는 break를 붙인다고 거의 습관처럼 익히는 편이 안전합니다.4
여러 case를 같은 처리로 묶기
switch의 매력 중 하나는 여러 값을 같은 처리로 쉽게 묶을 수 있다는 점입니다.
#include <iostream>
using namespace std;
int main() {
char cmd;
cin >> cmd;
switch (cmd) {
case 'q':
case 'Q':
cout << "프로그램을 종료합니다." << endl;
break;
default:
cout << "계속 진행합니다." << endl;
break;
}
return 0;
}'q'든 'Q'든 같은 의미로 처리하고 싶을 때 아주 편합니다. 메뉴 선택, 문자 명령, 간단한 계산기 같은 프로그램에서 자주 쓰이는 패턴입니다.
switch 안에서 변수 선언할 때의 주의점
case 안에서 변수를 선언할 때는 중괄호 블록을 사용하는 것이 안전합니다. 그렇지 않으면 컴파일 오류를 만날 수 있습니다.
switch (choice) {
case 1: {
int amount;
cin >> amount;
cout << amount << endl;
break;
}
case 2:
cout << "다른 메뉴" << endl;
break;
}초보자 입장에서는 간단히 이렇게 기억하면 됩니다. case 안에서 새로운 변수를 만들면 중괄호로 한 번 감싸자. 그러면 마음이 편합니다.
반복문이 필요한 이유
조건문이 갈림길이라면, 반복문은 같은 일을 자동으로 계속하게 만드는 장치입니다.
예를 들어 1부터 5까지 출력하고 싶다고 해 봅시다.
cout << 1 << endl;
cout << 2 << endl;
cout << 3 << endl;
cout << 4 << endl;
cout << 5 << endl;이렇게 써도 되긴 합니다. 하지만 1부터 100까지라면요? 손가락이 먼저 항의할 겁니다. 반복문은 바로 이런 수고를 줄여 줍니다.
for 문: 반복 횟수가 보일 때
for 문은 반복 횟수가 어느 정도 분명할 때 가장 자주 씁니다.
#include <iostream>
using namespace std;
int main() {
for (int i = 1; i <= 5; i++) {
cout << i << endl;
}
return 0;
}for 문은 세 부분으로 이루어집니다.
시작값:
int i = 1반복 조건:
i <= 5변화식:
i++
읽는 법은 이렇습니다.
"i를 1에서 시작해서, i가 5 이하인 동안 반복하고, 한 번 돌 때마다 i를 1 증가시킨다."
처음에는 조금 복잡해 보이지만, 몇 번만 보면 금방 익숙해집니다. for는 반복문의 만능 선수 같은 존재입니다.
for 문으로 합계 구하기
반복문은 단순 출력 말고도 누적 계산에 아주 강합니다.
#include <iostream>
using namespace std;
int main() {
int sum = 0;
for (int i = 1; i <= 100; i++) {
sum += i;
}
cout << "1부터 100까지의 합: " << sum << endl;
return 0;
}여기서 핵심은 sum += i;입니다. 반복할 때마다 현재 숫자를 누적해서 더합니다. 이런 패턴은 정말 많이 등장합니다. 합계, 개수 세기, 평균 계산, 최댓값 찾기 같은 작업의 출발점이 됩니다.
while 문: 조건이 살아 있는 동안 반복
while은 반복 횟수가 미리 정해져 있지 않을 때 잘 어울립니다. 조건이 참인 동안 계속 반복합니다.3
#include <iostream>
using namespace std;
int main() {
int i = 1;
while (i <= 5) {
cout << i << endl;
i++;
}
return 0;
}이 코드는 for 문 예제와 같은 결과를 냅니다. 하지만 느낌은 조금 다릅니다. for가 "몇 번 반복할지"에 더 초점을 둔다면, while은 "조건이 언제까지 참인지"에 더 초점을 둡니다.
예를 들어 비밀번호 재입력, 입력 검증, 파일 끝까지 읽기 같은 작업은 while이 잘 어울립니다.
while 문의 핵심: 조건을 바꾸는 코드가 있어야 한다
while에서 가장 흔한 실수는 조건을 바꾸지 않는 것입니다.
int i = 1;
while (i <= 5) {
cout << i << endl;
}이 코드는 i가 영원히 1이므로 끝나지 않습니다. 바로 무한 루프입니다.3
반복문은 조건만 쓰면 돌아가지 않습니다. 그 조건을 언젠가 거짓으로 만들 코드가 꼭 필요합니다.
int i = 1;
while (i <= 5) {
cout << i << endl;
i++;
}이 한 줄 i++가 루프를 건강하게 끝내는 열쇠입니다.
do-while 문: 일단 한 번은 실행
do-while은 while과 비슷하지만, 조건을 나중에 검사합니다. 그래서 블록이 적어도 한 번은 실행됩니다.3
#include <iostream>
using namespace std;
int main() {
int i = 1;
do {
cout << i << endl;
i++;
} while (i <= 5);
return 0;
}차이가 잘 안 느껴질 수 있으니 이런 예를 보겠습니다.
int i = 10;
while (i < 5) {
cout << "while 실행" << endl;
}
do {
cout << "do-while 실행" << endl;
} while (i < 5);while은 처음 조건이 거짓이므로 한 번도 실행되지 않습니다. 하지만 do-while은 먼저 본문을 실행하고 그다음 조건을 검사하므로, 한 번은 반드시 출력됩니다.3
입력을 최소 한 번은 받아야 하는 메뉴 프로그램이나 입력 검증에서 do-while이 종종 쓰입니다.
그리고 아주 자주 놓치는 문법 하나가 있습니다. do-while의 마지막 while (...) 뒤에는 세미콜론이 필요합니다.
for, while, do-while은 어떻게 고를까
초보자에게 가장 쉬운 선택 기준은 이것입니다.5
반복 횟수가 뚜렷하면
for언제 끝날지 입력이나 조건에 달려 있으면
while최소 한 번은 실행해야 하면
do-while
물론 절대 규칙은 아닙니다. 같은 문제를 여러 방식으로 풀 수도 있습니다. 중요한 것은 문법보다 문제의 모양에 맞는 선택입니다.
break와 continue: 반복문의 리모컨
반복문은 기본적으로 처음부터 끝까지 매 반복을 수행합니다. 하지만 때로는 중간에 바로 빠져나오거나, 이번 한 번만 건너뛰고 싶을 때가 있습니다. 그럴 때 break와 continue를 사용합니다.5
break: 반복문을 즉시 끝내기
#include <iostream>
using namespace std;
int main() {
for (int i = 1; i <= 10; i++) {
if (i == 5) {
break;
}
cout << i << endl;
}
return 0;
}이 코드는 1, 2, 3, 4까지만 출력하고 끝납니다. i == 5가 되는 순간 반복문을 아예 빠져나옵니다.
continue: 이번 차례만 건너뛰기
#include <iostream>
using namespace std;
int main() {
for (int i = 1; i <= 10; i++) {
if (i == 5) {
continue;
}
cout << i << endl;
}
return 0;
}이번에는 5만 빼고 1부터 10까지 출력됩니다. continue는 반복문을 끝내는 것이 아니라 현재 반복의 남은 부분만 건너뛰고 다음 반복으로 넘어갑니다.
둘의 차이는 아주 중요합니다.
break는 반복문 전체 종료continue는 이번 한 바퀴만 건너뜀
조건문과 반복문을 함께 쓰기
진짜 재미는 둘을 섞을 때 시작됩니다. 반복문 안에 조건문을 넣으면, 반복하면서 상황에 따라 다른 행동을 하게 만들 수 있습니다.
#include <iostream>
using namespace std;
int main() {
for (int i = 1; i <= 10; i++) {
if (i % 2 == 0) {
cout << i << "는 짝수" << endl;
} else {
cout << i << "는 홀수" << endl;
}
}
return 0;
}이 코드는 1부터 10까지 돌면서 숫자마다 홀수인지 짝수인지 판단합니다. 반복문이 몸이라면, 조건문은 그 몸이 어떤 동작을 할지 정하는 뇌 같은 역할을 합니다.
중첩 반복문: 반복 안에 반복
반복문 안에 반복문을 넣을 수도 있습니다. 이것을 중첩 반복문이라고 합니다.
#include <iostream>
using namespace std;
int main() {
for (int dan = 2; dan <= 4; dan++) {
for (int i = 1; i <= 9; i++) {
cout << dan << " x " << i << " = " << dan * i << endl;
}
cout << endl;
}
return 0;
}바깥쪽 반복문이 단을 바꾸고, 안쪽 반복문이 1부터 9까지 곱합니다. 처음에는 조금 낯설지만, 표를 만들거나 패턴을 출력할 때 아주 자주 쓰입니다.
다만 중첩이 깊어질수록 머리도 같이 꼬이기 쉽습니다. 초보자라면 두 겹까지만 자연스럽게 다뤄도 아주 잘하고 있는 것입니다.
실전 예제 1: 성적 등급 판정기
범위 비교는 if-else if가 잘 어울립니다.
#include <iostream>
using namespace std;
int main() {
int score;
cout << "점수를 입력하세요: ";
cin >> score;
if (score < 0 || score > 100) {
cout << "잘못된 점수입니다." << endl;
} else if (score >= 90) {
cout << "등급은 A입니다." << endl;
} else if (score >= 80) {
cout << "등급은 B입니다." << endl;
} else if (score >= 70) {
cout << "등급은 C입니다." << endl;
} else if (score >= 60) {
cout << "등급은 D입니다." << endl;
} else {
cout << "등급은 F입니다." << endl;
}
return 0;
}이 예제에서 중요한 부분은 두 가지입니다. 먼저 잘못된 입력을 먼저 걸러 낸다는 점, 그리고 높은 등급부터 차례대로 검사한다는 점입니다. 이런 코드는 실제 프로그램에서도 매우 흔합니다.
실전 예제 2: 간단한 메뉴 프로그램
메뉴 선택은 고정된 값 비교이므로 switch가 잘 어울립니다. 반복해서 메뉴를 보여 주고 싶으니 do-while도 함께 써 보겠습니다.
#include <iostream>
using namespace std;
int main() {
int choice;
do {
cout << "=== 메뉴 ===" << endl;
cout << "1. 게임 시작" << endl;
cout << "2. 설정" << endl;
cout << "3. 종료" << endl;
cout << "선택: ";
cin >> choice;
switch (choice) {
case 1:
cout << "게임을 시작합니다." << endl;
break;
case 2:
cout << "설정 화면입니다." << endl;
break;
case 3:
cout << "프로그램을 종료합니다." << endl;
break;
default:
cout << "잘못된 선택입니다." << endl;
break;
}
cout << endl;
} while (choice != 3);
return 0;
}이 코드는 초보자에게 아주 좋은 종합 연습입니다. 입력을 받고, 조건에 따라 분기하고, 종료할 때까지 반복합니다. 여기까지 오면 프로그램이 꽤 살아 움직이는 느낌이 듭니다.
실전 예제 3: 정답을 맞힐 때까지 반복하기
이번에는 while을 써 보겠습니다.
#include <iostream>
using namespace std;
int main() {
int answer = 7;
int guess = 0;
while (guess != answer) {
cout << "1부터 10 사이 숫자를 맞혀 보세요: ";
cin >> guess;
if (guess < answer) {
cout << "너무 작습니다." << endl;
} else if (guess > answer) {
cout << "너무 큽니다." << endl;
} else {
cout << "정답입니다!" << endl;
}
}
return 0;
}반복 횟수를 미리 모르기 때문에 while이 자연스럽습니다. 사용자가 한 번에 맞힐 수도 있고, 열 번 만에 맞힐 수도 있으니까요.
초보자가 자주 하는 실수
조건문과 반복문은 강력한 만큼 실수도 자주 납니다. 특히 아래 네 가지는 정말 많이 만납니다.
=와==를 혼동한다.switch에서break를 빼먹는다.if나while뒤에 실수로 세미콜론을 붙인다.반복 조건을 바꾸지 않아 무한 루프를 만든다.
하나씩 짧게 보겠습니다.
1. =와 ==를 헷갈리는 실수
if (x = 5) {
cout << "항상 이상하게 동작할 수 있습니다." << endl;
}이 코드는 비교가 아니라 대입입니다. 비교는 ==입니다.
if (x == 5) {
cout << "x는 5입니다." << endl;
}2. switch에서 break를 빼먹는 실수
switch (day) {
case 1:
cout << "월" << endl;
case 2:
cout << "화" << endl;
}day가 1이면 "월" 뒤에 "화"까지 나와 버릴 수 있습니다.
3. 세미콜론 하나가 만든 대형 사고
if (age >= 19);
{
cout << "항상 실행됩니다." << endl;
}if 뒤의 세미콜론 때문에 조건문이 사실상 끝나 버립니다. 중괄호 블록은 그냥 독립적으로 실행됩니다.
반복문에서도 비슷한 사고가 납니다.
while (i < 5);
{
cout << i << endl;
i++;
}이런 코드는 보기보다 훨씬 위험합니다.
4. 무한 루프를 만드는 실수
int i = 0;
while (i < 5) {
cout << i << endl;
}i가 바뀌지 않으니 조건이 계속 참입니다. 반복문을 쓸 때는 항상 스스로에게 물어보세요.
"이 변수는 언제 바뀌지? 그래서 이 루프는 언제 끝나지?"
이 질문만 잘해도 절반은 성공입니다.
읽기 좋은 코드를 위한 습관
문법을 아는 것만큼 중요한 것이 읽기 좋은 코드입니다. 특히 조건문과 반복문은 들여쓰기와 중괄호가 흐름을 보여 주기 때문에 습관이 중요합니다.
실행할 문장이 한 줄이어도 중괄호를 쓰는 습관을 들이세요.
조건식이 길어지면 괄호를 적절히 넣어 뜻을 분명히 하세요.
중첩이 깊어지면 나중에 함수로 분리할 수 있다는 신호로 받아들이세요.
switch의 각case는break로 끝내는 습관을 들이세요.
코드는 컴퓨터에게만 보여 주는 문서가 아닙니다. 미래의 나도 읽습니다. 그리고 미래의 나는 생각보다 자주 "이걸 내가 썼다고?"라는 표정을 짓습니다.
한눈에 정리
이번 장에서 배운 것은 프로그램을 살아 움직이게 만드는 핵심 문법입니다.
if, else, else if는 조건에 따라 다른 길을 고르게 해 줍니다. switch는 하나의 값이 여러 경우 중 어디에 해당하는지 깔끔하게 나누는 데 좋습니다. for는 반복 횟수가 보일 때 편하고, while은 조건 중심의 반복에 잘 맞습니다. do-while은 적어도 한 번은 실행해야 할 때 유용합니다. 여기에 break와 continue를 더하면 반복의 흐름을 더 세밀하게 다룰 수 있습니다.
이제 프로그램은 더 이상 한 줄로만 걷지 않습니다. 때로는 왼쪽으로 꺾고, 때로는 같은 자리를 몇 바퀴 돌고, 때로는 중간에 멈춥니다. 바로 이 순간부터 코딩은 훨씬 더 프로그램다워집니다.
다음 장에서는 이 흐름을 더 깔끔하게 정리하는 방법, 즉 함수로 프로그램을 나누는 법을 배웁니다. 조건문과 반복문으로 움직이게 만든 프로그램을, 이제는 더 읽기 좋고 재사용하기 쉬운 구조로 바꿔 보게 될 것입니다.
참고
1LearnCpp - Control flow introduction
2LearnCpp - Switch statement basics
이 노트는 보도·비평·교육·연구 목적으로 작성되었습니다. 저작권 문의가 있으시면 에서 알려주세요.