4-3 반복문 while: 조건 기반 반복 실행

4-3 반복문 while: 조건 기반 반복 실행

← 목차로 돌아가기

썸네일

프로그래밍에서 특정 작업을 여러 번 반복해야 할 때, 우리는 ‘반복문’을 사용합니다. 지난 장에서 for 반복문을 통해 시퀀스 데이터를 순회하는 방법을 배웠다면, 이번 장에서는 ‘특정 조건이 참인 동안’ 코드를 반복 실행하는 `while` 반복문에 대해 깊이 있게 알아보겠습니다. `while` 루프는 조건만 만족하면 무한히 반복될 수 있어, 프로그래머의 세심한 주의가 필요한 강력한 도구입니다.

핵심 요약

  • while 반복문: 특정 조건이 참(True)인 동안 코드 블록을 반복 실행하는 파이썬 문법입니다.
  • 조건 기반: `for` 루프가 정해진 횟수나 시퀀스 요소를 순회하는 반면, `while`은 조건식의 결과에 따라 반복 여부가 결정됩니다.
  • 무한 루프 방지: `while` 조건이 항상 참이 되지 않도록, 반복문 내부에서 조건에 영향을 주는 변화를 주어야 합니다.
  • 실용성: 사용자 입력 처리, 게임 루프, 특정 조건 충족 시까지 대기하는 시나리오 등에서 유용하게 사용됩니다.

반복문 while이란 무엇이며, 언제 사용해야 할까요?

반복문 `while`은 특정 조건이 참(True)인 동안 주어진 코드 블록을 계속해서 실행하는 파이썬의 제어 구조입니다. 제가 현업에서 데이터 처리 자동화 스크립트를 작성할 때, 특정 파일이 서버에 업로드될 때까지 기다리거나, 사용자로부터 올바른 입력이 들어올 때까지 반복적으로 요청해야 하는 경우가 많습니다. 이때 `for` 루프처럼 정해진 횟수나 컬렉션의 항목을 순회하는 방식으로는 해결하기 어렵습니다. 이러한 ‘조건 기반 반복’ 시나리오에 `while` 루프가 빛을 발합니다.

예를 들어, 사용자에게 “종료”를 입력할 때까지 계속해서 메시지를 받고 싶다면, 몇 번을 입력할지 미리 알 수 없으므로 `while` 루프를 사용하는 것이 적절합니다. 제가 예전에 Tkinter를 이용해 간단한 GUI 툴을 만들 때, 사용자의 특정 버튼 클릭을 기다리는 메인 루프도 사실상 `while True`와 같은 무한 루프 형태로 동작합니다. 이는 프로그램의 생명주기를 조건에 따라 관리하는 매우 기본적인 패턴입니다.

while 반복문의 기본 구조와 동작 원리

`while` 반복문은 `while` 키워드 뒤에 조건식을 작성하고, 그 아래 들여쓰기 된 코드 블록을 조건이 참인 동안 반복 실행합니다.

# while 반복문의 기본 구조
카운트 = 0
while 카운트 < 5:  # 조건식: 카운트가 5보다 작은 동안
    print(f"현재 카운트: {카운트}")
    카운트 += 1  # 조건에 영향을 주는 변화 (반복 종료를 위해 필수)
print("반복문 종료!")

이 코드가 하는 일: `카운트` 변수를 0으로 초기화하고, `카운트`가 5보다 작을 때마다 현재 카운트를 출력한 후 1씩 증가시킵니다. `카운트`가 5가 되는 순간 조건식이 거짓이 되어 반복문이 종료됩니다.

동작 원리는 간단합니다. 파이썬 인터프리터는 먼저 `while` 뒤의 조건식을 평가합니다. 만약 조건식이 `True`이면, `while` 블록 안의 코드를 실행합니다. 블록 안의 코드 실행이 끝나면 다시 조건식으로 돌아가 재평가하고, 이 과정을 조건식이 `False`가 될 때까지 반복합니다. 이 과정에서 비교 연산자의 역할이 매우 중요합니다. 조건식이 `False`가 되어야만 반복문이 끝난다는 점을 기억하세요.

무한 루프: 주의할 점과 방지 방법

