이미지 로딩 중...
AI Generated
2025. 11. 17. · 3 Views
Bash 반복문 완벽 마스터하기
쉘 스크립트의 꽃, 반복문을 처음부터 끝까지 완벽하게 정복해보세요. for, while, until 루프부터 break와 continue를 활용한 제어까지, 실무에서 바로 쓸 수 있는 모든 반복문 패턴을 친절하게 알려드립니다.
목차
1. for 루프 기본 문법
시작하며
여러분이 서버에서 100개의 로그 파일을 하나씩 확인해야 한다고 상상해보세요. 파일을 하나하나 열어서 검사하려면 얼마나 오래 걸릴까요?
손이 너무 아프겠죠? 이런 반복적인 작업을 자동화하지 못하면, 개발자의 소중한 시간이 단순 작업에 낭비됩니다.
실수도 늘어나고, 야근도 늘어나죠. 바로 이럴 때 필요한 것이 for 루프입니다.
단 몇 줄의 코드로 수백, 수천 개의 작업을 자동으로 처리할 수 있습니다.
개요
간단히 말해서, for 루프는 같은 작업을 여러 번 반복해주는 자동화 도구입니다. 실무에서 파일들을 일괄 처리하거나, 여러 서버에 동시에 명령을 실행하거나, 데이터를 순차적으로 처리할 때 필수적입니다.
예를 들어, 백업 파일들의 이름을 일괄 변경하거나 여러 디렉토리를 순회하며 정리하는 작업에 매우 유용합니다. 기존에는 같은 명령어를 복사-붙여넣기 했다면, 이제는 for 루프 하나로 모든 작업을 자동화할 수 있습니다.
for 루프는 세 가지 핵심 요소로 구성됩니다: 반복할 대상 목록, 각 항목을 담을 변수, 그리고 실행할 명령입니다. 이 세 가지만 이해하면 어떤 반복 작업도 자동화할 수 있습니다.
코드 예제
# 기본 for 루프: 여러 파일을 순회하며 처리
for file in document.txt report.pdf image.png
do
# 각 파일의 정보를 출력
echo "처리 중: $file"
# 파일 크기 확인
ls -lh "$file"
echo "---"
done
# 실행 결과:
# 처리 중: document.txt
# -rw-r--r-- 1 user user 1.2K ...
설명
이것이 하는 일: for 루프는 여러분이 제공한 목록에서 항목을 하나씩 꺼내서 처리하고, 목록이 끝날 때까지 반복합니다. 첫 번째로, for file in document.txt report.pdf image.png 부분은 처리할 파일 목록을 정의합니다.
여기서 file은 변수명으로, 여러분이 원하는 대로 바꿀 수 있습니다. 마치 상자의 이름을 정하는 것과 같죠.
이 변수에 목록의 각 항목이 순서대로 담깁니다. 그 다음으로, do와 done 사이의 코드가 각 항목마다 실행됩니다.
$file은 현재 처리 중인 항목을 가리킵니다. 첫 번째 반복에서는 document.txt가, 두 번째에는 report.pdf가 담기는 식입니다.
마지막으로, 목록의 모든 항목을 처리하면 루프가 자동으로 종료됩니다. 별도로 멈추라고 말하지 않아도 알아서 끝나죠.
여러분이 이 코드를 사용하면 수십 개의 파일도 몇 초 만에 처리할 수 있습니다. 사람이 하나씩 처리하면 실수할 수도 있지만, 스크립트는 정확하게 동일한 작업을 반복합니다.
시간 절약, 정확성 향상, 자동화라는 세 마리 토끼를 동시에 잡을 수 있습니다.
실전 팁
💡 변수명은 의미 있게 지으세요. i보다는 file, user, server처럼 명확한 이름을 사용하면 나중에 코드를 읽기 쉽습니다.
💡 파일명에 공백이 있을 수 있으니 반드시 "$file"처럼 변수를 큰따옴표로 감싸세요. 안 그러면 공백이 있는 파일명이 여러 개로 쪼개져서 오류가 발생합니다.
💡 목록이 길면 줄바꿈을 해도 됩니다: for file in *.txt *.log *.conf 대신 백슬래시로 이어쓰기를 하면 가독성이 좋아집니다.
💡 작업 전에 echo로 먼저 테스트하세요. 실제 파일을 삭제하거나 수정하기 전에 어떤 파일들이 처리되는지 확인하면 실수를 방지할 수 있습니다.
💡 와일드카드와 함께 사용하면 더 강력합니다: for file in *.log처럼 패턴 매칭을 활용하면 조건에 맞는 모든 파일을 자동으로 찾아 처리합니다.
2. 범위 기반 for 루프
시작하며
여러분이 1번부터 100번까지 번호가 매겨진 백업 파일을 생성해야 한다고 생각해보세요. backup1.tar, backup2.tar...
backup100.tar까지 일일이 타이핑하시겠어요? 이런 연속된 숫자 작업을 수동으로 하면 오타도 나고, 중간에 빠뜨리기도 쉽습니다.
특히 숫자가 많아지면 정말 지옥이죠. 바로 이럴 때 필요한 것이 범위 기반 for 루프입니다.
중괄호 확장 문법으로 시작과 끝만 지정하면 자동으로 순회합니다.
개요
간단히 말해서, 범위 기반 for 루프는 연속된 숫자나 문자를 자동으로 생성해서 반복하는 편리한 방법입니다. 실무에서 번호가 매겨진 파일 생성, 포트 번호 스캔, 날짜 범위 처리 등에 필수적입니다.
예를 들어, 8000번부터 8010번까지의 포트가 사용 중인지 확인하거나, 최근 30일간의 로그를 처리하는 작업에 매우 유용합니다. 기존에는 숫자를 하나하나 나열했다면, 이제는 {1..100} 형식으로 범위만 지정하면 됩니다.
범위 기반 루프의 핵심은 간결성과 명확성입니다. 시작점과 끝점만 보면 몇 번 반복할지 바로 알 수 있고, 증가값도 지정할 수 있습니다.
이러한 특징들이 코드를 읽기 쉽고 유지보수하기 좋게 만듭니다.
코드 예제
# 1부터 10까지 순회
for num in {1..10}
do
echo "현재 숫자: $num"
done
# 2씩 증가하며 순회 (홀수만 처리)
for odd in {1..20..2}
do
echo "홀수: $odd"
done
# 역순으로 카운트다운
for count in {10..1}
do
echo "발사까지 $count초..."
sleep 1
done
설명
이것이 하는 일: 범위 기반 for 루프는 시작 숫자부터 끝 숫자까지 자동으로 증가(또는 감소)하며 각 숫자에 대해 작업을 수행합니다. 첫 번째로, {1..10} 부분은 Bash가 자동으로 1, 2, 3, ..., 10으로 확장합니다.
여러분이 직접 타이핑하지 않아도 되죠. 이것은 Bash의 중괄호 확장(brace expansion) 기능으로, 루프가 시작되기 전에 미리 전체 목록으로 변환됩니다.
두 번째로, {1..20..2} 형식을 사용하면 증가값을 지정할 수 있습니다. 여기서 마지막 2는 "2씩 증가하라"는 의미입니다.
그래서 1, 3, 5, 7, ... 19처럼 홀수만 생성됩니다.
짝수만 필요하면 {2..20..2}를 사용하면 됩니다. 세 번째로, 시작 숫자가 끝 숫자보다 크면 자동으로 역순으로 동작합니다.
{10..1}은 10, 9, 8, ... 1로 카운트다운합니다.
타이머나 역순 처리가 필요할 때 매우 편리하죠. 여러분이 이 코드를 사용하면 반복 횟수를 명확하게 제어할 수 있고, 인덱스 기반 작업을 쉽게 할 수 있습니다.
배열의 특정 범위만 처리하거나, 파일명에 순차적인 번호를 붙이거나, 네트워크 포트를 스캔하는 등의 작업이 몇 줄로 해결됩니다.
실전 팁
💡 중괄호 안에는 변수를 직접 사용할 수 없습니다. {1..$max} 대신 seq 명령어를 사용하세요: for i in $(seq 1 $max)
💡 0으로 시작하는 숫자를 사용하면 자동으로 제로 패딩됩니다: {01..10}은 01, 02, ... 10을 생성합니다. 파일명 정렬에 유용합니다.
💡 문자 범위도 가능합니다: {a..z} 또는 {A..Z}로 알파벳을 순회할 수 있습니다. 디렉토리를 a, b, c로 분류할 때 편리합니다.
💡 큰 범위는 성능에 주의하세요. {1..1000000}은 백만 개의 항목을 메모리에 한 번에 생성합니다. 대신 while 루프로 하나씩 처리하는 게 효율적입니다.
💡 여러 범위를 결합할 수 있습니다: {1..3}{a..c}는 1a, 1b, 1c, 2a, 2b, 2c, 3a, 3b, 3c를 생성합니다. 조합이 필요한 테스트 케이스 생성에 유용합니다.
3. 배열 순회
시작하며
여러분이 여러 서버의 IP 주소 목록을 관리하고, 각 서버에 차례대로 명령을 실행해야 한다고 상상해보세요. IP를 하나하나 복사-붙여넣기 하시겠어요?
이런 데이터 집합을 효율적으로 관리하지 못하면, 코드가 지저분해지고 유지보수가 어려워집니다. 서버가 추가되거나 제거될 때마다 스크립트를 다시 짜야 하죠.
바로 이럴 때 필요한 것이 배열 순회입니다. 데이터를 배열에 담아두고 for 루프로 깔끔하게 처리할 수 있습니다.
개요
간단히 말해서, 배열 순회는 여러 데이터를 하나의 변수에 담아 체계적으로 관리하고 반복 처리하는 방법입니다. 실무에서 서버 목록, 사용자 이름 목록, 설정 값들을 관리할 때 필수적입니다.
예를 들어, 프로덕션 환경의 모든 웹 서버에 동일한 설정을 배포하거나, 여러 데이터베이스 백업을 순차적으로 복원하는 작업에 매우 유용합니다. 기존에는 각 항목을 개별 변수로 관리했다면, 이제는 배열 하나로 모든 항목을 그룹화할 수 있습니다.
Bash 배열의 핵심 특징은 유연성입니다. 인덱스로 접근할 수도 있고, 전체를 순회할 수도 있으며, 동적으로 항목을 추가하거나 제거할 수도 있습니다.
이러한 특징들이 복잡한 데이터 처리를 단순하게 만들어줍니다.
코드 예제
# 배열 선언: 서버 목록
servers=("web1.example.com" "web2.example.com" "api.example.com")
# 배열의 모든 요소 순회
for server in "${servers[@]}"
do
echo "연결 중: $server"
# 각 서버에 ping 테스트
ping -c 1 "$server" > /dev/null && echo "✓ $server 응답" || echo "✗ $server 무응답"
done
# 인덱스와 함께 순회
for i in "${!servers[@]}"
do
echo "서버 #$i: ${servers[$i]}"
done
설명
이것이 하는 일: 배열 순회는 배열에 저장된 여러 데이터를 하나씩 꺼내서 처리하거나, 인덱스를 이용해 위치와 값을 함께 다룹니다. 첫 번째로, servers=(...)로 배열을 선언합니다.
괄호 안에 공백으로 구분된 항목들이 배열의 요소가 됩니다. 배열은 순서가 있는 데이터 저장소로, 마치 번호가 매겨진 서랍장과 같습니다.
0번 서랍부터 시작해서 차례대로 데이터가 들어가죠. 그 다음으로, "${servers[@]}"는 배열의 모든 요소를 펼쳐서 반환합니다.
@ 기호가 "모든 요소"를 의미합니다. 큰따옴표로 감싸는 것이 중요한데, 안 그러면 공백이 포함된 요소가 여러 개로 쪼개집니다.
예를 들어 "New York"이 "New"와 "York" 두 개로 분리되는 실수를 방지합니다. 세 번째로, "${!servers[@]}"는 배열의 인덱스들을 반환합니다.
느낌표(!)가 "인덱스를 달라"는 의미입니다. 이렇게 하면 몇 번째 요소인지 알 수 있어서, "서버 #1", "서버 #2" 같은 번호 매기기가 가능합니다.
여러분이 이 코드를 사용하면 데이터 관리가 훨씬 체계적으로 변합니다. 새 서버를 추가할 때 배열에 한 줄만 추가하면 되고, 전체 로직은 그대로 유지됩니다.
코드 재사용성이 높아지고, 유지보수가 쉬워지며, 실수할 여지가 줄어듭니다.
실전 팁
💡 배열 요소에 접근할 때 항상 큰따옴표를 사용하세요: "${array[@]}". 공백이나 특수문자가 포함된 요소도 안전하게 처리됩니다.
💡 배열 길이는 ${#array[@]}로 확인합니다. 반복 전에 배열이 비어있는지 검사할 때 유용합니다.
💡 배열에 요소 추가는 array+=("new_item")으로 간단합니다. 동적으로 데이터를 수집할 때 이 방법을 사용하세요.
💡 명령어 출력을 배열로 저장: files=($(ls *.txt))보다는 mapfile -t files < <(ls *.txt)가 안전합니다. 특히 파일명에 공백이 있을 때 중요합니다.
💡 연관 배열(associative array)도 사용 가능합니다: declare -A config로 선언하면 키-값 쌍으로 데이터를 관리할 수 있습니다. 설정 파일 파싱에 유용합니다.
4. while 루프
시작하며
여러분이 로그 파일을 한 줄씩 읽으면서 에러 메시지를 찾아야 한다고 생각해보세요. 파일이 몇 줄인지도 모르고, 언제 끝날지도 모릅니다.
for 루프로는 어떻게 처리하시겠어요? 이런 조건 기반 반복 작업은 횟수를 미리 알 수 없을 때가 많습니다.
데이터가 있는 동안 계속 처리하거나, 특정 조건이 만족될 때까지 반복해야 하죠. 바로 이럴 때 필요한 것이 while 루프입니다.
조건이 참인 동안 계속 반복하며, 파일 읽기나 무한 루프 같은 작업에 완벽합니다.
개요
간단히 말해서, while 루프는 조건이 참(true)인 동안 계속 반복하는 유연한 반복문입니다. 실무에서 파일을 한 줄씩 읽거나, 서비스가 시작될 때까지 대기하거나, 사용자 입력을 계속 받는 작업에 필수적입니다.
예를 들어, 로그 파일을 실시간으로 모니터링하거나, 특정 프로세스가 종료될 때까지 기다리는 작업에 매우 유용합니다. 기존 for 루프는 반복 횟수를 미리 알아야 했다면, while은 조건만 제시하면 됩니다.
while 루프의 핵심은 유연성과 조건 기반 제어입니다. 무한 반복도 가능하고, 파일의 끝까지 읽기도 가능하며, 복잡한 조건을 조합할 수도 있습니다.
이러한 특징들이 예측 불가능한 상황에서도 안정적인 반복 처리를 가능하게 합니다.
코드 예제
# 파일을 한 줄씩 읽기
while IFS= read -r line
do
# 에러가 포함된 줄만 출력
if [[ "$line" == *"ERROR"* ]]; then
echo "발견: $line"
fi
done < /var/log/app.log
# 카운터를 사용한 while 루프
counter=1
while [ $counter -le 5 ]
do
echo "반복 #$counter"
((counter++)) # 카운터 증가
done
설명
이것이 하는 일: while 루프는 매번 조건을 검사해서 참이면 코드를 실행하고, 거짓이 되면 자동으로 멈춥니다. 첫 번째로, while IFS= read -r line 부분은 파일에서 한 줄을 읽어서 line 변수에 저장합니다.
IFS=는 앞뒤 공백을 보존하고, -r은 백슬래시를 문자 그대로 읽습니다. read 명령어는 줄을 성공적으로 읽으면 참(0)을 반환하고, 파일의 끝에 도달하면 거짓(1)을 반환합니다.
그래서 파일 전체를 자동으로 순회하게 되죠. 그 다음으로, < /var/log/app.log는 파일을 while 루프의 입력으로 리다이렉션합니다.
이것은 while 루프 전체에 파일을 "먹이는" 것과 같습니다. 루프가 한 줄씩 소화하면서 처리하죠.
세 번째로, 카운터를 사용한 방식에서는 [ $counter -le 5 ]가 조건입니다. -le는 "less than or equal"의 약자로 "작거나 같으면"이라는 뜻입니다.
((counter++))는 카운터를 1씩 증가시킵니다. 조건이 거짓이 될 때(counter가 6이 될 때) 루프가 멈춥니다.
여러분이 이 코드를 사용하면 파일 크기와 상관없이 메모리 효율적으로 처리할 수 있습니다. 한 번에 한 줄씩만 메모리에 로드하니까 몇 GB짜리 로그 파일도 문제없습니다.
또한 실시간 데이터 스트림 처리나 사용자 인터랙션 같은 동적인 상황에도 완벽하게 대응할 수 있습니다.
실전 팁
💡 무한 루프는 while true 또는 while : 형식으로 만듭니다. 데몬이나 서비스 모니터링 스크립트에서 자주 사용되며, 반드시 내부에 종료 조건이나 break를 넣으세요.
💡 파일 읽기 시 while read는 마지막 줄에 개행문자가 없으면 읽지 못할 수 있습니다. while IFS= read -r line || [[ -n "$line" ]] 패턴을 사용하면 안전합니다.
💡 조건에 명령어를 직접 사용할 수 있습니다: while grep -q "RUNNING" status.txt. 명령어가 성공(0)하는 동안 계속 반복합니다.
💡 sleep과 함께 사용하면 폴링(polling) 패턴을 만들 수 있습니다: 특정 조건이 만족될 때까지 몇 초마다 확인하는 방식입니다.
💡 복잡한 조건은 &&(AND)나 ||(OR)로 결합 가능합니다: while [ $count -lt 10 ] && [ -f "$file" ]처럼 여러 조건을 동시에 검사할 수 있습니다.
5. until 루프
시작하며
여러분이 서버가 완전히 종료될 때까지 기다려야 하는 상황을 생각해보세요. "서버가 실행 중이 아닐 때까지 기다려"라는 로직을 while로 표현하면 이중 부정이 되어 헷갈립니다.
이런 "~가 아닐 때까지" 반복하는 로직을 while로 작성하면 코드가 복잡하고 읽기 어려워집니다. 조건을 반대로 뒤집어야 하니 실수하기도 쉽죠.
바로 이럴 때 필요한 것이 until 루프입니다. 조건이 거짓인 동안 반복하므로, "~까지 기다려" 로직을 자연스럽게 표현할 수 있습니다.
개요
간단히 말해서, until 루프는 조건이 거짓(false)인 동안 계속 반복하는 while의 반대 개념입니다. 실무에서 특정 파일이 생성될 때까지 대기하거나, 프로세스가 종료될 때까지 모니터링하거나, 외부 서비스가 응답할 때까지 재시도하는 작업에 유용합니다.
예를 들어, 데이터베이스가 준비될 때까지 애플리케이션 시작을 지연시키거나, 배포가 완료될 때까지 헬스체크를 반복하는 작업에 매우 적합합니다. while은 "조건이 참인 동안" 반복했다면, until은 "조건이 참이 될 때까지" 반복합니다.
until 루프의 핵심은 가독성과 의도의 명확성입니다. "~까지"라는 목표 지향적 표현이 코드의 의도를 더 분명하게 드러냅니다.
이러한 특징이 대기나 재시도 로직을 작성할 때 코드를 훨씬 이해하기 쉽게 만듭니다.
코드 예제
# 파일이 생성될 때까지 대기
until [ -f /tmp/ready.flag ]
do
echo "준비 파일 대기 중..."
sleep 2
done
echo "준비 완료! 작업 시작"
# 서비스가 응답할 때까지 재시도
attempt=1
until curl -s http://localhost:8080/health > /dev/null
do
echo "시도 #$attempt: 서비스 연결 실패, 재시도 중..."
sleep 5
((attempt++))
# 최대 10번까지만 시도
[ $attempt -gt 10 ] && { echo "연결 실패"; exit 1; }
done
설명
이것이 하는 일: until 루프는 매번 조건을 검사해서 거짓이면 코드를 실행하고, 참이 되면 자동으로 멈춥니다. while과 정반대죠.
첫 번째로, until [ -f /tmp/ready.flag ] 부분은 파일이 존재하는지 검사합니다. -f는 "일반 파일이 존재하면 참"이라는 테스트입니다.
until은 이 조건이 거짓인 동안, 즉 파일이 없는 동안 계속 반복합니다. 파일이 생성되는 순간(조건이 참이 되는 순간) 루프를 빠져나옵니다.
그 다음으로, sleep 2는 2초간 대기합니다. 이것이 없으면 루프가 초당 수천 번 실행되어 CPU를 낭비하게 됩니다.
폴링 간격을 적절히 조절하는 것이 시스템 자원 관리에 중요합니다. 너무 짧으면 자원 낭비, 너무 길면 반응 지연이 발생하죠.
세 번째로, curl 명령어로 헬스체크를 합니다. -s는 조용한 모드로, 진행 상황을 출력하지 않습니다.
명령어가 성공하면(서비스가 응답하면) 0을 반환하고, 실패하면 0이 아닌 값을 반환합니다. until은 실패하는 동안(거짓인 동안) 계속 재시도하다가, 성공하면(참이 되면) 종료합니다.
여러분이 이 코드를 사용하면 대기 로직이 훨씬 자연스럽게 읽힙니다. "파일이 생성될 때까지 대기"라는 비즈니스 로직이 코드에 그대로 반영되어 있어서, 6개월 후에 다시 봐도 의도를 바로 이해할 수 있습니다.
또한 재시도 로직에 타임아웃을 추가하면 무한 대기를 방지하여 더 견고한 스크립트를 만들 수 있습니다.
실전 팁
💡 until과 while은 논리적으로 대체 가능하지만, 가독성을 고려해서 선택하세요. "~까지"라는 표현이 자연스러우면 until을 사용하세요.
💡 무한 루프 방지를 위해 항상 카운터나 타임아웃을 설정하세요. 네트워크 장애 등으로 조건이 영원히 만족되지 않을 수 있습니다.
💡 set -e(오류 시 즉시 종료)를 사용하는 스크립트에서는 until 내부 명령어가 실패해도 스크립트가 종료되지 않도록 주의하세요.
💡 외부 서비스 대기 시 지수 백오프(exponential backoff)를 고려하세요: 재시도 간격을 점점 늘려서 서버 부하를 줄입니다.
💡 조건 검사와 실제 작업 사이에 race condition이 발생할 수 있습니다. 가능하면 원자적(atomic) 연산을 사용하세요.
6. break와 continue 제어
시작하며
여러분이 1000개의 파일을 검사하다가 원하는 파일을 찾았다고 생각해보세요. 나머지 999개를 계속 검사하는 건 시간 낭비 아닌가요?
중간에 멈출 방법이 없을까요? 이런 조기 종료나 특정 항목 건너뛰기가 없으면, 불필요한 작업으로 성능이 낭비됩니다.
특히 대량 데이터를 처리할 때 치명적이죠. 바로 이럴 때 필요한 것이 break와 continue입니다.
break로 루프를 즉시 종료하거나, continue로 현재 반복만 건너뛸 수 있습니다.
개요
간단히 말해서, break는 루프를 완전히 빠져나가고, continue는 현재 반복을 건너뛰고 다음 반복으로 넘어갑니다. 실무에서 조건에 맞는 항목을 찾았을 때 즉시 종료하거나, 특정 조건의 항목만 제외하고 처리할 때 필수적입니다.
예를 들어, 백업 파일 중 손상된 파일은 건너뛰고 나머지만 복원하거나, 첫 번째 에러를 발견하는 즉시 검사를 중단하는 작업에 매우 유용합니다. 기존에는 조건문으로 복잡하게 플래그를 관리했다면, 이제는 break와 continue로 흐름을 직관적으로 제어할 수 있습니다.
break와 continue의 핵심은 효율성과 제어력입니다. 불필요한 반복을 줄여 성능을 향상시키고, 복잡한 조건 처리를 단순화합니다.
이러한 특징들이 실용적이고 효율적인 스크립트 작성을 가능하게 합니다.
코드 예제
# break: 조건을 만족하면 즉시 종료
for file in *.log
do
if grep -q "CRITICAL ERROR" "$file"; then
echo "치명적 에러 발견: $file"
break # 첫 번째 발견 시 즉시 종료
fi
done
# continue: 특정 항목만 건너뛰기
for user in alice bob charlie dave
do
# bob은 건너뛰기
[ "$user" = "bob" ] && continue
echo "$user에게 이메일 발송 중..."
# 실제 이메일 발송 로직
done
# 중첩 루프에서 break 레벨 지정
for i in {1..3}; do
for j in {1..3}; do
echo "i=$i, j=$j"
[ $j -eq 2 ] && break 2 # 외부 루프까지 종료
done
done
설명
이것이 하는 일: break와 continue는 루프의 실행 흐름을 직접 제어하여 조건에 따라 반복을 중단하거나 건너뜁니다. 첫 번째로, break 명령어는 현재 루프를 즉시 종료하고 루프 다음 코드로 이동합니다.
위 예제에서 "CRITICAL ERROR"가 발견되면 더 이상 다른 파일을 검사하지 않습니다. 마치 긴급 탈출구와 같죠.
이것은 특히 검색 작업에서 유용합니다. 원하는 것을 찾았으면 더 찾을 필요가 없으니까요.
그 다음으로, continue 명령어는 현재 반복의 나머지 코드를 건너뛰고 바로 다음 반복으로 넘어갑니다. bob을 만나면 이메일 발송 코드를 실행하지 않고 바로 charlie로 넘어갑니다.
이것은 예외 처리나 필터링에 매우 효과적입니다. 복잡한 if-else 중첩 없이 "이 경우는 패스"라고 깔끔하게 표현할 수 있습니다.
세 번째로, break 2처럼 숫자를 지정하면 여러 단계의 루프를 한 번에 빠져나갈 수 있습니다. 숫자는 몇 겹의 루프를 종료할지를 의미합니다.
중첩 루프에서 특정 조건이 만족되면 완전히 빠져나와야 할 때 유용합니다. break 1은 그냥 break와 같습니다.
여러분이 이 코드를 사용하면 성능이 크게 향상될 수 있습니다. 예를 들어 10만 개 파일 중 첫 100개 안에서 원하는 파일을 찾으면, 나머지 99,900개를 검사하지 않아도 됩니다.
또한 코드의 복잡도가 줄어들어 가독성이 좋아지고, 버그가 숨을 곳이 줄어듭니다. 조건이 복잡해질수록 break와 continue의 가치는 더욱 커집니다.
실전 팁
💡 break와 continue는 가장 안쪽 루프에만 영향을 줍니다. 외부 루프를 제어하려면 break 2, break 3 같은 레벨을 지정하세요.
💡 continue는 필터링 로직을 앞에 배치하는 "early return" 패턴에 완벽합니다. 처리하지 않을 조건들을 먼저 걸러내면 코드가 훨씬 깔끔해집니다.
💡 무한 루프(while true)에서는 break가 유일한 탈출 방법입니다. 반드시 적절한 조건에서 break가 실행되도록 하세요.
💡 디버깅 시 break 전에 echo로 왜 종료되는지 로그를 남기면 문제 파악이 쉽습니다: echo "종료 사유: $reason"; break
💡 함수 내부의 루프에서 break 대신 return을 사용하면 함수 전체를 종료할 수 있습니다. 루프만 종료할지, 함수를 종료할지 명확히 구분하세요.