`while` 반복문 내부에서 조건에 변화를 주지 않으면 ‘무한 루프’에 빠질 수 있으며, 이는 프로그램이 멈추는 원인이 됩니다. 제가 처음 파이썬을 배울 때 가장 많이 저지른 실수가 바로 이 무한 루프였습니다. 단순히 `카운트 += 1` 한 줄을 빼먹어서 컴퓨터가 멈추는 경험은 꽤 흔합니다.

무한 루프의 예시:

# 의도적인 무한 루프 (주의!)
# count = 0
# while count < 5:
#     print(f"현재 카운트: {count}")
#     # count += 1  <-- 이 줄이 없으면 무한 루프!
# print("반복문 종료!")

이 코드는 `count`가 영원히 5보다 작으므로, “현재 카운트: 0″을 계속 출력하며 끝나지 않습니다. 만약 이런 상황에 직면했다면, 터미널이나 IDE에서 `Ctrl+C`를 눌러 강제로 프로그램을 종료해야 합니다. 무한 루프를 방지하려면, 반드시 `while` 반복문 내부에 조건식의 결과에 영향을 주는 코드를 포함해야 합니다.

때로는 의도적으로 무한 루프를 만들고, 특정 조건이 충족될 때 `break` 문을 사용하여 루프를 종료시키는 패턴도 사용합니다. 이는 break와 continue 챕터에서 더 자세히 다루겠습니다.

`else` 블록과 함께 사용하는 while 문

`while` 반복문은 `else` 블록을 함께 사용할 수 있으며, 이는 `while` 루프가 정상적으로 종료되었을 때만 실행됩니다.

# while-else 문
i = 0
while i < 3:
    print(f"while 블록 실행 중: {i}")
    i += 1
else:
    print("while 루프가 정상적으로 완료되었습니다.")

print("\n--- break로 종료되는 경우 ---")
j = 0
while j < 3:
    print(f"while 블록 실행 중: {j}")
    if j == 1:
        print("break 문으로 루프를 중간에 종료합니다.")
        break  # break 문으로 종료되면 else 블록은 실행되지 않음
    j += 1
else:
    print("while 루프가 정상적으로 완료되었습니다. (이 메시지는 출력되지 않음)")

이 코드가 하는 일: 첫 번째 `while` 루프는 `i`가 0, 1, 2일 때 실행되고 `i`가 3이 되면 조건이 거짓이 되어 정상적으로 종료됩니다. 따라서 `else` 블록의 메시지가 출력됩니다. 두 번째 `while` 루프는 `j`가 1일 때 `break` 문을 만나 중간에 종료되므로 `else` 블록의 메시지는 출력되지 않습니다. 이 `else` 블록은 반복문이 끝까지 실행되었는지 여부를 확인하는 유용한 방법으로, 파일 처리 등에서 특정 조건을 찾지 못하고 루프가 끝났을 때 알림을 주는 용도로 활용할 수 있습니다.

실전 예제: 사용자 입력 유효성 검사

`while` 루프는 사용자로부터 올바른 입력을 받을 때까지 반복적으로 요청하는 ‘입력 유효성 검사’에 매우 효과적입니다. 제가 개발하는 GUI 프로그램에서는 사용자의 잘못된 입력 때문에 프로그램이 오작동하는 것을 막기 위해 이 패턴을 자주 사용합니다. 2024년 기준, 웹 서비스의 백엔드에서도 사용자의 요청 데이터를 검증할 때 유사한 로직이 적용됩니다.

# 사용자 입력 유효성 검사 예제
while True:
    try:
        나이 = int(input("나이를 입력해주세요: "))
        if 나이 > 0 and 나이 <= 120:
            print(f"입력된 나이: {나이}세")
            break  # 올바른 입력이므로 루프 종료
        else:
            print("나이는 1에서 120 사이여야 합니다. 다시 입력해주세요.")
    except ValueError:
        print("유효한 숫자를 입력해주세요.")

이 코드가 하는 일: `while True`로 무한 루프를 시작하고, 사용자에게 나이를 입력받습니다. try-except 블록을 사용하여 숫자가 아닌 입력에 대한 예외 처리를 합니다. 입력된 나이가 1에서 120 사이인 경우에만 `break`로 루프를 종료하고, 그렇지 않으면 오류 메시지를 출력하며 다시 입력을 요청합니다. 이처럼 `while` 루프는 우리가 원하는 조건이 충족될 때까지 기다리거나 작업을 수행하는 데 필수적인 도구입니다.

종합 예제: 간단한 숫자 카운트다운 프로그램

이번 장에서 배운 `while` 루프의 개념들을 총망라하여 간단한 카운트다운 프로그램을 만들어 보겠습니다. 사용자가 시작 숫자를 입력하면, 0까지 1초 간격으로 카운트다운하는 프로그램입니다.

import time # 시간 관련 기능을 사용하기 위해 time 모듈 임포트

print("숫자 카운트다운 프로그램")

# 사용자에게 시작 숫자 입력받기
시작_숫자 = -1 # 초기값 설정 (유효하지 않은 값으로 시작)
while 시작_숫자 <= 0:
    try:
        시작_숫자 = int(input("카운트다운을 시작할 양의 정수를 입력하세요: "))
        if 시작_숫자 <= 0:
            print("양의 정수를 입력해야 합니다. 다시 시도해주세요.")
    except ValueError:
        print("유효한 숫자가 아닙니다. 다시 시도해주세요.")

# 카운트다운 실행
print(f"\n{시작_숫자}부터 카운트다운을 시작합니다!")
현재_숫자 = 시작_숫자
while 현재_숫자 >= 0:
    print(현재_숫자)
    time.sleep(1) # 1초 대기
    현재_숫자 -= 1 # 1씩 감소
    
print("카운트다운 종료!")
print("프로그램을 마칩니다.")

이 코드가 하는 일: 먼저 `time` 모듈을 임포트하여 시간 지연 기능을 사용합니다. 사용자가 양의 정수를 입력할 때까지 `while` 루프를 반복하며 입력 유효성을 검사합니다. 올바른 숫자가 입력되면, 또 다른 `while` 루프를 사용하여 해당 숫자부터 0까지 1초 간격으로 숫자를 출력하며 카운트다운합니다. 이 예제는 `while` 루프의 조건 기반 반복, 입력 유효성 검사, 그리고 외부 모듈 (`time`)과의 연동을 명확하게 보여줍니다.

자주 묻는 질문 (FAQ)

Q1: `for` 루프와 `while` 루프는 언제 각각 사용해야 하나요?

A1: `for` 루프는 반복 횟수가 명확하거나, 리스트나 문자열과 같은 특정 시퀀스의 모든 요소를 순회해야 할 때 주로 사용합니다. 반면 `while` 루프는 특정 조건이 참인 동안 반복해야 할 때, 즉 반복 횟수를 미리 알 수 없을 때 적합합니다. 예를 들어, 사용자 입력에 따라 반복을 멈추거나, 특정 상태가 될 때까지 기다릴 때 유용합니다.

Q2: `while True`는 무한 루프인데, 왜 사용하는 경우가 있나요?

A2: `while True`는 의도적으로 무한 루프를 만들어 프로그램의 메인 루프나 특정 서비스 루프를 구성할 때 사용합니다. 이때는 루프 내부에 반드시 `if` 조건문과 `break` 문을 함께 사용하여, 특정 조건이 만족될 때 루프를 빠져나오도록 설계해야 합니다. 예를 들어, 게임의 메인 루프나 서버 프로그램의 요청 대기 루프 등이 이러한 방식으로 구현될 수 있습니다.

Q3: `while` 루프 안에서 변수를 업데이트하는 것을 잊으면 어떻게 되나요?

A3: `while` 루프의 조건식에 사용되는 변수를 루프 내부에서 업데이트하는 것을 잊으면, 조건식이 계속해서 참(True)으로 유지되어 프로그램이 ‘무한 루프’에 빠지게 됩니다. 이는 CPU 자원을 불필요하게 소모하고, 프로그램이 응답하지 않게 만들어 강제로 종료해야 하는 상황을 초래합니다. 항상 조건식을 거짓으로 만들 수 있는 변화 로직을 포함했는지 확인해야 합니다.

참고 자료

  1. [1] Python 공식 튜토리얼 — 제어 흐름 도구와 함수 정의 — https://docs.python.org/ko/3/tutorial/controlflow.html

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다